From adbc7fd0f5796dc2e52d55a1d864e6c8d0f2718e Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 17 Aug 2019 16:21:16 +0200 Subject: [PATCH] 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 747a148f54..1b7db0d339 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", + "-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 4414bb82a4..5e5981a67a 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;