1 // SemiTwist D Tools 2 // STManage: STBuild 3 // Written in the D programming language. 4 5 /++ 6 Author: 7 $(WEB www.semitwist.com, Nick Sabalausky) 8 9 This has been tested to work with DMD 2.058 through 2.062 10 +/ 11 12 //TODO: Clean all if stbuild.conf has changed 13 //TODO: Clean all if using a different build tool from last time 14 //TODO: User-defined options (ex: set preference for default: rebuild or xfbuild) 15 //TODO: Handle DMD patched for -ww 16 // Use STBUILD_OPTS env var: STBUILD_OPTS=dmdpatch_ww;whatever... 17 //TODO: Disallow crazy characters in target names 18 //TODO? Use Goldie to parse .conf file 19 //TODO: Get obj dir from conf switches instead of hardcoding to "obj/target/mode" 20 //TODO: Translate extraArgs between rebuild/xfbuild/rdmd 21 //TODO: When using xfbuild, make sure root filenames end in ".d" (ie "src/main.d" instead of "src/main") 22 //TODO: Fix: 'stbuild.conf' errors get displayed before header message. 23 24 module semitwist.apps.stmanage.stbuild.main; 25 26 import semitwist.cmd.all; 27 28 import semitwist.apps.stmanage.stbuild.cmdArgs; 29 import semitwist.apps.stmanage.stbuild.conf; 30 31 Options cmdArgs; 32 Conf conf; 33 34 void moveMapFiles(string subDir=".") 35 { 36 foreach(string name; dirEntries(".", SpanMode.shallow)) 37 { 38 if(name.globMatch("*.map")) 39 { 40 auto newName = "obj/"~subDir~"/"~name.baseName(); 41 if(exists(newName)) 42 remove(newName); 43 44 rename(name, newName); 45 } 46 } 47 } 48 49 int process(string target, string mode, bool verbose) 50 { 51 auto processor = ( cmdArgs.cleanOnly? &clean : &build ); 52 53 string[] targetsToProcess = (target == conf.targetAll)? conf.targetAllElems : [target]; 54 string[] modesToProcess = (mode == conf.modeAll)? conf.modeAllElems : [mode ]; 55 56 int errLevel = 0; 57 foreach(string currTarget; targetsToProcess) 58 foreach(string currMode; modesToProcess ) 59 { 60 auto result = processor(currTarget, currMode, verbose); 61 if(result > errLevel) 62 errLevel = result; 63 } 64 65 return errLevel; 66 } 67 68 int build(string target, string mode, bool verbose) 69 { 70 mixin(deferAssert!(`target != conf.targetAll`, "target 'all' passed to build()")); 71 mixin(deferAssert!(`mode != conf.modeAll`, "mode 'all' passed to build()")); 72 73 if(verbose) 74 cmd.echo("Building %s %s...".format(target, mode)); 75 76 auto objDir = "obj/"~target~"/"~mode; 77 if(!exists(objDir)) 78 mkdirRecurse(objDir); 79 80 int ret; 81 auto cmdLine = 82 buildToolExecName(cmdArgs.buildTool)~" "~ 83 cmdArgs.extraArgs~" "~ 84 conf.getFlags(target, mode, cmdArgs.buildTool); 85 86 if(cmdArgs.showCmd) cmd.echo(cmdLine); 87 ret = system(cmdLine); 88 moveMapFiles(target~"/"~mode); 89 90 return ret; 91 } 92 93 int clean(string target, string mode, bool verbose) 94 { 95 mixin(deferAssert!(`target != conf.targetAll`, "target 'all' passed to clean()")); 96 mixin(deferAssert!(`mode != conf.modeAll`, "mode 'all' passed to clean()")); 97 98 if(verbose) 99 cmd.echo("Cleaning %s %s...".format(target, mode)); 100 101 auto objDir = "obj/"~target~"/"~mode; 102 if(exists(objDir)) 103 foreach(string name; dirEntries(objDir, SpanMode.depth)) 104 { 105 if(name.globMatch("*.map") || name.baseName().globMatch("deps") || name.globMatch("*"~objExt)) 106 remove(name); 107 } 108 109 return 0; 110 } 111 112 int main(string[] args) 113 { 114 int errLevel = cmdArgs.process(args); 115 if(errLevel != -1) 116 return errLevel; 117 118 conf = cmdArgs.conf; 119 120 return process(cmdArgs.target, cmdArgs.mode, !cmdArgs.quiet); 121 }