@@ -50,37 +50,62 @@ string[] testRunnerBuildArgs(string[] userArgs) {
5050 return args;
5151}
5252
53+ string preferredCompiler;
54+
5355int main (string [] args) {
5456 // maybe override the normal config files
5557 // --opend-config-file
5658 // --opend-project-file
5759 try {
5860 import std.algorithm ;
5961 string [] buildSpecificArgs;
62+ string [] otherOpendArgs;
6063 string [] allOtherArgs;
61- foreach (arg; args)
64+ foreach (arg; args) {
6265 if (arg.startsWith(" --opend-to-build=" ))
6366 buildSpecificArgs ~= arg[" --opend-to-build=" .length .. $];
67+ else
68+ if (arg.startsWith(" --opend-" ))
69+ otherOpendArgs ~= arg[" --opend-" .length .. $];
6470 else
6571 allOtherArgs ~= arg;
72+ }
73+ foreach (arg; otherOpendArgs) {
74+ import std.string ;
75+ auto equal = arg.indexOf(" =" );
76+ if (equal == - 1 )
77+ throw new Exception (" opend arg without param: " ~ arg);
78+ auto name = arg[0 .. equal];
79+ auto value = arg[equal + 1 .. $];
80+
81+ switch (name) {
82+ case " compiler" :
83+ preferredCompiler = value;
84+ break ;
85+ default :
86+ throw new Exception (" unknown opend arg: " ~ name);
87+ }
88+ }
89+
6690
6791 if (allOtherArgs.length == 0 ) {
6892 return 1 ; // should never happen...
6993 } if (allOtherArgs.length == 1 ) {
70- return Commands.run(null );
94+ return Commands.run(null , buildSpecificArgs );
7195 } else switch (auto a = allOtherArgs[1 ]) {
7296 foreach (memberName; __traits (allMembers, Commands))
97+ static if (__traits(getProtection, __traits(getMember, Commands, memberName)) == " public" )
7398 case memberName: {
7499 string [] argsToSend = allOtherArgs[2 .. $];
75- if (a == " build" /* || a == "test"*/ || a == " publish" || a == " testOnly" || a == " check" || a == " run" )
76- argsToSend = buildSpecificArgs ~ allOtherArgs[2 .. $];
77- return __traits (getMember, Commands, memberName)(argsToSend);
100+ if (a == " build" || a == " test" || a == " publish" || a == " testOnly" || a == " check" || a == " run" )
101+ argsToSend = allOtherArgs[2 .. $];
102+ return __traits (getMember, Commands, memberName)(argsToSend, buildSpecificArgs );
78103 }
79104 case " -h" , " --help" :
80- Commands.help(null );
105+ Commands.help(null , null );
81106 return 0 ;
82107 default :
83- return Commands.build(buildSpecificArgs ~ allOtherArgs[1 .. $]);
108+ return Commands.build(allOtherArgs[1 .. $], buildSpecificArgs );
84109 }
85110 } catch (Throwable e) {
86111 import std.stdio ;
@@ -108,12 +133,19 @@ struct Commands {
108133 static :
109134
110135 // / Displays this information
111- int help (string [] args) {
136+ int help (string [] args, string [] extraBuildArgs ) {
112137 import std.stdio , std.string ;
113138
114- writeln(" `opend command_or_filename [args...]` where commands include:" );
139+ writeln(" `opend [--opend-args...] command_or_filename [args...]` where commands include:" );
140+
141+ writeln(" Where opend-args include:" );
142+ writeln(" \t --opend-compiler=ldmd2 prefer the ldc-based compiler in all cases" );
143+ writeln(" \t --opend-to-build=flag passes the given flag to the compiler when building" );
144+
145+ writeln(" Commands include:" );
115146
116147 foreach (memberName; __traits (allMembers, Commands))
148+ static if (__traits(getProtection, __traits(getMember, Commands, memberName)) == " public" )
117149 static if (memberName != " sendToCompilerDriver" )
118150 writefln(" %9s\t %s" , memberName, strip(__traits(docComment, __traits(getMember, Commands, memberName))));
119151
@@ -122,16 +154,18 @@ struct Commands {
122154 }
123155
124156 // / Does a debug build and immediately runs the program
125- int run (string [] args) {
157+ int run (string [] args, string [] extraBuildArgs ) {
126158 import std.stdio , std.string ;
127159 if (args.length == 0 ) {
128- help(null );
160+ help(null , null );
129161 return 1 ;
130162 }
131163
164+ args = extraBuildArgs ~ args;
165+
132166 auto oe = getOutputExecutable(args);
133167
134- if (auto err = build(oe.buildArgs))
168+ if (auto err = build(oe.buildArgs, null ))
135169 return err;
136170
137171 return spawnProcess ([oe.exe] ~ oe.args, [
@@ -140,7 +174,7 @@ struct Commands {
140174 }
141175
142176 // / Builds the code and runs its unittests
143- int test (string [] args) {
177+ int test (string [] args, string [] extraBuildArgs ) {
144178 // Check if user wants advanced test runner features
145179 if (args.length > 0 ) {
146180 switch (args[0 ]) {
@@ -154,7 +188,7 @@ struct Commands {
154188 // Delegate to test runner's help system to avoid duplication
155189 auto oe = getOutputExecutable(testRunnerBuildArgs([]));
156190
157- if (auto err = build(oe.buildArgs))
191+ if (auto err = build(oe.buildArgs, extraBuildArgs ))
158192 return err;
159193
160194 return spawnProcess ([oe.exe, " help" ], [
@@ -170,14 +204,14 @@ struct Commands {
170204 }
171205
172206 // Original test behavior - run all tests
173- return run ([" -g" , " -unittest" , " -main" , " -checkaction=context" ] ~ args);
207+ return run ([" -g" , " -unittest" , " -main" , " -checkaction=context" ] ~ extraBuildArgs ~ args, null );
174208 }
175209
176210 private int testList (string [] args) {
177211 // Build executable with test runner embedded (no -main since test_runner.d has its own)
178212 auto oe = getOutputExecutable(testRunnerBuildArgs(args));
179213
180- if (auto err = build(oe.buildArgs))
214+ if (auto err = build(oe.buildArgs, null ))
181215 return err;
182216
183217 return spawnProcess ([oe.exe, " list" ] ~ oe.args, [
@@ -197,7 +231,7 @@ struct Commands {
197231 // Build executable with test runner embedded (no -main since test_runner.d has its own)
198232 auto oe = getOutputExecutable(testRunnerBuildArgs(args[1 .. $]));
199233
200- if (auto err = build(oe.buildArgs))
234+ if (auto err = build(oe.buildArgs, null ))
201235 return err;
202236
203237 return spawnProcess ([oe.exe, " filter" , args[0 ]] ~ oe.args, [
@@ -216,7 +250,7 @@ struct Commands {
216250 // Build executable with test runner embedded (no -main since test_runner.d has its own)
217251 auto oe = getOutputExecutable(testRunnerBuildArgs(args[1 .. $]));
218252
219- if (auto err = build(oe.buildArgs))
253+ if (auto err = build(oe.buildArgs, null ))
220254 return err;
221255
222256 return spawnProcess ([oe.exe, " run" , args[0 ]] ~ oe.args, [
@@ -225,28 +259,30 @@ struct Commands {
225259 }
226260
227261 // / Builds the code and runs unittests but only for files explicitly listed, not auto-imported files
228- int testOnly (string [] args) {
229- return run ([" -g" , " -unittest=explicit" , " -main" , " -checkaction=context" ] ~ args);
262+ int testOnly (string [] args, string [] extraBuildArgs ) {
263+ return run ([" -g" , " -unittest=explicit" , " -main" , " -checkaction=context" ] ~ extraBuildArgs ~ args, null );
230264 }
231265
232266 // / Performs quick syntax and semantic tests, without performing code generation
233- int check (string [] args) {
234- return build (args ~ [" -o-" ]);
267+ int check (string [] args, string [] extraBuildArgs ) {
268+ return build (args ~ [" -o-" ], extraBuildArgs );
235269 }
236270
237271 // / Does a debug build with the given arguments
238- int build (string [] args) {
272+ int build (string [] args, string [] extraBuildArgs ) {
239273 // FIXME: support -gnone?
240274 // FIXME: pull info out of the cache to get the right libs and -i modifiers out
241- return sendToCompilerDriver ([" -g" , " -i" ] ~ args, " dmd" );
275+ return sendToCompilerDriver ([" -g" , " -i" ] ~ extraBuildArgs ~ args, " dmd" );
242276 }
243277
244278 // / Does a release build with the given arguments
245- int publish (string [] args) {
279+ int publish (string [] args, string [] extraBuildArgs ) {
246280 return sendToCompilerDriver ([" -i" , " -O2" ] ~ args, " ldmd2" );
247281 }
248282
249283 private int sendToCompilerDriver (string [] args, string preferredCompiler = null ) {
284+ if (.preferredCompiler ! is null )
285+ preferredCompiler = .preferredCompiler;
250286 version (OSX ) version(AArch64) if (preferredCompiler == " dmd" ) preferredCompiler = " ldmd2" ;
251287
252288 // extract --target
@@ -413,11 +449,11 @@ struct Commands {
413449 }
414450 switch (preferredCompiler) {
415451 case " dmd" :
416- return dmd (args);
452+ return dmd (args, null );
417453 case " ldmd2" :
418- return ldmd2 (args);
454+ return ldmd2 (args, null );
419455 case " ldc2" :
420- return ldc2 (args);
456+ return ldc2 (args, null );
421457 default :
422458 goto case " ldmd2" ;
423459 }
@@ -432,50 +468,50 @@ struct Commands {
432468
433469 // / Pre-compiles with the given arguments so future calls to `build` can use the cached library
434470 version (none )
435- int precompile (string [] args) {
471+ int precompile (string [] args, string [] extraBuildArgs ) {
436472 // any modules present in the precompile need to be written to the cache, knowing which output file they went into
437473 // FIXME
438474 return 1 ;
439475 }
440476
441477 // / Watches for changes to its source and attempts to automatically recompile and restart the application (if compatible)
442478 version (none )
443- int watch (string [] args) {
479+ int watch (string [] args, string [] extraBuildArgs ) {
444480 // FIXME
445481 return 1 ;
446482 }
447483
448484 // / Passes args to the compiler, then opens a debugger to run the generated file.
449485 version (none )
450- int dbg (string [] args) {
486+ int dbg (string [] args, string [] extraBuildArgs ) {
451487 // FIXME
452488 return 1 ;
453489 }
454490
455491 // / Allows for updating the OpenD compiler or libraries
456492 version (none )
457- int update (string [] args) {
493+ int update (string [] args, string [] extraBuildArgs ) {
458494 // FIXME
459495 return 1 ;
460496 }
461497
462498 // / Forwards arguments directly to the OpenD dmd driver
463- int dmd (string [] args) {
499+ int dmd (string [] args, string [] extraBuildArgs ) {
464500 return spawnProcess ([getCompilerPath(" dmd" )] ~ args, null ).wait.checkForCrash(" dmd" );
465501 }
466502
467503 // / Forwards arguments directly to the OpenD ldmd2 driver
468- int ldmd2 (string [] args) {
504+ int ldmd2 (string [] args, string [] extraBuildArgs ) {
469505 return spawnProcess ([getCompilerPath(" ldmd2" )] ~ args, null ).wait.checkForCrash(" ldmd2" );
470506 }
471507
472508 // / Forwards arguments directly to the OpenD ldc2 driver
473- int ldc2 (string [] args) {
509+ int ldc2 (string [] args, string [] extraBuildArgs ) {
474510 return spawnProcess ([getCompilerPath(" ldc2" )] ~ args, null ).wait.checkForCrash(" ldc2" );
475511 }
476512
477513 // / Installs optional components or updates to opend
478- int install (string [] args) {
514+ int install (string [] args, string [] extraBuildArgs ) {
479515
480516 // FIXME: remove any --opend-to-build= stuff before args[0]
481517
@@ -575,7 +611,7 @@ string getCompilerPath(string compiler) {
575611
576612string getBundledModulePath (string moduleName) {
577613 import std.file , std.path ;
578- import std.string ;
614+ import std.string ;
579615 return buildPath ([dirName(thisExePath()), " ../import/" ~ moduleName.replace(" ." , " /" ) ~ " .d" ]);
580616
581617}
@@ -608,6 +644,8 @@ OutputExecutable getOutputExecutable(string[] args) {
608644 version (Windows )
609645 extension = " .exe" ;
610646
647+ import std.path ;
648+
611649 foreach (idx, arg; args) {
612650 if (arg == " --" ) {
613651 buildArgsSplitter = idx;
@@ -616,7 +654,7 @@ OutputExecutable getOutputExecutable(string[] args) {
616654 }
617655 if (arg.length > 1 && arg[0 ] == ' -' ) {
618656 if (arg.length > 3 && arg[0 .. 3 ] == " -of" ) {
619- name = arg[3 .. $];
657+ name = baseName( arg[3 .. $]) ;
620658 extension = null ;
621659 nameExplicitlyGiven = true ;
622660 break ;
0 commit comments