From d6dc544140f4b089d59710bb9aaa7f674e623b37 Mon Sep 17 00:00:00 2001 From: Sebastian Wilzbach Date: Mon, 25 Dec 2017 23:29:59 +0100 Subject: [PATCH] Avoid creation of a temporary probe file for newer compilers --- source/dub/compilers/compiler.d | 48 ++++++++++++++++++++++++++++----- source/dub/compilers/utils.d | 22 ++++++++++----- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 2670bcf317..061de5d18a 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -115,19 +115,53 @@ interface Compiler { enforce(status == 0, format("%s failed with exit code %s.", args[0], status)); } + /** Detect the frontend version of a compiler_binary + Returns: 0 if the detection failed, otherwise the frontend version. + Note: This only works for DMD and LDC. + */ + private int frontendVersion(string compiler_binary) + { + import std.range : dropOne; + + auto res = execute([compiler_binary, "--version"]); + if (res.status == 0) { + auto versionRange = res.output.find("DMD64 D Compiler v").splitter("."); + if (!versionRange.empty && !versionRange.dropOne.empty) { + return versionRange.dropOne.front.to!int; + } + } + return 0; + } + + // DMD 2.076.0 and newer support passing files via stdin + private bool canUseStdin(string compiler_binary) + { + return frontendVersion(compiler_binary) >= 76 && compiler_binary.startsWith("dmd"); + } + /// Compiles platform probe file with the specified compiler and parses its output. protected final BuildPlatform probePlatform(string compiler_binary, string[] args, string arch_override) { import std.string : format; - import dub.compilers.utils : generatePlatformProbeFile, readPlatformProbe; + import dub.compilers.utils : generatePlatformProbeFile, readPlatformProbe, platformProbeFile; - auto fil = generatePlatformProbeFile(); + bool canUseStdin = this.canUseStdin(compiler_binary); + string fil = canUseStdin ? generatePlatformProbeFile().toNativeString() : "-"; - auto result = executeShell(escapeShellCommand(compiler_binary ~ args ~ fil.toNativeString())); - enforce(result.status == 0, format("Failed to invoke the compiler %s to determine the build platform: %s", - compiler_binary, result.output)); - - auto build_platform = readPlatformProbe(result.output); + auto p = pipeShell(escapeShellCommand(compiler_binary ~ args ~ fil), Redirect.all); + if (canUseStdin) { + p.stdin.write(platformProbeFile); + p.stdin.close; + } + // read stdout + string output; + auto app = appender!(ubyte[]); + p.stderr.byChunk(4096).each!(a => app.put(a)); + output = cast(string) app.data; + enforce(p.pid.wait== 0, format("Failed to invoke the compiler %s to determine the build platform: %s", + compiler_binary, output)); + + auto build_platform = readPlatformProbe(output); build_platform.compilerBinary = compiler_binary; if (build_platform.compiler != this.name) { diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 81983ee4f5..0062cf1f59 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -255,7 +255,21 @@ NativePath generatePlatformProbeFile() fil.close(); } - fil.write(q{ + fil.write(platformProbeFile); + fil.close(); + + return path; +} + + +/** + Platform probe file that will give, at compile time, information about the compiler (architecture, frontend version...) + + See_Also: `generatePlatformProbeFile`, `readPlatformProbe` +*/ +string platformProbeFile() +{ + return q{ module dub_platform_probe; import std.array; @@ -279,11 +293,7 @@ NativePath generatePlatformProbeFile() string determineArchitecture() } ~ '{' ~ archCheck ~ ` return '"' ~ ret.data.join("\", \"") ~ "\", "; }` ~ q{ - string determineCompiler() } ~ '{' ~ compilerCheck ~ " }"); - - fil.close(); - - return path; + string determineCompiler() } ~ '{' ~ compilerCheck ~ " }"; } /**