diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 7cab029..d0e6151 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -386,15 +386,16 @@ import dub.internal.vibecompat.data.json; import dub.internal.utils; - auto path = getTempDir() ~ "dub_platform_probe.d"; + auto path = getTempFile("dub_platform_probe", ".d"); auto fil = openFile(path, FileMode.CreateTrunc); scope (failure) { fil.close(); - removeFile(path); } fil.write(q{ + module dub_platform_probe; + template toString(int v) { enum toString = v.stringof; } pragma(msg, `{`); diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 9f5e65d..810c06b 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -178,9 +178,8 @@ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { - auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + auto res_file = getTempFile("dub-build", ".rsp"); std.file.write(res_file.toNativeString(), join(settings.dflags.map!(s => s.canFind(' ') ? "\""~s~"\"" : s), "\n")); - scope (exit) remove(res_file.toNativeString()); logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index e31053f..90bdcea 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -67,7 +67,12 @@ } settings.addDFlags(arch_flags); - auto result = executeShell(escapeShellCommand(compiler_binary ~ arch_flags ~ ["-c", "-o", (getTempDir()~"dub_platform_probe").toNativeString(), fil.toNativeString()])); + auto binary_file = getTempFile("dub_platform_probe"); + auto result = executeShell(escapeShellCommand( + compiler_binary ~ + arch_flags ~ + ["-c", "-o", binary_file.toNativeString(), fil.toNativeString()] + )); enforce(result.status == 0, format("Failed to invoke the compiler %s to determine the build platform: %s", compiler_binary, result.output)); @@ -176,9 +181,8 @@ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { - auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + auto res_file = getTempFile("dub-build", ".rsp"); std.file.write(res_file.toNativeString(), join(settings.dflags.map!(s => escape(s)), "\n")); - scope (exit) remove(res_file.toNativeString()); logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index f75caa8..fb214dd 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -166,9 +166,8 @@ void invoke(in BuildSettings settings, in BuildPlatform platform, void delegate(int, string) output_callback) { - auto res_file = getTempDir() ~ ("dub-build-"~uniform(0, uint.max).to!string~"-.rsp"); + auto res_file = getTempFile("dub-build", ".rsp"); std.file.write(res_file.toNativeString(), join(cast(string[])settings.dflags, "\n")); - scope (exit) remove(res_file.toNativeString()); logDiagnostic("%s %s", platform.compilerBinary, join(cast(string[])settings.dflags, " ")); invokeTool([platform.compilerBinary, "@"~res_file.toNativeString()], output_callback); diff --git a/source/dub/dub.d b/source/dub/dub.d index da578c2..6e504cc 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -362,7 +362,7 @@ } // generate main file - Path mainfile = getTempDir() ~ "dub_test_root.d"; + Path mainfile = getTempFile("dub_test_root", ".d"); tcinfo.sourceFiles[""] ~= mainfile.toNativeString(); tcinfo.mainSourceFile = mainfile.toNativeString(); if (!m_dryRun) { diff --git a/source/dub/internal/utils.d b/source/dub/internal/utils.d index c1ba34e..754c1c4 100644 --- a/source/dub/internal/utils.d +++ b/source/dub/internal/utils.d @@ -28,7 +28,70 @@ Path getTempDir() { - return std.file.tempDir; + return Path(std.file.tempDir()); +} + +private Path[] temporary_files; + +version (Posix) + private extern(C) int mkstemps(char *, int); +else + private extern(Windows) uint GetTempFileName( + const(char)* lpPathName, + const(char)* lpPrefixString, + uint uUnique, + char* lpTempFileName + ); + +Path getTempFile(string prefix, string extension = null) +{ + version (Posix) + { + auto name = (getTempDir() ~ prefix).toString(); + + // build 0-terminated template for mkstemp + auto suffix = "-XXXXXX" ~ extension; + auto pattern = new char[](name.length + suffix.length + 1); + pattern[0..name.length] = name[]; + pattern[name.length .. $-1] = suffix[]; + pattern[$-1] = '\0'; + + auto handle = mkstemps(pattern.ptr, to!int(extension.length)); + enforce(handle > 0); + + pattern = pattern[0..$-1]; // get rid of \0 + auto path = Path(assumeUnique(pattern)); + temporary_files ~= path; + return path; + } + else version (Windows) + { + import core.sys.windows.windows : MAX_PATH; + import std.string : toStringz, fromStringz; + + auto dir = getTempDir().toStringz(); + auto name = prefix.toStringz(); + char[MAX_PATH] output = void; + + auto status = GetTempFileName(dir, name, 0, output.ptr); + enforce(status != 0); + + auto path = Path(output.fromStringz() ~ extension); + temporary_files ~= path; + return path; + } + else + { + static assert (false, "please report the problem to https://github.com/D-Programming-Language/dub"); + } +} + +static ~this() +{ + foreach (path; temporary_files) + { + std.file.remove(path.toNativeString()); + } } bool isEmptyDir(Path p) {