diff --git a/build-files.txt b/build-files.txt
index 1944066..3a9ec14 100644
--- a/build-files.txt
+++ b/build-files.txt
@@ -58,6 +58,7 @@
source/dub/internal/sdlang/util.d
source/dub/internal/tinyendian.d
source/dub/internal/undead/xml.d
+source/dub/internal/temp_files.d
source/dub/internal/utils.d
source/dub/internal/vibecompat/core/file.d
source/dub/internal/vibecompat/data/json.d
diff --git a/changelog/build-cache.dd b/changelog/build-cache.dd
deleted file mode 100644
index a6ee0b7..0000000
--- a/changelog/build-cache.dd
+++ /dev/null
@@ -1,14 +0,0 @@
-Binary output will now be in a central cache
-
-Up until now, dub would output build artifact in the package directory.
-
-This allowed reuse of build artifact for dependencies, but also created
-issues with large amount of build artifacts in the packages folder,
-preventing the use of read-only location to store packages,
-and making garbage collection of build artifacts unreliable.
-
-Starting from this version, build artifacts will be output by default to
-`$HOME/.dub/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME]`
-on Linux, and
-`%APPDATA%/cache/build/$BASE_PACKAGE_NAME/$PACKAGE_VERSION/[+$SUB_PACKAGE_NAME]`
-on Windows.
diff --git a/changelog/metadata-cache.dd b/changelog/metadata-cache.dd
deleted file mode 100644
index 69cd539..0000000
--- a/changelog/metadata-cache.dd
+++ /dev/null
@@ -1,9 +0,0 @@
-DUB API breaking change: `Package.metadataCache` setter and getter have been removed
-
-Those two functions were used to provide access to the metadata cache file
-to the generator. They were never intended for public consumption,
-and the JSON file format was not stable.
-
-Due to the introduction of the build cache, they needed to be removed,
-as there was no way to provide a sensible transition path, and they should be unused.
-If you have a use case for it, please open an issue in dub repository.
\ No newline at end of file
diff --git a/source/dub/commandline.d b/source/dub/commandline.d
index 61c53e6..8729b63 100644
--- a/source/dub/commandline.d
+++ b/source/dub/commandline.d
@@ -30,12 +30,11 @@
import std.exception;
import std.file;
import std.getopt;
-import std.path : expandTilde, absolutePath, buildNormalizedPath;
-import std.process;
+import std.path : absolutePath, buildNormalizedPath, expandTilde, setExtension;
+import std.process : environment, spawnProcess, wait;
import std.stdio;
import std.string;
import std.typecons : Tuple, tuple;
-import std.path: setExtension;
/** Retrieves a list of all available commands.
@@ -800,7 +799,7 @@
Dub dub;
if (options.bare) {
- dub = new Dub(NativePath(options.root_path), NativePath(getcwd()));
+ dub = new Dub(NativePath(options.root_path), getWorkingDirectory());
dub.defaultPlacementLocation = options.placementLocation;
return dub;
@@ -2250,7 +2249,7 @@
auto source = VersionRange.fromString(free_args[1]);
if (existsFile(NativePath(free_args[2]))) {
auto target = NativePath(free_args[2]);
- if (!target.absolute) target = NativePath(getcwd()) ~ target;
+ if (!target.absolute) target = getWorkingDirectory() ~ target;
dub.packageManager.addOverride_(scope_, pack, source, target);
logInfo("Added override %s %s => %s", pack, source, target);
} else {
@@ -2409,7 +2408,7 @@
{
if (!m_testPackage.length)
return super.prepareDub(options);
- return new Dub(NativePath(options.root_path), NativePath(getcwd()));
+ return new Dub(NativePath(options.root_path), getWorkingDirectory());
}
override int execute(Dub dub, string[] free_args, string[] app_args)
@@ -2443,7 +2442,7 @@
auto path = NativePath(free_args[0]);
path.normalize();
enforceUsage(!path.empty, "Destination path must not be empty.");
- if (!path.absolute) path = NativePath(getcwd()) ~ path;
+ if (!path.absolute) path = getWorkingDirectory() ~ path;
enforceUsage(!path.startsWith(dub.rootPath), "Destination path must not be a sub directory of the tested package!");
setupPackage(dub, null);
diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d
index a8dacd0..ece4884 100644
--- a/source/dub/compilers/compiler.d
+++ b/source/dub/compilers/compiler.d
@@ -12,6 +12,7 @@
public import dub.platform : BuildPlatform, matchesSpecification;
import dub.internal.vibecompat.inet.path;
+import dub.internal.vibecompat.core.file;
import dub.internal.logging;
@@ -108,10 +109,24 @@
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);
+ deprecated("specify the working directory")
+ final void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback)
+ {
+ invoke(settings, platform, output_callback, getWorkingDirectory());
+ }
+
+ /// ditto
+ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd);
/// Invokes the underlying linker directly
- void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback);
+ deprecated("specify the working directory")
+ final void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback)
+ {
+ invokeLinker(settings, platform, objects, output_callback, getWorkingDirectory());
+ }
+
+ /// ditto
+ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd);
/// Convert linker flags to compiler format
string[] lflagsToDFlags(const string[] lflags) const;
@@ -124,17 +139,26 @@
This method should be used by `Compiler` implementations to invoke the
compiler or linker binary.
*/
+ deprecated("specify the working directory")
protected final void invokeTool(string[] args, void delegate(int, string) output_callback, string[string] env = null)
{
+ invokeTool(args, output_callback, getWorkingDirectory(), env);
+ }
+
+ /// ditto
+ protected final void invokeTool(string[] args, void delegate(int, string) output_callback, NativePath cwd, string[string] env = null)
+ {
import std.string;
int status;
if (output_callback) {
- auto result = executeShell(escapeShellCommand(args), env);
+ auto result = executeShell(escapeShellCommand(args),
+ env, Config.none, size_t.max, cwd.toNativeString());
output_callback(result.status, result.output);
status = result.status;
} else {
- auto compiler_pid = spawnShell(escapeShellCommand(args), env);
+ auto compiler_pid = spawnShell(escapeShellCommand(args),
+ env, Config.none, cwd.toNativeString());
status = compiler_pid.wait();
}
diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d
index a181222..2039747 100644
--- a/source/dub/compilers/dmd.d
+++ b/source/dub/compilers/dmd.d
@@ -360,22 +360,26 @@
settings.addDFlags("-of"~tpath);
}
- void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback)
+ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd)
{
auto res_file = getTempFile("dub-build", ".rsp");
+ // clean-up early to avoid build-up of temporaries when invoke is called
+ // many times in one DUB session. (e.g. when using DUB as a library)
+ scope (exit)
+ removeFile(res_file);
const(string)[] args = settings.dflags;
if (platform.frontendVersion >= 2066) args ~= "-vcolumns";
writeFile(res_file, escapeArgs(args).join("\n"));
- logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" "));
+ logDiagnostic("[cwd=%s] %s %s", cwd, platform.compilerBinary, escapeArgs(args).join(" "));
string[string] env;
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, env);
+ invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, cwd, env);
}
- void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback)
+ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd)
{
import std.string;
auto tpath = NativePath(settings.targetPath) ~ getTargetFileName(settings, platform);
@@ -396,12 +400,12 @@
auto res_file = getTempFile("dub-build", ".lnk");
writeFile(res_file, escapeArgs(args).join("\n"));
- logDiagnostic("%s %s", platform.compilerBinary, escapeArgs(args).join(" "));
+ logDiagnostic("[cwd=%s] %s %s", cwd, platform.compilerBinary, escapeArgs(args).join(" "));
string[string] env;
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, env);
+ invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, cwd, env);
}
string[] lflagsToDFlags(const string[] lflags) const
diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d
index 9b42b33..d7a8e4c 100644
--- a/source/dub/compilers/gdc.d
+++ b/source/dub/compilers/gdc.d
@@ -17,7 +17,7 @@
import std.algorithm;
import std.array;
import std.exception;
-import std.process;
+import std.process : execute;
import std.typecons;
@@ -205,7 +205,7 @@
settings.addDFlags("-o", tpath);
}
- void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback)
+ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd)
{
auto res_file = getTempFile("dub-build", ".rsp");
writeFile(res_file, join(settings.dflags.map!(s => escape(s)), "\n"));
@@ -215,10 +215,10 @@
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, env);
+ invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, cwd, env);
}
- void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback)
+ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd)
{
import std.string;
string[] args;
@@ -237,7 +237,7 @@
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool(args, output_callback, env);
+ invokeTool(args, output_callback, cwd, env);
}
string[] lflagsToDFlags(const string[] lflags) const
diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d
index f071d7b..6b8f545 100644
--- a/source/dub/compilers/ldc.d
+++ b/source/dub/compilers/ldc.d
@@ -245,7 +245,7 @@
settings.addDFlags("-of"~tpath);
}
- void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback)
+ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd)
{
auto res_file = getTempFile("dub-build", ".rsp");
const(string)[] args = settings.dflags;
@@ -257,10 +257,10 @@
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, env);
+ invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, cwd, env);
}
- void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback)
+ void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd)
{
import std.string;
auto tpath = NativePath(settings.targetPath) ~ getTargetFileName(settings, platform);
@@ -280,7 +280,7 @@
foreach (aa; [settings.environments, settings.buildEnvironments])
foreach (k, v; aa)
env[k] = v;
- invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, env);
+ invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback, cwd, env);
}
string[] lflagsToDFlags(const string[] lflags) const
diff --git a/source/dub/dub.d b/source/dub/dub.d
index 2d3df65..7a78711 100644
--- a/source/dub/dub.d
+++ b/source/dub/dub.d
@@ -158,7 +158,7 @@
SkipPackageSuppliers skip_registry = SkipPackageSuppliers.none)
{
m_rootPath = NativePath(root_path);
- if (!m_rootPath.absolute) m_rootPath = NativePath(getcwd()) ~ m_rootPath;
+ if (!m_rootPath.absolute) m_rootPath = getWorkingDirectory() ~ m_rootPath;
init();
@@ -384,7 +384,7 @@
@property void rootPath(NativePath root_path)
{
m_rootPath = root_path;
- if (!m_rootPath.absolute) m_rootPath = NativePath(getcwd()) ~ m_rootPath;
+ if (!m_rootPath.absolute) m_rootPath = getWorkingDirectory() ~ m_rootPath;
}
/// Returns the name listed in the dub.json of the current
@@ -686,6 +686,8 @@
void generateProject(string ide, GeneratorSettings settings)
{
settings.cache = this.m_dirs.cache;
+ if (settings.overrideToolWorkingDirectory is NativePath.init)
+ settings.overrideToolWorkingDirectory = m_rootPath;
// With a requested `unittest` config, switch to the special test runner
// config (which doesn't require an existing `unittest` configuration).
if (settings.config == "unittest") {
@@ -705,7 +707,9 @@
void testProject(GeneratorSettings settings, string config, NativePath custom_main_file)
{
settings.cache = this.m_dirs.cache;
- if (!custom_main_file.empty && !custom_main_file.absolute) custom_main_file = getWorkingDirectory() ~ custom_main_file;
+ if (settings.overrideToolWorkingDirectory is NativePath.init)
+ settings.overrideToolWorkingDirectory = m_rootPath;
+ if (!custom_main_file.empty && !custom_main_file.absolute) custom_main_file = m_rootPath ~ custom_main_file;
const test_config = m_project.addTestRunnerConfiguration(settings, !m_dryRun, config, custom_main_file);
if (!test_config) return; // target type "none"
@@ -761,6 +765,9 @@
import std.stdio;
import std.ascii : newline;
+ if (settings.overrideToolWorkingDirectory is NativePath.init)
+ settings.overrideToolWorkingDirectory = m_rootPath;
+
// Split comma-separated lists
string[] requestedDataSplit =
requestedData
@@ -1314,8 +1321,8 @@
if (!run) {
// TODO: ddox should copy those files itself
- version(Windows) runCommand(`xcopy /S /D "`~tool_path~`public\*" docs\`);
- else runCommand("rsync -ru '"~tool_path~"public/' docs/");
+ version(Windows) runCommand(`xcopy /S /D "`~tool_path~`public\*" docs\`, null, m_rootPath.toNativeString());
+ else runCommand("rsync -ru '"~tool_path~"public/' docs/", null, m_rootPath.toNativeString());
}
}
@@ -1370,6 +1377,7 @@
if (this.defaultPostRunEnvironments)
settings.buildSettings.addPostRunEnvironments(this.defaultPostRunEnvironments);
settings.run = true;
+ settings.overrideToolWorkingDirectory = m_rootPath;
return settings;
}
@@ -1888,7 +1896,7 @@
result.systemSettings = NativePath("/var/lib/dub/");
result.userSettings = NativePath(environment.get("HOME")) ~ ".dub/";
if (!result.userSettings.absolute)
- result.userSettings = NativePath(getcwd()) ~ result.userSettings;
+ result.userSettings = getWorkingDirectory() ~ result.userSettings;
result.userPackages = result.userSettings;
}
result.cache = result.userPackages ~ "cache";
diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d
index 74b26c9..cdcad88 100644
--- a/source/dub/generators/build.d
+++ b/source/dub/generators/build.d
@@ -203,7 +203,7 @@
{
import std.path : absolutePath;
- auto cwd = NativePath(getcwd());
+ auto cwd = settings.toolWorkingDirectory;
bool generate_binary = !(buildsettings.options & BuildOption.syntaxOnly);
auto build_id = buildsettings.computeBuildID(config, settings);
@@ -233,7 +233,9 @@
if (!cached && buildsettings.postBuildCommands.length) {
logInfo("Post-build", Color.light_green, "Running commands");
runBuildCommands(CommandType.postBuild, buildsettings.postBuildCommands, pack, m_project, settings, buildsettings,
- [["DUB_BUILD_PATH" : target_path is NativePath.init ? "" : target_path.parentPath.toNativeString.absolutePath]]);
+ [["DUB_BUILD_PATH" : target_path is NativePath.init
+ ? ""
+ : target_path.parentPath.toNativeString.absolutePath(settings.toolWorkingDirectory.toNativeString)]]);
}
return cached;
@@ -288,7 +290,7 @@
private void performRDMDBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config, out NativePath target_path)
{
- auto cwd = NativePath(getcwd());
+ auto cwd = settings.toolWorkingDirectory;
//Added check for existence of [AppNameInPackagejson].d
//If exists, use that as the starting file.
NativePath mainsrc;
@@ -333,14 +335,14 @@
if (buildsettings.preBuildCommands.length){
logInfo("Pre-build", Color.light_green, "Running commands");
- runCommands(buildsettings.preBuildCommands);
+ runCommands(buildsettings.preBuildCommands, null, cwd.toNativeString());
}
logInfo("Building", Color.light_green, "%s %s [%s]", pack.name.color(Mode.bold), pack.version_, config.color(Color.blue));
logInfo("Running rdmd...");
logDiagnostic("rdmd %s", join(flags, " "));
- auto rdmd_pid = spawnProcess("rdmd" ~ flags);
+ auto rdmd_pid = spawnProcess("rdmd" ~ flags, null, Config.none, cwd.toNativeString());
auto result = rdmd_pid.wait();
enforce(result == 0, "Build command failed with exit code "~to!string(result));
@@ -353,7 +355,7 @@
private void performDirectBuild(GeneratorSettings settings, ref BuildSettings buildsettings, in Package pack, string config, out NativePath target_path)
{
- auto cwd = NativePath(getcwd());
+ auto cwd = settings.toolWorkingDirectory;
auto generate_binary = !(buildsettings.options & BuildOption.syntaxOnly);
// make file paths relative to shrink the command line
@@ -481,13 +483,19 @@
/// 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).
-
+ deprecated("Use the overload taking in the current working directory")
static string pathToObjName(const scope ref BuildPlatform platform, string path)
{
+ return pathToObjName(platform, path, getWorkingDirectory);
+ }
+
+ /// ditto
+ static string pathToObjName(const scope ref BuildPlatform platform, string path, NativePath cwd)
+ {
import std.digest.crc : crc32Of;
import std.path : buildNormalizedPath, dirSeparator, relativePath, stripDrive;
if (path.endsWith(".d")) path = path[0 .. $-2];
- auto ret = buildNormalizedPath(getcwd(), path).replace(dirSeparator, ".");
+ auto ret = buildNormalizedPath(cwd.toNativeString(), path).replace(dirSeparator, ".");
auto idx = ret.lastIndexOf('.');
const objSuffix = getObjSuffix(platform);
return idx < 0 ? ret ~ objSuffix : format("%s_%(%02x%)%s", ret[idx+1 .. $], crc32Of(ret[0 .. idx]), objSuffix);
@@ -503,7 +511,7 @@
bs.targetType = TargetType.object;
gs.compiler.prepareBuildSettings(bs, gs.platform, BuildSetting.commandLine);
gs.compiler.setTarget(bs, gs.platform, objPath);
- gs.compiler.invoke(bs, gs.platform, gs.compileCallback);
+ gs.compiler.invoke(bs, gs.platform, gs.compileCallback, gs.toolWorkingDirectory);
return objPath;
}
@@ -527,7 +535,7 @@
void compileSource(size_t i, string src) {
logInfo("Compiling", Color.light_green, "%s", src);
- const objPath = pathToObjName(settings.platform, src);
+ const objPath = pathToObjName(settings.platform, src, settings.toolWorkingDirectory);
objs[i] = compileUnit(src, objPath, buildsettings, settings);
}
@@ -541,7 +549,7 @@
lbuildsettings.sourceFiles = is_static_library ? [] : lbuildsettings.sourceFiles.filter!(f => isLinkerFile(settings.platform, f)).array;
settings.compiler.setTarget(lbuildsettings, settings.platform);
settings.compiler.prepareBuildSettings(lbuildsettings, settings.platform, BuildSetting.commandLineSeparate|BuildSetting.sourceFiles);
- settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback);
+ settings.compiler.invokeLinker(lbuildsettings, settings.platform, objs, settings.linkCallback, settings.toolWorkingDirectory);
// 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)) {
@@ -553,7 +561,7 @@
settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine);
// invoke the compiler
- settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback);
+ settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback, settings.toolWorkingDirectory);
} else {
// determine path for the temporary object file
string tempobjname = buildsettings.targetName ~ getObjSuffix(settings.platform);
@@ -573,7 +581,7 @@
settings.compiler.prepareBuildSettings(buildsettings, settings.platform, BuildSetting.commandLine);
- settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback);
+ settings.compiler.invoke(buildsettings, settings.platform, settings.compileCallback, settings.toolWorkingDirectory);
if (generate_binary) {
if (settings.tempBuild) {
@@ -581,7 +589,7 @@
} else {
logInfo("Linking", Color.light_green, "%s", buildsettings.targetName.color(Mode.bold));
}
- settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback);
+ settings.compiler.invokeLinker(lbuildsettings, settings.platform, [tempobj.toNativeString()], settings.linkCallback, settings.toolWorkingDirectory);
}
}
}
@@ -589,7 +597,7 @@
private void runTarget(NativePath exe_file_path, in BuildSettings buildsettings, string[] run_args, GeneratorSettings settings)
{
if (buildsettings.targetType == TargetType.executable) {
- auto cwd = NativePath(getcwd());
+ auto cwd = settings.toolWorkingDirectory;
auto runcwd = cwd;
if (buildsettings.workingDirectory.length) {
runcwd = NativePath(buildsettings.workingDirectory);
@@ -735,10 +743,10 @@
auto prj = new Project(pman, pack);
final static class TestCompiler : GDCCompiler {
- override void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) {
+ override void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd) {
assert(!settings.dflags[].any!(f => f.canFind("bar")));
}
- override void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) {
+ override void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd) {
assert(false);
}
}
diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d
index 4c0f994..6aff2d6 100644
--- a/source/dub/generators/generator.d
+++ b/source/dub/generators/generator.d
@@ -806,6 +806,7 @@
BuildSettings buildSettings;
BuildMode buildMode = BuildMode.separate;
int targetExitStatus;
+ NativePath overrideToolWorkingDirectory;
bool combined; // compile all in one go instead of each dependency separately
bool filterVersions;
@@ -820,6 +821,16 @@
void delegate(int status, string output) compileCallback;
void delegate(int status, string output) linkCallback;
void delegate(int status, string output) runCallback;
+
+ /// Returns `overrideToolWorkingDirectory` or if that's not set, just the
+ /// current working directory of the application. This may differ if dub is
+ /// called with the `--root` parameter or when using DUB as a library.
+ NativePath toolWorkingDirectory() const
+ {
+ return overrideToolWorkingDirectory is NativePath.init
+ ? getWorkingDirectory()
+ : overrideToolWorkingDirectory;
+ }
}
@@ -1166,10 +1177,10 @@
auto prj = new Project(pman, pack);
final static class TestCompiler : GDCCompiler {
- override void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) {
+ override void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback, NativePath cwd) {
assert(false);
}
- override void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback) {
+ override void invokeLinker(in BuildSettings settings, in BuildPlatform platform, string[] objects, void delegate(int, string) output_callback, NativePath cwd) {
assert(false);
}
}
diff --git a/source/dub/generators/sublimetext.d b/source/dub/generators/sublimetext.d
index d46fbd9..f1d3689 100644
--- a/source/dub/generators/sublimetext.d
+++ b/source/dub/generators/sublimetext.d
@@ -34,7 +34,7 @@
auto root = Json([
"folders": targets.byValue.map!(f => targetFolderJson(f)).array.Json,
- "build_systems": buildSystems(settings.platform),
+ "build_systems": buildSystems(settings.platform, settings.toolWorkingDirectory.toNativeString()),
"settings": [ "include_paths": buildSettings.importPaths.map!Json.array.Json ].Json,
]);
@@ -61,7 +61,7 @@
}
-private Json buildSystems(BuildPlatform buildPlatform, string workingDiretory = getcwd())
+private Json buildSystems(BuildPlatform buildPlatform, string workingDiretory)
{
static immutable BUILD_TYPES = [
//"plain",
@@ -123,5 +123,5 @@
auto buildPlatform = BuildPlatform();
buildPlatform.architecture ~= "x86_64";
- auto result = buildPlatform.buildSystems.toString;
+ auto result = buildPlatform.buildSystems(getcwd()).toString;
}
diff --git a/source/dub/generators/visuald.d b/source/dub/generators/visuald.d
index 9b86ef9..a5feb5f 100644
--- a/source/dub/generators/visuald.d
+++ b/source/dub/generators/visuald.d
@@ -183,7 +183,7 @@
auto sp = NativePath(s);
assert(sp.absolute, format("Source path in %s expected to be absolute: %s", packname, s));
//if( !sp.absolute ) sp = pack.path ~ sp;
- addSourceFile(sp.relativeTo(getWorkingDirectory() ~ basepath), determineStructurePath(sp, targets[packname]), action);
+ addSourceFile(sp.relativeTo(settings.toolWorkingDirectory ~ basepath), determineStructurePath(sp, targets[packname]), action);
}
foreach (p; targets[packname].packages)
@@ -245,6 +245,7 @@
void generateProjectConfiguration(Appender!(char[]) ret, string pack, string type, GeneratorSettings settings, in TargetInfo[string] targets)
{
+ auto cwd = settings.toolWorkingDirectory;
auto buildsettings = targets[pack].buildSettings.dup;
auto basepath = NativePath(".dub/");
@@ -255,7 +256,7 @@
auto ret = new string[settings.length];
foreach (i; 0 .. settings.length) {
// \" is interpreted as an escaped " by cmd.exe, so we need to avoid that
- auto p = NativePath(settings[i]).relativeTo(getWorkingDirectory() ~ basepath);
+ auto p = NativePath(settings[i]).relativeTo(cwd ~ basepath);
p.endsWithSlash = false;
ret[i] = '"' ~ p.toNativeString() ~ '"';
}
@@ -328,7 +329,7 @@
// compute directory for intermediate files (need dummy/ because of how -op determines the resulting path)
size_t ndummy = 0;
foreach (f; buildsettings.sourceFiles) {
- auto rpath = NativePath(f).relativeTo(getWorkingDirectory() ~ basepath);
+ auto rpath = NativePath(f).relativeTo(cwd ~ basepath);
size_t nd = 0;
foreach (s; rpath.bySegment)
if (s == "..")
@@ -423,7 +424,7 @@
auto wdir = NativePath(buildsettings.workingDirectory);
if (!wdir.absolute) wdir = m_project.rootPackage.path ~ wdir;
ret.formattedWrite(" %s\n",
- wdir.relativeTo(getWorkingDirectory() ~ basepath).toNativeString());
+ wdir.relativeTo(cwd ~ basepath).toNativeString());
ret.put(" \n");
ret.put(" \n");
ret.put(" *.obj;*.cmd;*.build;*.dep\n");
diff --git a/source/dub/init.d b/source/dub/init.d
index 5cf47f8..2e835a6 100644
--- a/source/dub/init.d
+++ b/source/dub/init.d
@@ -16,7 +16,7 @@
import std.exception;
import std.file;
import std.format;
-import std.process;
+import std.process : environment;
import std.string;
diff --git a/source/dub/internal/temp_files.d b/source/dub/internal/temp_files.d
new file mode 100644
index 0000000..ddfaf34
--- /dev/null
+++ b/source/dub/internal/temp_files.d
@@ -0,0 +1,45 @@
+/**
+ Provides methods to generate temporary file names and folders and
+ automatically clean them up on program exit.
+
+ Copyright: © 2012 Matthias Dondorff, © 2012-2023 Sönke Ludwig
+ License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
+ Authors: Matthias Dondorff, Sönke Ludwig, Jan Jurzitza
+*/
+module dub.internal.temp_files;
+
+import std.file;
+
+import dub.internal.vibecompat.core.file;
+
+NativePath getTempDir()
+{
+ return NativePath(std.file.tempDir());
+}
+
+NativePath getTempFile(string prefix, string extension = null)
+{
+ import std.uuid : randomUUID;
+ import std.array: replace;
+
+ string fileName = prefix ~ "-" ~ randomUUID.toString() ~ extension;
+
+ if (extension !is null && extension == ".d")
+ fileName = fileName.replace("-", "_");
+
+ auto path = getTempDir() ~ fileName;
+ temporary_files ~= path;
+ return path;
+}
+
+private NativePath[] temporary_files;
+
+static ~this()
+{
+ foreach (path; temporary_files)
+ {
+ auto spath = path.toNativeString();
+ if (spath.exists)
+ std.file.remove(spath);
+ }
+}
diff --git a/source/dub/internal/utils.d b/source/dub/internal/utils.d
index 538f034..5b68728 100644
--- a/source/dub/internal/utils.d
+++ b/source/dub/internal/utils.d
@@ -30,28 +30,7 @@
public import std.net.curl : HTTPStatusException;
}
-
-private NativePath[] temporary_files;
-
-NativePath getTempDir()
-{
- return NativePath(std.file.tempDir());
-}
-
-NativePath getTempFile(string prefix, string extension = null)
-{
- import std.uuid : randomUUID;
- import std.array: replace;
-
- string fileName = prefix ~ "-" ~ randomUUID.toString() ~ extension;
-
- if (extension !is null && extension == ".d")
- fileName = fileName.replace("-", "_");
-
- auto path = getTempDir() ~ fileName;
- temporary_files ~= path;
- return path;
-}
+public import dub.internal.temp_files;
/**
* Obtain a lock for a file at the given path.
@@ -99,16 +78,6 @@
}
}
-static ~this()
-{
- foreach (path; temporary_files)
- {
- auto spath = path.toNativeString();
- if (spath.exists)
- std.file.remove(spath);
- }
-}
-
bool isWritableDir(NativePath p, bool create_if_missing = false)
{
import std.random;
@@ -176,12 +145,24 @@
moveFile(tmppath, path);
}
-void runCommand(string command, string[string] env = null, string workDir = null)
+deprecated("specify a working directory explicitly")
+void runCommand(string command, string[string] env = null)
+{
+ runCommands((&command)[0 .. 1], env, null);
+}
+
+void runCommand(string command, string[string] env, string workDir)
{
runCommands((&command)[0 .. 1], env, workDir);
}
-void runCommands(in string[] commands, string[string] env = null, string workDir = null)
+deprecated("specify a working directory explicitly")
+void runCommands(in string[] commands, string[string] env = null)
+{
+ runCommands(commands, env, null);
+}
+
+void runCommands(in string[] commands, string[string] env, string workDir)
{
import std.stdio : stdin, stdout, stderr, File;
diff --git a/source/dub/package_.d b/source/dub/package_.d
index 48a755d..c77e872 100644
--- a/source/dub/package_.d
+++ b/source/dub/package_.d
@@ -418,7 +418,7 @@
*/
void addBuildTypeSettings(ref BuildSettings settings, in BuildPlatform platform, string build_type)
const {
- import std.process;
+ import std.process : environment;
string dflags = environment.get("DFLAGS", "");
settings.addDFlags(dflags.split());
diff --git a/source/dub/project.d b/source/dub/project.d
index 3fb66a2..f473839 100644
--- a/source/dub/project.d
+++ b/source/dub/project.d
@@ -1405,10 +1405,21 @@
}
if (i == res.length) //no globbing found in the path
return [res];
- import std.path : globMatch;
import std.file : dirEntries, SpanMode;
- return dirEntries(res[0 .. sepIdx], SpanMode.depth)
- .map!(de => de.name)
+ import std.path : buildNormalizedPath, globMatch, isAbsolute, relativePath;
+ auto cwd = gsettings.toolWorkingDirectory.toNativeString;
+ auto path = res[0 .. sepIdx];
+ bool prependCwd = false;
+ if (!isAbsolute(path))
+ {
+ prependCwd = true;
+ path = buildNormalizedPath(cwd, path);
+ }
+
+ return dirEntries(path, SpanMode.depth)
+ .map!(de => prependCwd
+ ? de.name.relativePath(cwd)
+ : de.name)
.filter!(name => globMatch(name, res))
.array;
}
diff --git a/source/dub/version_.d b/source/dub/version_.d
index efd57b2..4d34bc2 100644
--- a/source/dub/version_.d
+++ b/source/dub/version_.d
@@ -1,2 +1,2 @@
module dub.version_;
-enum dubVersion = "v1.31.0-rc.1";
+enum dubVersion = "v1.31.0";
diff --git a/test/dub-as-a-library-cwd.sh b/test/dub-as-a-library-cwd.sh
new file mode 100755
index 0000000..e0faea2
--- /dev/null
+++ b/test/dub-as-a-library-cwd.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+. $(dirname "${BASH_SOURCE[0]}")/common.sh
+$DUB --root="$CURR_DIR/dub-as-a-library-cwd"
diff --git a/test/dub-as-a-library-cwd/.gitignore b/test/dub-as-a-library-cwd/.gitignore
new file mode 100644
index 0000000..9a2c0e8
--- /dev/null
+++ b/test/dub-as-a-library-cwd/.gitignore
@@ -0,0 +1 @@
+/dub-as-a-library-cwd
diff --git a/test/dub-as-a-library-cwd/.no_test b/test/dub-as-a-library-cwd/.no_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/dub-as-a-library-cwd/.no_test
diff --git a/test/dub-as-a-library-cwd/dub.json b/test/dub-as-a-library-cwd/dub.json
new file mode 100644
index 0000000..15adddf
--- /dev/null
+++ b/test/dub-as-a-library-cwd/dub.json
@@ -0,0 +1,8 @@
+{
+ "name": "dub-as-a-library-cwd",
+ "dependencies": {
+ "dub": {
+ "path": "../.."
+ }
+ }
+}
diff --git a/test/dub-as-a-library-cwd/source/app.d b/test/dub-as-a-library-cwd/source/app.d
new file mode 100644
index 0000000..446c361
--- /dev/null
+++ b/test/dub-as-a-library-cwd/source/app.d
@@ -0,0 +1,45 @@
+import dub.compilers.buildsettings;
+import dub.compilers.compiler;
+import dub.dub;
+import dub.generators.generator;
+import dub.internal.vibecompat.inet.path;
+import std.algorithm;
+import std.file;
+import std.path;
+import std.stdio;
+
+void main(string[] args)
+{
+ auto project = buildNormalizedPath(getcwd, "subproject");
+ chdir(buildNormalizedPath(getcwd, ".."));
+
+ bool found;
+
+ auto dub = new Dub(project, null, SkipPackageSuppliers.none);
+ dub.packageManager.getOrLoadPackage(NativePath(project));
+ dub.loadPackage();
+ dub.project.validate();
+
+ GeneratorSettings gs;
+ gs.buildType = "debug";
+ gs.config = "application";
+ gs.compiler = getCompiler(dub.defaultCompiler);
+ gs.run = false;
+ gs.force = true;
+ gs.tempBuild = true;
+ gs.platform = gs.compiler.determinePlatform(gs.buildSettings,
+ dub.defaultCompiler, dub.defaultArchitecture);
+
+ gs.compileCallback = (status, output) {
+ found = output.canFind("FIND_THIS_STRING");
+ if (!found)
+ stderr.writeln("Did not find required string!\nExit status:",
+ status, "\n\nOutput:\n", output);
+ };
+
+ stderr.writeln("Checking if building works from a library in a different cwd:");
+ dub.generateProject("build", gs);
+ stderr.writeln("Success: ", found);
+
+ assert(found);
+}
diff --git a/test/dub-as-a-library-cwd/subproject/dub.sdl b/test/dub-as-a-library-cwd/subproject/dub.sdl
new file mode 100644
index 0000000..cb896c9
--- /dev/null
+++ b/test/dub-as-a-library-cwd/subproject/dub.sdl
@@ -0,0 +1 @@
+name "subproject"
diff --git a/test/dub-as-a-library-cwd/subproject/source/app.d b/test/dub-as-a-library-cwd/subproject/source/app.d
new file mode 100644
index 0000000..a891a6f
--- /dev/null
+++ b/test/dub-as-a-library-cwd/subproject/source/app.d
@@ -0,0 +1,11 @@
+module app;
+
+deprecated("FIND_THIS_STRING")
+void foo()
+{
+}
+
+void main(string[] args)
+{
+ foo();
+}