llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: Pierre Ossman (ThinLinc team) (CendioOssman)

<details>
<summary>Changes</summary>

Various fixes to make sure clang can find libstdc++ headers and library for 
current versions of gcc.

Tested with a cross-compiler setup, but should hopefully work correctly for a 
native setup as well.

Also adds support for statically linking libstdc++ and libgcc_s.

---
Full diff: https://github.com/llvm/llvm-project/pull/155219.diff


4 Files Affected:

- (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+116-31) 
- (modified) clang/lib/Driver/ToolChains/Darwin.h (+17) 
- (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+11-6) 
- (modified) clang/test/Driver/pic.c (+2-2) 


``````````diff
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 234683f2f4882..f71b875d08c11 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -681,6 +681,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
 
+  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
+
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
   // Build the input file for -filelist (list of linker input files) in case we
   // need it later
@@ -1177,7 +1179,31 @@ Tool *MachO::buildAssembler() const {
 
 DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
                          const ArgList &Args)
-    : Darwin(D, Triple, Args) {}
+    : Darwin(D, Triple, Args), GCCInstallation(D) {
+  GCCInstallation.init(Triple, Args);
+  if (GCCInstallation.isValid()) {
+    StringRef LibDir = GCCInstallation.getParentLibPath();
+    StringRef TripleStr = GCCInstallation.getTriple().str();
+    const Generic_GCC::GCCVersion &Version = GCCInstallation.getVersion();
+
+    std::string Path;
+
+    // Try /gcc/$triple/$version/
+    Path = LibDir.str() + "/gcc/" + TripleStr.str() + "/" + Version.Text;
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+
+    // Try /gcc/$triple/lib/
+    Path = LibDir.str() + "/gcc/" + TripleStr.str() + "/lib";
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+
+    // Try /../$triple/lib/
+    Path = LibDir.str() + "/../" + TripleStr.str() + "/lib";
+    if (getVFS().exists(Path))
+      getFilePaths().push_back(Path);
+  }
+}
 
 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
   // Always error about undefined 'TARGET_OS_*' macros.
@@ -1547,14 +1573,6 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList 
&Args,
     return;
   }
 
-  // Reject -static-libgcc for now, we can deal with this when and if someone
-  // cares. This is useful in situations where someone wants to statically link
-  // something like libstdc++, and needs its runtime support routines.
-  if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
-    getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
-    return;
-  }
-
   const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
 
   if (!Sanitize.needsSharedRt()) {
@@ -2793,9 +2811,52 @@ void AppleMachO::AddGnuCPlusPlusIncludePaths(
     const llvm::opt::ArgList &DriverArgs,
     llvm::opt::ArgStringList &CC1Args) const {}
 
+bool DarwinClang::addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                                           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);
+  // GPLUSPLUS_BACKWARD_INCLUDE_DIR
+  addSystemInclude(DriverArgs, CC1Args, IncludeDir + "/backward");
+
+  return true;
+}
+
 void DarwinClang::AddGnuCPlusPlusIncludePaths(
     const llvm::opt::ArgList &DriverArgs,
     llvm::opt::ArgStringList &CC1Args) const {
+  if (GCCInstallation.isValid()) {
+    // This is a stripped down version of 
Generic_GCC::addGCCLibStdCxxIncludePaths.
+    StringRef LibDir = GCCInstallation.getParentLibPath();
+    StringRef TripleStr = GCCInstallation.getTriple().str();
+    const Generic_GCC::GCCVersion &Version = GCCInstallation.getVersion();
+
+    // Try /../$triple/include/c++/$version
+    if (addLibStdCXXIncludePaths(
+            LibDir.str() + "/../" + TripleStr + "/include/c++/" + Version.Text,
+            TripleStr, DriverArgs, CC1Args))
+      return;
+
+    // Try /gcc/$triple/$version/include/c++/
+    if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
+                                    Version.Text + "/include/c++/",
+                                TripleStr, DriverArgs, CC1Args))
+      return;
+
+    // Try /../include/c++/$version
+    if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + 
Version.Text,
+                                TripleStr, DriverArgs, CC1Args))
+      return;
+
+    getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
+    return;
+  }
+
   llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);
   llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
 
