diff options
Diffstat (limited to 'clang/lib/Driver/Tools.cpp')
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 83 |
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); } |