[clang] bcaca36 - [Driver] Gnu.cpp: fix libstdc++ search path for multilib

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 21 12:01:49 PDT 2021


Author: Fangrui Song
Date: 2021-03-21T12:01:44-07:00
New Revision: bcaca360f8b64d267c787a5f3088e73420e78f53

URL: https://github.com/llvm/llvm-project/commit/bcaca360f8b64d267c787a5f3088e73420e78f53
DIFF: https://github.com/llvm/llvm-project/commit/bcaca360f8b64d267c787a5f3088e73420e78f53.diff

LOG: [Driver] Gnu.cpp: fix libstdc++ search path for multilib

With this change, on Debian x86-64 (with a MULTILIB_OSDIRNAMES local patch
../lib64 -> ../lib; this does not matter because /usr/lib64/crt{1,i,n}.o do not exist),
`clang++ --target=aarch64-linux-gnu a.cc -Wl,--dynamic-linker=/usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 -Wl,-rpath,/usr/aarch64-linux-gnu/lib`
built executable can run under qemu-user. Previously this failed with
`/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../include/c++/10/iostream:38:10: fatal error: 'bits/c++config.h' file not found`

On Arch Linux, due to the MULTILIB_OSDIRNAMES patch and the existence of
/usr/lib64/crt{1,i,n}.o, clang driver may pick
/usr/lib64/crt{1,i,n}.o and cause a linker error. -B can work around the problem.
`clang++ --target=aarch64-linux-gnu -B /usr/aarch64-linux-gnu/lib a.cc -Wl,--dynamic-linker=/usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 -Wl,-rpath,/usr/aarch64-linux-gnu/lib64:/usr/aarch64-linux-gnu/lib`

Added: 
    

Modified: 
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Gnu.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index b5efa587f8dc..426ab8c4aad4 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2945,6 +2945,23 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
     return;
 }
 
+bool Generic_GCC::addLibStdCXXIncludePaths(
+    Twine IncludeDir, StringRef Triple, Twine IncludeSuffix,
+    const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args) const {
+  if (!getVFS().exists(IncludeDir))
+    return false;
+
+  // GPLUSPLUS_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir);
+  // GPLUSPLUS_TOOL_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args,
+                   IncludeDir + "/" + Triple + IncludeSuffix);
+  // GPLUSPLUS_BACKWARD_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
+  return true;
+}
+
 /// Helper to add the variant paths of a libstdc++ installation.
 bool Generic_GCC::addLibStdCXXIncludePaths(
     Twine Base, Twine Suffix, StringRef GCCTriple, StringRef GCCMultiarchTriple,
@@ -2965,13 +2982,8 @@ bool Generic_GCC::addLibStdCXXIncludePaths(
   } else {
     // Otherwise try to use multiarch naming schemes which have normalized the
     // triples and put the triple before the suffix.
-    //
-    // GCC surprisingly uses *both* the GCC triple with a multilib suffix and
-    // the target triple, so we support that here.
     addSystemInclude(DriverArgs, CC1Args,
                      Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix);
-    addSystemInclude(DriverArgs, CC1Args,
-                     Base + "/" + TargetMultiarchTriple + Suffix);
   }
 
   addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward");
@@ -2992,16 +3004,23 @@ Generic_GCC::addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
   StringRef InstallDir = GCCInstallation.getInstallPath();
   StringRef TripleStr = GCCInstallation.getTriple().str();
   const Multilib &Multilib = GCCInstallation.getMultilib();
-  const std::string GCCMultiarchTriple = getMultiarchTriple(
+  const std::string Triple = getMultiarchTriple(
       getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
   const std::string TargetMultiarchTriple =
       getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
   const GCCVersion &Version = GCCInstallation.getVersion();
 
   // The primary search for libstdc++ supports multiarch variants.
+  if (addLibStdCXXIncludePaths(
+          LibDir.str() + "/../" + Triple + "/include/c++/" + Version.Text,
+          TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
+    return true;
+
+  // Debian host g++ needs this for
+  // /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/{c++/10,x86_64-linux-gnu/c++/10,c++/10/backward}
+  // FIXME Some other toolchains incorrectly rely on this hierarchy.
   if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
-                               "/c++/" + Version.Text, TripleStr,
-                               GCCMultiarchTriple, TargetMultiarchTriple,
+                               "/c++/" + Version.Text, TripleStr, Triple, "",
                                Multilib.includeSuffix(), DriverArgs, CC1Args))
     return true;
 

diff  --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index 90d3bafc1f00..aa03c6ed6a05 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -351,6 +351,12 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain {
   addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                            llvm::opt::ArgStringList &CC1Args) const;
 
+  bool addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                                Twine IncludeSuffix,
+                                const llvm::opt::ArgList &DriverArgs,
+                                llvm::opt::ArgStringList &CC1Args) const;
+  // FIXME This is used for libstdc++ include directories used by Debian host
+  // g++. It should not used by other toolchains.
   bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
                                 StringRef GCCMultiarchTriple,
                                 StringRef TargetMultiarchTriple,


        


More information about the cfe-commits mailing list