@@ -2848,39 +2909,57 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList 
&Args,
     break;
 
   case ToolChain::CST_Libstdcxx:
-    // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;
-    // it was previously found in the gcc lib dir. However, for all the Darwin
-    // platforms we care about it was -lstdc++.6, so we search for that
-    // explicitly if we can't see an obvious -lstdc++ candidate.
+    AddGnuCPlusPlusStdlibLibArgs(Args, CmdArgs);
+    break;
+  }
+}
 
-    // Check in the sysroot first.
-    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
-      SmallString<128> P(A->getValue());
-      llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
+void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
+    const ArgList &Args, ArgStringList &CmdArgs) const {
+  CmdArgs.push_back("-lstdc++");
+}
 
-      if (!getVFS().exists(P)) {
-        llvm::sys::path::remove_filename(P);
-        llvm::sys::path::append(P, "libstdc++.6.dylib");
-        if (getVFS().exists(P)) {
-          CmdArgs.push_back(Args.MakeArgString(P));
+void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
+    const ArgList &Args, ArgStringList &CmdArgs) const {
+  if (GCCInstallation.isValid()) {
+    if (Args.hasArg(options::OPT_static_libstdcxx)) {
+      // ld64 doesn't support -Bstatic, so we need to find the actual library
+      for (const auto &Path : getFilePaths()) {
+        llvm::SmallString<128> UsrLibStdCxx(Path);
+        llvm::sys::path::append(UsrLibStdCxx, "libstdc++.a");
+        if (getVFS().exists(UsrLibStdCxx)) {
+          CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
+          // libstdcxx++ needs symbols from here
+          if (Args.hasArg(options::OPT_static_libgcc))
+            CmdArgs.push_back("-lgcc_eh");
+          else
+            CmdArgs.push_back("-lgcc_s.1");
           return;
         }
       }
     }
+  } else {
+    // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;
+    // it was previously found in the gcc lib dir. However, for all the Darwin
+    // platforms we care about it was -lstdc++.6, so we search for that
+    // explicitly if we can't see an obvious -lstdc++ candidate.
+
+    llvm::SmallString<128> UsrLibStdCxx = GetEffectiveSysroot(Args);
+    llvm::sys::path::append(UsrLibStdCxx, "usr", "lib", "libstdc++.dylib");
 
-    // Otherwise, look in the root.
     // FIXME: This should be removed someday when we don't have to care about
     // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
-    if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
-        getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
-      CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
-      return;
+    if (!getVFS().exists(UsrLibStdCxx)) {
+      llvm::sys::path::remove_filename(UsrLibStdCxx);
+      llvm::sys::path::append(UsrLibStdCxx, "libstdc++.6.dylib");
+      if (getVFS().exists(UsrLibStdCxx)) {
+        CmdArgs.push_back(Args.MakeArgString(UsrLibStdCxx));
+        return;
+      }
     }
-
-    // Otherwise, let the linker search.
-    CmdArgs.push_back("-lstdc++");
-    break;
   }
+
+  CmdArgs.push_back("-lstdc++");
 }
 
 void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
@@ -3785,3 +3864,9 @@ void AppleMachO::printVerboseInfo(raw_ostream &OS) const {
   CudaInstallation->print(OS);
   RocmInstallation->print(OS);
 }
+
+void DarwinClang::printVerboseInfo(raw_ostream &OS) const {
+  // Print the information about how we detected the GCC installation.
+  GCCInstallation.print(OS);
+  Darwin::printVerboseInfo(OS);
+}
diff --git a/clang/lib/Driver/ToolChains/Darwin.h 
b/clang/lib/Driver/ToolChains/Darwin.h
index d1cfb6f4a5bf7..06990df8f7bbe 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
 
+#include "Gnu.h"
 #include "clang/Basic/DarwinSDKInfo.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Driver/CudaInstallationDetector.h"
@@ -338,6 +339,9 @@ class LLVM_LIBRARY_VISIBILITY AppleMachO : public MachO {
   virtual void
   AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                               llvm::opt::ArgStringList &CC1Args) const;
+  virtual void
+  AddGnuCPlusPlusStdlibLibArgs(const llvm::opt::ArgList &Args,
+                               llvm::opt::ArgStringList &CmdArgs) const;
 };
 
 /// Darwin - The base Darwin tool chain.
