From: Hans Wennborg Date: Fri, 20 Sep 2013 18:16:35 +0000 (+0000) Subject: clang-cl: implement custom search for cl.exe in /fallback mode X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc40bf9ed03b5cca61d7de9fd0cc925a11935eb0;p=clang clang-cl: implement custom search for cl.exe in /fallback mode This solves the problem of fallback onto ourselves if clang-cl has been renamed to cl.exe and put on the PATH, as happens with the VS integration. Differential Revision: http://llvm-reviews.chandlerc.com/D1731 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191099 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index c2ba2e93af..4302f1a9cd 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -22,6 +22,7 @@ #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Arg.h" @@ -31,6 +32,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" @@ -6641,6 +6643,40 @@ 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 OptPath = llvm::sys::Process::GetEnv("PATH"); + if (!OptPath.hasValue()) + return FallbackName; + +#ifdef LLVM_ON_WIN32 + const StringRef PathSeparators = ";"; +#else + const StringRef PathSeparators = ":"; +#endif + + SmallVector PathSegments; + llvm::SplitString(OptPath.getValue(), PathSegments, PathSeparators); + + for (size_t i = 0, e = PathSegments.size(); i != e; ++i) { + const 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; +} + Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -6693,9 +6729,8 @@ Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, Output.getFilename()); CmdArgs.push_back(Fo); - // FIXME: If we've put clang-cl as cl.exe on the path, we have a problem. - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("cl.exe")); + const Driver &D = getToolChain().getDriver(); + std::string Exec = FindFallback("cl.exe", D.getClangProgramPath()); - return new Command(JA, *this, Exec, CmdArgs); + return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); }