From c12b3ba4eedfd9c1ed1712bd163126fcbcab8a50 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 15:51:08 +0200 Subject: [PATCH 1/8] Support a few more ldc2 command-line options --- source/dub/compilers/ldc.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 11c287227..48e5b3617 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -27,15 +27,15 @@ class LDCCompiler : Compiler { private static immutable s_options = [ tuple(BuildOption.debugMode, ["-d-debug"]), tuple(BuildOption.releaseMode, ["-release"]), - //tuple(BuildOption.coverage, ["-?"]), + tuple(BuildOption.coverage, ["-cov"]), tuple(BuildOption.debugInfo, ["-g"]), tuple(BuildOption.debugInfoC, ["-gc"]), - //tuple(BuildOption.alwaysStackFrame, ["-?"]), + tuple(BuildOption.alwaysStackFrame, ["-disable-fp-elim"]), //tuple(BuildOption.stackStomping, ["-?"]), tuple(BuildOption.inline, ["-enable-inlining", "-Hkeep-all-bodies"]), tuple(BuildOption.noBoundsCheck, ["-boundscheck=off"]), tuple(BuildOption.optimize, ["-O3"]), - //tuple(BuildOption.profile, ["-?"]), + tuple(BuildOption.profile, ["-fdmd-trace-functions"]), tuple(BuildOption.unittests, ["-unittest"]), tuple(BuildOption.verbose, ["-v"]), tuple(BuildOption.ignoreUnknownPragmas, ["-ignore"]), From 4cc1733f0fd90738bf648c6792660449e5bf3178 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 15:52:23 +0200 Subject: [PATCH 2/8] Restrict extra ldc2 invocation for static libs to Windows hosts Don't perform the does-default-target-triple-contain-msvc check on non-Windows hosts (which would need a hacked LLVM to return true on other hosts). --- source/dub/compilers/ldc.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 48e5b3617..747a148f5 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -179,7 +179,8 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) else return settings.targetName; case TargetType.library: case TargetType.staticLibrary: - if (generatesCOFF(platform)) return settings.targetName ~ ".lib"; + if (platform.platform.canFind("windows") && generatesCOFF(platform)) + return settings.targetName ~ ".lib"; else return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: if (platform.platform.canFind("windows")) From c5dac5b4e1604efaa8789068c1d6bc8473bf97dd Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 16:21:16 +0200 Subject: [PATCH 3/8] Support separate linking with ldc2 This is basically #1548 with an augmented set of compiler flags being included in the linking command lines. --- source/dub/compilers/ldc.d | 35 ++++++++++++++++++++++++++++++++++- source/dub/generators/build.d | 8 ++------ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 747a148f5..10951b1c9 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -232,7 +232,20 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { - assert(false, "Separate linking not implemented for LDC"); + import std.string; + auto tpath = NativePath(settings.targetPath) ~ getTargetFileName(settings, platform); + auto args = ["-of"~tpath.toNativeString()]; + args ~= objects; + args ~= settings.sourceFiles; + version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order + args ~= lflagsToDFlags(settings.lflags); + args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; + + auto res_file = getTempFile("dub-build", ".lnk"); + std.file.write(res_file.toNativeString(), escapeArgs(args).join("\n")); + + logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" ")); + invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); } string[] lflagsToDFlags(in string[] lflags) const @@ -245,6 +258,26 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) return args.map!(s => s.canFind(' ') ? "\""~s~"\"" : s); } + private static bool isLinkerDFlag(string arg) + { + switch (arg) { + case "-g", "-gc", "-m32", "-m64", "-shared", "-lib", + "-betterC", "-disable-linker-strip-dead", "-static": + return true; + default: + return arg.startsWith("-L") + || arg.startsWith("-Xcc=") + || arg.startsWith("-defaultlib=") + || arg.startsWith("-flto") + || arg.startsWith("-fsanitize=") + || arg.startsWith("-link-") + || arg.startsWith("-linker=") + || arg.startsWith("-march=") + || arg.startsWith("-mscrtlib=") + || arg.startsWith("-mtriple="); + } + } + private static bool generatesCOFF(in BuildPlatform platform) { import std.string : splitLines, strip; diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 4414bb82a..5e5981a67 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -476,12 +476,8 @@ class BuildGenerator : ProjectGenerator { settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback); - /* - NOTE: for DMD experimental separate compile/link is used, but this is not yet implemented - on the other compilers. Later this should be integrated somehow in the build process - (either in the dub.json, or using a command line flag) - */ - } else if (generate_binary && (settings.buildMode == BuildMode.allAtOnce || settings.compiler.name != "dmd" || is_static_library)) { + // NOTE: separate compile/link is not yet enabled for GDC. + } else if (generate_binary && (settings.buildMode == BuildMode.allAtOnce || settings.compiler.name == "gdc" || is_static_library)) { // don't include symbols of dependencies (will be included by the top level target) if (is_static_library) buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !f.isLinkerFile()).array; From 485f0d1093592f71bd7198708e671cd20931f21d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 20:48:46 +0200 Subject: [PATCH 4/8] Enable specifying full target triples as --arch for ldc2 By treating all 'architectures' containing a `-` as `-mtriple` values. E.g., `dub --arch=wasm32-unknown-unknown-wasm` to cross-compile to WebAssembly. This dub switch is already used when probing the compiler, so the build platform detection works as expected. Also add `wasm` as detected platform and use the .wasm executable file extension (for ldc2). This fixes #1749 when moving the `-mtriple` option from the dub config file to the dub command line. --- source/dub/compilers/ldc.d | 9 ++++++++- source/dub/platform.d | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 10951b1c9..2eec2a3fc 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -80,10 +80,15 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) { string[] arch_flags; switch (arch_override) { - default: throw new Exception("Unsupported architecture: "~arch_override); case "": break; case "x86": arch_flags = ["-march=x86"]; break; case "x86_64": arch_flags = ["-march=x86-64"]; break; + default: + if (arch_override.canFind('-')) + arch_flags = ["-mtriple="~arch_override]; + else + throw new Exception("Unsupported architecture: "~arch_override); + break; } settings.addDFlags(arch_flags); @@ -176,6 +181,8 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) case TargetType.executable: if (platform.platform.canFind("windows")) return settings.targetName ~ ".exe"; + else if (platform.platform.canFind("wasm")) + return settings.targetName ~ ".wasm"; else return settings.targetName; case TargetType.library: case TargetType.staticLibrary: diff --git a/source/dub/platform.d b/source/dub/platform.d index 88da7b28d..0c27199d1 100644 --- a/source/dub/platform.d +++ b/source/dub/platform.d @@ -42,6 +42,7 @@ enum string platformCheck = q{ version(Android) ret ~= "android"; version(Cygwin) ret ~= "cygwin"; version(MinGW) ret ~= "mingw"; + version(WebAssembly) ret ~= "wasm"; return ret; }; From b4e14d543394ee57b55c8fcf427a1108228783b3 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 22:46:29 +0200 Subject: [PATCH 5/8] ldc2: Fix MSVC target detection for static libs With --arch, the build (target) platform might now diverge from the host platform. The compiler's default triple doesn't matter when cross-compiling, so use the .lib MSVC format when targeting Windows but not MinGW. This fixes one aspect of #1599. --- source/dub/compilers/ldc.d | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 2eec2a3fc..289d61166 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -174,29 +174,30 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) const { assert(settings.targetName.length > 0, "No target name set."); + const p = platform.platform; final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Configurations must have a concrete target type."); case TargetType.none: return null; case TargetType.sourceLibrary: return null; case TargetType.executable: - if (platform.platform.canFind("windows")) + if (p.canFind("windows")) return settings.targetName ~ ".exe"; - else if (platform.platform.canFind("wasm")) + else if (p.canFind("wasm")) return settings.targetName ~ ".wasm"; else return settings.targetName; case TargetType.library: case TargetType.staticLibrary: - if (platform.platform.canFind("windows") && generatesCOFF(platform)) + if (p.canFind("windows") && !p.canFind("mingw")) return settings.targetName ~ ".lib"; else return "lib" ~ settings.targetName ~ ".a"; case TargetType.dynamicLibrary: - if (platform.platform.canFind("windows")) + if (p.canFind("windows")) return settings.targetName ~ ".dll"; - else if (platform.platform.canFind("osx")) + else if (p.canFind("osx")) return "lib" ~ settings.targetName ~ ".dylib"; else return "lib" ~ settings.targetName ~ ".so"; case TargetType.object: - if (platform.platform.canFind("windows")) + if (p.canFind("windows")) return settings.targetName ~ ".obj"; else return settings.targetName ~ ".o"; } @@ -284,29 +285,4 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) || arg.startsWith("-mtriple="); } } - - private static bool generatesCOFF(in BuildPlatform platform) - { - import std.string : splitLines, strip; - import std.uni : toLower; - - static bool[string] compiler_coff_map; - - if (auto pret = platform.compilerBinary in compiler_coff_map) - return *pret; - - auto result = executeShell(escapeShellCommand([platform.compilerBinary, "-version"])); - enforce (result.status == 0, "Failed to determine linker used by LDC. \"" - ~platform.compilerBinary~" -version\" failed with exit code " - ~result.status.to!string()~"."); - - bool ret = result.output - .splitLines - .find!(l => l.strip.toLower.startsWith("default target:")) - .front - .canFind("msvc"); - - compiler_coff_map[platform.compilerBinary] = ret; - return ret; - } } From d55e9b7ce78e1dbd354769cc0fe7fc925718fd66 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 18 Aug 2019 14:59:23 +0200 Subject: [PATCH 6/8] ldc2: Only use `-L--no-as-needed` for Linux *targets* --- source/dub/compilers/ldc.d | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 289d61166..84e0a8e41 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -245,7 +245,8 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) auto args = ["-of"~tpath.toNativeString()]; args ~= objects; args ~= settings.sourceFiles; - version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order + if (platform.platform.canFind("linux")) + args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order args ~= lflagsToDFlags(settings.lflags); args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; From 944c93af898c8fc557f8231d7fed33bd8b50c65d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 20 Aug 2019 00:52:12 +0200 Subject: [PATCH 7/8] Improve cross-compilation support (replace `version` checks by BuildPlatform runtime checks) Also fixes #1249. For LDC as implicit cross compiler, the file extensions for libraries and object files etc. don't depend on the compiler, but solely on the target. Targets selected with `--arch` are correctly probed by dub, so that the parsed `BuildPlatform` represents the target platform. --- source/dub/compilers/compiler.d | 2 +- source/dub/compilers/dmd.d | 26 +++++++++-------- source/dub/compilers/gdc.d | 7 +++-- source/dub/compilers/ldc.d | 4 +-- source/dub/compilers/utils.d | 48 +++++++++++++++---------------- source/dub/dub.d | 3 -- source/dub/generators/build.d | 36 ++++++++++++----------- source/dub/generators/generator.d | 6 ++-- source/dub/generators/visuald.d | 2 +- source/dub/project.d | 8 +++--- 10 files changed, 73 insertions(+), 69 deletions(-) diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 42e6cf9e9..f81d0cf25 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -72,7 +72,7 @@ interface Compiler { /// Replaces high level fields with low level fields and converts /// dmd flags to compiler-specific flags - void prepareBuildSettings(ref BuildSettings settings, BuildSetting supported_fields = BuildSetting.all) const; + void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting supported_fields = BuildSetting.all) const; /// Removes any dflags that match one of the BuildOptions values and populates the BuildSettings.options field. void extractBuildOptions(ref BuildSettings settings) const; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index bf06e4cfa..3d695fb9d 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -132,7 +132,7 @@ config /etc/dmd.conf ); } - void prepareBuildSettings(ref BuildSettings settings, BuildSetting fields = BuildSetting.all) const + void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); @@ -163,9 +163,11 @@ config /etc/dmd.conf } if (!(fields & BuildSetting.libs)) { - resolveLibs(settings); - version(Windows) settings.addSourceFiles(settings.libs.map!(l => l~".lib")().array()); - else settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); + resolveLibs(settings, platform); + if (platform.platform.canFind("windows")) + settings.addSourceFiles(settings.libs.map!(l => l~".lib")().array()); + else + settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } if (!(fields & BuildSetting.sourceFiles)) { @@ -178,10 +180,8 @@ config /etc/dmd.conf settings.lflags = null; } - version (Posix) { - if (settings.options & BuildOption.pic) - settings.addDFlags("-fPIC"); - } + if (platform.platform.canFind("posix") && (settings.options & BuildOption.pic)) + settings.addDFlags("-fPIC"); assert(fields & BuildSetting.dflags); assert(fields & BuildSetting.copyFiles); @@ -248,9 +248,10 @@ config /etc/dmd.conf settings.addDFlags("-lib"); break; case TargetType.dynamicLibrary: - version (Windows) settings.addDFlags("-shared"); - else version (OSX) settings.addDFlags("-shared"); - else settings.prependDFlags("-shared", "-defaultlib=libphobos2.so"); + if (platform.platform.canFind("windows") || platform.platform.canFind("osx")) + settings.addDFlags("-shared"); + else + settings.prependDFlags("-shared", "-defaultlib=libphobos2.so"); break; case TargetType.object: settings.addDFlags("-c"); @@ -280,7 +281,8 @@ config /etc/dmd.conf auto args = ["-of"~tpath.toNativeString()]; args ~= objects; args ~= settings.sourceFiles; - version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order by DMD + if (platform.platform.canFind("linux")) + args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order by DMD args ~= lflagsToDFlags(settings.lflags); args ~= settings.dflags.filter!(f => isLinkerDFlag(f)).array; diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index 4a9c0d211..eb753d845 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -85,7 +85,7 @@ class GDCCompiler : Compiler { ); } - void prepareBuildSettings(ref BuildSettings settings, BuildSetting fields = BuildSetting.all) const + void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); @@ -121,7 +121,7 @@ class GDCCompiler : Compiler { } if (!(fields & BuildSetting.libs)) { - resolveLibs(settings); + resolveLibs(settings, platform); settings.addDFlags(settings.libs.map!(l => "-l"~l)().array()); } @@ -222,7 +222,8 @@ class GDCCompiler : Compiler { args = [ "ar", "rcs", tpath ] ~ objects; } else { args = platform.compilerBinary ~ objects ~ settings.sourceFiles ~ settings.lflags ~ settings.dflags.filter!(f => isLinkageFlag(f)).array; - version(linux) args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order by DMD + if (platform.platform.canFind("linux")) + args ~= "-L--no-as-needed"; // avoids linker errors due to libraries being specified in the wrong order } logDiagnostic("%s", args.join(" ")); invokeTool(args, output_callback); diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 84e0a8e41..7e77d0e14 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -99,7 +99,7 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) ); } - void prepareBuildSettings(ref BuildSettings settings, BuildSetting fields = BuildSetting.all) const + void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); @@ -138,7 +138,7 @@ config /etc/ldc2.conf (x86_64-pc-linux-gnu) } if (!(fields & BuildSetting.libs)) { - resolveLibs(settings); + resolveLibs(settings, platform); settings.addLFlags(settings.libs.map!(l => "-l"~l)().array()); } diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 03b3c33ab..da847bcf3 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -40,37 +40,36 @@ void enforceBuildRequirements(ref BuildSettings settings) Linker files include static/dynamic libraries, resource files, object files and DLL definition files. */ -bool isLinkerFile(string f) +bool isLinkerFile(in ref BuildPlatform platform, string f) { import std.path; switch (extension(f)) { default: return false; - version (Windows) { - case ".lib", ".obj", ".res", ".def": - return true; - } else { - case ".a", ".o", ".so", ".dylib": - return true; - } + case ".lib", ".obj", ".res", ".def": + return platform.platform.canFind("windows"); + case ".a", ".o", ".so", ".dylib": + return !platform.platform.canFind("windows"); } } unittest { - version (Windows) { - assert(isLinkerFile("test.obj")); - assert(isLinkerFile("test.lib")); - assert(isLinkerFile("test.res")); - assert(!isLinkerFile("test.o")); - assert(!isLinkerFile("test.d")); - } else { - assert(isLinkerFile("test.o")); - assert(isLinkerFile("test.a")); - assert(isLinkerFile("test.so")); - assert(isLinkerFile("test.dylib")); - assert(!isLinkerFile("test.obj")); - assert(!isLinkerFile("test.d")); - } + BuildPlatform p; + + p.platform = ["windows"]; + assert(isLinkerFile(p, "test.obj")); + assert(isLinkerFile(p, "test.lib")); + assert(isLinkerFile(p, "test.res")); + assert(!isLinkerFile(p, "test.o")); + assert(!isLinkerFile(p, "test.d")); + + p.platform = ["something else"]; + assert(isLinkerFile(p, "test.o")); + assert(isLinkerFile(p, "test.a")); + assert(isLinkerFile(p, "test.so")); + assert(isLinkerFile(p, "test.dylib")); + assert(!isLinkerFile(p, "test.obj")); + assert(!isLinkerFile(p, "test.d")); } @@ -80,7 +79,7 @@ unittest { This function tries to invoke "pkg-config" if possible and falls back to direct flag translation if that fails. */ -void resolveLibs(ref BuildSettings settings) +void resolveLibs(ref BuildSettings settings, in ref BuildPlatform platform) { import std.string : format; import std.array : array; @@ -90,7 +89,8 @@ void resolveLibs(ref BuildSettings settings) if (settings.targetType == TargetType.library || settings.targetType == TargetType.staticLibrary) { logDiagnostic("Ignoring all import libraries for static library build."); settings.libs = null; - version(Windows) settings.sourceFiles = settings.sourceFiles.filter!(f => !f.endsWith(".lib")).array; + if (platform.platform.canFind("windows")) + settings.sourceFiles = settings.sourceFiles.filter!(f => !f.endsWith(".lib")).array; } version (Posix) { diff --git a/source/dub/dub.d b/source/dub/dub.d index c8d4845ee..4e85269ff 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -32,9 +32,6 @@ import std.range : assumeSorted, empty; import std.string; import std.encoding : sanitize; -// Workaround for libcurl liker errors when building with LDC -version (LDC) pragma(lib, "curl"); - // Set output path and options for coverage reports version (DigitalMars) version (D_Coverage) static if (__VERSION__ >= 2068) { diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 5e5981a67..47fcfee92 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -27,8 +27,10 @@ import std.process; import std.string; import std.encoding : sanitize; -version(Windows) enum objSuffix = ".obj"; -else enum objSuffix = ".o"; +string getObjSuffix(in ref BuildPlatform platform) +{ + return platform.platform.canFind("windows") ? ".obj" : ".o"; +} class BuildGenerator : ProjectGenerator { private { @@ -230,7 +232,7 @@ class BuildGenerator : ProjectGenerator { // do not pass all source files to RDMD, only the main source file buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(s => !s.endsWith(".d"))().array(); - settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); + settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); auto generate_binary = !buildsettings.dflags.canFind("-o-"); @@ -416,13 +418,14 @@ class BuildGenerator : ProjectGenerator { /// Calls with path that resolve to the same file on the filesystem will return the same, /// unless they include different symbolic links (which are not resolved). - static string pathToObjName(string path) + static string pathToObjName(in ref BuildPlatform platform, string path) { import std.digest.crc : crc32Of; import std.path : buildNormalizedPath, dirSeparator, relativePath, stripDrive; if (path.endsWith(".d")) path = path[0 .. $-2]; auto ret = buildNormalizedPath(getcwd(), path).replace(dirSeparator, "."); auto idx = ret.lastIndexOf('.'); + const objSuffix = getObjSuffix(platform); return idx < 0 ? ret ~ objSuffix : format("%s_%(%02x%)%s", ret[idx+1 .. $], crc32Of(ret[0 .. idx]), objSuffix); } @@ -434,7 +437,7 @@ class BuildGenerator : ProjectGenerator { bs.lflags = null; bs.sourceFiles = [ srcFile ]; bs.targetType = TargetType.object; - gs.compiler.prepareBuildSettings(bs, BuildSetting.commandLine); + gs.compiler.prepareBuildSettings(bs, gs.platform, BuildSetting.commandLine); gs.compiler.setTarget(bs, gs.platform, objPath); gs.compiler.invoke(bs, gs.platform, gs.compileCallback); return objPath; @@ -456,12 +459,13 @@ class BuildGenerator : ProjectGenerator { import std.parallelism, std.range : walkLength; auto lbuildsettings = buildsettings; - auto srcs = buildsettings.sourceFiles.filter!(f => !isLinkerFile(f)); + auto srcs = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)); auto objs = new string[](srcs.walkLength); void compileSource(size_t i, string src) { logInfo("Compiling %s...", src); - objs[i] = compileUnit(src, pathToObjName(src), buildsettings, settings); + const objPath = pathToObjName(settings.platform, src); + objs[i] = compileUnit(src, objPath, buildsettings, settings); } if (settings.parallelBuild) { @@ -471,40 +475,40 @@ class BuildGenerator : ProjectGenerator { } logInfo("Linking..."); - lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f=> f.isLinkerFile()).array; + lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; settings.compiler.setTarget(lbuildsettings, settings.platform); - settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); + settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback); // NOTE: separate compile/link is not yet enabled for GDC. } else if (generate_binary && (settings.buildMode == BuildMode.allAtOnce || settings.compiler.name == "gdc" || is_static_library)) { // don't include symbols of dependencies (will be included by the top level target) - if (is_static_library) buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !f.isLinkerFile()).array; + if (is_static_library) buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)).array; // setup for command line settings.compiler.setTarget(buildsettings, settings.platform); - settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); + settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); // invoke the compiler settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); } else { // determine path for the temporary object file - string tempobjname = buildsettings.targetName ~ objSuffix; + string tempobjname = buildsettings.targetName ~ getObjSuffix(settings.platform); NativePath tempobj = NativePath(buildsettings.targetPath) ~ tempobjname; // setup linker command line auto lbuildsettings = buildsettings; - lbuildsettings.sourceFiles = lbuildsettings.sourceFiles.filter!(f => isLinkerFile(f)).array; + lbuildsettings.sourceFiles = lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array; if (generate_binary) settings.compiler.setTarget(lbuildsettings, settings.platform); - settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); + settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); // setup compiler command line buildsettings.libs = null; buildsettings.lflags = null; if (generate_binary) buildsettings.addDFlags("-c", "-of"~tempobj.toNativeString()); - buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(f)).array; + buildsettings.sourceFiles = buildsettings.sourceFiles.filter!(f => !isLinkerFile(settings.platform, f)).array; - settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); + settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine); settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index ddbbc33db..1d8990f86 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -353,7 +353,7 @@ class ProjectGenerator { auto pdepti = &targets[depname]; configureDependents(*pdepti, targets, level + 1); - mergeFromDependency(pdepti.buildSettings, ti.buildSettings); + mergeFromDependency(pdepti.buildSettings, ti.buildSettings, genSettings.platform); } } @@ -519,7 +519,7 @@ class ProjectGenerator child.addOptions(BuildOptions(parent.options & inheritedBuildOptions)); } - private static void mergeFromDependency(in ref BuildSettings child, ref BuildSettings parent) + private static void mergeFromDependency(in ref BuildSettings child, ref BuildSettings parent, in ref BuildPlatform platform) { import dub.compilers.utils : isLinkerFile; @@ -532,7 +532,7 @@ class ProjectGenerator parent.addStringImportPaths(child.stringImportPaths); // linking of static libraries is done by parent if (child.targetType == TargetType.staticLibrary) { - parent.addSourceFiles(child.sourceFiles.filter!isLinkerFile.array); + parent.addSourceFiles(child.sourceFiles.filter!(f => isLinkerFile(platform, f)).array); parent.addLibs(child.libs); parent.addLFlags(child.lflags); } diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 87c8e519c..df65729b3 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -194,7 +194,7 @@ class VisualDGenerator : ProjectGenerator { addFile(p.recipePath.toNativeString(), false); if (files.targetType == TargetType.staticLibrary) - foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(s))) addFile(s, true); + foreach(s; files.sourceFiles.filter!(s => !isLinkerFile(settings.platform, s))) addFile(s, true); else foreach(s; files.sourceFiles.filter!(s => !s.endsWith(".lib"))) addFile(s, true); diff --git a/source/dub/project.d b/source/dub/project.d index 48b675292..5f94b2530 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -790,7 +790,7 @@ class Project { else static if (attributeName == "stringImportPaths") bs.stringImportPaths = bs.stringImportPaths.map!(ensureTrailingSlash).array(); - compiler.prepareBuildSettings(bs, BuildSetting.all & ~to!BuildSetting(attributeName)); + compiler.prepareBuildSettings(bs, platform, BuildSetting.all & ~to!BuildSetting(attributeName)); values = bs.dflags; break; @@ -801,7 +801,7 @@ class Project { bs.sourceFiles = null; bs.targetType = TargetType.none; // Force Compiler to NOT omit dependency libs when package is a library. - compiler.prepareBuildSettings(bs, BuildSetting.all & ~to!BuildSetting(attributeName)); + compiler.prepareBuildSettings(bs, platform, BuildSetting.all & ~to!BuildSetting(attributeName)); if (bs.lflags) values = compiler.lflagsToDFlags( bs.lflags ); @@ -1026,13 +1026,13 @@ class Project { if (projectDescription.rootPackage in projectDescription.targetLookup) { // Copy linker files from sourceFiles to linkerFiles auto target = projectDescription.lookupTarget(projectDescription.rootPackage); - foreach (file; target.buildSettings.sourceFiles.filter!(isLinkerFile)) + foreach (file; target.buildSettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f))) target.buildSettings.addLinkerFiles(file); // Remove linker files from sourceFiles target.buildSettings.sourceFiles = target.buildSettings.sourceFiles - .filter!(a => !isLinkerFile(a)) + .filter!(a => !isLinkerFile(settings.platform, a)) .array(); projectDescription.lookupTarget(projectDescription.rootPackage) = target; } From cfb281e289e7f72bfdd0f3e04407470d27cb8c4b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 20 Aug 2019 02:07:31 +0200 Subject: [PATCH 8/8] Fix linking shared libs with ldmd2 and gdmd --- source/dub/compilers/dmd.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 3d695fb9d..051e1228f 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -248,7 +248,7 @@ config /etc/dmd.conf settings.addDFlags("-lib"); break; case TargetType.dynamicLibrary: - if (platform.platform.canFind("windows") || platform.platform.canFind("osx")) + if (platform.compiler != "dmd" || platform.platform.canFind("windows") || platform.platform.canFind("osx")) settings.addDFlags("-shared"); else settings.prependDFlags("-shared", "-defaultlib=libphobos2.so");