11 #include "clang/Frontend/CompilerInvocation.h" 12 #include "clang/Tooling/ArgumentsAdjusters.h" 13 #include "llvm/Support/FileSystem.h" 14 #include "llvm/Support/FileUtilities.h" 15 #include "llvm/Support/MemoryBuffer.h" 16 #include "llvm/Support/Path.h" 17 #include "llvm/Support/Program.h" 25 llvm::Optional<std::string> queryXcrun(llvm::ArrayRef<llvm::StringRef> Argv) {
26 auto Xcrun = llvm::sys::findProgramByName(
"xcrun");
28 log(
"Couldn't find xcrun. Hopefully you have a non-apple toolchain...");
31 llvm::SmallString<64> OutFile;
32 llvm::sys::fs::createTemporaryFile(
"clangd-xcrun",
"", OutFile);
33 llvm::FileRemover OutRemover(OutFile);
34 llvm::Optional<llvm::StringRef> Redirects[3] = {
35 {
""}, {OutFile}, {
""}};
36 vlog(
"Invoking {0} to find clang installation", *Xcrun);
37 int Ret = llvm::sys::ExecuteAndWait(*Xcrun, Argv,
41 log(
"xcrun exists but failed with code {0}. " 42 "If you have a non-apple toolchain, this is OK. " 43 "Otherwise, try xcode-select --install.",
48 auto Buf = llvm::MemoryBuffer::getFile(OutFile);
50 log(
"Can't read xcrun output: {0}", Buf.getError().message());
53 StringRef
Path = Buf->get()->getBuffer().trim();
55 log(
"xcrun produced no output");
62 std::string resolve(std::string Path) {
63 llvm::SmallString<128> Resolved;
64 if (llvm::sys::fs::real_path(Path, Resolved)) {
65 log(
"Failed to resolve possible symlink {0}", Path);
68 return Resolved.str();
74 std::string detectClangPath() {
86 if (
auto MacClang = queryXcrun({
"xcrun",
"--find",
"clang"}))
87 return resolve(std::move(*MacClang));
90 for (
const char *
Name : {
"clang",
"gcc",
"cc"})
91 if (
auto PathCC = llvm::sys::findProgramByName(
Name))
92 return resolve(std::move(*PathCC));
95 std::string ClangdExecutable =
96 llvm::sys::fs::getMainExecutable(
"clangd", (
void *)&Dummy);
97 SmallString<128> ClangPath;
98 ClangPath = llvm::sys::path::parent_path(ClangdExecutable);
99 llvm::sys::path::append(ClangPath,
"clang");
100 return ClangPath.str();
105 const llvm::Optional<std::string> detectSysroot() {
111 if (::getenv(
"SDKROOT"))
113 return queryXcrun({
"xcrun",
"--show-sdk-path"});
117 std::string detectStandardResourceDir() {
119 return CompilerInvocation::GetResourcesPath(
"clangd", (
void *)&Dummy);
128 Result.
Sysroot = detectSysroot();
138 auto Has = [&](llvm::StringRef Flag) {
139 for (llvm::StringRef Arg : Cmd) {
140 if (Arg.consume_front(Flag) && (Arg.empty() || Arg[0] ==
'='))
148 Cmd = tooling::getClangStripDependencyFileAdjuster()(Cmd,
"");
152 Cmd = tooling::getStripPluginsAdjuster()(Cmd,
"");
153 Cmd = tooling::getClangSyntaxOnlyAdjuster()(Cmd,
"");
160 if (
Sysroot && !Has(
"-isysroot") && !Has(
"--sysroot")) {
161 Cmd.push_back(
"-isysroot");
167 if (ClangPath && llvm::sys::path::is_absolute(*ClangPath) && !Cmd.empty()) {
168 std::string &Driver = Cmd.front();
169 if (Driver ==
"clang" || Driver ==
"clang++" || Driver ==
"gcc" ||
170 Driver ==
"g++" || Driver ==
"cc" || Driver ==
"c++") {
171 llvm::SmallString<128> QualifiedDriver =
172 llvm::sys::path::parent_path(*ClangPath);
173 llvm::sys::path::append(QualifiedDriver, Driver);
174 Driver = QualifiedDriver.str();
179 CommandMangler::operator clang::tooling::ArgumentsAdjuster() {
180 return [Mangler{*
this}](
const std::vector<std::string> &Args,
181 llvm::StringRef
File) {
183 Mangler.adjust(Result);
void adjust(std::vector< std::string > &Cmd) const
Documents should not be synced at all.
llvm::Optional< std::string > ClangPath
void vlog(const char *Fmt, Ts &&... Vals)
static CommandMangler forTests()
void log(const char *Fmt, Ts &&... Vals)
std::string Path
A typedef to represent a file path.
static constexpr llvm::StringLiteral Name
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< std::string > Sysroot
static CommandMangler detect()
llvm::Optional< std::string > ResourceDir