1+ import sys .io .File ;
2+ import haxe .io .Path ;
3+ using StringTools ;
4+
5+ class NinjaGenerator {
6+ var buf : StringBuf ;
7+
8+ public function new () {
9+ buf = new StringBuf ();
10+ }
11+
12+ function comment (value : String , empty_line = false ) {
13+ buf .add (' # $value \n ' );
14+ if (empty_line ) buf .add (' \n ' );
15+ }
16+
17+ function bind (name : String , value : String ) {
18+ buf .add (' $name = $value \n\n ' );
19+ }
20+
21+ function rule (name : String , args : Map <String , String >) {
22+ buf .add (' rule $name \n ' );
23+ for (key => value in args ) {
24+ buf .add (' $key = $value \n ' );
25+ }
26+ buf .add (' \n ' );
27+ }
28+
29+ function build (out : Array <String >, rule : String , input : Array <String >, ? args : Map <String , String >) {
30+ if (args == null ) args = [];
31+ buf .add (' build ${out .join (' ' )}: $rule ${input .join (' ' )}\n ' );
32+ for (key => value in args ) {
33+ buf .add (' $key = $value \n ' );
34+ }
35+ buf .add (' \n ' );
36+ }
37+
38+ function save (path : String ) {
39+ var str = this .buf .toString ();
40+ File .saveContent (path , str );
41+ }
42+
43+ public static function gen (config : HlcConfig , output : String ) {
44+ var gen = new NinjaGenerator ();
45+ gen .comment (' Automatically generated file, do not edit' , true );
46+ gen .bind (' ninja_required_version' , ' 1.2' );
47+
48+ var compiler_flavor : CCFlavor = switch Sys .systemName () {
49+ case " Windows" : MSVC ;
50+ case _ : GCC ;
51+ }
52+
53+ switch compiler_flavor {
54+ case GCC :
55+ var opt_flag = config .defines .exists (" debug" ) ? " -g" : ' -O2' ;
56+ var rpath = switch Sys .systemName () {
57+ case " Mac" : " -rpath @executable_path -rpath /usr/local/lib" ;
58+ case _ : " -Wl,-rpath,$$ORIGIN:/usr/local/lib" ;
59+ };
60+ gen .bind (' cflags' , ' $opt_flag -std=c11 -DHL_MAKE -Wall -I. -pthread' );
61+ final libflags = config .libs .map ((lib ) -> switch lib {
62+ case " std" : " -lhl" ;
63+ case " uv" : ' /usr/local/lib/ $lib .hdll -luv' ;
64+ case var lib : ' /usr/local/lib/ $lib .hdll' ;
65+ }).join (' ' );
66+ gen .bind (' ldflags' , ' -pthread -lm -L/usr/local/lib $libflags $rpath ' );
67+ gen .rule (' cc' , [
68+ " command" => " cc -MD -MF $out.d $cflags -c $in -o $out" ,
69+ " deps" => " gcc" ,
70+ " depfile" => " $out.d" ,
71+ ]);
72+ gen .rule (' ld' , [
73+ " command" => " cc $in -o $out $ldflags"
74+ ]);
75+ case MSVC :
76+ gen .bind (' hashlink' , Sys .getEnv (' HASHLINK' ));
77+ gen .bind (' cflags' , " /DHL_MAKE /std:c11 /I. /I$hashlink\\ include" );
78+ final libflags = config .libs .map ((lib ) -> switch lib {
79+ case " std" : " libhl.lib" ;
80+ case var lib : ' $lib .lib' ;
81+ });
82+ gen .bind (' ldflags' , " /LIBPATH:$hashlink " + libflags );
83+ gen .rule (' cc' , [
84+ " command" => " cl.exe /nologo /showIncludes $cflags /c $in /Fo$out" ,
85+ " deps" => " msvc" ,
86+ ]);
87+ gen .rule (' ld' , [
88+ " command" => " link.exe /nologo /OUT:$out $ldflags @$out.rsp" ,
89+ " rspfile" => " $out.rsp" ,
90+ " rspfile_content" => " $in"
91+ ]);
92+ }
93+
94+ final objects = [];
95+
96+ for (file in config .files ) {
97+ final out_path = haxe.io. Path .withExtension (file , ' o' );
98+ objects .push (out_path );
99+ gen .build ([out_path .toString ()], " cc" , [file ], []);
100+ }
101+
102+ final exe_path = Path .withExtension (Path .withoutDirectory (output ), switch compiler_flavor {
103+ case MSVC : " exe" ;
104+ case GCC : null ;
105+ });
106+ gen .build ([exe_path ], ' ld' , objects , []);
107+
108+ gen .save (Path .join ([Path .directory (output ), ' build.ninja' ]));
109+ }
110+
111+ public static function run (dir : String ) {
112+ switch Sys .systemName () {
113+ case " Windows" :
114+ var devcmd = findVsDevCmdScript ();
115+ Sys .command (" cmd.exe" , [" /C" , devcmd , " -arch=x64" , ' &&' , ' ninja' , ' -C' , dir ]);
116+ case _ :
117+ Sys .command (" ninja" , [" -C" , dir ]);
118+ }
119+ }
120+
121+ private static function findVsDevCmdScript (): Null <String > {
122+ var proc = new sys.io. Process (' C:\\ Program Files (x86) \\ Microsoft Visual Studio \\ Installer \\ vswhere.exe' , [
123+ " -latest" ,
124+ " -products" , " *" ,
125+ " -requires" ,
126+ " Microsoft.VisualStudio.Component.VC.Tools.x86.x64" ,
127+ " -property" ,
128+ " installationPath"
129+ ]);
130+ proc .stdin .close ();
131+ var stdout = proc .stdout .readAll ();
132+ if (proc .exitCode (true ) == 0 ) {
133+ var instPath = stdout .toString ().trim ();
134+ return ' $instPath \\ Common7 \\ Tools \\ vsdevcmd.bat' ;
135+ } else {
136+ return null ;
137+ }
138+ }
139+ }
140+
141+ enum abstract CCFlavor (String ) {
142+ var MSVC = " msvc" ;
143+ /**
144+ * GCC, Clang, etc
145+ **/
146+ var GCC = " gcc" ;
147+ }
148+
149+ typedef HlcConfig = {
150+ var version : Int ;
151+ var libs : Array <String >;
152+ var defines : haxe. DynamicAccess <String >;
153+ var files : Array <String >;
154+ };
155+
1156class Build {
2157
3158 var output : String ;
4159 var name : String ;
5160 var targetDir : String ;
6161 var dataPath : String ;
7- var config : {
8- var version : Int ;
9- var libs : Array <String >;
10- var defines : haxe. DynamicAccess <String >;
11- var files : Array <String >;
12- };
162+ var config : HlcConfig ;
13163
14164 public function new (dataPath ,output ,config ) {
15165 this .output = output ;
@@ -21,11 +171,15 @@ class Build {
21171 }
22172
23173 public function run () {
24- var tpl = config .defines .get (" hlgen.makefile" );
25- if ( tpl != null )
26- generateTemplates (tpl );
27- if ( config .defines .get (" hlgen.silent" ) == null )
28- Sys .println (" Code generated in " + output + " automatic native compilation not yet implemented" );
174+ switch config .defines .get (" hlgen.makefile" ) {
175+ case " ninja" :
176+ NinjaGenerator .gen (config , output );
177+ NinjaGenerator .run (Path .directory (output ));
178+ case var tpl :
179+ generateTemplates (tpl );
180+ if ( config .defines .get (" hlgen.silent" ) == null )
181+ Sys .println (" Code generated in " + output + " automatic native compilation not yet implemented" );
182+ }
29183 }
30184
31185 function isAscii ( bytes : haxe.io. Bytes ) {
0 commit comments