diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index e03095d..75bd325 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -214,7 +214,7 @@ void extractBuildOptions(ref BuildSettings settings) const; /// Adds the appropriate flag to set a target path - void setTarget(ref BuildSettings settings, in BuildPlatform platform) const; + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string targetPath = null) const; /// Invokes the compiler using the given flags void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback); diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index b4ef823..fc1faa9 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -153,7 +153,7 @@ settings.dflags = newflags.data; } - void setTarget(ref BuildSettings settings, in BuildPlatform platform) const + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -170,8 +170,9 @@ break; } - auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); - settings.addDFlags("-of"~tpath.toNativeString()); + if (tpath is null) + tpath = (Path(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + settings.addDFlags("-of"~tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index c213d38..d09b9fc 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -156,7 +156,7 @@ settings.dflags = newflags.data; } - void setTarget(ref BuildSettings settings, in BuildPlatform platform) const + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -172,8 +172,9 @@ break; } - auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); - settings.addDFlags("-o", tpath.toNativeString()); + if (tpath is null) + tpath = (Path(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + settings.addDFlags("-o", tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) @@ -188,7 +189,30 @@ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { - assert(false, "Separate linking not implemented for GDC"); + import std.string; + string[] args; + // As the user is supposed to call setTarget prior to invoke, -o target is already set. + if (settings.targetType == TargetType.staticLibrary || settings.targetType == TargetType.staticLibrary) { + auto tpath = extractTarget(settings.dflags); + assert(tpath !is null, "setTarget should be called before invoke"); + args = [ "ar", "rcs", tpath ] ~ objects; + } else { + args = platform.compiler ~ 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 speficied in the wrong order by DMD + } + logDiagnostic("%s", args.join(" ")); + invokeTool(args, output_callback); + } +} + +private string extractTarget(const string[] args) { auto i = args.countUntil("-o"); return i >= 0 ? args[i+1] : null; } + +private bool isLinkageFlag(string flag) { + switch (flag) { + case "-c": + return false; + default: + return true; } } diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 0c39cec..f75caa8 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -143,7 +143,7 @@ settings.dflags = newflags.data; } - void setTarget(ref BuildSettings settings, in BuildPlatform platform) const + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -159,8 +159,9 @@ break; } - auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); - settings.addDFlags("-of"~tpath.toNativeString()); + if (tpath is null) + tpath = (Path(settings.targetPath) ~ getTargetFileName(settings, platform)).toNativeString(); + settings.addDFlags("-of"~tpath); } void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) @@ -175,6 +176,6 @@ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) { - assert(false, "Separate linking not implemented for GDC"); + assert(false, "Separate linking not implemented for LDC"); } } diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 9dee164..56a72a6 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -350,16 +350,17 @@ static string pathToObjName(string path) { return std.path.buildNormalizedPath(getcwd(), path~objSuffix)[1..$].replace("/", "."); } /// Compile a single source file (srcFile), and write the object to objName. static string compileUnit(string srcFile, string objName, BuildSettings bs, GeneratorSettings gs) { - Path tempobj = Path(bs.targetPath)~objName; - string objPath = tempobj.toNativeString(); - bs.libs = null; - bs.lflags = null; - bs.addDFlags("-c", "-of"~objPath); - bs.sourceFiles = [ srcFile ]; - gs.compiler.prepareBuildSettings(bs, BuildSetting.commandLine); - gs.compiler.invoke(bs, gs.platform, gs.compileCallback); - return objPath; - } + Path tempobj = Path(bs.targetPath)~objName; + string objPath = tempobj.toNativeString(); + bs.libs = null; + bs.lflags = null; + bs.addDFlags("-c"); + bs.sourceFiles = [ srcFile ]; + gs.compiler.prepareBuildSettings(bs, BuildSetting.commandLine); + gs.compiler.setTarget(bs, gs.platform, objPath); + gs.compiler.invoke(bs, gs.platform, gs.compileCallback); + return objPath; + } void buildWithCompiler(GeneratorSettings settings, BuildSettings buildsettings) { @@ -375,10 +376,6 @@ } if (settings.buildMode == BuildMode.singleFile && generate_binary) { auto lbuildsettings = buildsettings; - lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f=> f.isLinkerFile()).array; - settings.compiler.setTarget(lbuildsettings, settings.platform); - settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); - auto objs = appender!(string[])(); logInfo("Compiling using %s...", settings.platform.compilerBinary); foreach (file; buildsettings.sourceFiles.filter!(f=>!isLinkerFile(f))) { @@ -387,6 +384,9 @@ } logInfo("Linking..."); + lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f=> f.isLinkerFile()).array; + settings.compiler.setTarget(lbuildsettings, settings.platform); + settings.compiler.prepareBuildSettings(lbuildsettings, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles); settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs.data, settings.linkCallback); /*