diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index ba9f84f..b4ef823 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -204,7 +204,7 @@ default: if (arg.startsWith("-defaultlib=")) return true; return false; - case "-g", "-gc", "-m32", "-m64", "-shared": + case "-g", "-gc", "-m32", "-m64", "-shared", "-lib": return true; } } diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 50b5972..9dee164 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -26,6 +26,9 @@ import std.string; import std.encoding : sanitize; +version(Windows) enum objSuffix = ".obj"; +else enum objSuffix = ".o"; + class BuildGenerator : ProjectGenerator { private { Project m_project; @@ -341,6 +344,23 @@ return true; } + /// Output an unique name to represent the source file. + /// 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) { 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; + } + void buildWithCompiler(GeneratorSettings settings, BuildSettings buildsettings) { auto generate_binary = !(buildsettings.options & BuildOptions.syntaxOnly); @@ -353,13 +373,28 @@ if (generate_binary && existsFile(tpath)) removeFile(tpath); } + 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))) { + logInfo("Compiling %s...", file); + objs.put(compileUnit(file, pathToObjName(file), buildsettings, settings)); + } + + logInfo("Linking..."); + settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs.data, 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) */ - if (settings.buildMode == BuildMode.allAtOnce || settings.platform.compilerBinary != "dmd" || !generate_binary || is_static_library) { + } else if (settings.buildMode == BuildMode.allAtOnce || settings.platform.compilerBinary != "dmd" || !generate_binary || is_static_library) { // setup for command line if (generate_binary) settings.compiler.setTarget(buildsettings, settings.platform); settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); @@ -372,9 +407,7 @@ settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback); } else { // determine path for the temporary object file - string tempobjname = buildsettings.targetName; - version(Windows) tempobjname ~= ".obj"; - else tempobjname ~= ".o"; + string tempobjname = buildsettings.targetName ~ objSuffix; Path tempobj = Path(buildsettings.targetPath) ~ tempobjname; // setup linker command line diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 723361c..8010988 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -222,7 +222,7 @@ enum BuildMode { separate, /// Compile and link separately allAtOnce, /// Perform compile and link with a single compiler invocation - //singleFile, /// Compile each file separately + singleFile, /// Compile each file separately //multipleObjects, /// Generate an object file per module //multipleObjectsPerModule, /// Use the -multiobj switch to generate multiple object files per module //compileOnly /// Do not invoke the linker (can be done using a post build command) diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 86de079..e96d66c 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -334,7 +334,7 @@ final switch (settings.buildMode) with (BuildMode) { case separate: singlefilemode = 2; break; case allAtOnce: singlefilemode = 0; break; - //case singleFile: singlefilemode = 1; break; + case singleFile: singlefilemode = 1; break; //case compileOnly: singlefilemode = 3; break; } ret.formattedWrite(" %s\n", singlefilemode);