diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 3cd09a8..d48ead6 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -74,6 +74,9 @@ /// Removes any dflags that match one of the BuildOptions values and populates the BuildSettings.options field. void extractBuildOptions(ref BuildSettings settings) const; + /// Computes the full file name of the generated binary. + string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) const; + /// Adds the appropriate flag to set a target path void setTarget(ref BuildSettings settings, in BuildPlatform platform, string targetPath = null) const; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index e5c7cdd..b294330 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -164,6 +164,33 @@ settings.dflags = newflags.data; } + string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) + const { + assert(settings.targetName.length > 0, "No target name set."); + 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")) + return settings.targetName ~ ".exe"; + else return settings.targetName; + case TargetType.library: + case TargetType.staticLibrary: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".lib"; + else return "lib" ~ settings.targetName ~ ".a"; + case TargetType.dynamicLibrary: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".dll"; + else return "lib" ~ settings.targetName ~ ".so"; + case TargetType.object: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".obj"; + else return settings.targetName ~ ".o"; + } + } + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index 22aef92..cf11e45 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -167,6 +167,31 @@ settings.dflags = newflags.data; } + string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) + const { + assert(settings.targetName.length > 0, "No target name set."); + 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")) + return settings.targetName ~ ".exe"; + else return settings.targetName; + case TargetType.library: + case TargetType.staticLibrary: + return "lib" ~ settings.targetName ~ ".a"; + case TargetType.dynamicLibrary: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".dll"; + else return "lib" ~ settings.targetName ~ ".so"; + case TargetType.object: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".obj"; + else return settings.targetName ~ ".o"; + } + } + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index 562edb1..6a3c993 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -151,6 +151,43 @@ settings.dflags = newflags.data; } + string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) + const { + import std.string : splitLines, strip; + import std.uni : toLower; + + assert(settings.targetName.length > 0, "No target name set."); + + 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 generates_coff = result.output.splitLines.find!(l => l.strip.toLower.startsWith("default target:")).front.canFind("-windows-msvc"); + + 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")) + return settings.targetName ~ ".exe"; + else return settings.targetName; + case TargetType.library: + case TargetType.staticLibrary: + if (generates_coff) return settings.targetName ~ ".lib"; + else return "lib" ~ settings.targetName ~ ".a"; + case TargetType.dynamicLibrary: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".dll"; + else return "lib" ~ settings.targetName ~ ".so"; + case TargetType.object: + if (platform.platform.canFind("windows")) + return settings.targetName ~ ".obj"; + else return settings.targetName ~ ".o"; + } + } + void setTarget(ref BuildSettings settings, in BuildPlatform platform, string tpath = null) const { final switch (settings.targetType) { diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 6975e4c..6cdff13 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -15,41 +15,6 @@ /** - Given a set of build settings and a target platform, determines the target - binary file name. - - The returned string contains the file name, as well as the platform - specific file extension. The directory is not included. -*/ -string getTargetFileName(in BuildSettings settings, in BuildPlatform platform) -{ - assert(settings.targetName.length > 0, "No target name set."); - 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")) - return settings.targetName ~ ".exe"; - else return settings.targetName; - case TargetType.library: - case TargetType.staticLibrary: - if (platform.platform.canFind("windows") && platform.compiler == "dmd") - return settings.targetName ~ ".lib"; - else return "lib" ~ settings.targetName ~ ".a"; - case TargetType.dynamicLibrary: - if( platform.platform.canFind("windows") ) - return settings.targetName ~ ".dll"; - else return "lib" ~ settings.targetName ~ ".so"; - case TargetType.object: - if (platform.platform.canFind("windows")) - return settings.targetName ~ ".obj"; - else return settings.targetName ~ ".o"; - } -} - - -/** Alters the build options to comply with the specified build requirements. And enabled options that do not comply will get disabled. diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 1873d91..b2d4ae0 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -67,9 +67,9 @@ foreach (ldep; ti.linkDependencies) { auto dbs = targets[ldep].buildSettings; if (bs.targetType != TargetType.staticLibrary) { - bs.addSourceFiles((Path(dbs.targetPath) ~ getTargetFileName(dbs, settings.platform)).toNativeString()); + bs.addSourceFiles(getTargetPath(dbs, settings).toNativeString()); } else { - additional_dep_files ~= Path(dbs.targetPath) ~ getTargetFileName(dbs, settings.platform); + additional_dep_files ~= getTargetPath(dbs, settings); } } if (buildTarget(settings, bs, ti.pack, ti.config, ti.packages, additional_dep_files)) @@ -96,7 +96,7 @@ // run the generated executable auto buildsettings = targets[m_project.rootPackage.name].buildSettings; if (settings.run && !(buildsettings.options & BuildOption.syntaxOnly)) { - auto exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); + auto exe_file_path = getTargetPath(buildsettings, settings); runTarget(exe_file_path, buildsettings, settings.runArgs, settings); } } @@ -151,10 +151,10 @@ if (settings.tempBuild) target_path = getTempDir() ~ format(".dub/build/%s-%s/%s/", pack.name, pack.version_, build_id); else target_path = pack.path ~ format(".dub/build/%s/", build_id); - if (!settings.force && isUpToDate(target_path, buildsettings, settings.platform, pack, packages, additional_dep_files)) { + if (!settings.force && isUpToDate(target_path, buildsettings, settings, pack, packages, additional_dep_files)) { logInfo("%s %s: target for configuration \"%s\" is up to date.", pack.name, pack.version_, config); logDiagnostic("Using existing build in %s.", target_path.toNativeString()); - copyTargetFile(target_path, buildsettings, settings.platform); + copyTargetFile(target_path, buildsettings, settings); return true; } @@ -180,7 +180,7 @@ cbuildsettings.targetPath = target_path.relativeTo(cwd).toNativeString(); buildWithCompiler(settings, cbuildsettings); - copyTargetFile(target_path, buildsettings, settings.platform); + copyTargetFile(target_path, buildsettings, settings); return false; } @@ -220,11 +220,11 @@ m_temporaryFiles ~= tmpdir; tmp_target = true; } - exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); + exe_file_path = getTargetPath(buildsettings, settings); settings.compiler.setTarget(buildsettings, settings.platform); } - logDiagnostic("Application output name is '%s'", getTargetFileName(buildsettings, settings.platform)); + logDiagnostic("Application output name is '%s'", settings.compiler.getTargetFileName(buildsettings, settings.platform)); string[] flags = ["--build-only", "--compiler="~settings.platform.compilerBinary]; if (settings.force) flags ~= "--force"; @@ -289,7 +289,7 @@ m_temporaryFiles ~= tmppath; is_temp_target = true; } - exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); + exe_file_path = getTargetPath(buildsettings, settings); } if( buildsettings.preBuildCommands.length ){ @@ -336,9 +336,9 @@ settings.platform.compiler, settings.platform.frontendVersion, hashstr); } - private void copyTargetFile(Path build_path, BuildSettings buildsettings, BuildPlatform platform) + private void copyTargetFile(Path build_path, BuildSettings buildsettings, GeneratorSettings settings) { - auto filename = getTargetFileName(buildsettings, platform); + auto filename = settings.compiler.getTargetFileName(buildsettings, settings.platform); auto src = build_path ~ filename; logDiagnostic("Copying target from %s to %s", src.toNativeString(), buildsettings.targetPath); if (!existsFile(Path(buildsettings.targetPath))) @@ -346,11 +346,11 @@ hardLinkFile(src, Path(buildsettings.targetPath) ~ filename, true); } - private bool isUpToDate(Path target_path, BuildSettings buildsettings, BuildPlatform platform, in Package main_pack, in Package[] packages, in Path[] additional_dep_files) + private bool isUpToDate(Path target_path, BuildSettings buildsettings, GeneratorSettings settings, in Package main_pack, in Package[] packages, in Path[] additional_dep_files) { import std.datetime; - auto targetfile = target_path ~ getTargetFileName(buildsettings, platform); + auto targetfile = target_path ~ settings.compiler.getTargetFileName(buildsettings, settings.platform); if (!existsFile(targetfile)) { logDiagnostic("Target '%s' doesn't exist, need rebuild.", targetfile.toNativeString()); return false; @@ -416,7 +416,7 @@ Path target_file; scope (failure) { logDiagnostic("FAIL %s %s %s" , buildsettings.targetPath, buildsettings.targetName, buildsettings.targetType); - auto tpath = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); + auto tpath = getTargetPath(buildsettings, settings); if (generate_binary && existsFile(tpath)) removeFile(tpath); } @@ -541,3 +541,8 @@ return prj.path ~ f; return prj.path ~ "source/app.d"; } + +private Path getTargetPath(in ref BuildSettings bs, in ref GeneratorSettings settings) +{ + return Path(bs.targetPath) ~ settings.compiler.getTargetFileName(bs, settings.platform); +} diff --git a/source/dub/generators/targetdescription.d b/source/dub/generators/targetdescription.d index 5f6fb5e..d2aec6e 100644 --- a/source/dub/generators/targetdescription.d +++ b/source/dub/generators/targetdescription.d @@ -9,7 +9,6 @@ import dub.compilers.buildsettings; import dub.compilers.compiler; -import dub.compilers.utils : getTargetFileName; import dub.description; import dub.generators.generator; import dub.internal.vibecompat.inet.path; @@ -53,7 +52,7 @@ foreach (ld; ti.linkDependencies) { auto ltarget = targets[ld]; auto ltbs = ltarget.buildSettings; - auto targetfil = (Path(ltbs.targetPath) ~ getTargetFileName(ltbs, settings.platform)).toNativeString(); + auto targetfil = (Path(ltbs.targetPath) ~ settings.compiler.getTargetFileName(ltbs, settings.platform)).toNativeString(); d.buildSettings.addLinkerFiles(targetfil); } diff --git a/source/dub/package_.d b/source/dub/package_.d index 49dc122..0afcf55 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -521,8 +521,11 @@ */ PackageDescription describe(BuildPlatform platform, string config) const { - import dub.compilers.utils : getTargetFileName; - + return describe(platform, getCompiler(platform.compilerBinary), config); + } + /// ditto + PackageDescription describe(BuildPlatform platform, Compiler compiler, string config) + const { PackageDescription ret; ret.configuration = config; ret.path = m_path.toNativeString(); @@ -542,8 +545,8 @@ ret.targetType = bs.targetType; ret.targetPath = bs.targetPath; ret.targetName = bs.targetName; - if (ret.targetType != TargetType.none) - ret.targetFileName = getTargetFileName(bs, platform); + if (ret.targetType != TargetType.none && compiler) + ret.targetFileName = compiler.getTargetFileName(bs, platform); ret.workingDirectory = bs.workingDirectory; ret.mainSourceFile = bs.mainSourceFile; ret.dflags = bs.dflags;