[clang] [clang][Driver][Darwin] Handle modern gcc/libstdc++ in Darwin toolchain (PR #155219)
Pierre Ossman via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 25 00:48:57 PDT 2025
https://github.com/CendioOssman created https://github.com/llvm/llvm-project/pull/155219
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.
>From 4a3af37be0c4aad6bf0a35c7a236a8364fbd4aa6 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 09:51:53 +0200
Subject: [PATCH 1/7] Allow subclass override of libstdc+++ for Darwin
---
clang/lib/Driver/ToolChains/Darwin.cpp | 68 +++++++++++++++-----------
clang/lib/Driver/ToolChains/Darwin.h | 6 +++
2 files changed, 45 insertions(+), 29 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 234683f2f4882..9d5c1854f194b 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2848,39 +2848,49 @@ 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.
-
- // 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");
-
- 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));
- return;
- }
- }
- }
+ AddGnuCPlusPlusStdlibLibArgs(Args, CmdArgs);
+ break;
+ }
+}
- // 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;
+void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
+ const ArgList &Args, ArgStringList &CmdArgs) const {
+ CmdArgs.push_back("-lstdc++");
+}
+
+void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
+ const ArgList &Args, ArgStringList &CmdArgs) const {
+ // 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.
+
+ // 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");
+
+ 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));
+ return;
+ }
}
+ }
- // Otherwise, let the linker search.
- CmdArgs.push_back("-lstdc++");
- break;
+ // 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;
}
+
+ // Otherwise, let the linker search.
+ CmdArgs.push_back("-lstdc++");
}
void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index d1cfb6f4a5bf7..3cefe489f7cf4 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -338,6 +338,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.
@@ -689,6 +692,9 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
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,
>From 14fd23364a4627dad541dd84cd7f211fcc9de14e Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 10:03:10 +0200
Subject: [PATCH 2/7] Fix sysroot handling for libstdc++ for Darwin
---
clang/lib/Driver/ToolChains/Darwin.cpp | 29 ++++++++------------------
1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 9d5c1854f194b..afac7c7ff35a9 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2865,31 +2865,20 @@ void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
// platforms we care about it was -lstdc++.6, so we search for that
// explicitly if we can't see an obvious -lstdc++ candidate.
- // 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");
-
- 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));
- return;
- }
- }
- }
+ 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++");
}
>From e731838f4473a1fa044f13bc9eb7f6e3e20caaf8 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 10:39:11 +0200
Subject: [PATCH 3/7] Allow gcc detection on Darwin systems
---
clang/lib/Driver/ToolChains/Gnu.cpp | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 01b146db24f3e..e6f9452bc163b 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.
@@ -2556,6 +2558,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));
>From e2743ef5f174ae4d742b3b3ad6377f667d7ad7cd Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 10:57:43 +0200
Subject: [PATCH 4/7] Always look for distribution supplied gcc
A cross compiling gcc is generally installed outside of the sysroot, so
we should always search the root system for our desired triple.
---
clang/lib/Driver/ToolChains/Gnu.cpp | 6 ++----
clang/test/Driver/pic.c | 4 ++--
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index e6f9452bc163b..1d17fb6753bd9 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2163,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
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"
//
>From b6667b3d397eb0c17eb25aad91258eab68f1b3d6 Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 12:53:07 +0200
Subject: [PATCH 5/7] Respect added library paths for Darwin toolchain
---
clang/lib/Driver/ToolChains/Darwin.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index afac7c7ff35a9..f4921dba9fd6d 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
>From 079c4ef6777300b469c35aa809a39b5bf5f204bd Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Thu, 21 Aug 2025 11:00:45 +0200
Subject: [PATCH 6/7] Find proper gcc installations for Darwin
---
clang/lib/Driver/ToolChains/Darwin.cpp | 109 +++++++++++++++++++++----
clang/lib/Driver/ToolChains/Darwin.h | 11 +++
2 files changed, 103 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index f4921dba9fd6d..6fde8cf931fa5 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1179,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.
@@ -2795,9 +2819,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++");
@@ -2862,22 +2929,24 @@ void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
const ArgList &Args, ArgStringList &CmdArgs) const {
- // 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");
-
- // 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(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;
+ if (!GCCInstallation.isValid()) {
+ // 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");
+
+ // 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(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;
+ }
}
}
@@ -3786,3 +3855,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 3cefe489f7cf4..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"
@@ -643,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);
@@ -673,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.
@@ -689,6 +695,11 @@ 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;
>From f180e434c2377b3c6857ad0297e313959be96afc Mon Sep 17 00:00:00 2001
From: Pierre Ossman <ossman at cendio.se>
Date: Fri, 22 Aug 2025 13:29:40 +0200
Subject: [PATCH 7/7] Handle -static-libstdc++ for libstdc++ on Darwin
---
clang/lib/Driver/ToolChains/Darwin.cpp | 27 +++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 6fde8cf931fa5..f71b875d08c11 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1573,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()) {
@@ -2929,7 +2921,24 @@ void AppleMachO::AddGnuCPlusPlusStdlibLibArgs(
void DarwinClang::AddGnuCPlusPlusStdlibLibArgs(
const ArgList &Args, ArgStringList &CmdArgs) const {
- if (!GCCInstallation.isValid()) {
+ 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
More information about the cfe-commits
mailing list