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