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

Reply via email to