diff --git a/man/man1/rdmd.1 b/man/man1/rdmd.1 index d8fe3c71ce..503a3aaff8 100644 --- a/man/man1/rdmd.1 +++ b/man/man1/rdmd.1 @@ -78,6 +78,10 @@ Print dependencies in makefile format to file and continue .IP --man Open web browser on manual page +.IP --objdir=\fIobj_dir_path\fR +Specify directory to store compiled object files +[default = \fItmp_dir_path\fR/objs] + .IP --tmpdir=\fItmp_dir_path\fR Specify directory to store cached program and other temporaries [default = as per \fIhttp://dlang.org/phobos/std_file.html#.tempDir\fR] diff --git a/rdmd.d b/rdmd.d index cc7b80e2a2..57d71c0b48 100755 --- a/rdmd.d +++ b/rdmd.d @@ -134,6 +134,7 @@ int main(string[] args) string[] eval; // set by --eval bool makeDepend; string makeDepFile; + string objDir; getopt(argsBeforeProgram, std.getopt.config.caseSensitive, std.getopt.config.passThrough, @@ -153,6 +154,7 @@ int main(string[] args) "makedepfile", &makeDepFile, "man", { man(); bailout = true; }, "tmpdir", &userTempDir, + "objdir", &objDir, "o", &dashOh); if (bailout) return 0; if (dryRun) chatty = true; // dry-run implies chatty @@ -233,20 +235,23 @@ int main(string[] args) // Compute the object directory and ensure it exists immutable workDir = getWorkPath(root, compilerFlags); lockWorkPath(workDir); // will be released by the OS on process exit - string objDir = buildPath(workDir, "objs"); - Filesystem.mkdirRecurseIfLive(objDir); - - if (lib) + if (!objDir) { - // When using -lib, the behavior of the DMD -of switch - // changes: instead of being relative to the current - // directory, it becomes relative to the output directory. - // When building libraries, DMD does not generate any object - // files; thus, we can override objDir (which is normally a - // temporary directory) to be the current directory, so that - // the relative -of path becomes correct. - objDir = "."; + objDir = buildPath(workDir, "objs"); + + if (lib) + { + // When using -lib, the behavior of the DMD -of switch + // changes: instead of being relative to the current + // directory, it becomes relative to the output directory. + // When building libraries, DMD does not generate any object + // files; thus, we can override objDir (which is normally a + // temporary directory) to be the current directory, so that + // the relative -of path becomes correct. + objDir = "."; + } } + Filesystem.mkdirRecurseIfLive(objDir); // Fetch dependencies const myDeps = getDependencies(root, workDir, objDir, compilerFlags); @@ -524,6 +529,8 @@ private int rebuild(string root, string fullExe, // run mode because we haven't created any! if (!dryRun) { + // Be sure to only clean up objDir if it is the default one, + // under our temporary work directory, and not when it's user-specified. if (Filesystem.exists(objDir) && objDir.startsWith(workDir)) { // We swallow the exception because of a potential race: two diff --git a/rdmd_test.d b/rdmd_test.d index 460842e41b..6d8917d609 100755 --- a/rdmd_test.d +++ b/rdmd_test.d @@ -552,6 +552,19 @@ void runTests(string rdmdApp, string compiler, string model) enforce(exists(altLibName)); } + // Test --objdir + { + TmpDir srcDir = "rdmdTestSrc"; + TmpDir objDir = "rdmdTestObj"; + + string srcName = srcDir.buildPath("test.d"); + std.file.write(srcName, `void main() {}`); + + res = execute(rdmdArgs ~ ["--build-only", "--force", "--objdir=" ~ objDir, srcName]); + enforce(res.status == 0, res.output); + enforce(exists(objDir.buildPath("test" ~ objExt))); + } + /* rdmd --build-only --force -c main.d fails: ./main: No such file or directory: https://issues.dlang.org/show_bug.cgi?id=16962 */ { TmpDir srcDir = "rdmdTest";