From 10ca1582c4f037a63a1a91befc458458c1e668b2 Mon Sep 17 00:00:00 2001 From: anonymous Date: Sun, 28 Aug 2016 00:40:34 +0200 Subject: [PATCH 1/5] compile the root module in the same step as getting the dependencies This avoids calling dmd twice when running a single file, which is a common task. --- rdmd.d | 97 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/rdmd.d b/rdmd.d index 27e8e55f37..1443e64fee 100644 --- a/rdmd.d +++ b/rdmd.d @@ -114,6 +114,14 @@ int main(string[] args) assert(programPos > 0); auto argsBeforeProgram = args[0 .. programPos]; + /* Catch -main and handle it like --main. This needs to be done, because + rdmd compiles the root file independently from the dependencies, but -main + must be present in only one of the calls to dmd. */ + foreach (ref arg; argsBeforeProgram) + { + if (arg == "-main") arg = "--main"; + } + bool bailout; // bailout set by functions called in getopt if // program should exit string[] loop; // set by --loop @@ -234,7 +242,7 @@ int main(string[] args) } // Fetch dependencies - const myDeps = getDependencies(root, workDir, objDir, compilerFlags); + const myDeps = compileRootAndGetDeps(root, workDir, objDir, compilerFlags); // --makedepend mode. Just print dependencies and exit. if (makeDepend) @@ -437,9 +445,9 @@ private void unlockWorkPath() } } -// Rebuild the executable fullExe starting from modules in myDeps +// Rebuild the executable fullExe from root and myDeps, // passing the compiler flags compilerFlags. Generates one large -// object file. +// object file for the dependencies. private int rebuild(string root, string fullExe, string workDir, string objDir, in string[string] myDeps, @@ -470,46 +478,58 @@ private int rebuild(string root, string fullExe, } } - auto fullExeTemp = fullExe ~ ".tmp"; + immutable fullExeTemp = fullExe ~ ".tmp"; + immutable rootObj = buildPath(objDir, "rdmd.root"~objExt); + immutable depsObj = buildPath(objDir, "rdmd.deps"~objExt); - string[] buildTodo() + assert(dryRun || std.file.exists(rootObj), + "should have been created by compileRootAndGetDeps"); + + int result = 0; + string[] objs = [ rootObj ]; + + // compile dependencies + if (myDeps.byValue.any) // if there is any source dependency at all { - auto todo = compilerFlags - ~ [ "-of"~fullExeTemp ] - ~ [ "-od"~objDir ] - ~ [ "-I"~dirName(root) ] - ~ [ root ]; + auto todo = compilerFlags ~ [ + "-c", + "-of"~depsObj, + "-I"~dirName(root), + ]; foreach (k, objectFile; myDeps) { if(objectFile !is null) todo ~= [ k ]; } - // Need to add void main(){}? - if (addStubMain) + + // Different shells and OS functions have different limits, + // but 1024 seems to be the smallest maximum outside of MS-DOS. + enum maxLength = 1024; + auto commandLength = escapeShellCommand(todo).length; + if (commandLength + compiler.length >= maxLength) { - auto stubMain = buildPath(myOwnTmpDir, "stubmain.d"); - std.file.write(stubMain, "void main(){}"); - todo ~= [ stubMain ]; + auto rspName = buildPath(workDir, "rdmd.rsp"); + + // DMD uses Windows-style command-line parsing in response files + // regardless of the operating system it's running on. + std.file.write(rspName, + array(map!escapeWindowsArgument(todo)).join(" ")); + + todo = [ "@"~rspName ]; } - return todo; + + result = run([ compiler ] ~ todo); + objs ~= depsObj; } - auto todo = buildTodo(); - // Different shells and OS functions have different limits, - // but 1024 seems to be the smallest maximum outside of MS-DOS. - enum maxLength = 1024; - auto commandLength = escapeShellCommand(todo).length; - if (commandLength + compiler.length >= maxLength) + // link + if (!result) { - auto rspName = buildPath(workDir, "rdmd.rsp"); - - // DMD uses Windows-style command-line parsing in response files - // regardless of the operating system it's running on. - std.file.write(rspName, array(map!escapeWindowsArgument(todo)).join(" ")); - - todo = [ "@"~rspName ]; + string[] cmd = [ compiler ] ~ compilerFlags ~ + [ "-of"~fullExeTemp, "-od"~objDir ] ~ objs; + if (addStubMain) cmd ~= "-main"; + result = run(cmd); } - immutable result = run([ compiler ] ~ todo); if (result) { // build failed @@ -571,12 +591,12 @@ private int exec(string[] args) return run(args, null, true); } -// Given module rootModule, returns a mapping of all dependees .d -// source filenames to their corresponding .o files sitting in +// Given module rootModule, compiles it to rdmd.root.o and returns a mapping of +// all dependees .d source filenames to their corresponding .o files sitting in // directory workDir. The mapping is obtained by running dmd -v against // rootModule. -private string[string] getDependencies(string rootModule, string workDir, +private string[string] compileRootAndGetDeps(string rootModule, string workDir, string objDir, string[] compilerFlags) { immutable depsFilename = buildPath(workDir, "rdmd.deps"); @@ -694,10 +714,13 @@ private string[string] getDependencies(string rootModule, string workDir, immutable rootDir = dirName(rootModule); // Collect dependencies - auto depsGetter = - // "cd "~shellQuote(rootDir)~" && " - [ compiler ] ~ compilerFlags ~ - ["-v", "-o-", rootModule, "-I"~rootDir]; + auto depsGetter = [ compiler ] ~ compilerFlags ~ [ + "-v", + "-c", + "-of"~buildPath(objDir, "rdmd.root"~objExt), + rootModule, + "-I"~rootDir + ]; scope(failure) { From 4ab9444d8baca328abe03727569d803d67e1a6fd Mon Sep 17 00:00:00 2001 From: anonymous Date: Sun, 28 Aug 2016 12:16:49 +0200 Subject: [PATCH 2/5] explicit `!is null` --- rdmd.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rdmd.d b/rdmd.d index 1443e64fee..8107ef6392 100644 --- a/rdmd.d +++ b/rdmd.d @@ -489,7 +489,8 @@ private int rebuild(string root, string fullExe, string[] objs = [ rootObj ]; // compile dependencies - if (myDeps.byValue.any) // if there is any source dependency at all + if (myDeps.byValue.any!(o => o !is null)) + // if there is any source dependency at all { auto todo = compilerFlags ~ [ "-c", From 821d038171b7da0c17d65b67e9284de1d8dc30d6 Mon Sep 17 00:00:00 2001 From: anonymous Date: Sun, 28 Aug 2016 12:57:08 +0200 Subject: [PATCH 3/5] name object files after root module Moving --main functionality from linking to compilation of root module so that dmd doesn't mess with the object files. --- rdmd.d | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/rdmd.d b/rdmd.d index 8107ef6392..7923761697 100644 --- a/rdmd.d +++ b/rdmd.d @@ -242,7 +242,8 @@ int main(string[] args) } // Fetch dependencies - const myDeps = compileRootAndGetDeps(root, workDir, objDir, compilerFlags); + const myDeps = compileRootAndGetDeps(root, workDir, objDir, compilerFlags, + addStubMain); // --makedepend mode. Just print dependencies and exit. if (makeDepend) @@ -300,7 +301,7 @@ int main(string[] args) if (chain(root.only, myDeps.byKey).array.anyNewerThan(lastBuildTime)) { immutable result = rebuild(root, exe, workDir, objDir, - myDeps, compilerFlags, addStubMain); + myDeps, compilerFlags); if (result) return result; @@ -451,7 +452,7 @@ private void unlockWorkPath() private int rebuild(string root, string fullExe, string workDir, string objDir, in string[string] myDeps, - string[] compilerFlags, bool addStubMain) + string[] compilerFlags) { version (Windows) fullExe = fullExe.defaultExtension(".exe"); @@ -479,8 +480,8 @@ private int rebuild(string root, string fullExe, } immutable fullExeTemp = fullExe ~ ".tmp"; - immutable rootObj = buildPath(objDir, "rdmd.root"~objExt); - immutable depsObj = buildPath(objDir, "rdmd.deps"~objExt); + immutable rootObj = buildPath(objDir, root.baseName(".d")~objExt); + immutable depsObj = buildPath(objDir, root.baseName(".d")~".deps"~objExt); assert(dryRun || std.file.exists(rootObj), "should have been created by compileRootAndGetDeps"); @@ -527,7 +528,6 @@ private int rebuild(string root, string fullExe, { string[] cmd = [ compiler ] ~ compilerFlags ~ [ "-of"~fullExeTemp, "-od"~objDir ] ~ objs; - if (addStubMain) cmd ~= "-main"; result = run(cmd); } @@ -598,7 +598,7 @@ private int exec(string[] args) // rootModule. private string[string] compileRootAndGetDeps(string rootModule, string workDir, - string objDir, string[] compilerFlags) + string objDir, string[] compilerFlags, bool addStubMain) { immutable depsFilename = buildPath(workDir, "rdmd.deps"); @@ -718,11 +718,21 @@ private string[string] compileRootAndGetDeps(string rootModule, string workDir, auto depsGetter = [ compiler ] ~ compilerFlags ~ [ "-v", "-c", - "-of"~buildPath(objDir, "rdmd.root"~objExt), + "-of"~buildPath(objDir, rootModule.baseName(".d")~objExt), rootModule, "-I"~rootDir ]; + // Need to add void main(){}? + if (addStubMain) + { + /* TODO: Can be simplified to `depsGetter ~= "-main";` when issue 16440 + is fixed. */ + auto stubMain = buildPath(myOwnTmpDir, "stubmain.d"); + std.file.write(stubMain, "void main(){}"); + depsGetter ~= [ stubMain ]; + } + scope(failure) { // Delete the deps file on failure, we don't want to be fooled From 0e44ee7569a4518d5560b84ef394d93a22016c38 Mon Sep 17 00:00:00 2001 From: anonymous Date: Mon, 29 Aug 2016 00:52:49 +0200 Subject: [PATCH 4/5] spaces around ~ please --- rdmd.d | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/rdmd.d b/rdmd.d index 7923761697..cdb885ecc7 100644 --- a/rdmd.d +++ b/rdmd.d @@ -480,8 +480,9 @@ private int rebuild(string root, string fullExe, } immutable fullExeTemp = fullExe ~ ".tmp"; - immutable rootObj = buildPath(objDir, root.baseName(".d")~objExt); - immutable depsObj = buildPath(objDir, root.baseName(".d")~".deps"~objExt); + immutable rootObj = buildPath(objDir, root.baseName(".d") ~ objExt); + immutable depsObj = buildPath(objDir, + root.baseName(".d") ~ ".deps" ~ objExt); assert(dryRun || std.file.exists(rootObj), "should have been created by compileRootAndGetDeps"); @@ -495,8 +496,8 @@ private int rebuild(string root, string fullExe, { auto todo = compilerFlags ~ [ "-c", - "-of"~depsObj, - "-I"~dirName(root), + "-of" ~ depsObj, + "-I" ~ dirName(root), ]; foreach (k, objectFile; myDeps) { if(objectFile !is null) @@ -516,7 +517,7 @@ private int rebuild(string root, string fullExe, std.file.write(rspName, array(map!escapeWindowsArgument(todo)).join(" ")); - todo = [ "@"~rspName ]; + todo = [ "@" ~ rspName ]; } result = run([ compiler ] ~ todo); @@ -527,7 +528,7 @@ private int rebuild(string root, string fullExe, if (!result) { string[] cmd = [ compiler ] ~ compilerFlags ~ - [ "-of"~fullExeTemp, "-od"~objDir ] ~ objs; + [ "-of" ~ fullExeTemp, "-od" ~ objDir ] ~ objs; result = run(cmd); } @@ -718,9 +719,9 @@ private string[string] compileRootAndGetDeps(string rootModule, string workDir, auto depsGetter = [ compiler ] ~ compilerFlags ~ [ "-v", "-c", - "-of"~buildPath(objDir, rootModule.baseName(".d")~objExt), + "-of" ~ buildPath(objDir, rootModule.baseName(".d")~objExt), rootModule, - "-I"~rootDir + "-I" ~ rootDir ]; // Need to add void main(){}? From 4da871db19f0311082cfa5fe25284d91142169a9 Mon Sep 17 00:00:00 2001 From: anonymous Date: Mon, 29 Aug 2016 00:59:52 +0200 Subject: [PATCH 5/5] missed one --- rdmd.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdmd.d b/rdmd.d index cdb885ecc7..df048944ad 100644 --- a/rdmd.d +++ b/rdmd.d @@ -719,7 +719,7 @@ private string[string] compileRootAndGetDeps(string rootModule, string workDir, auto depsGetter = [ compiler ] ~ compilerFlags ~ [ "-v", "-c", - "-of" ~ buildPath(objDir, rootModule.baseName(".d")~objExt), + "-of" ~ buildPath(objDir, rootModule.baseName(".d") ~ objExt), rootModule, "-I" ~ rootDir ];