[pkg-d-commits] [ldc] 49/95: Move MSVC environment setup to driver/tool.cpp [NFC]
Matthias Klumpp
mak at moszumanska.debian.org
Thu Jul 13 20:53:59 UTC 2017
This is an automated email from the git hooks/post-receive script.
mak pushed a commit to annotated tag v1.3.0-beta1
in repository ldc.
commit 0842277572865d8274cd71a43df144f1870a0dc0
Author: Martin <noone at nowhere.com>
Date: Mon Mar 13 23:03:33 2017 +0100
Move MSVC environment setup to driver/tool.cpp [NFC]
---
driver/linker.cpp | 205 -----------------------------------------------------
driver/tool.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
driver/tool.h | 15 +++-
3 files changed, 218 insertions(+), 208 deletions(-)
diff --git a/driver/linker.cpp b/driver/linker.cpp
index 5d0673b..f9d6db0 100644
--- a/driver/linker.cpp
+++ b/driver/linker.cpp
@@ -25,16 +25,10 @@
#include "llvm/Linker/Linker.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Program.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
-#if _WIN32
-#include "llvm/Support/SystemUtils.h"
-#include "llvm/Support/ConvertUTF.h"
-#include <Windows.h>
-#endif
#include <algorithm>
@@ -498,205 +492,6 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
//////////////////////////////////////////////////////////////////////////////
-#ifdef _WIN32
-
-namespace windows {
-
-bool needsQuotes(const llvm::StringRef &arg) {
- return // not already quoted
- !(arg.size() > 1 && arg[0] == '"' &&
- arg.back() == '"') && // empty or min 1 space or min 1 double quote
- (arg.empty() || arg.find(' ') != arg.npos || arg.find('"') != arg.npos);
-}
-
-size_t countPrecedingBackslashes(llvm::StringRef arg, size_t index) {
- size_t count = 0;
-
- for (size_t i = index - 1; i >= 0; --i) {
- if (arg[i] != '\\')
- break;
- ++count;
- }
-
- return count;
-}
-
-std::string quoteArg(llvm::StringRef arg) {
- if (!needsQuotes(arg))
- return arg;
-
- std::string quotedArg;
- quotedArg.reserve(3 + 2 * arg.size()); // worst case
-
- quotedArg.push_back('"');
-
- const size_t argLength = arg.size();
- for (size_t i = 0; i < argLength; ++i) {
- if (arg[i] == '"') {
- // Escape all preceding backslashes (if any).
- // Note that we *don't* need to escape runs of backslashes that don't
- // precede a double quote! See MSDN:
- // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
- quotedArg.append(countPrecedingBackslashes(arg, i), '\\');
-
- // Escape the double quote.
- quotedArg.push_back('\\');
- }
-
- quotedArg.push_back(arg[i]);
- }
-
- // Make sure our final double quote doesn't get escaped by a trailing
- // backslash.
- quotedArg.append(countPrecedingBackslashes(arg, argLength), '\\');
- quotedArg.push_back('"');
-
- return quotedArg;
-}
-
-int executeAndWait(const char *commandLine) {
- STARTUPINFO si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
-
- PROCESS_INFORMATION pi;
- ZeroMemory(&pi, sizeof(pi));
-
- DWORD exitCode;
-
-#if UNICODE
- std::wstring wcommandLine;
- if (!llvm::ConvertUTF8toWide(commandLine, wcommandLine))
- return -3;
- auto cmdline = const_cast<wchar_t *>(wcommandLine.data());
-#else
- auto cmdline = const_cast<char *>(commandLine);
-#endif
- // according to MSDN, only CreateProcessW (unicode) may modify the passed
- // command line
- if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0,
- NULL, NULL, &si, &pi)) {
- exitCode = -1;
- } else {
- if (WaitForSingleObject(pi.hProcess, INFINITE) != 0 ||
- !GetExitCodeProcess(pi.hProcess, &exitCode))
- exitCode = -2;
-
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- }
-
- return exitCode;
-}
-
-bool setupMsvcEnvironment() {
- if (getenv("VSINSTALLDIR"))
- return true;
-
- llvm::SmallString<128> tmpFilePath;
- if (llvm::sys::fs::createTemporaryFile("ldc_dumpEnv", "", tmpFilePath))
- return false;
-
- /* Run `%ComSpec% /s /c "...\dumpEnv.bat <x86|amd64> > <tmpFilePath>"` to dump
- * the MSVC environment to the temporary file.
- *
- * cmd.exe /c treats the following string argument (the command)
- * in a very peculiar way if it starts with a double-quote.
- * By adding /s and enclosing the command in extra double-quotes
- * (WITHOUT additionally escaping the command), the command will
- * be parsed properly.
- */
-
- auto comspecEnv = getenv("ComSpec");
- if (!comspecEnv) {
- warning(Loc(),
- "'ComSpec' environment variable is not set, assuming 'cmd.exe'.");
- comspecEnv = "cmd.exe";
- }
- std::string cmdExecutable = comspecEnv;
- std::string batchFile = exe_path::prependBinDir("dumpEnv.bat");
- std::string arch =
- global.params.targetTriple->isArch64Bit() ? "amd64" : "x86";
-
- llvm::SmallString<512> commandLine;
- commandLine += quoteArg(cmdExecutable);
- commandLine += " /s /c \"";
- commandLine += quoteArg(batchFile);
- commandLine += ' ';
- commandLine += arch;
- commandLine += " > ";
- commandLine += quoteArg(tmpFilePath);
- commandLine += '"';
-
- const int exitCode = executeAndWait(commandLine.c_str());
- if (exitCode != 0) {
- error(Loc(), "`%s` failed with status: %d", commandLine.c_str(), exitCode);
- llvm::sys::fs::remove(tmpFilePath);
- return false;
- }
-
- auto fileBuffer = llvm::MemoryBuffer::getFile(tmpFilePath);
- llvm::sys::fs::remove(tmpFilePath);
- if (fileBuffer.getError())
- return false;
-
- const auto contents = (*fileBuffer)->getBuffer();
- const auto size = contents.size();
-
- // Parse the file.
- std::vector<std::pair<llvm::StringRef, llvm::StringRef>> env;
-
- size_t i = 0;
- // for each line
- while (i < size) {
- llvm::StringRef key, value;
-
- for (size_t j = i; j < size; ++j) {
- const char c = contents[j];
- if (c == '=' && key.empty()) {
- key = contents.slice(i, j);
- i = j + 1;
- } else if (c == '\n' || c == '\r' || c == '\0') {
- if (!key.empty()) {
- value = contents.slice(i, j);
- }
- // break and continue with next line
- i = j + 1;
- break;
- }
- }
-
- if (!key.empty() && !value.empty())
- env.emplace_back(key, value);
- }
-
- if (global.params.verbose)
- fprintf(global.stdmsg, "Applying environment variables:\n");
-
- bool haveVsInstallDir = false;
-
- for (const auto &pair : env) {
- const std::string key = pair.first.str();
- const std::string value = pair.second.str();
-
- if (global.params.verbose)
- fprintf(global.stdmsg, " %s=%s\n", key.c_str(), value.c_str());
-
- SetEnvironmentVariableA(key.c_str(), value.c_str());
-
- if (key == "VSINSTALLDIR")
- haveVsInstallDir = true;
- }
-
- return haveVsInstallDir;
-}
-
-} // namespace windows
-
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-
static int linkObjToBinaryMSVC(bool sharedLib) {
Logger::println("*** Linking executable ***");
diff --git a/driver/tool.cpp b/driver/tool.cpp
index 2f33084..c409210 100644
--- a/driver/tool.cpp
+++ b/driver/tool.cpp
@@ -9,7 +9,14 @@
#include "driver/tool.h"
#include "mars.h"
+#include "driver/exe_path.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
+#ifdef _WIN32
+#include <Windows.h>
+#endif
int executeToolAndWait(const std::string &tool_,
std::vector<std::string> const &args, bool verbose) {
@@ -53,3 +60,202 @@ int executeToolAndWait(const std::string &tool_,
}
return 0;
}
+
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef _WIN32
+
+namespace windows {
+
+bool needsQuotes(const llvm::StringRef &arg) {
+ return // not already quoted
+ !(arg.size() > 1 && arg[0] == '"' &&
+ arg.back() == '"') && // empty or min 1 space or min 1 double quote
+ (arg.empty() || arg.find(' ') != arg.npos || arg.find('"') != arg.npos);
+}
+
+size_t countPrecedingBackslashes(llvm::StringRef arg, size_t index) {
+ size_t count = 0;
+
+ for (size_t i = index - 1; i >= 0; --i) {
+ if (arg[i] != '\\')
+ break;
+ ++count;
+ }
+
+ return count;
+}
+
+std::string quoteArg(llvm::StringRef arg) {
+ if (!needsQuotes(arg))
+ return arg;
+
+ std::string quotedArg;
+ quotedArg.reserve(3 + 2 * arg.size()); // worst case
+
+ quotedArg.push_back('"');
+
+ const size_t argLength = arg.size();
+ for (size_t i = 0; i < argLength; ++i) {
+ if (arg[i] == '"') {
+ // Escape all preceding backslashes (if any).
+ // Note that we *don't* need to escape runs of backslashes that don't
+ // precede a double quote! See MSDN:
+ // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
+ quotedArg.append(countPrecedingBackslashes(arg, i), '\\');
+
+ // Escape the double quote.
+ quotedArg.push_back('\\');
+ }
+
+ quotedArg.push_back(arg[i]);
+ }
+
+ // Make sure our final double quote doesn't get escaped by a trailing
+ // backslash.
+ quotedArg.append(countPrecedingBackslashes(arg, argLength), '\\');
+ quotedArg.push_back('"');
+
+ return quotedArg;
+}
+
+int executeAndWait(const char *commandLine) {
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+
+ PROCESS_INFORMATION pi;
+ ZeroMemory(&pi, sizeof(pi));
+
+ DWORD exitCode;
+
+#if UNICODE
+ std::wstring wcommandLine;
+ if (!llvm::ConvertUTF8toWide(commandLine, wcommandLine))
+ return -3;
+ auto cmdline = const_cast<wchar_t *>(wcommandLine.data());
+#else
+ auto cmdline = const_cast<char *>(commandLine);
+#endif
+ // according to MSDN, only CreateProcessW (unicode) may modify the passed
+ // command line
+ if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0,
+ NULL, NULL, &si, &pi)) {
+ exitCode = -1;
+ } else {
+ if (WaitForSingleObject(pi.hProcess, INFINITE) != 0 ||
+ !GetExitCodeProcess(pi.hProcess, &exitCode))
+ exitCode = -2;
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ }
+
+ return exitCode;
+}
+
+bool setupMsvcEnvironment() {
+ if (getenv("VSINSTALLDIR"))
+ return true;
+
+ llvm::SmallString<128> tmpFilePath;
+ if (llvm::sys::fs::createTemporaryFile("ldc_dumpEnv", "", tmpFilePath))
+ return false;
+
+ /* Run `%ComSpec% /s /c "...\dumpEnv.bat <x86|amd64> > <tmpFilePath>"` to dump
+ * the MSVC environment to the temporary file.
+ *
+ * cmd.exe /c treats the following string argument (the command)
+ * in a very peculiar way if it starts with a double-quote.
+ * By adding /s and enclosing the command in extra double-quotes
+ * (WITHOUT additionally escaping the command), the command will
+ * be parsed properly.
+ */
+
+ auto comspecEnv = getenv("ComSpec");
+ if (!comspecEnv) {
+ warning(Loc(),
+ "'ComSpec' environment variable is not set, assuming 'cmd.exe'.");
+ comspecEnv = "cmd.exe";
+ }
+ std::string cmdExecutable = comspecEnv;
+ std::string batchFile = exe_path::prependBinDir("dumpEnv.bat");
+ std::string arch =
+ global.params.targetTriple->isArch64Bit() ? "amd64" : "x86";
+
+ llvm::SmallString<512> commandLine;
+ commandLine += quoteArg(cmdExecutable);
+ commandLine += " /s /c \"";
+ commandLine += quoteArg(batchFile);
+ commandLine += ' ';
+ commandLine += arch;
+ commandLine += " > ";
+ commandLine += quoteArg(tmpFilePath);
+ commandLine += '"';
+
+ const int exitCode = executeAndWait(commandLine.c_str());
+ if (exitCode != 0) {
+ error(Loc(), "`%s` failed with status: %d", commandLine.c_str(), exitCode);
+ llvm::sys::fs::remove(tmpFilePath);
+ return false;
+ }
+
+ auto fileBuffer = llvm::MemoryBuffer::getFile(tmpFilePath);
+ llvm::sys::fs::remove(tmpFilePath);
+ if (fileBuffer.getError())
+ return false;
+
+ const auto contents = (*fileBuffer)->getBuffer();
+ const auto size = contents.size();
+
+ // Parse the file.
+ std::vector<std::pair<llvm::StringRef, llvm::StringRef>> env;
+
+ size_t i = 0;
+ // for each line
+ while (i < size) {
+ llvm::StringRef key, value;
+
+ for (size_t j = i; j < size; ++j) {
+ const char c = contents[j];
+ if (c == '=' && key.empty()) {
+ key = contents.slice(i, j);
+ i = j + 1;
+ } else if (c == '\n' || c == '\r' || c == '\0') {
+ if (!key.empty()) {
+ value = contents.slice(i, j);
+ }
+ // break and continue with next line
+ i = j + 1;
+ break;
+ }
+ }
+
+ if (!key.empty() && !value.empty())
+ env.emplace_back(key, value);
+ }
+
+ if (global.params.verbose)
+ fprintf(global.stdmsg, "Applying environment variables:\n");
+
+ bool haveVsInstallDir = false;
+
+ for (const auto &pair : env) {
+ const std::string key = pair.first.str();
+ const std::string value = pair.second.str();
+
+ if (global.params.verbose)
+ fprintf(global.stdmsg, " %s=%s\n", key.c_str(), value.c_str());
+
+ SetEnvironmentVariableA(key.c_str(), value.c_str());
+
+ if (key == "VSINSTALLDIR")
+ haveVsInstallDir = true;
+ }
+
+ return haveVsInstallDir;
+}
+
+} // namespace windows
+
+#endif // _WIN32
diff --git a/driver/tool.h b/driver/tool.h
index d4dc5f8..c96f851 100644
--- a/driver/tool.h
+++ b/driver/tool.h
@@ -1,5 +1,4 @@
-//===-- driver/tool.h - External tool invocation helpers ---------*- C++
-//-*-===//
+//===-- driver/tool.h - External tool invocation helpers --------*- C++ -*-===//
//
// LDC – the LLVM D compiler
//
@@ -8,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Functionaliy for invoking external tools executables, such as the system
+// Functionality for invoking external tools executables, such as the system
// assembler, linker, ...
//
//===----------------------------------------------------------------------===//
@@ -23,4 +22,14 @@ int executeToolAndWait(const std::string &tool,
std::vector<std::string> const &args,
bool verbose = false);
+#ifdef _WIN32
+
+namespace windows {
+// Tries to set up the MSVC environment variables and returns true if
+// successful.
+bool setupMsvcEnvironment();
+}
+
+#endif
+
#endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git
More information about the pkg-d-commits
mailing list