@@ -640,6 +644,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO {
 
 /// DarwinClang - The Darwin toolchain used by Clang.
 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
+protected:
+  Generic_GCC::GCCInstallationDetector GCCInstallation;
+
 public:
   DarwinClang(const Driver &D, const llvm::Triple &Triple,
               const llvm::opt::ArgList &Args);
@@ -670,6 +677,8 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
   void AddLinkARCArgs(const llvm::opt::ArgList &Args,
                       llvm::opt::ArgStringList &CmdArgs) const override;
 
+  void printVerboseInfo(raw_ostream &OS) const override;
+
   unsigned GetDefaultDwarfVersion() const override;
   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
   // Darwin defaults to standalone/full debug info.
@@ -686,9 +695,17 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
                                StringRef Sanitizer,
                                bool shared = true) const;
 
+  bool
+  addLibStdCXXIncludePaths(Twine IncludeDir, StringRef Triple,
+                           const llvm::opt::ArgList &DriverArgs,
+                           llvm::opt::ArgStringList &CC1Args) const;
+
   void
   AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                               llvm::opt::ArgStringList &CC1Args) const 
override;
+  void
+  AddGnuCPlusPlusStdlibLibArgs(const llvm::opt::ArgList &Args,
+                               llvm::opt::ArgStringList &CmdArgs) const 
override;
 
   bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                    llvm::opt::ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp 
b/clang/lib/Driver/ToolChains/Gnu.cpp
index 01b146db24f3e..1d17fb6753bd9 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -1864,9 +1864,11 @@ static bool findBiarchMultilibs(const Driver &D,
                             .flag("-m64", /*Disallow=*/true)
                             .makeMultilib();
 
-  // GCC toolchain for IAMCU doesn't have crtbegin.o, so look for libgcc.a.
+  // GCC toolchain for IAMCU and Darwin doesn't have crtbegin.o, so look for 
libgcc.a.
   FilterNonExistent NonExistent(
-      Path, TargetTriple.isOSIAMCU() ? "/libgcc.a" : "/crtbegin.o", 
D.getVFS());
+      Path,
+      (TargetTriple.isOSIAMCU() || TargetTriple.isOSDarwin()) ? "/libgcc.a" : 
"/crtbegin.o",
+      D.getVFS());
 
   // Determine default multilib from: 32, 64, x32
   // Also handle cases such as 64 on 32, 32 on 64, etc.
@@ -2161,10 +2163,8 @@ void Generic_GCC::GCCInstallationDetector::init(
 
     // Next, look for prefix(es) that correspond to distribution-supplied gcc
     // installations.
-    if (D.SysRoot.empty()) {
-      // Typically /usr.
-      AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot);
-    }
+    // Typically /usr.
+    AddDefaultGCCPrefixes(TargetTriple, Prefixes, "");
 
     // Try to respect gcc-config on Gentoo if --gcc-toolchain is not provided.
     // This avoids accidentally enforcing the system GCC version when using a
@@ -2556,6 +2556,11 @@ void 
Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
     return;
   }
 
+  if (TargetTriple.isOSDarwin()) {
+    LibDirs.push_back("/lib");
+    return;
+  }
+
   switch (TargetTriple.getArch()) {
   case llvm::Triple::aarch64:
     LibDirs.append(begin(AArch64LibDirs), end(AArch64LibDirs));
diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c
index f5d0745422790..24bc26937dda3 100644
--- a/clang/test/Driver/pic.c
+++ b/clang/test/Driver/pic.c
@@ -26,8 +26,8 @@
 //
 // CHECK-PIE-LD: "{{.*}}ld{{(.exe)?}}"
 // CHECK-PIE-LD: "-pie"
-// CHECK-PIE-LD: "Scrt1.o" "crti.o" "crtbeginS.o"
-// CHECK-PIE-LD: "crtendS.o" "crtn.o"
+// CHECK-PIE-LD: "Scrt1.o" "crti.o" "{{.*}}crtbeginS.o"
+// CHECK-PIE-LD: "{{.*}}crtendS.o" "crtn.o"
 //
 // CHECK-NOPIE-LD: "-nopie"
 //

``````````

</details>


https://github.com/llvm/llvm-project/pull/155219
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to