aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2018-11-12 13:55:55 +0000
committerIlya Biryukov <ibiryukov@google.com>2018-11-12 13:55:55 +0000
commit4b7ff1091978ab2202459ae06de89ee761d2077f (patch)
tree77183049f263b9dafe7f66ed0ee72e0192427f1b
parentcc40f56a8ca1d689368db5d2a23d595dae528c2a (diff)
Make clang-based tools find libc++ on MacOS
Summary: When they read compiler args from compile_commands.json. This change allows to run clang-based tools, like clang-tidy or clangd, built from head using the compile_commands.json file produced for XCode toolchains. On MacOS clang can find the C++ standard library relative to the compiler installation dir. The logic to do this was based on resource dir as an approximation of where the compiler is installed. This broke the tools that read 'compile_commands.json' and don't ship with the compiler, as they typically change resource dir. To workaround this, we now use compiler install dir detected by the driver to better mimic the behavior of the original compiler when replaying the compilations using other tools. Reviewers: sammccall, arphaman, EricWF Reviewed By: sammccall Subscribers: ioeric, christof, kadircet, cfe-commits Differential Revision: https://reviews.llvm.org/D54310 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@346652 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Lex/HeaderSearchOptions.h7
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp8
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp11
-rw-r--r--lib/Tooling/Tooling.cpp3
-rw-r--r--test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector1
-rw-r--r--test/Tooling/clang-check-mac-libcxx-abspath.cpp17
-rw-r--r--test/Tooling/clang-check-mac-libcxx-relpath.cpp17
7 files changed, 54 insertions, 10 deletions
diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h
index e5b52b3032..bdf7b43f46 100644
--- a/include/clang/Lex/HeaderSearchOptions.h
+++ b/include/clang/Lex/HeaderSearchOptions.h
@@ -108,6 +108,13 @@ public:
/// etc.).
std::string ResourceDir;
+ /// Compiler install dir as detected by the Driver.
+ /// This is typically the directory that contains the clang executable, i.e.
+ /// the 'bin/' subdir of a clang distribution.
+ /// Only used to add include dirs for libc++ on Darwin. Please avoid relying
+ /// on this field for other purposes.
+ std::string InstallDir;
+
/// The directory used for the module cache.
std::string ModuleCachePath;
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index 2d4c40f8b9..3a5e1e8b15 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -11,17 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/Utils.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
-#include "clang/Driver/Action.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/Utils.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
using namespace clang;
using namespace llvm::opt;
@@ -102,5 +103,8 @@ std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine(
CCArgs.size(),
*Diags))
return nullptr;
+ // Patch up the install dir, so we find the same standard library as the
+ // original compiler on MacOS.
+ CI->getHeaderSearchOpts().InstallDir = TheDriver.getInstalledDir();
return CI;
}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index deedb22f3e..2f62ad3faf 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -476,14 +476,9 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
if (triple.isOSDarwin()) {
// On Darwin, libc++ may be installed alongside the compiler in
// include/c++/v1.
- if (!HSOpts.ResourceDir.empty()) {
- // Remove version from foo/lib/clang/version
- StringRef NoVer = llvm::sys::path::parent_path(HSOpts.ResourceDir);
- // Remove clang from foo/lib/clang
- StringRef Lib = llvm::sys::path::parent_path(NoVer);
- // Remove lib from foo/lib
- SmallString<128> P = llvm::sys::path::parent_path(Lib);
-
+ if (!HSOpts.InstallDir.empty()) {
+ // Get from foo/bin to foo.
+ SmallString<128> P(llvm::sys::path::parent_path(HSOpts.InstallDir));
// Get foo/include/c++/v1
llvm::sys::path::append(P, "include", "c++", "v1");
AddUnmappedPath(P, CXXSystem, false);
diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp
index cfdb32f0ae..f113e47cdc 100644
--- a/lib/Tooling/Tooling.cpp
+++ b/lib/Tooling/Tooling.cpp
@@ -327,6 +327,9 @@ bool ToolInvocation::run() {
Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(),
Input.release());
}
+ // Patch up the install dir, so we find the same standard library as the
+ // original compiler on MacOS.
+ Invocation->getHeaderSearchOpts().InstallDir = Driver->getInstalledDir();
return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
std::move(PCHContainerOps));
}
diff --git a/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector b/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector
new file mode 100644
index 0000000000..8512477b5d
--- /dev/null
+++ b/test/Tooling/Inputs/mock-libcxx/include/c++/v1/mock_vector
@@ -0,0 +1 @@
+class vector {};
diff --git a/test/Tooling/clang-check-mac-libcxx-abspath.cpp b/test/Tooling/clang-check-mac-libcxx-abspath.cpp
new file mode 100644
index 0000000000..476ba3ce08
--- /dev/null
+++ b/test/Tooling/clang-check-mac-libcxx-abspath.cpp
@@ -0,0 +1,17 @@
+// Clang on MacOS can find libc++ living beside the installed compiler.
+// This test makes sure our libTooling-based tools emulate this properly.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// Install the mock libc++ (simulates the libc++ directory structure).
+// RUN: cp -r %S/Inputs/mock-libcxx %t/
+//
+// Pretend clang is installed beside the mock library that we provided.
+// RUN: echo '[{"directory":"%t","command":"%t/mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
+// RUN: cp "%s" "%t/test.cpp"
+// clang-check will produce an error code if the mock library is not found.
+// RUN: clang-check -p "%t" "%t/test.cpp"
+
+#include <mock_vector>
+vector v;
diff --git a/test/Tooling/clang-check-mac-libcxx-relpath.cpp b/test/Tooling/clang-check-mac-libcxx-relpath.cpp
new file mode 100644
index 0000000000..099be5ecd4
--- /dev/null
+++ b/test/Tooling/clang-check-mac-libcxx-relpath.cpp
@@ -0,0 +1,17 @@
+// Clang on MacOS can find libc++ living beside the installed compiler.
+// This test makes sure our libTooling-based tools emulate this properly.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+//
+// Install the mock libc++ (simulates the libc++ directory structure).
+// RUN: cp -r %S/Inputs/mock-libcxx %t/
+//
+// Pretend clang is installed beside the mock library that we provided.
+// RUN: echo '[{"directory":"%t","command":"mock-libcxx/bin/clang++ -stdlib=libc++ -target x86_64-apple-darwin -c test.cpp","file":"test.cpp"}]' | sed -e 's/\\/\//g' > %t/compile_commands.json
+// RUN: cp "%s" "%t/test.cpp"
+// clang-check will produce an error code if the mock library is not found.
+// RUN: clang-check -p "%t" "%t/test.cpp"
+
+#include <mock_vector>
+vector v;