diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 7ad45e9..1d84c56 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -154,6 +154,9 @@ /// Adds the appropriate flag to set a target path void setTarget(ref BuildSettings settings, in BuildPlatform platform); + /// Invokes the compiler using the given flags + void invoke(in BuildSettings settings, in BuildPlatform platform); + /// Invokes the underlying linker directly void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects); @@ -265,8 +268,10 @@ string[] platform; /// e.g. ["x86", "x86_64"] string[] architecture; - /// e.g. "dmd" + /// Canonical compiler name e.g. "dmd" string compiler; + /// Compiler binary name e.g. "ldmd2" + string compilerBinary; /// Build platforms can be specified via a string specification. /// diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 210fd4f..5b25e8e 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -12,11 +12,14 @@ import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; +import dub.utils; import std.algorithm; import std.array; import std.conv; import std.exception; +import std.file; +import std.random; import std.typecons; @@ -54,6 +57,7 @@ build_platform.platform = .determinePlatform(); build_platform.architecture = .determineArchitecture(); build_platform.compiler = this.name; + build_platform.compilerBinary = compiler_binary; switch (arch_override) { default: throw new Exception("Unsupported architecture: "~arch_override); @@ -153,6 +157,18 @@ settings.addDFlags("-of"~tpath.toNativeString()); } + void invoke(in BuildSettings settings, in BuildPlatform platform) + { + auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + std.file.write(res_file.toNativeString(), join(settings.dflags.map!(s => s.canFind(' ') ? "\""~s~"\"" : s), "\n")); + scope (exit) remove(res_file.toNativeString()); + + logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); + auto compiler_pid = spawnProcess([platform.compilerBinary, "@"~res_file.toNativeString()]); + auto result = compiler_pid.wait(); + enforce(result == 0, "DMD compile run failed with exit code "~to!string(result)); + } + void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects) { import std.string; diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index a56ff83..45221ed 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -12,11 +12,14 @@ import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; +import dub.utils; import std.algorithm; import std.array; import std.conv; import std.exception; +import std.file; +import std.random; import std.typecons; @@ -54,6 +57,7 @@ build_platform.platform = .determinePlatform(); build_platform.architecture = .determineArchitecture(); build_platform.compiler = this.name; + build_platform.compilerBinary = compiler_binary; enforce(arch_override.length == 0, "Architecture override not implemented for GDC."); return build_platform; @@ -143,6 +147,18 @@ settings.addDFlags("-o", tpath.toNativeString()); } + void invoke(in BuildSettings settings, in BuildPlatform platform) + { + auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + std.file.write(res_file.toNativeString(), join(settings.dflags.map!(s => s.canFind(' ') ? "\""~s~"\"" : s), "\n")); + scope (exit) remove(res_file.toNativeString()); + + logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); + auto compiler_pid = spawnProcess([platform.compilerBinary, "@"~res_file.toNativeString()]); + auto result = compiler_pid.wait(); + enforce(result == 0, "GDC compile run failed with exit code "~to!string(result)); + } + void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects) { assert(false, "Separate linking not implemented for GDC"); diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 57def93..61d6749 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -12,11 +12,14 @@ import dub.internal.vibecompat.core.log; import dub.internal.vibecompat.inet.path; import dub.platform; +import dub.utils; import std.algorithm; import std.array; import std.conv; import std.exception; +import std.file; +import std.random; import std.typecons; @@ -54,6 +57,7 @@ build_platform.platform = .determinePlatform(); build_platform.architecture = .determineArchitecture(); build_platform.compiler = this.name; + build_platform.compilerBinary = compiler_binary; enforce(arch_override.length == 0, "Architecture override not implemented for LDC."); return build_platform; @@ -143,6 +147,18 @@ settings.addDFlags("-of"~tpath.toNativeString()); } + void invoke(in BuildSettings settings, in BuildPlatform platform) + { + auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + std.file.write(res_file.toNativeString(), join(cast(string[])settings.dflags, "\n")); + scope (exit) remove(res_file.toNativeString()); + + logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); + auto compiler_pid = spawnProcess([platform.compilerBinary, "@"~res_file.toNativeString()]); + auto result = compiler_pid.wait(); + enforce(result == 0, "LDC compile run failed with exit code "~to!string(result)); + } + void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects) { assert(false, "Separate linking not implemented for GDC"); diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 2c85c06..5a47dbb 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -57,12 +57,7 @@ } // find the temp directory - auto tmp = environment.get("TEMP"); - if( !tmp.length ) tmp = environment.get("TMP"); - if( !tmp.length ){ - version(Posix) tmp = "/tmp"; - else tmp = "."; - } + auto tmp = getTempDir(); if( settings.config.length ) logInfo("Building configuration \""~settings.config~"\", build type "~settings.buildType); else logInfo("Building default configuration, build type "~settings.buildType); @@ -78,7 +73,7 @@ if( settings.run ){ import std.random; auto rnd = to!string(uniform(uint.min, uint.max)); - buildsettings.targetPath = (Path(tmp)~"dub/"~rnd).toNativeString(); + buildsettings.targetPath = (tmp~"dub/"~rnd).toNativeString(); } exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); } @@ -111,18 +106,10 @@ if( generate_binary ) settings.compiler.setTarget(buildsettings, settings.platform); settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); - // write response file instead of passing flags directly to the compiler - auto res_file = Path(buildsettings.targetPath) ~ "dub-build.rsp"; - cleanup_files ~= res_file; - std.file.write(res_file.toNativeString(), join(buildsettings.dflags.map!(s => s.canFind(' ') ? "\""~s~"\"" : s), "\n")); - // invoke the compiler logInfo("Running %s...", settings.compilerBinary); - logDiagnostic("%s %s", settings.compilerBinary, join(buildsettings.dflags, " ")); if( settings.run ) cleanup_files ~= exe_file_path; - auto compiler_pid = spawnProcess([settings.compilerBinary, "@"~res_file.toNativeString()]); - auto result = compiler_pid.wait(); - enforce(result == 0, "Build command failed with exit code "~to!string(result)); + settings.compiler.invoke(buildsettings, settings.platform); } else { // determine path for the temporary object file version(Windows) enum tempobjname = "temp.obj"; @@ -141,16 +128,8 @@ buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !f.endsWith(".lib"))().array(); settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); - // write response file instead of passing flags directly to the compiler - auto res_file = Path(buildsettings.targetPath) ~ "dub-build.rsp"; - cleanup_files ~= res_file; - cleanup_files ~= tempobj; - std.file.write(res_file.toNativeString(), join(buildsettings.dflags.map!(s => s.canFind(' ') ? "\""~s~"\"" : s), "\n")); - logInfo("Running %s (compile)...", settings.compilerBinary); - logDiagnostic("%s %s", settings.compilerBinary, join(buildsettings.dflags, " ")); - auto result = spawnProcess([settings.compilerBinary, "@"~res_file.toNativeString()]).wait(); - enforce(result == 0, "Build command failed with exit code "~to!string(result)); + settings.compiler.invoke(buildsettings, settings.platform); logInfo("Linking...", settings.compilerBinary); if( settings.run ) cleanup_files ~= exe_file_path; diff --git a/source/dub/utils.d b/source/dub/utils.d index 4c9332d..11e983c 100644 --- a/source/dub/utils.d +++ b/source/dub/utils.d @@ -26,6 +26,17 @@ import std.zip; +Path getTempDir() +{ + auto tmp = environment.get("TEMP"); + if( !tmp.length ) tmp = environment.get("TMP"); + if( !tmp.length ){ + version(Posix) tmp = "/tmp/"; + else tmp = "./"; + } + return Path(tmp); +} + package bool isEmptyDir(Path p) { foreach(DirEntry e; dirEntries(p.toNativeString(), SpanMode.shallow)) return false;