aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/Tools.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2014-10-20 20:08:04 +0000
committerZachary Turner <zturner@google.com>2014-10-20 20:08:04 +0000
commit63350417e19b3f062a89f44214bc6a70613f7682 (patch)
tree04835d188af5672ff15e35cb0acedf31a814d1fe /clang/lib/Driver/Tools.cpp
parent65c275686955f19f411ceaab593b42ebdcd242f3 (diff)
downloadllvm-63350417e19b3f062a89f44214bc6a70613f7682.zip
llvm-63350417e19b3f062a89f44214bc6a70613f7682.tar.gz
llvm-63350417e19b3f062a89f44214bc6a70613f7682.tar.bz2
Improve Windows toolchain support for non-standard environments.
Typically clang finds Visual Studio by the user explicitly setting up a Visual Studio environment via vcvarsall. But we still try to behave intelligently and fallback to different methods of finding Visual Studio when this is not done. This patch improves various fallback codepaths to make Visual Studio locating more robust. Specifically, this patch: * Adds support for searching environment variables for VS 12.0 * Correctly locates include folders for Windows SDK 8.x (this was previously broken, and would cause clang to error) * Prefers locating link.exe in the same location as cl.exe. This is helpful in case another link.exe is in the path earlier than Visual Studio (e.g. GnuWin32) * Minor cleanup in the registry reading code to make it more robust in the presence of long pathnames. llvm-svn: 220226
Diffstat (limited to 'clang/lib/Driver/Tools.cpp')
-rw-r--r--clang/lib/Driver/Tools.cpp83
1 files changed, 51 insertions, 32 deletions
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 28cb4df..f5b6bd8 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -7806,6 +7806,50 @@ static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
}
+// Try to find Exe from a Visual Studio distribution. This first tries to find
+// an installed copy of Visual Studio and, failing that, looks in the PATH,
+// making sure that whatever executable that's found is not a same-named exe
+// from clang itself to prevent clang from falling back to itself.
+static std::string FindVisualStudioExecutable(const ToolChain &TC,
+ const char *Exe,
+ const char *ClangProgramPath) {
+ // Since a particular Visual Studio executable is tied to a set of system
+ // includes and libraries, first try to use the same location that we use for
+ // the include paths to ensure that a consistent build environment is located.
+ const toolchains::Windows &WTC = static_cast<const toolchains::Windows &>(TC);
+ std::string visualStudioDir;
+ if (WTC.getVisualStudioDir(visualStudioDir)) {
+ SmallString<128> VSDir(visualStudioDir);
+ llvm::sys::path::append(VSDir, "VC\\bin");
+ llvm::sys::path::append(VSDir, Exe);
+ if (llvm::sys::fs::can_execute(VSDir.c_str()))
+ return VSDir.str();
+ }
+
+ // If it could not be found, we're already probably broken, but try to
+ // fallback to PATH anyway.
+ llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
+ if (!OptPath.hasValue())
+ return Exe;
+
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ SmallVector<StringRef, 8> PathSegments;
+ llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
+
+ for (StringRef PathSegment : PathSegments) {
+ if (PathSegment.empty())
+ continue;
+
+ SmallString<128> FilePath(PathSegment);
+ llvm::sys::path::append(FilePath, Exe);
+ if (llvm::sys::fs::can_execute(FilePath.c_str()) &&
+ !llvm::sys::fs::equivalent(FilePath.c_str(), ClangProgramPath))
+ return FilePath.str();
+ }
+
+ return Exe;
+}
+
void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -7891,8 +7935,11 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
A.renderAsInput(Args, CmdArgs);
}
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
+ // It's not sufficient to just use link from the program PATH, because other
+ // environments like GnuWin32 install their own link.exe which may come first.
+ llvm::SmallString<128> linkPath(FindVisualStudioExecutable(
+ getToolChain(), "link.exe", C.getDriver().getClangProgramPath()));
+ const char *Exec = Args.MakeArgString(linkPath);
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
@@ -7904,35 +7951,6 @@ void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput));
}
-// Try to find FallbackName on PATH that is not identical to ClangProgramPath.
-// If one cannot be found, return FallbackName.
-// We do this special search to prevent clang-cl from falling back onto itself
-// if it's available as cl.exe on the path.
-static std::string FindFallback(const char *FallbackName,
- const char *ClangProgramPath) {
- llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH");
- if (!OptPath.hasValue())
- return FallbackName;
-
- const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
- SmallVector<StringRef, 8> PathSegments;
- llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr);
-
- for (size_t i = 0, e = PathSegments.size(); i != e; ++i) {
- StringRef PathSegment = PathSegments[i];
- if (PathSegment.empty())
- continue;
-
- SmallString<128> FilePath(PathSegment);
- llvm::sys::path::append(FilePath, FallbackName);
- if (llvm::sys::fs::can_execute(Twine(FilePath)) &&
- !llvm::sys::fs::equivalent(Twine(FilePath), ClangProgramPath))
- return FilePath.str();
- }
-
- return FallbackName;
-}
-
std::unique_ptr<Command> visualstudio::Compile::GetCommand(
Compilation &C, const JobAction &JA, const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
@@ -8014,7 +8032,8 @@ std::unique_ptr<Command> visualstudio::Compile::GetCommand(
CmdArgs.push_back(Fo);
const Driver &D = getToolChain().getDriver();
- std::string Exec = FindFallback("cl.exe", D.getClangProgramPath());
+ std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe",
+ D.getClangProgramPath());
return llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec),
CmdArgs);
}