This option may be used with OSs without a "system" libc++ to select the
underlying ABI library used by libc++. Also, teach ToolChain to search the
installation directory for libc++ libraries and headers. Toolchains which
know better should be overriding the relevant ToolChain members.
http://llvm-reviews.chandlerc.com/D1968
Files:
include/clang/Driver/Options.td
include/clang/Driver/ToolChain.h
lib/Driver/ToolChain.cpp
lib/Driver/ToolChains.cpp
lib/Driver/ToolChains.h
test/Driver/Inputs/linux_libcxx_tree/usr/include/c++/v1/.keep
test/Driver/Inputs/linux_libcxx_tree/usr/local/bin/.keep
test/Driver/Inputs/linux_libcxx_tree/usr/local/include/c++/v1/.keep
test/Driver/linux-libcxx.cpp
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1226,6 +1226,8 @@
Group<CompileOnly_Group>, HelpText<"Language standard to compile for">;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">;
+def stdlib_abi_EQ : Joined<["-", "--"], "stdlib-abi=">, Flags<[CC1Option]>,
+ HelpText<"C++ ABI library to use">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">;
def s : Flag<["-"], "s">;
@@ -1361,6 +1363,7 @@
def _signed_char : Flag<["--"], "signed-char">, Alias<fsigned_char>;
def _std : Separate<["--"], "std">, Alias<std_EQ>;
def _stdlib : Separate<["--"], "stdlib">, Alias<stdlib_EQ>;
+def _stdlib_abi : Separate<["--"], "stdlib-abi">, Alias<stdlib_abi_EQ>;
def _sysroot_EQ : Joined<["--"], "sysroot=">;
def _sysroot : Separate<["--"], "sysroot">, Alias<_sysroot_EQ>;
def _target_help : Flag<["--"], "target-help">;
Index: include/clang/Driver/ToolChain.h
===================================================================
--- include/clang/Driver/ToolChain.h
+++ include/clang/Driver/ToolChain.h
@@ -47,6 +47,13 @@
CST_Libstdcxx
};
+ enum CXXABILibType {
+ CALT_Libcxxabi,
+ CALT_Libstdcxx,
+ CALT_Libsupcxx,
+ CALT_Libcxxrt
+ };
+
enum RuntimeLibType {
RLT_CompilerRT,
RLT_Libgcc
@@ -205,6 +212,11 @@
return ToolChain::RLT_Libgcc;
}
+ /// GetDefaultRuntimeLibType - Get the default C++ ABI library variant to use.
+ virtual CXXABILibType GetDefaultCXXABILibType() const {
+ return ToolChain::CALT_Libcxxabi;
+ }
+
/// IsUnwindTablesDefault - Does this tool chain use -funwind-tables
/// by default.
virtual bool IsUnwindTablesDefault() const;
@@ -286,6 +298,10 @@
// given compilation arguments.
virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const;
+ // GetCXXStdlibType - Determine the C++ ABI library type to use with the given
+ // compilation arguments.
+ virtual CXXABILibType GetCXXABILibType(const llvm::opt::ArgList &Args) const;
+
/// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set
/// the include paths to use for the given C++ standard library type.
virtual void
Index: lib/Driver/ToolChain.cpp
===================================================================
--- lib/Driver/ToolChain.cpp
+++ lib/Driver/ToolChain.cpp
@@ -331,6 +331,25 @@
return ToolChain::CST_Libstdcxx;
}
+ToolChain::CXXABILibType
+ToolChain::GetCXXABILibType(const ArgList &Args) const {
+ if (Arg *A = Args.getLastArg(options::OPT_stdlib_abi_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value == "libc++abi")
+ return ToolChain::CALT_Libcxxabi;
+ if (Value == "libcxxrt")
+ return ToolChain::CALT_Libcxxrt;
+ if (Value == "libstdc++")
+ return ToolChain::CALT_Libstdcxx;
+ if (Value == "libsupc++")
+ return ToolChain::CALT_Libsupcxx;
+ getDriver().Diag(diag::err_drv_invalid_stdlib_name)
+ << A->getAsString(Args);
+ }
+
+ return GetDefaultCXXABILibType();
+}
+
/// \brief Utility function to add a system include directory to CC1 arguments.
/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
ArgStringList &CC1Args,
@@ -384,16 +403,64 @@
// header search paths with it. Once all systems are overriding this
// function, the CC1 flag and this line can be removed.
DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
+
+ // Default logic for locating libc++ headers.
+ if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
+ std::string InstalledIncludePath = getDriver().getInstalledDir();
+ InstalledIncludePath += "/../include/c++/v1";
+ if (llvm::sys::fs::exists(InstalledIncludePath)) {
+ // Prefer an installation of libc++ in our install tree.
+ addSystemInclude(DriverArgs, CC1Args, InstalledIncludePath);
+ } else {
+ // Otherwise, use a fixed path relative to sysroot.
+ addSystemInclude(DriverArgs, CC1Args,
+ getDriver().SysRoot + "/usr/include/c++/v1");
+ }
+ return;
+ }
}
void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
switch (Type) {
- case ToolChain::CST_Libcxx:
- CmdArgs.push_back("-lc++");
+ case ToolChain::CST_Libcxx: {
+ // Unless we know any better, look for libc++ in our install directory.
+ std::string InstalledLibPath = getDriver().getInstalledDir();
+ InstalledLibPath += "/../lib";
+
+ CmdArgs.push_back(Args.MakeArgString("-L" + InstalledLibPath));
+
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back(Args.MakeArgString(InstalledLibPath));
+
+ CXXABILibType ABIType = GetCXXABILibType(Args);
+ if (ABIType == ToolChain::CALT_Libstdcxx)
+ CmdArgs.push_back("-lc++gnu");
+ else
+ CmdArgs.push_back("-lc++");
+
+ switch (ABIType) {
+ case ToolChain::CALT_Libcxxabi:
+ CmdArgs.push_back("-lc++abi");
+ break;
+
+ case ToolChain::CALT_Libcxxrt:
+ CmdArgs.push_back("-lcxxrt");
+ break;
+
+ case ToolChain::CALT_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+
+ case ToolChain::CALT_Libsupcxx:
+ CmdArgs.push_back("-lsupc++");
+ break;
+ }
+
break;
+ }
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
Index: lib/Driver/ToolChains.cpp
===================================================================
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -2011,6 +2011,21 @@
}
}
+void NetBSD::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CXXStdlibType Type = GetCXXStdlibType(Args);
+
+ switch (Type) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ CmdArgs.push_back("-lstdc++");
+ break;
+ }
+}
+
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -2667,10 +2682,9 @@
// Check if libc++ has been enabled and provide its include paths if so.
if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
- // libc++ is always installed at a fixed path on Linux currently.
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/usr/include/c++/v1");
- return;
+ // Fall back to the base class, which searches the install tree first,
+ // as libc++ is (generally) not the system C++ library on Linux.
+ return ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
}
// We need a detected GCC installation on Linux to provide libstdc++'s
Index: lib/Driver/ToolChains.h
===================================================================
--- lib/Driver/ToolChains.h
+++ lib/Driver/ToolChains.h
@@ -527,6 +527,8 @@
virtual void
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
+ virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
virtual bool IsUnwindTablesDefault() const {
return true;
}
Index: test/Driver/linux-libcxx.cpp
===================================================================
--- /dev/null
+++ test/Driver/linux-libcxx.cpp
@@ -0,0 +1,11 @@
+// RUN: %clangxx -stdlib=libc++ -stdlib-abi=libc++abi -target x86_64-unknown-linux --sysroot %S/Inputs/linux_libcxx_tree -ccc-install-dir %S/Inputs/linux_libcxx_tree/usr/local/bin %s -### 2>&1 | FileCheck -check-prefix=LIBCXXABI-USR-LOCAL %s
+// RUN: %clangxx -stdlib=libc++ -stdlib-abi=libc++abi -target x86_64-unknown-linux --sysroot %S/Inputs/linux_libcxx_tree -ccc-install-dir %S/Inputs/linux_libcxx_tree/nonexistent %s -### 2>&1 | FileCheck -check-prefix=LIBCXXABI-NONEXISTENT %s
+// RUN: %clangxx -stdlib=libc++ -stdlib-abi=libstdc++ -target x86_64-unknown-linux --sysroot %S/Inputs/linux_libcxx_tree -ccc-install-dir %S/Inputs/linux_libcxx_tree/usr/local/bin %s -### 2>&1 | FileCheck -check-prefix=LIBSTDCXX-USR-LOCAL %s
+
+// LIBCXXABI-USR-LOCAL: "-internal-isystem" "{{.*}}/linux_libcxx_tree/usr/local/bin/../include/c++/v1"
+// LIBCXXABI-USR-LOCAL: "-L{{.*}}/linux_libcxx_tree/usr/local/bin/../lib" "-rpath" "{{.*}}/linux_libcxx_tree/usr/local/bin/../lib" "-lc++" "-lc++abi"
+
+// LIBCXXABI-NONEXISTENT: "-internal-isystem" "{{.*}}/linux_libcxx_tree/usr/include/c++/v1"
+
+// LIBSTDCXX-USR-LOCAL: "-internal-isystem" "{{.*}}/linux_libcxx_tree/usr/local/bin/../include/c++/v1"
+// LIBSTDCXX-USR-LOCAL: "-L{{.*}}/linux_libcxx_tree/usr/local/bin/../lib" "-rpath" "{{.*}}/linux_libcxx_tree/usr/local/bin/../lib" "-lc++gnu" "-lstdc++"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits