diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index c1d6e72..62a8bf8 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -56,7 +56,7 @@ void prepareBuildSettings(ref BuildSettings settings, BuildSetting supported_fields = BuildSetting.all); /// Adds the appropriate flag to set a target path - void setTarget(ref BuildSettings settings, Path binary_path); + void setTarget(ref BuildSettings settings, in BuildPlatform platform); } @@ -64,6 +64,8 @@ /// include paths. struct BuildSettings { TargetType targetType; + string targetPath; + string targetName; string[] dflags; string[] lflags; string[] libs; @@ -81,7 +83,7 @@ void addLFlags(in string[] value...) { add(lflags, value); } void addLibs(in string[] value...) { add(libs, value); } void addSourceFiles(in string[] value...) { add(sourceFiles, value); } - void removeSourceFiles(in string[] value...) { remove(sourceFiles, value); } + void removeSourceFiles(in string[] value...) { removePaths(sourceFiles, value); } void addCopyFiles(in string[] value...) { add(copyFiles, value); } void addVersions(in string[] value...) { add(versions, value); } void addImportPaths(in string[] value...) { add(importPaths, value); } @@ -110,9 +112,15 @@ } } - private void remove(ref string[] arr, in string[] vals) + private void removePaths(ref string[] arr, in string[] vals) { - arr = arr.filter!(s => !vals.canFind(s))().array(); + bool matches(string s){ + foreach( p; vals ) + if( Path(s) == Path(p) ) + return true; + return false; + } + arr = arr.filter!(s => !matches(s))().array(); } } @@ -150,6 +158,29 @@ staticLibrary } +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); + 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"; + } +} + + private { Compiler[] s_compilers; diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index e50dd6e..4f78840 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -91,7 +91,7 @@ assert(fields & BuildSetting.copyFiles); } - void setTarget(ref BuildSettings settings, Path binary_path) + void setTarget(ref BuildSettings settings, in BuildPlatform platform) { final switch(settings.targetType){ case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -105,6 +105,7 @@ break; } - settings.addDFlags("-of"~binary_path.toNativeString()); + auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); + settings.addDFlags("-of"~tpath.toNativeString()); } } diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index f5b3c92..65719fb 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -132,7 +132,7 @@ assert(fields & BuildSetting.copyFiles); } - void setTarget(ref BuildSettings settings, Path binary_path) + void setTarget(ref BuildSettings settings, in BuildPlatform platform) { final switch(settings.targetType){ case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -147,6 +147,7 @@ break; } - settings.addDFlags("-o", binary_path.toNativeString()); + auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); + settings.addDFlags("-o", tpath.toNativeString()); } } diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index beaa59d..f05926a 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -88,7 +88,7 @@ assert(fields & BuildSetting.copyFiles); } - void setTarget(ref BuildSettings settings, Path binary_path) + void setTarget(ref BuildSettings settings, in BuildPlatform platform) { final switch(settings.targetType){ case TargetType.autodetect: assert(false, "Invalid target type: autodetect"); @@ -103,6 +103,7 @@ break; } - settings.addDFlags("-of"~binary_path.toNativeString()); + auto tpath = Path(settings.targetPath) ~ getTargetFileName(settings, platform); + settings.addDFlags("-of"~tpath.toNativeString()); } } diff --git a/source/dub/dub.d b/source/dub/dub.d index 0694fc8..6a0c236 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -91,8 +91,6 @@ @property inout(PackageManager) packageManager() inout { return m_packageManager; } - @property Path binaryPath() const { return m_project.binaryPath; } - void loadPackageFromCwd() { loadPackage(m_cwd); diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 086dda9..9198f76 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -41,14 +41,8 @@ void generateProject(GeneratorSettings settings) { - //Added check for existance of [AppNameInPackagejson].d - //If exists, use that as the starting file. - auto outfile = getBinName(m_project); - auto mainsrc = getMainSourceFile(m_project); auto cwd = Path(getcwd()); - logDebug("Application output name is '%s'", outfile); - auto buildsettings = settings.buildSettings; m_project.addBuildSettings(buildsettings, settings.platform, settings.config); buildsettings.addDFlags(["-w"/*, "-property"*/]); @@ -72,11 +66,9 @@ // setup for command line settings.compiler.prepareBuildSettings(buildsettings, BuildSetting.commandLine); - Path run_exe_file; + Path exe_file_path; if( generate_binary ){ - if( !settings.run ){ - settings.compiler.setTarget(buildsettings, m_project.binaryPath~outfile); - } else { + if( settings.run ){ import std.random; auto rnd = to!string(uniform(uint.min, uint.max)) ~ "-"; auto tmp = environment.get("TEMP"); @@ -85,10 +77,13 @@ version(Posix) tmp = "/tmp"; else tmp = "."; } - run_exe_file = Path(tmp~"/.rdmd/source/"~rnd~outfile); - settings.compiler.setTarget(buildsettings, run_exe_file); + buildsettings.targetPath = Path(tmp~"/.rdmd/source/").toNativeString(); + buildsettings.targetName = rnd ~ buildsettings.targetName; } + exe_file_path = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); + settings.compiler.setTarget(buildsettings, settings.platform); } + logDebug("Application output name is '%s'", exe_file_path.toNativeString()); string[] flags = buildsettings.dflags; @@ -127,7 +122,7 @@ logInfo("Copying files..."); foreach( f; buildsettings.copyFiles ){ auto src = Path(f); - auto dst = (run_exe_file.empty ? m_project.binaryPath : run_exe_file.parentPath) ~ Path(f).head; + auto dst = exe_file_path.parentPath ~ Path(f).head; logDebug(" %s to %s", src.toNativeString(), dst.toNativeString()); try copyFile(src, dst, true); catch logWarn("Failed to copy to %s", dst.toNativeString()); @@ -135,29 +130,14 @@ } if( settings.run ){ - auto prg_pid = spawnProcess(run_exe_file.toNativeString(), settings.runArgs); + logDebug("Running %s...", exe_file_path.toNativeString()); + auto prg_pid = spawnProcess(exe_file_path.toNativeString(), settings.runArgs); result = prg_pid.wait(); - remove(run_exe_file.toNativeString()); + remove(exe_file_path.toNativeString()); foreach( f; buildsettings.copyFiles ) - remove((run_exe_file.parentPath ~ Path(f).head).toNativeString()); + remove((exe_file_path.parentPath ~ Path(f).head).toNativeString()); enforce(result == 0, "Program exited with code "~to!string(result)); } } } } - -private string getBinName(in Project prj) -{ - // take the project name as the base or fall back to "app" - string ret = prj.name; - if( ret.length == 0 ) ret ="app"; - version(Windows) { ret ~= ".exe"; } - return ret; -} - -private Path getMainSourceFile(in Project prj) -{ - auto p = Path("source") ~ (prj.name ~ ".d"); - return existsFile(p) ? p : Path("source/app.d"); -} - diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index c64ead6..b38743e 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -49,23 +49,23 @@ */ ProjectGenerator createProjectGenerator(string generator_type, Project app, PackageManager mgr) { - enforce(app !is null, "app==null, Need an application to work on!"); - enforce(mgr !is null, "mgr==null, Need a package manager to work on!"); + assert(app !is null && mgr !is null, "Project and package manager needed to create a generator."); + generator_type = generator_type.toLower(); switch(generator_type) { default: throw new Exception("Unknown project generator: "~generator_type); case "build": - logTrace("Generating build generator."); + logTrace("Creating build generator."); return new BuildGenerator(app, mgr); case "rdmd": - logTrace("Generating rdmd generator."); + logTrace("Creating rdmd generator."); return new RdmdGenerator(app, mgr); case "mono-d": - logTrace("Generating MonoD generator."); + logTrace("Creating MonoD generator."); return new MonoDGenerator(app, mgr); case "visuald": - logTrace("Generating VisualD generator."); + logTrace("Creating VisualD generator."); return new VisualDGenerator(app, mgr); } } diff --git a/source/dub/generators/monod.d b/source/dub/generators/monod.d index 8478689..9eb39fa 100644 --- a/source/dub/generators/monod.d +++ b/source/dub/generators/monod.d @@ -217,11 +217,11 @@ config.configName, config.platformName); sln.put(" True\n"); - auto outpath = pack.binaryPath.relativeTo(pack.path).toNativeString(); + auto outpath = Path(buildsettings.targetPath).toNativeString(); sln.formattedWrite(" %s\n", outpath.length ? outpath : "."); sln.put(" True\n"); sln.put(" Executable\n"); - sln.formattedWrite(" %s\n", pack.name); + sln.formattedWrite(" %s\n", buildsettings.targetName); sln.put(" False\n"); sln.formattedWrite(" %s\n", (Path("obj/")~config.configName).toNativeString()); sln.put(" 0\n"); diff --git a/source/dub/generators/rdmd.d b/source/dub/generators/rdmd.d index 9e3e3f6..9cd1661 100644 --- a/source/dub/generators/rdmd.d +++ b/source/dub/generators/rdmd.d @@ -43,11 +43,8 @@ { //Added check for existance of [AppNameInPackagejson].d //If exists, use that as the starting file. - auto outfile = getBinName(m_project); auto mainsrc = getMainSourceFile(m_project); - logDebug("Application output name is '%s'", outfile); - auto buildsettings = settings.buildSettings; m_project.addBuildSettings(buildsettings, settings.platform, settings.config); // do not pass all source files to RDMD, only the main source file @@ -69,9 +66,7 @@ // or with "/" instead of "\" Path run_exe_file; if( generate_binary ){ - if( !settings.run ){ - settings.compiler.setTarget(buildsettings, m_project.binaryPath~outfile); - } else { + if( settings.run ){ import std.random; auto rnd = to!string(uniform(uint.min, uint.max)) ~ "-"; auto tmp = environment.get("TEMP"); @@ -80,11 +75,15 @@ version(Posix) tmp = "/tmp"; else tmp = "."; } - run_exe_file = Path(tmp~"/.rdmd/source/"~rnd~outfile); - settings.compiler.setTarget(buildsettings, run_exe_file); + buildsettings.targetPath = (Path(tmp)~"/.rdmd/source/").toNativeString(); + buildsettings.targetName = rnd ~ buildsettings.targetName; + run_exe_file = Path(buildsettings.targetPath) ~ getTargetFileName(buildsettings, settings.platform); } + settings.compiler.setTarget(buildsettings, settings.platform); } + logDebug("Application output name is '%s'", getTargetFileName(buildsettings, settings.platform)); + string[] flags = ["--build-only", "--compiler="~settings.compilerBinary]; flags ~= buildsettings.dflags; flags ~= (mainsrc).toNativeString(); @@ -124,7 +123,7 @@ logInfo("Copying files..."); foreach( f; buildsettings.copyFiles ){ auto src = Path(f); - auto dst = (run_exe_file.empty ? m_project.binaryPath : run_exe_file.parentPath) ~ Path(f).head; + auto dst = (run_exe_file.empty ? Path(buildsettings.targetPath) : run_exe_file.parentPath) ~ Path(f).head; logDebug(" %s to %s", src.toNativeString(), dst.toNativeString()); try copyFile(src, dst, true); catch logWarn("Failed to copy to %s", dst.toNativeString()); @@ -143,24 +142,10 @@ } } -private string getBinName(in Project prj) -{ - // take the project name as the base or fall back to "app" - string ret = prj.name; - if( ret.length == 0 ) ret ="app"; - version(Windows) { ret ~= ".exe"; } - return ret; -} - private Path getMainSourceFile(in Project prj) { - foreach(p; ["source", "src", "."]){ - foreach(f; [prj.name, "app"]){ - auto fp = Path(p) ~ (f ~ ".d"); - if( existsFile(fp) ) - return fp; - } - } - return Path("app.d"); + foreach( f; ["source/app.d", "src/app.d", "source/"~prj.name~".d", "src/"~prj.name~".d"]) + if( exists(f) ) + return Path(f); + return Path("source/app.d"); } - diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d index 7f682c6..f3359b9 100644 --- a/source/dub/generators/visuald.d +++ b/source/dub/generators/visuald.d @@ -281,13 +281,13 @@ %s", type == Config.Release? "1":"0"); // Lib or exe? - bool createLib = pack != m_app.mainPackage(); - string libIdentifier = createLib? "1" : "0"; + bool is_lib = buildsettings.targetType == TargetType.executable; string debugSuffix = type == Config.Debug? "_d" : ""; - string extension = createLib? "lib" : "exe"; + auto bin_path = Path(buildsettings.targetPath); + bin_path.endsWithSlash = true; ret.formattedWrite(" %s - bin\\$(ProjectName)%s.%s", libIdentifier, debugSuffix, extension); + %s%s%s.%s", is_lib ? "1" : "0", bin_path.toNativeString(), buildsettings.targetName, debugSuffix, is_lib ? "lib" : "exe"); // include paths and string imports string imports = join(getSettings!"importPaths"(), " "); diff --git a/source/dub/package_.d b/source/dub/package_.d index c642209..077290e 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -151,12 +151,6 @@ @property Path path() const { return m_path; } @property Path packageInfoFile() const { return m_path ~ "package.json"; } @property const(Dependency[string]) dependencies() const { return m_info.dependencies; } - @property Path binaryPath() - const { - auto p = m_info.binaryPath; - if( !p.length ) return this.path; - return this.path ~ Path(p); - } @property string[] configurations() const { @@ -175,6 +169,7 @@ BuildSettings ret; m_info.buildSettings.getPlatformSettings(ret, platform, this.path); conf.buildSettings.getPlatformSettings(ret, platform, this.path); + if( ret.targetName.empty ) ret.targetName = this.name; return ret; } assert(false, "Unknown configuration for "~m_info.name~": "~config); @@ -230,7 +225,6 @@ struct PackageInfo { string name; string version_; - string binaryPath; string description; string homepage; string[] authors; @@ -244,18 +238,9 @@ { foreach( string field, value; json ){ switch(field){ - default: - /*auto didx = std.string.indexOf(field, "-"); - string basename, suffix; - if( didx >= 0 ) basename = field[0 .. didx], suffix = field[didx .. $]; - else basename = field; - if( basename == "defaultConfiguration" ){ - this.defaultConfiguration[suffix] = value.get!string(); - }*/ - break; + default: break; case "name": this.name = value.get!string; break; case "version": this.version_ = value.get!string; break; - case "binaryPath": this.binaryPath = value.get!string; break; case "description": this.description = value.get!string; break; case "homepage": this.homepage = value.get!string; break; case "authors": this.authors = deserializeJson!(string[])(value); break; @@ -375,6 +360,8 @@ struct BuildSettingsTemplate { TargetType targetType = TargetType.autodetect; + string targetPath; + string targetName; string[][string] dflags; string[][string] lflags; string[][string] libs; @@ -404,6 +391,14 @@ enforce(suffix.empty, "targetType does not support platform customization."); targetType = value.get!string().to!TargetType(); break; + case "targetPath": + enforce(suffix.empty, "targetPath does not support platform customization."); + this.targetPath = value.get!string; + break; + case "targetName": + enforce(suffix.empty, "targetName does not support platform customization."); + this.targetName = value.get!string; + break; case "dflags": this.dflags[suffix] = deserializeJson!(string[])(value); break; case "lflags": this.lflags[suffix] = deserializeJson!(string[])(value); break; case "libs": this.libs[suffix] = deserializeJson!(string[])(value); break; @@ -427,6 +422,9 @@ Json toJson() const { auto ret = Json.EmptyObject; + if( targetType != TargetType.autodetect ) ret["targetType"] = targetType.to!string(); + if( !targetPath.empty ) ret["targetPath"] = targetPath; + if( !targetName.empty ) ret["targetName"] = targetPath; foreach(suffix, arr; dflags) ret["dflags"~suffix] = serializeToJson(arr); foreach(suffix, arr; lflags) ret["lflags"~suffix] = serializeToJson(arr); foreach(suffix, arr; libs) ret["libs"~suffix] = serializeToJson(arr); @@ -447,6 +445,8 @@ void getPlatformSettings(ref BuildSettings dst, BuildPlatform platform, Path base_path) const { dst.targetType = this.targetType; + dst.targetPath = this.targetPath; + dst.targetName = this.targetName; // collect source files from all source folders foreach(suffix, paths; sourcePaths){ diff --git a/source/dub/project.d b/source/dub/project.d index 8d1c2f1..0e3c0f5 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -54,8 +54,6 @@ reinit(); } - @property Path binaryPath() const { return m_main.binaryPath; } - /// Gathers information @property string info() const { @@ -205,7 +203,11 @@ auto pkgconf = getPackageConfig(pkg, platform, config); auto psettings = pkg.getBuildSettings(platform, pkgconf); processVars(dst, pkg.path.toNativeString(), psettings); - if( pkg is m_main ) dst.targetType = psettings.targetType; + if( pkg is m_main ){ + dst.targetType = psettings.targetType; + dst.targetPath = psettings.targetPath; + dst.targetName = psettings.targetName; + } } // add version identifiers for available packages