From ee03e9582c62997aefd45ca9825fcb448a3b9f04 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Mon, 4 Nov 2024 17:09:00 +0100 Subject: [PATCH 01/11] Add ninja generator. --- other/haxelib/Run.hx | 131 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 9 deletions(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 6f0fe346f..049608038 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -1,15 +1,124 @@ +import sys.io.File; +import haxe.io.Path; + +class NinjaGenerator { + var buf:StringBuf; + + public function new() { + buf = new StringBuf(); + } + + function comment(value:String, empty_line = false) { + buf.add('# $comment \n'); + if (empty_line) buf.add('\n'); + } + + function bind(name:String, value:String) { + buf.add('$name = $value\n\n'); + } + + function rule(name:String, args:Map) { + buf.add('rule $name\n'); + for (key => value in args) { + buf.add(' $key = $value\n'); + } + buf.add('\n'); + } + + function build(out:Array, rule:String, input:Array, ?args:Map) { + args ??= []; + buf.add('build ${out.join(' ')}: $rule ${input.join(' ')}\n'); + for (key => value in args) { + buf.add(' $key = $value\n'); + } + buf.add('\n'); + } + + function save(path:String) { + var str = this.buf.toString(); + File.saveContent(path, str); + } + + public static function gen(config: HlcConfig, output: String) { + var gen = new NinjaGenerator(); + gen.comment('Automatically generated file, do not edit', true); + gen.bind('ninja_required_version', '1.2'); + + var compiler_flavor: CCFlavor = switch Sys.systemName() { + case "Windows": MSVC; + case _: GCC; + } + + switch compiler_flavor { + case GCC: + gen.bind('cflags', '-DHL_MAKE -Wall -I.'); + final libflags = config.libs.map((lib) -> switch lib { + case "std": "-lhl"; + case var lib: '-l:$lib.hdll'; + }).join(' '); + gen.bind('ldflags', '-lm $libflags'); + gen.rule('cc', [ + "command" => "cc -MD -MF $out.d $cflags -c $in -o $out", + "deps" => "gcc", + "depfile" => "$out.d", + ]); + gen.rule('ld', [ + "command" => "cc $ldflags $in -o $out" + ]); + case MSVC: + gen.bind('cflags', '/DHL_MAKE /I.'); + gen.bind('ldflags', 'libhl.lib'); + gen.rule('cc', [ + "command" => "cl.exe /showIncludes $cflags /c $in ", + "deps" => "msvc", + ]); + gen.rule('ld', [ + "command" => "link.exe /OUT$out $ldflags @$out.rsp", + "rspfile" => "$out.rsp", + "rspfile_content" => "$in" + ]); + } + + final objects = []; + + for (file in config.files) { + final out_path = haxe.io.Path.withExtension(file, 'o'); + objects.push(out_path); + gen.build([out_path.toString()], "cc", [file], []); + } + + final exe_path = Path.withExtension(Path.withoutDirectory(output), switch compiler_flavor { + case MSVC: "exe"; + case GCC: null; + }); + gen.build([exe_path], 'ld', objects, []); + + gen.save(Path.join([Path.directory(output), 'build.ninja'])); + } +} + +enum abstract CCFlavor(String) { + var MSVC = "msvc"; + /** + * GCC, Clang, etc + **/ + var GCC = "gcc"; +} + +typedef HlcConfig = { + var version:Int; + var libs:Array; + var defines:haxe.DynamicAccess; + var files:Array; +}; + class Build { var output : String; var name : String; var targetDir : String; var dataPath : String; - var config : { - var version : Int; - var libs : Array; - var defines : haxe.DynamicAccess; - var files : Array; - }; + var config : HlcConfig; public function new(dataPath,output,config) { this.output = output; @@ -22,10 +131,14 @@ class Build { public function run() { var tpl = config.defines.get("hlgen.makefile"); - if( tpl != null ) + if( tpl != null && tpl != "ninja"){ generateTemplates(tpl); - if( config.defines.get("hlgen.silent") == null ) - Sys.println("Code generated in "+output+" automatic native compilation not yet implemented"); + if( config.defines.get("hlgen.silent") == null ) + Sys.println("Code generated in "+output+" automatic native compilation not yet implemented"); + } else { + NinjaGenerator.gen(config, output); + Sys.command('ninja', ['-C', Path.directory(output)]); + } } function isAscii( bytes : haxe.io.Bytes ) { From aa8b3f31e4374498b5528b89f171dadfe4fcd0d9 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:59:16 +0100 Subject: [PATCH 02/11] Improve Windows support for Ninja generator. --- other/haxelib/Run.hx | 47 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 049608038..2a750e60e 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -1,5 +1,6 @@ import sys.io.File; import haxe.io.Path; +using StringTools; class NinjaGenerator { var buf:StringBuf; @@ -9,7 +10,7 @@ class NinjaGenerator { } function comment(value:String, empty_line = false) { - buf.add('# $comment \n'); + buf.add('# $value \n'); if (empty_line) buf.add('\n'); } @@ -51,7 +52,7 @@ class NinjaGenerator { switch compiler_flavor { case GCC: - gen.bind('cflags', '-DHL_MAKE -Wall -I.'); + gen.bind('cflags', '-std=c11 -DHL_MAKE -Wall -I.'); final libflags = config.libs.map((lib) -> switch lib { case "std": "-lhl"; case var lib: '-l:$lib.hdll'; @@ -66,14 +67,15 @@ class NinjaGenerator { "command" => "cc $ldflags $in -o $out" ]); case MSVC: - gen.bind('cflags', '/DHL_MAKE /I.'); - gen.bind('ldflags', 'libhl.lib'); + gen.bind('hashlink', Sys.getEnv('HASHLINK')); + gen.bind('cflags', "/DHL_MAKE /std:c11 /I. /I$hashlink\\include"); + gen.bind('ldflags', "/LIBPATH:$hashlink libhl.lib"); gen.rule('cc', [ - "command" => "cl.exe /showIncludes $cflags /c $in ", + "command" => "cl.exe /nologo /showIncludes $cflags /c $in /Fo$out", "deps" => "msvc", ]); gen.rule('ld', [ - "command" => "link.exe /OUT$out $ldflags @$out.rsp", + "command" => "link.exe /nologo /OUT:$out $ldflags @$out.rsp", "rspfile" => "$out.rsp", "rspfile_content" => "$in" ]); @@ -95,6 +97,37 @@ class NinjaGenerator { gen.save(Path.join([Path.directory(output), 'build.ninja'])); } + + public static function run(dir:String) { + switch Sys.systemName() { + case "Windows": + var devcmd = findVsDevCmdScript(); + Sys.command("cmd.exe", ["/C", devcmd, "-arch=x64", '&&', 'ninja', '-C', dir]); + case _: + Sys.command("ninja", ["-C", dir]); + } + } + + // private static function writeBat(vsdevcmd:String, out_dir:String) + + private static function findVsDevCmdScript(): Null { + var proc = new sys.io.Process('C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe', [ + "-latest", + "-products", "*", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-property", + "installationPath" + ]); + proc.stdin.close(); + var stdout = proc.stdout.readAll(); + if (proc.exitCode(true) == 0) { + var instPath = stdout.toString().trim(); + return '$instPath\\Common7\\Tools\\vsdevcmd.bat'; + } else { + return null; + } + } } enum abstract CCFlavor(String) { @@ -137,7 +170,7 @@ class Build { Sys.println("Code generated in "+output+" automatic native compilation not yet implemented"); } else { NinjaGenerator.gen(config, output); - Sys.command('ninja', ['-C', Path.directory(output)]); + NinjaGenerator.run(Path.directory(output)); } } From 96fcc155a8701e1aa4309fa2c2e08670c4338527 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:30:55 +0100 Subject: [PATCH 03/11] Use Ninja generator in CI. --- .github/workflows/build.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6abc6f76c..569cbe433 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -155,7 +155,7 @@ jobs: set -eux haxelib setup ~/haxelib - haxelib install hashlink + haxelib dev hashlink other/haxelib haxelib list @@ -233,9 +233,8 @@ jobs: popd fi - haxe -hl src/_main.c -cp other/tests -main HelloWorld - make hlc - ./hlc + haxe -hl out/main.c -cp other/tests -main HelloWorld + out/main ;; esac From d7844a73d3255a131d793d8769c1abcc29dfe768 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:34:48 +0100 Subject: [PATCH 04/11] Install Ninja in CI. --- .github/workflows/build.yml | 3 ++- Brewfile | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 569cbe433..5b79f9720 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,7 +127,8 @@ jobs: libturbojpeg-dev \ libuv1-dev \ libvorbis-dev \ - libsqlite3-dev + libsqlite3-dev \ + ninja-build ;; darwin*) diff --git a/Brewfile b/Brewfile index 9fa2ce060..631cfaab9 100644 --- a/Brewfile +++ b/Brewfile @@ -11,3 +11,4 @@ brew "mbedtls" brew "libuv" brew "openssl" brew "sqlite" +brew "ninja" From 466c99d58ca7a0f4b920ba7008f2deba3c650b13 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:51:03 +0100 Subject: [PATCH 05/11] Add rpath flags to Ninja generator. --- other/haxelib/Run.hx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 2a750e60e..fce0a66c8 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -51,13 +51,19 @@ class NinjaGenerator { } switch compiler_flavor { - case GCC: - gen.bind('cflags', '-std=c11 -DHL_MAKE -Wall -I.'); + case GCC: + var opt_flag = config.defines.exists("debug") ? "-g" : '-O2'; + var rpath = switch Sys.systemName() { + case "Mac": "-rpath @executable_path"; + case _: "-Wl,-rpath,$$ORIGIN"; + }; + gen.bind('cflags', '$opt_flag -std=c11 -DHL_MAKE -Wall -I. -pthread'); final libflags = config.libs.map((lib) -> switch lib { case "std": "-lhl"; + case "uv": '-l:$lib.hdll -luv'; case var lib: '-l:$lib.hdll'; }).join(' '); - gen.bind('ldflags', '-lm $libflags'); + gen.bind('ldflags', '-pthread -lm $libflags $rpath'); gen.rule('cc', [ "command" => "cc -MD -MF $out.d $cflags -c $in -o $out", "deps" => "gcc", From 27ab3ec8a60f8ccd2cc5214e58759a7b162e94e6 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:53:01 +0100 Subject: [PATCH 06/11] Add `-L/usr/local/lib` to Ninja generator to ensure libhl is found. --- other/haxelib/Run.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index fce0a66c8..da389506a 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -63,7 +63,7 @@ class NinjaGenerator { case "uv": '-l:$lib.hdll -luv'; case var lib: '-l:$lib.hdll'; }).join(' '); - gen.bind('ldflags', '-pthread -lm $libflags $rpath'); + gen.bind('ldflags', '-pthread -lm -L/usr/local/lib $libflags $rpath'); gen.rule('cc', [ "command" => "cc -MD -MF $out.d $cflags -c $in -o $out", "deps" => "gcc", From 10898207dbc344fb0c636f2ec9d306ef9f9c8cb0 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:05:46 +0100 Subject: [PATCH 07/11] Apprently shared libraries need to come after object files. --- other/haxelib/Run.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index da389506a..3f9d6e503 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -27,7 +27,7 @@ class NinjaGenerator { } function build(out:Array, rule:String, input:Array, ?args:Map) { - args ??= []; + if(args == null) args = []; buf.add('build ${out.join(' ')}: $rule ${input.join(' ')}\n'); for (key => value in args) { buf.add(' $key = $value\n'); @@ -70,7 +70,7 @@ class NinjaGenerator { "depfile" => "$out.d", ]); gen.rule('ld', [ - "command" => "cc $ldflags $in -o $out" + "command" => "cc $in -o $out $ldflags" ]); case MSVC: gen.bind('hashlink', Sys.getEnv('HASHLINK')); From b03c0c2fba33f102eed68e4d3ff5877acabefb73 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:06:53 +0100 Subject: [PATCH 08/11] Add /usr/local/lib to the rpath. --- other/haxelib/Run.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 3f9d6e503..3e9a8f051 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -54,8 +54,8 @@ class NinjaGenerator { case GCC: var opt_flag = config.defines.exists("debug") ? "-g" : '-O2'; var rpath = switch Sys.systemName() { - case "Mac": "-rpath @executable_path"; - case _: "-Wl,-rpath,$$ORIGIN"; + case "Mac": "-rpath @executable_path -rpath /usr/local/lib"; + case _: "-Wl,-rpath,$$ORIGIN,/usr/local/lib"; }; gen.bind('cflags', '$opt_flag -std=c11 -DHL_MAKE -Wall -I. -pthread'); final libflags = config.libs.map((lib) -> switch lib { From 0dca5288563a5562375a978b4fd41b2240978eae Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:08:34 +0100 Subject: [PATCH 09/11] Fix typo. --- other/haxelib/Run.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 3e9a8f051..0194c8e24 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -55,7 +55,7 @@ class NinjaGenerator { var opt_flag = config.defines.exists("debug") ? "-g" : '-O2'; var rpath = switch Sys.systemName() { case "Mac": "-rpath @executable_path -rpath /usr/local/lib"; - case _: "-Wl,-rpath,$$ORIGIN,/usr/local/lib"; + case _: "-Wl,-rpath,$$ORIGIN:/usr/local/lib"; }; gen.bind('cflags', '$opt_flag -std=c11 -DHL_MAKE -Wall -I. -pthread'); final libflags = config.libs.map((lib) -> switch lib { From 6f69b832e3121f127129ea8f2a38b581b37d2ca0 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:12:22 +0100 Subject: [PATCH 10/11] Disable Ninja generator by default. --- .github/workflows/build.yml | 2 +- other/haxelib/Run.hx | 18 ++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5b79f9720..b5309f07c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -234,7 +234,7 @@ jobs: popd fi - haxe -hl out/main.c -cp other/tests -main HelloWorld + haxe -hl out/main.c -cp other/tests -main HelloWorld -D hlgen.makefile=ninja out/main ;; esac diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 0194c8e24..4ec739c38 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -114,8 +114,6 @@ class NinjaGenerator { } } - // private static function writeBat(vsdevcmd:String, out_dir:String) - private static function findVsDevCmdScript(): Null { var proc = new sys.io.Process('C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe', [ "-latest", @@ -169,14 +167,14 @@ class Build { } public function run() { - var tpl = config.defines.get("hlgen.makefile"); - if( tpl != null && tpl != "ninja"){ - generateTemplates(tpl); - if( config.defines.get("hlgen.silent") == null ) - Sys.println("Code generated in "+output+" automatic native compilation not yet implemented"); - } else { - NinjaGenerator.gen(config, output); - NinjaGenerator.run(Path.directory(output)); + switch config.defines.get("hlgen.makefile") { + case "ninja": + NinjaGenerator.gen(config, output); + NinjaGenerator.run(Path.directory(output)); + case var tpl: + generateTemplates(tpl); + if( config.defines.get("hlgen.silent") == null ) + Sys.println("Code generated in "+output+" automatic native compilation not yet implemented"); } } From f42af6487d18d4c4c062195862bb815d484b092c Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Sat, 30 Nov 2024 10:11:42 +0100 Subject: [PATCH 11/11] Add fmt sample, and temp hack to hopefully make the ninja generator work on macOS. --- .github/workflows/build.yml | 7 +++++-- other/fmtsample/FmtSample.hx | 10 ++++++++++ other/haxelib/Run.hx | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 other/fmtsample/FmtSample.hx diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5309f07c..239d129bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -234,8 +234,11 @@ jobs: popd fi - haxe -hl out/main.c -cp other/tests -main HelloWorld -D hlgen.makefile=ninja - out/main + haxe -hl out/helloworld/main.c -cp other/tests -main HelloWorld -D hlgen.makefile=ninja + out/helloworld/main + + haxe -hl out/fmtsample/main.c -cp other/fmtsample -main FmtSample -D hlgen.makefile=ninja + out/fmtsample/main ;; esac diff --git a/other/fmtsample/FmtSample.hx b/other/fmtsample/FmtSample.hx new file mode 100644 index 000000000..6939fbf74 --- /dev/null +++ b/other/fmtsample/FmtSample.hx @@ -0,0 +1,10 @@ +function main() { + var out = haxe.io.Bytes.alloc(16); + var src = haxe.io.Bytes.ofString("Hello World!"); + hl.Format.digest(out.getData(), src.getData(), src.length, 0 /* md5 */); + final expected = "ed076287532e86365e841e92bfc50d8c"; + final got = out.toHex(); + if (got != expected) { + throw 'expected $expected, got $got'; + } +} \ No newline at end of file diff --git a/other/haxelib/Run.hx b/other/haxelib/Run.hx index 4ec739c38..03942eeb8 100644 --- a/other/haxelib/Run.hx +++ b/other/haxelib/Run.hx @@ -60,8 +60,8 @@ class NinjaGenerator { gen.bind('cflags', '$opt_flag -std=c11 -DHL_MAKE -Wall -I. -pthread'); final libflags = config.libs.map((lib) -> switch lib { case "std": "-lhl"; - case "uv": '-l:$lib.hdll -luv'; - case var lib: '-l:$lib.hdll'; + case "uv": '/usr/local/lib/$lib.hdll -luv'; + case var lib: '/usr/local/lib/$lib.hdll'; }).join(' '); gen.bind('ldflags', '-pthread -lm -L/usr/local/lib $libflags $rpath'); gen.rule('cc', [