Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 116 additions & 31 deletions clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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++");

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
17 changes: 17 additions & 0 deletions clang/lib/Driver/ToolChains/Darwin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand All @@ -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,
Expand Down
17 changes: 11 additions & 6 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Driver/pic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
//
Expand Down