llvm-project/clang/lib/Driver/ToolChains.cpp

3477 lines
124 KiB
C++
Raw Normal View History

//===--- ToolChains.cpp - ToolChain Implementations -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ToolChains.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
// FIXME: This needs to be listed last until we fix the broken include guards
// in these files and the LLVM config.h files.
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include <cstdlib> // ::getenv
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
MachO::MachO(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
}
/// Darwin - Darwin tool chain for i386 and x86_64.
Darwin::Darwin(const Driver & D, const llvm::Triple & Triple,
const ArgList & Args)
: MachO(D, Triple, Args), TargetInitialized(false) {
// Compute the initial Darwin version from the triple
unsigned Major, Minor, Micro;
if (!Triple.getMacOSXVersion(Major, Minor, Micro))
getDriver().Diag(diag::err_drv_invalid_darwin_version) <<
Triple.getOSName();
llvm::raw_string_ostream(MacosxVersionMin)
<< Major << '.' << Minor << '.' << Micro;
// FIXME: DarwinVersion is only used to find GCC's libexec directory.
// It should be removed when we stop supporting that.
DarwinVersion[0] = Minor + 4;
DarwinVersion[1] = Micro;
DarwinVersion[2] = 0;
// Compute the initial iOS version from the triple
Triple.getiOSVersion(Major, Minor, Micro);
llvm::raw_string_ostream(iOSVersionMin)
<< Major << '.' << Minor << '.' << Micro;
}
types::ID MachO::LookupTypeForExtension(const char *Ext) const {
types::ID Ty = types::lookupTypeForExtension(Ext);
// Darwin always preprocesses assembly files (unless -x is used explicitly).
if (Ty == types::TY_PP_Asm)
return types::TY_Asm;
return Ty;
}
bool MachO::HasNativeLLVMSupport() const {
return true;
}
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
if (isTargetIOSBased())
return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
if (isNonFragile)
return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
}
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
bool Darwin::hasBlocksRuntime() const {
if (isTargetIOSBased())
return !isIPhoneOSVersionLT(3, 2);
else {
assert(isTargetMacOS() && "unexpected darwin target");
return !isMacosxVersionLT(10, 6);
}
}
static const char *GetArmArchForMArch(StringRef Value) {
return llvm::StringSwitch<const char*>(Value)
.Case("armv6k", "armv6")
.Case("armv6m", "armv6m")
.Case("armv5tej", "armv5")
.Case("xscale", "xscale")
.Case("armv4t", "armv4t")
.Case("armv7", "armv7")
.Cases("armv7a", "armv7-a", "armv7")
.Cases("armv7r", "armv7-r", "armv7")
.Cases("armv7em", "armv7e-m", "armv7em")
.Cases("armv7k", "armv7-k", "armv7k")
.Cases("armv7m", "armv7-m", "armv7m")
.Cases("armv7s", "armv7-s", "armv7s")
.Default(0);
}
static const char *GetArmArchForMCpu(StringRef Value) {
return llvm::StringSwitch<const char *>(Value)
.Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "arm926ej-s","armv5")
.Cases("arm10e", "arm10tdmi", "armv5")
.Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5")
.Case("xscale", "xscale")
.Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
.Case("cortex-m0", "armv6m")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "cortex-a9-mp", "armv7")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "krait", "armv7")
.Cases("cortex-r4", "cortex-r5", "armv7r")
.Case("cortex-m3", "armv7m")
.Case("cortex-m4", "armv7em")
.Case("swift", "armv7s")
.Default(0);
}
static bool isSoftFloatABI(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
options::OPT_mfloat_abi_EQ);
if (!A)
return false;
return A->getOption().matches(options::OPT_msoft_float) ||
(A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
A->getValue() == StringRef("soft"));
}
StringRef MachO::getMachOArchName(const ArgList &Args) const {
switch (getTriple().getArch()) {
default:
return getArchName();
case llvm::Triple::thumb:
case llvm::Triple::arm: {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
if (const char *Arch = GetArmArchForMArch(A->getValue()))
return Arch;
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
if (const char *Arch = GetArmArchForMCpu(A->getValue()))
return Arch;
return "arm";
}
}
}
Darwin::~Darwin() {
}
MachO::~MachO() {
}
std::string MachO::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
return Triple.getTriple();
}
std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
types::ID InputType) const {
llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
// If the target isn't initialized (e.g., an unknown Darwin platform, return
// the default triple).
if (!isTargetInitialized())
return Triple.getTriple();
SmallString<16> Str;
Str += isTargetIOSBased() ? "ios" : "macosx";
Str += getTargetVersion().getAsString();
Triple.setOSName(Str);
return Triple.getTriple();
}
void Generic_ELF::anchor() {}
Tool *MachO::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::LipoJobClass:
if (!Lipo)
Lipo.reset(new tools::darwin::Lipo(*this));
return Lipo.get();
case Action::DsymutilJobClass:
if (!Dsymutil)
Dsymutil.reset(new tools::darwin::Dsymutil(*this));
return Dsymutil.get();
case Action::VerifyDebugInfoJobClass:
if (!VerifyDebug)
VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
return VerifyDebug.get();
default:
return ToolChain::getTool(AC);
}
}
Tool *MachO::buildLinker() const {
return new tools::darwin::Link(*this);
}
Tool *MachO::buildAssembler() const {
return new tools::darwin::Assemble(*this);
}
DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: Darwin(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
// For iOS, 64-bit, promote certain warnings to errors.
if (!isTargetMacOS() && getTriple().isArch64Bit()) {
// Always enable -Wdeprecated-objc-isa-usage and promote it
// to an error.
CC1Args.push_back("-Wdeprecated-objc-isa-usage");
CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
// Also error about implicit function declarations, as that
// can impact calling conventions.
CC1Args.push_back("-Werror=implicit-function-declaration");
}
}
/// \brief Determine whether Objective-C automated reference counting is
/// enabled.
static bool isObjCAutoRefCount(const ArgList &Args) {
return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
}
void DarwinClang::AddLinkARCArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Avoid linking compatibility stubs on i386 mac.
if (isTargetMacOS() && getArch() == llvm::Triple::x86)
return;
ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
runtime.hasSubscripting())
return;
CmdArgs.push_back("-force_load");
SmallString<128> P(getDriver().ClangExecutable);
llvm::sys::path::remove_filename(P); // 'clang'
llvm::sys::path::remove_filename(P); // 'bin'
llvm::sys::path::append(P, "lib", "arc", "libarclite_");
// Mash in the platform.
if (isTargetIOSSimulator())
P += "iphonesimulator";
else if (isTargetIPhoneOS())
P += "iphoneos";
else
P += "macosx";
P += ".a";
CmdArgs.push_back(Args.MakeArgString(P));
}
void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
StringRef DarwinStaticLib, bool AlwaysLink,
bool IsEmbedded) const {
SmallString<128> P(getDriver().ResourceDir);
llvm::sys::path::append(P, "lib", IsEmbedded ? "macho_embedded" : "darwin",
DarwinStaticLib);
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build (unless
// we explicitly force linking with this library).
if (AlwaysLink || llvm::sys::fs::exists(P.str()))
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Darwin only supports the compiler-rt based runtime libraries.
switch (GetRuntimeLibType(Args)) {
case ToolChain::RLT_CompilerRT:
break;
default:
getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform)
<< Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "darwin";
return;
}
// Darwin doesn't support real static executables, don't link any runtime
// libraries with -static.
if (Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_fapple_kext) ||
Args.hasArg(options::OPT_mkernel))
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;
}
// If we are building profile support, link that library in.
if (Args.hasArg(options::OPT_fprofile_arcs) ||
Args.hasArg(options::OPT_fprofile_generate) ||
Args.hasArg(options::OPT_fprofile_instr_generate) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage)) {
// Select the appropriate runtime library for the target.
if (isTargetIOSBased())
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
else
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a");
}
const SanitizerArgs &Sanitize = getSanitizerArgs();
// Add Ubsan runtime library, if required.
if (Sanitize.needsUbsanRt()) {
// FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
if (isTargetIOSBased()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
<< "-fsanitize=undefined";
} else {
assert(isTargetMacOS() && "unexpected non OS X target");
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true);
// The Ubsan runtime library requires C++.
AddCXXStdlibLibArgs(Args, CmdArgs);
}
}
// Add ASAN runtime library, if required. Dynamic libraries and bundles
// should not be linked with the runtime library.
if (Sanitize.needsAsanRt()) {
// FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
if (isTargetIPhoneOS()) {
getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
<< "-fsanitize=address";
} else {
if (!Args.hasArg(options::OPT_dynamiclib) &&
!Args.hasArg(options::OPT_bundle)) {
// The ASAN runtime library requires C++.
AddCXXStdlibLibArgs(Args, CmdArgs);
}
if (isTargetMacOS()) {
AddLinkRuntimeLib(Args, CmdArgs,
"libclang_rt.asan_osx_dynamic.dylib",
true);
} else {
if (isTargetIOSSimulator()) {
AddLinkRuntimeLib(Args, CmdArgs,
"libclang_rt.asan_iossim_dynamic.dylib",
true);
}
}
}
}
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
if (isTargetIOSBased()) {
// If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
// it never went into the SDK.
// Linking against libgcc_s.1 isn't needed for iOS 5.0+
if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
getTriple().getArch() != llvm::Triple::arm64)
CmdArgs.push_back("-lgcc_s.1");
// We currently always need a static runtime library for iOS.
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a");
} else {
assert(isTargetMacOS() && "unexpected non MacOS platform");
// The dynamic runtime library was merged with libSystem for 10.6 and
// beyond; only 10.4 and 10.5 need an additional runtime library.
if (isMacosxVersionLT(10, 5))
CmdArgs.push_back("-lgcc_s.10.4");
else if (isMacosxVersionLT(10, 6))
CmdArgs.push_back("-lgcc_s.10.5");
// For OS X, we thought we would only need a static runtime library when
// targeting 10.4, to provide versions of the static functions which were
// omitted from 10.4.dylib.
//
// Unfortunately, that turned out to not be true, because Darwin system
// headers can still use eprintf on i386, and it is not exported from
// libSystem. Therefore, we still must provide a runtime library just for
// the tiny tiny handful of projects that *might* use that symbol.
if (isMacosxVersionLT(10, 5)) {
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.10.4.a");
} else {
if (getTriple().getArch() == llvm::Triple::x86)
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.eprintf.a");
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.osx.a");
}
}
}
void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const OptTable &Opts = getDriver().getOpts();
// Support allowing the SDKROOT environment variable used by xcrun and other
// Xcode tools to define the default sysroot, by making it the default for
// isysroot.
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
// Warn if the path does not exist.
if (!llvm::sys::fs::exists(A->getValue()))
getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
} else {
if (char *env = ::getenv("SDKROOT")) {
// We only use this value as the default if it is an absolute path,
// exists, and it is not the root path.
if (llvm::sys::path::is_absolute(env) && llvm::sys::fs::exists(env) &&
StringRef(env) != "/") {
Args.append(Args.MakeSeparateArg(
0, Opts.getOption(options::OPT_isysroot), env));
}
}
}
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
Arg *iOSSimVersion = Args.getLastArg(
options::OPT_mios_simulator_version_min_EQ);
if (OSXVersion && (iOSVersion || iOSSimVersion)) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
<< (iOSVersion ? iOSVersion : iOSSimVersion)->getAsString(Args);
iOSVersion = iOSSimVersion = 0;
} else if (iOSVersion && iOSSimVersion) {
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< iOSVersion->getAsString(Args)
<< iOSSimVersion->getAsString(Args);
iOSSimVersion = 0;
} else if (!OSXVersion && !iOSVersion && !iOSSimVersion) {
// If no deployment target was specified on the command line, check for
// environment defines.
StringRef OSXTarget;
StringRef iOSTarget;
StringRef iOSSimTarget;
if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
OSXTarget = env;
if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
iOSTarget = env;
if (char *env = ::getenv("IOS_SIMULATOR_DEPLOYMENT_TARGET"))
iOSSimTarget = env;
2011-10-08 19:31:46 +08:00
// If no '-miphoneos-version-min' specified on the command line and
// IPHONEOS_DEPLOYMENT_TARGET is not defined, see if we can set the default
// based on -isysroot.
if (iOSTarget.empty()) {
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef first, second;
StringRef isysroot = A->getValue();
std::tie(first, second) = isysroot.split(StringRef("SDKs/iPhoneOS"));
if (second != "")
iOSTarget = second.substr(0,3);
}
}
// If no OSX or iOS target has been specified and we're compiling for armv7,
// go ahead as assume we're targeting iOS.
StringRef MachOArchName = getMachOArchName(Args);
if (OSXTarget.empty() && iOSTarget.empty() &&
(MachOArchName == "armv7" || MachOArchName == "armv7s" ||
MachOArchName == "arm64"))
iOSTarget = iOSVersionMin;
// Handle conflicting deployment targets
//
// FIXME: Don't hardcode default here.
// Do not allow conflicts with the iOS simulator target.
if (!iOSSimTarget.empty() && (!OSXTarget.empty() || !iOSTarget.empty())) {
getDriver().Diag(diag::err_drv_conflicting_deployment_targets)
<< "IOS_SIMULATOR_DEPLOYMENT_TARGET"
<< (!OSXTarget.empty() ? "MACOSX_DEPLOYMENT_TARGET" :
"IPHONEOS_DEPLOYMENT_TARGET");
}
// Allow conflicts among OSX and iOS for historical reasons, but choose the
// default platform.
if (!OSXTarget.empty() && !iOSTarget.empty()) {
if (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::arm64 ||
getTriple().getArch() == llvm::Triple::thumb)
OSXTarget = "";
else
iOSTarget = "";
}
if (!OSXTarget.empty()) {
const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
Args.append(OSXVersion);
} else if (!iOSTarget.empty()) {
const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
iOSVersion = Args.MakeJoinedArg(0, O, iOSTarget);
Args.append(iOSVersion);
} else if (!iOSSimTarget.empty()) {
const Option O = Opts.getOption(
options::OPT_mios_simulator_version_min_EQ);
iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget);
Args.append(iOSSimVersion);
} else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em") {
// Otherwise, assume we are targeting OS X.
const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
Args.append(OSXVersion);
}
}
DarwinPlatformKind Platform;
if (OSXVersion)
Platform = MacOS;
else if (iOSVersion)
Platform = IPhoneOS;
else if (iOSSimVersion)
Platform = IPhoneOSSimulator;
else
llvm_unreachable("Unable to infer Darwin variant");
// Reject invalid architecture combinations.
if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 &&
getTriple().getArch() != llvm::Triple::x86_64)) {
getDriver().Diag(diag::err_drv_invalid_arch_for_deployment_target)
<< getTriple().getArchName() << iOSSimVersion->getAsString(Args);
}
// Set the tool chain target information.
unsigned Major, Minor, Micro;
bool HadExtra;
if (Platform == MacOS) {
assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!");
if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor,
Micro, HadExtra) || HadExtra ||
Major != 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSXVersion->getAsString(Args);
} else if (Platform == IPhoneOS || Platform == IPhoneOSSimulator) {
const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion;
assert(Version && "Unknown target platform!");
if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor,
Micro, HadExtra) || HadExtra ||
Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< Version->getAsString(Args);
} else
llvm_unreachable("unknown kind of Darwin platform");
// In GCC, the simulator historically was treated as being OS X in some
// contexts, like determining the link logic, despite generally being called
// with an iOS deployment target. For compatibility, we detect the
// simulator as iOS + x86, and treat it differently in a few contexts.
if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64))
Platform = IPhoneOSSimulator;
setTarget(Platform, Major, Minor, Micro);
}
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
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 (!llvm::sys::fs::exists(P.str())) {
llvm::sys::path::remove_filename(P);
llvm::sys::path::append(P, "libstdc++.6.dylib");
if (llvm::sys::fs::exists(P.str())) {
CmdArgs.push_back(Args.MakeArgString(P.str()));
return;
}
}
}
// 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 (!llvm::sys::fs::exists("/usr/lib/libstdc++.dylib") &&
llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib")) {
CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
return;
}
// Otherwise, let the linker search.
CmdArgs.push_back("-lstdc++");
break;
}
}
}
void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// For Darwin platforms, use the compiler-rt-based support library
// instead of the gcc-provided one (which is also incidentally
// only present in the gcc lib dir, which makes it hard to find).
SmallString<128> P(getDriver().ResourceDir);
llvm::sys::path::append(P, "lib", "darwin");
// Use the newer cc_kext for iOS ARM after 6.0.
if (!isTargetIPhoneOS() || isTargetIOSSimulator() ||
getTriple().getArch() == llvm::Triple::arm64 ||
!isIPhoneOSVersionLT(6, 0)) {
llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
} else {
llvm::sys::path::append(P, "libclang_rt.cc_kext_ios5.a");
}
// For now, allow missing resource libraries to support developers who may
// not have compiler-rt checked out or integrated into their build.
if (llvm::sys::fs::exists(P.str()))
CmdArgs.push_back(Args.MakeArgString(P.str()));
}
DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const {
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
const OptTable &Opts = getDriver().getOpts();
// FIXME: We really want to get out of the tool chain level argument
// translation business, as it makes the driver functionality much
// more opaque. For now, we follow gcc closely solely for the
// purpose of easily achieving feature parity & testability. Once we
// have something that works, we should reevaluate each translation
// and try to push it down into tool specific logic.
for (ArgList::const_iterator it = Args.begin(),
ie = Args.end(); it != ie; ++it) {
Arg *A = *it;
if (A->getOption().matches(options::OPT_Xarch__)) {
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
llvm::Triple::ArchType XarchArch =
tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
if (!(XarchArch == getArch() ||
(BoundArch && XarchArch ==
tools::darwin::getArchTypeForMachOArchName(BoundArch))))
continue;
Arg *OriginalArg = A;
unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
unsigned Prev = Index;
Arg *XarchArg = Opts.ParseOneArg(Args, Index);
// If the argument parsing failed or more than one argument was
// consumed, the -Xarch_ argument's parameter tried to consume
// extra arguments. Emit an error and ignore.
//
// We also want to disallow any options which would alter the
// driver behavior; that isn't going to work in our model. We
// use isDriverOption() as an approximation, although things
// like -O4 are going to slip through.
if (!XarchArg || Index > Prev + 1) {
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
<< A->getAsString(Args);
continue;
} else if (XarchArg->getOption().hasFlag(options::DriverOption)) {
getDriver().Diag(diag::err_drv_invalid_Xarch_argument_isdriver)
<< A->getAsString(Args);
continue;
}
XarchArg->setBaseArg(A);
A = XarchArg;
DAL->AddSynthesizedArg(A);
// Linker input arguments require custom handling. The problem is that we
// have already constructed the phase actions, so we can not treat them as
// "input arguments".
if (A->getOption().hasFlag(options::LinkerInput)) {
// Convert the argument into individual Zlinker_input_args.
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
DAL->AddSeparateArg(OriginalArg,
Opts.getOption(options::OPT_Zlinker_input),
A->getValue(i));
}
continue;
}
}
// Sob. These is strictly gcc compatible for the time being. Apple
// gcc translates options twice, which means that self-expanding
// options add duplicates.
switch ((options::ID) A->getOption().getID()) {
default:
DAL->append(A);
break;
case options::OPT_mkernel:
case options::OPT_fapple_kext:
DAL->append(A);
DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
break;
case options::OPT_dependency_file:
DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF),
A->getValue());
break;
case options::OPT_gfull:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
DAL->AddFlagArg(A,
Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
break;
case options::OPT_gused:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
DAL->AddFlagArg(A,
Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
break;
case options::OPT_shared:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
break;
case options::OPT_fconstant_cfstrings:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
break;
case options::OPT_fno_constant_cfstrings:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
break;
case options::OPT_Wnonportable_cfstrings:
DAL->AddFlagArg(A,
Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
break;
case options::OPT_Wno_nonportable_cfstrings:
DAL->AddFlagArg(A,
Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
break;
case options::OPT_fpascal_strings:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
break;
case options::OPT_fno_pascal_strings:
DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
break;
}
}
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64)
if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ), "core2");
// Add the arch options based on the particular spelling of -arch, to match
// how the driver driver works.
if (BoundArch) {
StringRef Name = BoundArch;
const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
const Option MArch = Opts.getOption(options::OPT_march_EQ);
// This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
// which defines the list of which architectures we accept.
if (Name == "ppc")
;
else if (Name == "ppc601")
DAL->AddJoinedArg(0, MCpu, "601");
else if (Name == "ppc603")
DAL->AddJoinedArg(0, MCpu, "603");
else if (Name == "ppc604")
DAL->AddJoinedArg(0, MCpu, "604");
else if (Name == "ppc604e")
DAL->AddJoinedArg(0, MCpu, "604e");
else if (Name == "ppc750")
DAL->AddJoinedArg(0, MCpu, "750");
else if (Name == "ppc7400")
DAL->AddJoinedArg(0, MCpu, "7400");
else if (Name == "ppc7450")
DAL->AddJoinedArg(0, MCpu, "7450");
else if (Name == "ppc970")
DAL->AddJoinedArg(0, MCpu, "970");
else if (Name == "ppc64" || Name == "ppc64le")
DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
else if (Name == "i386")
;
else if (Name == "i486")
DAL->AddJoinedArg(0, MArch, "i486");
else if (Name == "i586")
DAL->AddJoinedArg(0, MArch, "i586");
else if (Name == "i686")
DAL->AddJoinedArg(0, MArch, "i686");
else if (Name == "pentium")
DAL->AddJoinedArg(0, MArch, "pentium");
else if (Name == "pentium2")
DAL->AddJoinedArg(0, MArch, "pentium2");
else if (Name == "pentpro")
DAL->AddJoinedArg(0, MArch, "pentiumpro");
else if (Name == "pentIIm3")
DAL->AddJoinedArg(0, MArch, "pentium2");
else if (Name == "x86_64")
DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
else if (Name == "x86_64h") {
DAL->AddFlagArg(0, Opts.getOption(options::OPT_m64));
DAL->AddJoinedArg(0, MArch, "x86_64h");
}
else if (Name == "arm")
DAL->AddJoinedArg(0, MArch, "armv4t");
else if (Name == "armv4t")
DAL->AddJoinedArg(0, MArch, "armv4t");
else if (Name == "armv5")
DAL->AddJoinedArg(0, MArch, "armv5tej");
else if (Name == "xscale")
DAL->AddJoinedArg(0, MArch, "xscale");
else if (Name == "armv6")
DAL->AddJoinedArg(0, MArch, "armv6k");
else if (Name == "armv6m")
DAL->AddJoinedArg(0, MArch, "armv6m");
else if (Name == "armv7")
DAL->AddJoinedArg(0, MArch, "armv7a");
else if (Name == "armv7em")
DAL->AddJoinedArg(0, MArch, "armv7em");
else if (Name == "armv7k")
DAL->AddJoinedArg(0, MArch, "armv7k");
else if (Name == "armv7m")
DAL->AddJoinedArg(0, MArch, "armv7m");
else if (Name == "armv7s")
DAL->AddJoinedArg(0, MArch, "armv7s");
else if (Name == "arm64")
DAL->AddJoinedArg(0, MArch, "arm64");
else if (Name == "armv8")
DAL->AddJoinedArg(0, MArch, "arm64");
}
return DAL;
}
void MachO::AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
// Embedded targets are simple at the moment, not supporting sanitizers and
// with different libraries for each member of the product { static, PIC } x
// { hard-float, soft-float }
llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
CompilerRT +=
tools::arm::getARMFloatABI(getDriver(), Args, getTriple()) == "hard"
? "hard"
: "soft";
CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic.a" : "_static.a";
AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
}
DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const {
// First get the generic Apple args, before moving onto Darwin-specific ones.
DerivedArgList *DAL = MachO::TranslateArgs(Args, BoundArch);
const OptTable &Opts = getDriver().getOpts();
// If no architecture is bound, none of the translations here are relevant.
if (!BoundArch)
return DAL;
// Add an explicit version min argument for the deployment target. We do this
// after argument translation because -Xarch_ arguments may add a version min
// argument.
AddDeploymentTarget(*DAL);
// For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
// FIXME: It would be far better to avoid inserting those -static arguments,
// but we can't check the deployment target in the translation code until
// it is set here.
if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0) &&
getTriple().getArch() != llvm::Triple::arm64) {
for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
++it;
if (A->getOption().getID() != options::OPT_mkernel &&
A->getOption().getID() != options::OPT_fapple_kext)
continue;
assert(it != ie && "unexpected argument translation");
A = *it;
assert(A->getOption().getID() == options::OPT_static &&
"missing expected -static argument");
it = DAL->getArgs().erase(it);
}
}
// Default to use libc++ on OS X 10.9+ and iOS 7+.
if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
(isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
!Args.getLastArg(options::OPT_stdlib_EQ))
DAL->AddJoinedArg(0, Opts.getOption(options::OPT_stdlib_EQ), "libc++");
// Validate the C++ standard library choice.
CXXStdlibType Type = GetCXXStdlibType(*DAL);
if (Type == ToolChain::CST_Libcxx) {
// Check whether the target provides libc++.
StringRef where;
// Complain about targeting iOS < 5.0 in any way.
if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
where = "iOS 5.0";
if (where != StringRef()) {
getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment)
<< where;
}
}
return DAL;
}
bool MachO::IsUnwindTablesDefault() const {
return getArch() == llvm::Triple::x86_64;
}
bool MachO::UseDwarfDebugFlags() const {
if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
return S[0] != '\0';
return false;
}
bool Darwin::UseSjLjExceptions() const {
// Darwin uses SjLj exceptions on ARM.
return (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::thumb);
}
bool MachO::isPICDefault() const {
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
return true;
}
bool MachO::isPIEDefault() const {
return false;
}
bool MachO::isPICDefaultForced() const {
return (getArch() == llvm::Triple::x86_64 ||
getArch() == llvm::Triple::arm64);
}
bool MachO::SupportsProfiling() const {
// Profiling instrumentation is only supported on x86.
return getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::x86_64;
}
void Darwin::addMinVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
VersionTuple TargetVersion = getTargetVersion();
// If we had an explicit -mios-simulator-version-min argument, honor that,
// otherwise use the traditional deployment targets. We can't just check the
// is-sim attribute because existing code follows this path, and the linker
// may not handle the argument.
//
// FIXME: We may be able to remove this, once we can verify no one depends on
// it.
if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ))
CmdArgs.push_back("-ios_simulator_version_min");
else if (isTargetIOSBased())
CmdArgs.push_back("-iphoneos_version_min");
else {
assert(isTargetMacOS() && "unexpected target");
CmdArgs.push_back("-macosx_version_min");
}
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}
void Darwin::addStartObjectFileArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib)) {
// Derived from darwin_dylib1 spec.
if (isTargetIOSSimulator()) {
; // iOS simulator does not need dylib1.o.
} else if (isTargetIPhoneOS()) {
if (isIPhoneOSVersionLT(3, 1))
CmdArgs.push_back("-ldylib1.o");
} else {
if (isMacosxVersionLT(10, 5))
CmdArgs.push_back("-ldylib1.o");
else if (isMacosxVersionLT(10, 6))
CmdArgs.push_back("-ldylib1.10.5.o");
}
} else {
if (Args.hasArg(options::OPT_bundle)) {
if (!Args.hasArg(options::OPT_static)) {
// Derived from darwin_bundle1 spec.
if (isTargetIOSSimulator()) {
; // iOS simulator does not need bundle1.o.
} else if (isTargetIPhoneOS()) {
if (isIPhoneOSVersionLT(3, 1))
CmdArgs.push_back("-lbundle1.o");
} else {
if (isMacosxVersionLT(10, 6))
CmdArgs.push_back("-lbundle1.o");
}
}
} else {
if (Args.hasArg(options::OPT_pg) && SupportsProfiling()) {
if (Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_object) ||
Args.hasArg(options::OPT_preload)) {
CmdArgs.push_back("-lgcrt0.o");
} else {
CmdArgs.push_back("-lgcrt1.o");
// darwin_crt2 spec is empty.
}
// By default on OS X 10.8 and later, we don't link with a crt1.o
// file and the linker knows to use _main as the entry point. But,
// when compiling with -pg, we need to link with the gcrt1.o file,
// so pass the -no_new_main option to tell the linker to use the
// "start" symbol as the entry point.
if (isTargetMacOS() && !isMacosxVersionLT(10, 8))
CmdArgs.push_back("-no_new_main");
} else {
if (Args.hasArg(options::OPT_static) ||
Args.hasArg(options::OPT_object) ||
Args.hasArg(options::OPT_preload)) {
CmdArgs.push_back("-lcrt0.o");
} else {
// Derived from darwin_crt1 spec.
if (isTargetIOSSimulator()) {
; // iOS simulator does not need crt1.o.
} else if (isTargetIPhoneOS()) {
if (getArch() == llvm::Triple::arm64)
; // iOS does not need any crt1 files for arm64
else if (isIPhoneOSVersionLT(3, 1))
CmdArgs.push_back("-lcrt1.o");
else if (isIPhoneOSVersionLT(6, 0))
CmdArgs.push_back("-lcrt1.3.1.o");
} else {
if (isMacosxVersionLT(10, 5))
CmdArgs.push_back("-lcrt1.o");
else if (isMacosxVersionLT(10, 6))
CmdArgs.push_back("-lcrt1.10.5.o");
else if (isMacosxVersionLT(10, 8))
CmdArgs.push_back("-lcrt1.10.6.o");
// darwin_crt2 spec is empty.
}
}
}
}
}
if (!isTargetIPhoneOS() && Args.hasArg(options::OPT_shared_libgcc) &&
isMacosxVersionLT(10, 5)) {
const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
CmdArgs.push_back(Str);
}
}
bool Darwin::SupportsObjCGC() const {
return isTargetMacOS();
}
void Darwin::CheckObjCARC() const {
if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
return;
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
/// \brief Parse a GCCVersion object out of a string of text.
///
/// This is the primary means of forming GCCVersion objects.
/*static*/
Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
std::pair<StringRef, StringRef> First = VersionText.split('.');
std::pair<StringRef, StringRef> Second = First.second.split('.');
GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "", "", "" };
if (First.first.getAsInteger(10, GoodVersion.Major) ||
GoodVersion.Major < 0)
return BadVersion;
GoodVersion.MajorStr = First.first.str();
if (Second.first.getAsInteger(10, GoodVersion.Minor) ||
GoodVersion.Minor < 0)
return BadVersion;
GoodVersion.MinorStr = Second.first.str();
// First look for a number prefix and parse that if present. Otherwise just
// stash the entire patch string in the suffix, and leave the number
// unspecified. This covers versions strings such as:
// 4.4
// 4.4.0
// 4.4.x
// 4.4.2-rc4
// 4.4.x-patched
// And retains any patch number it finds.
StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str();
if (!PatchText.empty()) {
if (size_t EndNumber = PatchText.find_first_not_of("0123456789")) {
// Try to parse the number and any suffix.
if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
GoodVersion.Patch < 0)
return BadVersion;
GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
}
}
return GoodVersion;
}
/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
bool Generic_GCC::GCCVersion::isOlderThan(int RHSMajor, int RHSMinor,
int RHSPatch,
StringRef RHSPatchSuffix) const {
if (Major != RHSMajor)
return Major < RHSMajor;
if (Minor != RHSMinor)
return Minor < RHSMinor;
if (Patch != RHSPatch) {
// Note that versions without a specified patch sort higher than those with
// a patch.
if (RHSPatch == -1)
return true;
if (Patch == -1)
return false;
// Otherwise just sort on the patch itself.
return Patch < RHSPatch;
}
if (PatchSuffix != RHSPatchSuffix) {
// Sort empty suffixes higher.
if (RHSPatchSuffix.empty())
return true;
if (PatchSuffix.empty())
return false;
// Provide a lexicographic sort to make this a total ordering.
return PatchSuffix < RHSPatchSuffix;
}
// The versions are equal.
return false;
}
static llvm::StringRef getGCCToolchainDir(const ArgList &Args) {
const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain);
if (A)
return A->getValue();
return GCC_INSTALL_PREFIX;
}
/// \brief Initialize a GCCInstallationDetector from the driver.
///
/// This performs all of the autodetection and sets up the various paths.
2012-04-17 19:16:26 +08:00
/// Once constructed, a GCCInstallationDetector is essentially immutable.
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
///
/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and
/// should instead pull the target out of the driver. This is currently
/// necessary because the driver doesn't store the final version of the target
/// triple.
void
Generic_GCC::GCCInstallationDetector::init(
const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args) {
llvm::Triple BiarchVariantTriple =
TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
: TargetTriple.get32BitArchVariant();
// The library directories which may contain GCC installations.
SmallVector<StringRef, 4> CandidateLibDirs, CandidateBiarchLibDirs;
// The compatible GCC triples for this particular architecture.
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
SmallVector<StringRef, 10> CandidateTripleAliases;
SmallVector<StringRef, 10> CandidateBiarchTripleAliases;
CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs,
CandidateTripleAliases, CandidateBiarchLibDirs,
CandidateBiarchTripleAliases);
// Compute the set of prefixes for our search.
SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
D.PrefixDirs.end());
StringRef GCCToolchainDir = getGCCToolchainDir(Args);
if (GCCToolchainDir != "") {
if (GCCToolchainDir.back() == '/')
GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the /
Prefixes.push_back(GCCToolchainDir);
} else {
// If we have a SysRoot, try that first.
if (!D.SysRoot.empty()) {
Prefixes.push_back(D.SysRoot);
Prefixes.push_back(D.SysRoot + "/usr");
}
// Then look for gcc installed alongside clang.
Prefixes.push_back(D.InstalledDir + "/..");
// And finally in /usr.
if (D.SysRoot.empty())
Prefixes.push_back("/usr");
}
// Loop over the various components which exist and select the best GCC
// installation available. GCC installs are ranked by version number.
Version = GCCVersion::Parse("0.0.0");
for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
if (!llvm::sys::fs::exists(Prefixes[i]))
continue;
for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) {
const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str();
if (!llvm::sys::fs::exists(LibDir))
continue;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
CandidateTripleAliases[k]);
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
}
for (unsigned j = 0, je = CandidateBiarchLibDirs.size(); j < je; ++j) {
const std::string LibDir = Prefixes[i] + CandidateBiarchLibDirs[j].str();
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
if (!llvm::sys::fs::exists(LibDir))
continue;
for (unsigned k = 0, ke = CandidateBiarchTripleAliases.size(); k < ke;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
++k)
ScanLibDirForGCCTriple(TargetTriple, Args, LibDir,
CandidateBiarchTripleAliases[k],
/*NeedsBiarchSuffix=*/ true);
}
}
}
void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
for (std::set<std::string>::const_iterator
I = CandidateGCCInstallPaths.begin(),
E = CandidateGCCInstallPaths.end();
I != E; ++I)
OS << "Found candidate GCC installation: " << *I << "\n";
if (!GCCInstallPath.empty())
OS << "Selected GCC installation: " << GCCInstallPath << "\n";
for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
I != E; ++I) {
OS << "Candidate multilib: " << *I << "\n";
}
if (Multilibs.size() != 0 || !SelectedMultilib.isDefault())
OS << "Selected multilib: " << SelectedMultilib << "\n";
}
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
if (BiarchSibling.hasValue()) {
M = BiarchSibling.getValue();
return true;
}
return false;
}
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple,
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
SmallVectorImpl<StringRef> &LibDirs,
SmallVectorImpl<StringRef> &TripleAliases,
SmallVectorImpl<StringRef> &BiarchLibDirs,
SmallVectorImpl<StringRef> &BiarchTripleAliases) {
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
// Declare a bunch of static data sets that we'll select between below. These
// are specifically designed to always refer to string literals to avoid any
// lifetime or initialization issues.
static const char *const AArch64LibDirs[] = { "/lib" };
static const char *const AArch64Triples[] = { "aarch64-none-linux-gnu",
"aarch64-linux-gnu" };
static const char *const AArch64beLibDirs[] = { "/lib" };
static const char *const AArch64beTriples[] = { "aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const ARMLibDirs[] = { "/lib" };
static const char *const ARMTriples[] = { "arm-linux-gnueabi",
"arm-linux-androideabi" };
static const char *const ARMHFTriples[] = { "arm-linux-gnueabihf",
"armv7hl-redhat-linux-gnueabi" };
static const char *const ARMebLibDirs[] = { "/lib" };
static const char *const ARMebTriples[] = { "armeb-linux-gnueabi",
"armeb-linux-androideabi" };
static const char *const ARMebHFTriples[] = { "armeb-linux-gnueabihf",
"armebv7hl-redhat-linux-gnueabi" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const X86_64LibDirs[] = { "/lib64", "/lib" };
static const char *const X86_64Triples[] = {
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-pc-linux-gnu",
"x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu", "x86_64-slackware-linux",
"x86_64-linux-android"
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
};
static const char *const X86LibDirs[] = { "/lib32", "/lib" };
static const char *const X86Triples[] = {
"i686-linux-gnu", "i686-pc-linux-gnu", "i486-linux-gnu", "i386-linux-gnu",
"i386-redhat-linux6E", "i686-redhat-linux", "i586-redhat-linux",
"i386-redhat-linux", "i586-suse-linux", "i486-slackware-linux",
"i686-montavista-linux", "i686-linux-android"
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
};
static const char *const MIPSLibDirs[] = { "/lib" };
static const char *const MIPSTriples[] = { "mips-linux-gnu",
"mips-mti-linux-gnu" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const MIPSELLibDirs[] = { "/lib" };
static const char *const MIPSELTriples[] = { "mipsel-linux-gnu",
"mipsel-linux-android" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const MIPS64LibDirs[] = { "/lib64", "/lib" };
static const char *const MIPS64Triples[] = { "mips64-linux-gnu",
"mips-mti-linux-gnu" };
static const char *const MIPS64ELLibDirs[] = { "/lib64", "/lib" };
static const char *const MIPS64ELTriples[] = { "mips64el-linux-gnu",
"mips-mti-linux-gnu",
"mips64el-linux-android" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const PPCLibDirs[] = { "/lib32", "/lib" };
static const char *const PPCTriples[] = {
"powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe",
"powerpc-suse-linux", "powerpc-montavista-linuxspe"
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
};
static const char *const PPC64LibDirs[] = { "/lib64", "/lib" };
static const char *const PPC64Triples[] = { "powerpc64-linux-gnu",
"powerpc64-unknown-linux-gnu",
"powerpc64-suse-linux",
"ppc64-redhat-linux" };
static const char *const PPC64LELibDirs[] = { "/lib64", "/lib" };
static const char *const PPC64LETriples[] = { "powerpc64le-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"powerpc64le-suse-linux",
"ppc64le-redhat-linux" };
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
static const char *const SPARCv8LibDirs[] = { "/lib32", "/lib" };
static const char *const SPARCv8Triples[] = { "sparc-linux-gnu",
"sparcv8-linux-gnu" };
static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" };
static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu",
"sparcv9-linux-gnu" };
static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
static const char *const SystemZTriples[] = {
"s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
"s390x-suse-linux", "s390x-redhat-linux"
};
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
switch (TargetTriple.getArch()) {
case llvm::Triple::arm64:
case llvm::Triple::aarch64:
LibDirs.append(AArch64LibDirs,
AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs));
TripleAliases.append(AArch64Triples,
AArch64Triples + llvm::array_lengthof(AArch64Triples));
BiarchLibDirs.append(AArch64LibDirs,
AArch64LibDirs + llvm::array_lengthof(AArch64LibDirs));
BiarchTripleAliases.append(
AArch64Triples, AArch64Triples + llvm::array_lengthof(AArch64Triples));
break;
case llvm::Triple::aarch64_be:
LibDirs.append(AArch64beLibDirs,
AArch64beLibDirs + llvm::array_lengthof(AArch64beLibDirs));
TripleAliases.append(AArch64beTriples,
AArch64beTriples + llvm::array_lengthof(AArch64beTriples));
BiarchLibDirs.append(AArch64beLibDirs,
AArch64beLibDirs + llvm::array_lengthof(AArch64beLibDirs));
BiarchTripleAliases.append(
AArch64beTriples, AArch64beTriples + llvm::array_lengthof(AArch64beTriples));
break;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
case llvm::Triple::arm:
case llvm::Triple::thumb:
LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
TripleAliases.append(ARMHFTriples,
ARMHFTriples + llvm::array_lengthof(ARMHFTriples));
} else {
TripleAliases.append(ARMTriples,
ARMTriples + llvm::array_lengthof(ARMTriples));
}
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
LibDirs.append(ARMebLibDirs, ARMebLibDirs + llvm::array_lengthof(ARMebLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
TripleAliases.append(ARMebHFTriples,
ARMebHFTriples + llvm::array_lengthof(ARMebHFTriples));
} else {
TripleAliases.append(ARMebTriples,
ARMebTriples + llvm::array_lengthof(ARMebTriples));
}
break;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
case llvm::Triple::x86_64:
LibDirs.append(X86_64LibDirs,
X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
TripleAliases.append(X86_64Triples,
X86_64Triples + llvm::array_lengthof(X86_64Triples));
BiarchLibDirs.append(X86LibDirs,
X86LibDirs + llvm::array_lengthof(X86LibDirs));
BiarchTripleAliases.append(X86Triples,
X86Triples + llvm::array_lengthof(X86Triples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::x86:
LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs));
TripleAliases.append(X86Triples,
X86Triples + llvm::array_lengthof(X86Triples));
BiarchLibDirs.append(X86_64LibDirs,
X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs));
BiarchTripleAliases.append(
X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::mips:
LibDirs.append(MIPSLibDirs,
MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
TripleAliases.append(MIPSTriples,
MIPSTriples + llvm::array_lengthof(MIPSTriples));
BiarchLibDirs.append(MIPS64LibDirs,
MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
BiarchTripleAliases.append(
MIPS64Triples, MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::mipsel:
LibDirs.append(MIPSELLibDirs,
MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
TripleAliases.append(MIPSELTriples,
MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
TripleAliases.append(MIPSTriples,
MIPSTriples + llvm::array_lengthof(MIPSTriples));
BiarchLibDirs.append(
MIPS64ELLibDirs,
MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
BiarchTripleAliases.append(
MIPS64ELTriples,
MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
break;
case llvm::Triple::mips64:
LibDirs.append(MIPS64LibDirs,
MIPS64LibDirs + llvm::array_lengthof(MIPS64LibDirs));
TripleAliases.append(MIPS64Triples,
MIPS64Triples + llvm::array_lengthof(MIPS64Triples));
BiarchLibDirs.append(MIPSLibDirs,
MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs));
BiarchTripleAliases.append(MIPSTriples,
MIPSTriples + llvm::array_lengthof(MIPSTriples));
break;
case llvm::Triple::mips64el:
LibDirs.append(MIPS64ELLibDirs,
MIPS64ELLibDirs + llvm::array_lengthof(MIPS64ELLibDirs));
TripleAliases.append(
MIPS64ELTriples,
MIPS64ELTriples + llvm::array_lengthof(MIPS64ELTriples));
BiarchLibDirs.append(MIPSELLibDirs,
MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs));
BiarchTripleAliases.append(
MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples));
BiarchTripleAliases.append(
MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::ppc:
LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
TripleAliases.append(PPCTriples,
PPCTriples + llvm::array_lengthof(PPCTriples));
BiarchLibDirs.append(PPC64LibDirs,
PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
BiarchTripleAliases.append(
PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::ppc64:
LibDirs.append(PPC64LibDirs,
PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs));
TripleAliases.append(PPC64Triples,
PPC64Triples + llvm::array_lengthof(PPC64Triples));
BiarchLibDirs.append(PPCLibDirs,
PPCLibDirs + llvm::array_lengthof(PPCLibDirs));
BiarchTripleAliases.append(PPCTriples,
PPCTriples + llvm::array_lengthof(PPCTriples));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
break;
case llvm::Triple::ppc64le:
LibDirs.append(PPC64LELibDirs,
PPC64LELibDirs + llvm::array_lengthof(PPC64LELibDirs));
TripleAliases.append(PPC64LETriples,
PPC64LETriples + llvm::array_lengthof(PPC64LETriples));
break;
case llvm::Triple::sparc:
LibDirs.append(SPARCv8LibDirs,
SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
TripleAliases.append(SPARCv8Triples,
SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
BiarchLibDirs.append(SPARCv9LibDirs,
SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
BiarchTripleAliases.append(
SPARCv9Triples, SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
break;
case llvm::Triple::sparcv9:
LibDirs.append(SPARCv9LibDirs,
SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
TripleAliases.append(SPARCv9Triples,
SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
BiarchLibDirs.append(SPARCv8LibDirs,
SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
BiarchTripleAliases.append(
SPARCv8Triples, SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
break;
case llvm::Triple::systemz:
LibDirs.append(SystemZLibDirs,
SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
TripleAliases.append(SystemZTriples,
SystemZTriples + llvm::array_lengthof(SystemZTriples));
break;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
default:
// By default, just rely on the standard lib directories and the original
// triple.
break;
}
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
// Always append the drivers target triple to the end, in case it doesn't
// match any of our aliases.
TripleAliases.push_back(TargetTriple.str());
// Also include the multiarch variant if it's different.
if (TargetTriple.str() != BiarchTriple.str())
BiarchTripleAliases.push_back(BiarchTriple.str());
}
namespace {
// Filter to remove Multilibs that don't exist as a suffix to Path
2014-02-25 12:21:44 +08:00
class FilterNonExistent : public MultilibSet::FilterCallback {
std::string Base;
public:
2014-02-25 12:21:44 +08:00
FilterNonExistent(std::string Base) : Base(Base) {}
bool operator()(const Multilib &M) const override {
return !llvm::sys::fs::exists(Base + M.gccSuffix() + "/crtbegin.o");
}
};
} // end anonymous namespace
static void addMultilibFlag(bool Enabled, const char *const Flag,
std::vector<std::string> &Flags) {
if (Enabled)
Flags.push_back(std::string("+") + Flag);
else
Flags.push_back(std::string("-") + Flag);
}
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
static bool isMipsArch(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
}
static bool isMips32(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel;
}
static bool isMips64(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
}
static bool isMipsEL(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mipsel || Arch == llvm::Triple::mips64el;
}
static bool isMipsEB(llvm::Triple::ArchType Arch) {
return Arch == llvm::Triple::mips || Arch == llvm::Triple::mips64;
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
}
static bool isMips16(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mips16,
options::OPT_mno_mips16);
return A && A->getOption().matches(options::OPT_mips16);
}
static bool isMips32r2(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_march_EQ,
options::OPT_mcpu_EQ);
return A && A->getValue() == StringRef("mips32r2");
}
static bool isMips64r2(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_march_EQ,
options::OPT_mcpu_EQ);
return A && A->getValue() == StringRef("mips64r2");
}
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
static bool isMicroMips(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mmicromips,
options::OPT_mno_micromips);
return A && A->getOption().matches(options::OPT_mmicromips);
}
static bool isMipsFP64(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mfp64, options::OPT_mfp32);
return A && A->getOption().matches(options::OPT_mfp64);
}
static bool isMipsNan2008(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_mnan_EQ);
return A && A->getValue() == StringRef("2008");
}
bool Generic_GCC::GCCInstallationDetector::findMIPSMultilibs(
const llvm::Triple &TargetTriple, StringRef Path,
const llvm::opt::ArgList &Args) {
// Some MIPS toolchains put libraries and object files compiled
// using different options in to the sub-directoris which names
// reflects the flags used for compilation. For example sysroot
// directory might looks like the following examples:
//
// /usr
// /lib <= crt*.o files compiled with '-mips32'
// /mips16
// /usr
// /lib <= crt*.o files compiled with '-mips16'
// /el
// /usr
// /lib <= crt*.o files compiled with '-mips16 -EL'
//
// or
//
// /usr
// /lib <= crt*.o files compiled with '-mips32r2'
// /mips16
// /usr
// /lib <= crt*.o files compiled with '-mips32r2 -mips16'
// /mips32
// /usr
// /lib <= crt*.o files compiled with '-mips32'
2014-02-25 12:21:44 +08:00
FilterNonExistent NonExistent(Path);
// Check for FSF toolchain multilibs
MultilibSet FSFMipsMultilibs;
{
Multilib MArchMips32 = Multilib()
.gccSuffix("/mips32")
.osSuffix("/mips32")
.includeSuffix("/mips32")
.flag("+m32").flag("-m64").flag("-mmicromips").flag("-march=mips32r2");
Multilib MArchMicroMips = Multilib()
.gccSuffix("/micromips")
.osSuffix("/micromips")
.includeSuffix("/micromips")
.flag("+m32").flag("-m64").flag("+mmicromips");
Multilib MArchMips64r2 = Multilib()
.gccSuffix("/mips64r2")
.osSuffix("/mips64r2")
.includeSuffix("/mips64r2")
.flag("-m32").flag("+m64").flag("+march=mips64r2");
Multilib MArchMips64 = Multilib()
.gccSuffix("/mips64")
.osSuffix("/mips64")
.includeSuffix("/mips64")
.flag("-m32").flag("+m64").flag("-march=mips64r2");
Multilib MArchDefault = Multilib()
.flag("+m32").flag("-m64").flag("+march=mips32r2");
Multilib Mips16 = Multilib()
.gccSuffix("/mips16")
.osSuffix("/mips16")
.includeSuffix("/mips16")
.flag("+mips16");
Multilib MAbi64 = Multilib()
.gccSuffix("/64")
.osSuffix("/64")
.includeSuffix("/64")
.flag("+mabi=64").flag("-mabi=n32").flag("-m32");
Multilib BigEndian = Multilib()
.flag("+EB").flag("-EL");
Multilib LittleEndian = Multilib()
.gccSuffix("/el")
.osSuffix("/el")
.includeSuffix("/el")
.flag("+EL").flag("-EB");
Multilib SoftFloat = Multilib()
.gccSuffix("/sof")
.osSuffix("/sof")
.includeSuffix("/sof")
.flag("+msoft-float");
Multilib FP64 = Multilib()
.gccSuffix("/fp64")
.osSuffix("/fp64")
.includeSuffix("/fp64")
.flag("+mfp64");
Multilib Nan2008 = Multilib()
.gccSuffix("/nan2008")
.osSuffix("/nan2008")
.includeSuffix("/nan2008")
.flag("+mnan=2008");
FSFMipsMultilibs = MultilibSet()
.Either(MArchMips32, MArchMicroMips,
MArchMips64r2, MArchMips64, MArchDefault)
.Maybe(Mips16)
.FilterOut("/mips64/mips16")
.FilterOut("/mips64r2/mips16")
.FilterOut("/micromips/mips16")
.Maybe(MAbi64)
.FilterOut("/micromips/64")
.FilterOut("/mips32/64")
.FilterOut("^/64")
.FilterOut("/mips16/64")
.Either(BigEndian, LittleEndian)
.Maybe(SoftFloat)
.Maybe(FP64)
.Maybe(Nan2008)
.FilterOut(".*sof/nan2008")
.FilterOut(".*sof/fp64")
2014-02-25 12:21:44 +08:00
.FilterOut(NonExistent);
}
// Check for Code Sourcery toolchain multilibs
MultilibSet CSMipsMultilibs;
{
Multilib MArchMips16 = Multilib()
.gccSuffix("/mips16")
.osSuffix("/mips16")
.includeSuffix("/mips16")
.flag("+m32").flag("+mips16");
Multilib MArchMicroMips = Multilib()
.gccSuffix("/micromips")
.osSuffix("/micromips")
.includeSuffix("/micromips")
.flag("+m32").flag("+mmicromips");
Multilib MArchDefault = Multilib()
.flag("-mips16").flag("-mmicromips");
Multilib SoftFloat = Multilib()
.gccSuffix("/soft-float")
.osSuffix("/soft-float")
.includeSuffix("/soft-float")
.flag("+msoft-float");
Multilib Nan2008 = Multilib()
.gccSuffix("/nan2008")
.osSuffix("/nan2008")
.includeSuffix("/nan2008")
.flag("+mnan=2008");
Multilib DefaultFloat = Multilib()
.flag("-msoft-float").flag("-mnan=2008");
Multilib BigEndian = Multilib()
.flag("+EB").flag("-EL");
Multilib LittleEndian = Multilib()
.gccSuffix("/el")
.osSuffix("/el")
.includeSuffix("/el")
.flag("+EL").flag("-EB");
// Note that this one's osSuffix is ""
Multilib MAbi64 = Multilib()
.gccSuffix("/64")
.includeSuffix("/64")
.flag("+mabi=64").flag("-mabi=n32").flag("-m32");
CSMipsMultilibs = MultilibSet()
.Either(MArchMips16, MArchMicroMips, MArchDefault)
.Either(SoftFloat, Nan2008, DefaultFloat)
.FilterOut("/micromips/nan2008")
.FilterOut("/mips16/nan2008")
.Either(BigEndian, LittleEndian)
.Maybe(MAbi64)
.FilterOut("/mips16.*/64")
.FilterOut("/micromips.*/64")
2014-02-25 12:21:44 +08:00
.FilterOut(NonExistent);
}
MultilibSet AndroidMipsMultilibs = MultilibSet()
.Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
2014-02-25 12:21:44 +08:00
.FilterOut(NonExistent);
MultilibSet DebianMipsMultilibs;
{
Multilib MAbiN32 = Multilib()
.gccSuffix("/n32")
.includeSuffix("/n32")
.flag("+mabi=n32");
Multilib M64 = Multilib()
.gccSuffix("/64")
.includeSuffix("/64")
.flag("+m64").flag("-m32").flag("-mabi=n32");
Multilib M32 = Multilib()
.flag("-m64").flag("+m32").flag("-mabi=n32");
DebianMipsMultilibs = MultilibSet()
.Either(M32, M64, MAbiN32)
2014-02-25 12:21:44 +08:00
.FilterOut(NonExistent);
}
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
Multilib::flags_list Flags;
addMultilibFlag(isMips32(TargetArch), "m32", Flags);
addMultilibFlag(isMips64(TargetArch), "m64", Flags);
addMultilibFlag(isMips16(Args), "mips16", Flags);
addMultilibFlag(isMips32r2(Args), "march=mips32r2", Flags);
addMultilibFlag(isMips64r2(Args), "march=mips64r2", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
addMultilibFlag(isMipsFP64(Args), "mfp64", Flags);
addMultilibFlag(!isMipsFP64(Args), "mfp32", Flags);
addMultilibFlag(isMipsNan2008(Args), "mnan=2008", Flags);
addMultilibFlag(tools::mips::hasMipsAbiArg(Args, "n32"), "mabi=n32", Flags);
// Default is to assume mabi=64
bool IsMABI64 =
tools::mips::hasMipsAbiArg(Args, "64") ||
(!tools::mips::hasMipsAbiArg(Args, "n32") && isMips64(TargetArch));
addMultilibFlag(IsMABI64, "mabi=64", Flags);
addMultilibFlag(isSoftFloatABI(Args), "msoft-float", Flags);
addMultilibFlag(isSoftFloatABI(Args), "mfloat-abi=soft", Flags);
addMultilibFlag(!isSoftFloatABI(Args), "mhard-float", Flags);
addMultilibFlag(!isSoftFloatABI(Args), "mfloat-abi=hard", Flags);
addMultilibFlag(isMipsEL(TargetArch), "EL", Flags);
addMultilibFlag(isMipsEB(TargetArch), "EB", Flags);
if (TargetTriple.getEnvironment() == llvm::Triple::Android) {
// Select Android toolchain. It's the only choice in that case.
Multilibs.clear();
Multilibs.combineWith(AndroidMipsMultilibs);
return Multilibs.select(Flags, SelectedMultilib);
}
// Sort candidates. Toolchain that best meets the directories goes first.
// Then select the first toolchains matches command line flags.
MultilibSet *candidates[] = { &DebianMipsMultilibs, &FSFMipsMultilibs,
&CSMipsMultilibs };
std::sort(
std::begin(candidates), std::end(candidates),
[](MultilibSet *a, MultilibSet *b) { return a->size() > b->size(); });
for (const auto &candidate : candidates) {
Multilibs.clear();
Multilibs.combineWith(*candidate);
if (Multilibs.select(Flags, SelectedMultilib)) {
if (candidate == &DebianMipsMultilibs)
BiarchSibling = Multilib();
return true;
}
}
return false;
}
bool Generic_GCC::GCCInstallationDetector::findBiarchMultilibs(
const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args,
bool NeedsBiarchSuffix) {
// Some versions of SUSE and Fedora on ppc64 put 32-bit libs
// in what would normally be GCCInstallPath and put the 64-bit
// libs in a subdirectory named 64. The simple logic we follow is that
// *if* there is a subdirectory of the right name with crtbegin.o in it,
// we use that. If not, and if not a biarch triple alias, we look for
// crtbegin.o without the subdirectory.
Multilib Default;
Multilib Alt64 = Multilib()
.gccSuffix("/64")
.includeSuffix("/64")
.flag("-m32").flag("+m64");
Multilib Alt32 = Multilib()
.gccSuffix("/32")
.includeSuffix("/32")
.flag("+m32").flag("-m64");
2014-02-25 12:21:44 +08:00
FilterNonExistent NonExistent(Path);
// Decide whether the default multilib is 32bit, correcting for
// when the default multilib and the alternate appear backwards
bool DefaultIs32Bit;
2014-02-25 12:21:44 +08:00
if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
DefaultIs32Bit = false;
2014-02-25 12:21:44 +08:00
else if (TargetTriple.isArch64Bit() && !NonExistent(Alt64))
DefaultIs32Bit = true;
else {
if (NeedsBiarchSuffix)
DefaultIs32Bit = TargetTriple.isArch64Bit();
else
DefaultIs32Bit = TargetTriple.isArch32Bit();
}
if (DefaultIs32Bit)
Default.flag("+m32").flag("-m64");
else
Default.flag("-m32").flag("+m64");
Multilibs.push_back(Default);
Multilibs.push_back(Alt64);
Multilibs.push_back(Alt32);
2014-02-25 12:21:44 +08:00
Multilibs.FilterOut(NonExistent);
Multilib::flags_list Flags;
addMultilibFlag(TargetTriple.isArch64Bit(), "m64", Flags);
addMultilibFlag(TargetTriple.isArch32Bit(), "m32", Flags);
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
if (!Multilibs.select(Flags, SelectedMultilib))
return false;
if (SelectedMultilib == Alt64 || SelectedMultilib == Alt32) {
BiarchSibling = Default;
}
return true;
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
}
void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
const llvm::Triple &TargetTriple, const ArgList &Args,
const std::string &LibDir, StringRef CandidateTriple,
bool NeedsBiarchSuffix) {
llvm::Triple::ArchType TargetArch = TargetTriple.getArch();
// There are various different suffixes involving the triple we
// check for. We also record what is necessary to walk from each back
// up to the lib directory.
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
const std::string LibSuffixes[] = {
"/gcc/" + CandidateTriple.str(),
// Debian puts cross-compilers in gcc-cross
"/gcc-cross/" + CandidateTriple.str(),
"/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(),
// The Freescale PPC SDK has the gcc libraries in
// <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well.
"/" + CandidateTriple.str(),
// Ubuntu has a strange mis-matched pair of triples that this happens to
// match.
// FIXME: It may be worthwhile to generalize this and look for a second
// triple.
"/i386-linux-gnu/gcc/" + CandidateTriple.str()
};
const std::string InstallSuffixes[] = {
"/../../..", // gcc/
"/../../..", // gcc-cross/
"/../../../..", // <triple>/gcc/
"/../..", // <triple>/
"/../../../.." // i386-linux-gnu/gcc/<triple>/
};
// Only look at the final, weird Ubuntu suffix for i386-linux-gnu.
const unsigned NumLibSuffixes =
(llvm::array_lengthof(LibSuffixes) - (TargetArch != llvm::Triple::x86));
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
for (unsigned i = 0; i < NumLibSuffixes; ++i) {
StringRef LibSuffix = LibSuffixes[i];
llvm::error_code EC;
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
if (CandidateVersion.Major != -1) // Filter obviously bad entries.
if (!CandidateGCCInstallPaths.insert(LI->path()).second)
continue; // Saw this path before; no need to look at it again.
if (CandidateVersion.isOlderThan(4, 1, 1))
continue;
if (CandidateVersion <= Version)
continue;
Multilibs.clear();
SelectedMultilib = Multilib();
BiarchSibling.reset();
// Debian mips multilibs behave more like the rest of the biarch ones,
// so handle them there
if (isMipsArch(TargetArch)) {
if (!findMIPSMultilibs(TargetTriple, LI->path(), Args))
continue;
} else if (!findBiarchMultilibs(TargetTriple, LI->path(), Args,
NeedsBiarchSuffix))
continue;
Version = CandidateVersion;
GCCTriple.setTriple(CandidateTriple);
// FIXME: We hack together the directory name here instead of
// using LI to ensure stable path separators across Windows and
// Linux.
Make a major refactoring to how the GCC installation detection works. The fundamental shift here is to stop making *any* assumptions about the *host* triple. Where these assumptions you ask? Why, they were in one of the two target triples referenced of course. This was the single biggest place where the previously named "host triple" was actually used as such. ;] The reason we were reasoning about the host is in order to detect the use of '-m32' or '-m64' flags to change the target. These flags shift the default target only slightly, which typically means a slight deviation from the host. When using these flags, the GCC installation is under a different triple from the one actually targeted in the compilation, and we used the host triple to find it. Too bad that wasn't even correct. Consider an x86 Linux host which has a PPC64 cross-compiling GCC toolchain installed. This toolchain is also configured for multiarch compiling and can target PPC32 with eth '-m32' flag. When targeting 'powerpc-linux-gnu' or some other PPC32 triple, we have to look for the PPC64 variant of the triple to find the GCC install, and that triple is neither the host nor target. The new logic computes the multiarch's alternate triple from the target triple, and looks under both sides. It also looks more aggressively for the correct subdirectory of the GCC installation, and exposes the subdirectory in a nice programmatic way. This '/32' or '/64' suffix is something we can reuse in many other parts of the toolchain. An important note -- while this likely fixes a large category of cross-compile use cases, that's not my primary goal, and I've not done testing (or added test cases) for scenarios that may now work. If someone else wants to try more interesting PPC cross compiles, I'd love to have reports. But my focus is on factoring away the references to the "host" triple. The refactoring is my goal, and so I'm mostly relying on the existing (pretty good) test coverage we have here. Future patches will leverage this new functionality to factor out more and more of the toolchain's triple manipulation. llvm-svn: 148935
2012-01-25 15:21:38 +08:00
GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str();
GCCParentLibPath = GCCInstallPath + InstallSuffixes[i];
IsValid = true;
}
}
}
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), GCCInstallation() {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
}
Generic_GCC::~Generic_GCC() {
}
Tool *Generic_GCC::getTool(Action::ActionClass AC) const {
switch (AC) {
case Action::PreprocessJobClass:
if (!Preprocess)
Preprocess.reset(new tools::gcc::Preprocess(*this));
return Preprocess.get();
case Action::CompileJobClass:
if (!Compile)
Compile.reset(new tools::gcc::Compile(*this));
return Compile.get();
default:
return ToolChain::getTool(AC);
}
}
Tool *Generic_GCC::buildAssembler() const {
return new tools::gnutools::Assemble(*this);
}
Tool *Generic_GCC::buildLinker() const {
return new tools::gcc::Link(*this);
}
void Generic_GCC::printVerboseInfo(raw_ostream &OS) const {
// Print the information about how we detected the GCC installation.
GCCInstallation.print(OS);
}
bool Generic_GCC::IsUnwindTablesDefault() const {
return getArch() == llvm::Triple::x86_64;
}
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
bool Generic_GCC::isPICDefault() const {
return false;
}
bool Generic_GCC::isPIEDefault() const {
return false;
}
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
bool Generic_GCC::isPICDefaultForced() const {
return false;
}
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
bool Generic_GCC::IsIntegratedAssemblerDefault() const {
return getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
getTriple().getArch() == llvm::Triple::arm64 ||
getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumb ||
getTriple().getArch() == llvm::Triple::thumbeb;
}
void Generic_ELF::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Generic_GCC::GCCVersion &V = GCCInstallation.getVersion();
bool UseInitArrayDefault =
getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
getTriple().getArch() == llvm::Triple::arm64 ||
(getTriple().getOS() == llvm::Triple::Linux &&
(!V.isOlderThan(4, 7, 0) ||
getTriple().getEnvironment() == llvm::Triple::Android));
if (DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array,
UseInitArrayDefault))
CC1Args.push_back("-fuse-init-array");
}
/// Hexagon Toolchain
std::string Hexagon_TC::GetGnuDir(const std::string &InstalledDir) {
// Locate the rest of the toolchain ...
if (strlen(GCC_INSTALL_PREFIX))
return std::string(GCC_INSTALL_PREFIX);
std::string InstallRelDir = InstalledDir + "/../../gnu";
if (llvm::sys::fs::exists(InstallRelDir))
return InstallRelDir;
std::string PrefixRelDir = std::string(LLVM_PREFIX) + "/../gnu";
if (llvm::sys::fs::exists(PrefixRelDir))
return PrefixRelDir;
return InstallRelDir;
}
static void GetHexagonLibraryPaths(
const ArgList &Args,
const std::string Ver,
const std::string MarchString,
const std::string &InstalledDir,
ToolChain::path_list *LibPaths)
{
bool buildingLib = Args.hasArg(options::OPT_shared);
//----------------------------------------------------------------------------
// -L Args
//----------------------------------------------------------------------------
for (arg_iterator
it = Args.filtered_begin(options::OPT_L),
ie = Args.filtered_end();
it != ie;
++it) {
for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
LibPaths->push_back((*it)->getValue(i));
}
//----------------------------------------------------------------------------
// Other standard paths
//----------------------------------------------------------------------------
const std::string MarchSuffix = "/" + MarchString;
const std::string G0Suffix = "/G0";
const std::string MarchG0Suffix = MarchSuffix + G0Suffix;
const std::string RootDir = Hexagon_TC::GetGnuDir(InstalledDir) + "/";
// lib/gcc/hexagon/...
std::string LibGCCHexagonDir = RootDir + "lib/gcc/hexagon/";
if (buildingLib) {
LibPaths->push_back(LibGCCHexagonDir + Ver + MarchG0Suffix);
LibPaths->push_back(LibGCCHexagonDir + Ver + G0Suffix);
}
LibPaths->push_back(LibGCCHexagonDir + Ver + MarchSuffix);
LibPaths->push_back(LibGCCHexagonDir + Ver);
// lib/gcc/...
LibPaths->push_back(RootDir + "lib/gcc");
// hexagon/lib/...
std::string HexagonLibDir = RootDir + "hexagon/lib";
if (buildingLib) {
LibPaths->push_back(HexagonLibDir + MarchG0Suffix);
LibPaths->push_back(HexagonLibDir + G0Suffix);
}
LibPaths->push_back(HexagonLibDir + MarchSuffix);
LibPaths->push_back(HexagonLibDir);
}
Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Linux(D, Triple, Args) {
const std::string InstalledDir(getDriver().getInstalledDir());
const std::string GnuDir = Hexagon_TC::GetGnuDir(InstalledDir);
// Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
// program paths
const std::string BinDir(GnuDir + "/bin");
if (llvm::sys::fs::exists(BinDir))
getProgramPaths().push_back(BinDir);
// Determine version of GCC libraries and headers to use.
const std::string HexagonDir(GnuDir + "/lib/gcc/hexagon");
llvm::error_code ec;
GCCVersion MaxVersion= GCCVersion::Parse("0.0.0");
for (llvm::sys::fs::directory_iterator di(HexagonDir, ec), de;
!ec && di != de; di = di.increment(ec)) {
GCCVersion cv = GCCVersion::Parse(llvm::sys::path::filename(di->path()));
if (MaxVersion < cv)
MaxVersion = cv;
}
GCCLibAndIncVersion = MaxVersion;
ToolChain::path_list *LibPaths= &getFilePaths();
// Remove paths added by Linux toolchain. Currently Hexagon_TC really targets
// 'elf' OS type, so the Linux paths are not appropriate. When we actually
// support 'linux' we'll need to fix this up
LibPaths->clear();
GetHexagonLibraryPaths(
Args,
GetGCCLibAndIncVersion(),
GetTargetCPU(Args),
InstalledDir,
LibPaths);
}
Hexagon_TC::~Hexagon_TC() {
}
Tool *Hexagon_TC::buildAssembler() const {
return new tools::hexagon::Assemble(*this);
}
Tool *Hexagon_TC::buildLinker() const {
return new tools::hexagon::Link(*this);
}
void Hexagon_TC::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
std::string Ver(GetGCCLibAndIncVersion());
std::string GnuDir = Hexagon_TC::GetGnuDir(D.InstalledDir);
std::string HexagonDir(GnuDir + "/lib/gcc/hexagon/" + Ver);
addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include");
addExternCSystemInclude(DriverArgs, CC1Args, HexagonDir + "/include-fixed");
addExternCSystemInclude(DriverArgs, CC1Args, GnuDir + "/hexagon/include");
}
void Hexagon_TC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
const Driver &D = getDriver();
std::string Ver(GetGCCLibAndIncVersion());
SmallString<128> IncludeDir(Hexagon_TC::GetGnuDir(D.InstalledDir));
llvm::sys::path::append(IncludeDir, "hexagon/include/c++/");
llvm::sys::path::append(IncludeDir, Ver);
addSystemInclude(DriverArgs, CC1Args, IncludeDir.str());
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
}
ToolChain::CXXStdlibType
Hexagon_TC::GetCXXStdlibType(const ArgList &Args) const {
Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
if (!A)
return ToolChain::CST_Libstdcxx;
StringRef Value = A->getValue();
if (Value != "libstdc++") {
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
return ToolChain::CST_Libstdcxx;
}
static int getHexagonVersion(const ArgList &Args) {
Arg *A = Args.getLastArg(options::OPT_march_EQ, options::OPT_mcpu_EQ);
// Select the default CPU (v4) if none was given.
if (!A)
return 4;
// FIXME: produce errors if we cannot parse the version.
StringRef WhichHexagon = A->getValue();
if (WhichHexagon.startswith("hexagonv")) {
int Val;
if (!WhichHexagon.substr(sizeof("hexagonv") - 1).getAsInteger(10, Val))
return Val;
}
if (WhichHexagon.startswith("v")) {
int Val;
if (!WhichHexagon.substr(1).getAsInteger(10, Val))
return Val;
}
// FIXME: should probably be an error.
return 4;
}
StringRef Hexagon_TC::GetTargetCPU(const ArgList &Args)
{
int V = getHexagonVersion(Args);
// FIXME: We don't support versions < 4. We should error on them.
switch (V) {
default:
llvm_unreachable("Unexpected version");
case 5:
return "v5";
case 4:
return "v4";
case 3:
return "v3";
case 2:
return "v2";
case 1:
return "v1";
}
}
// End Hexagon
/// TCEToolChain - A tool chain using the llvm bitcode tools to perform
/// all subcommands. See http://tce.cs.tut.fi for our peculiar target.
/// Currently does not support anything else but compilation.
TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
// Path mangling to find libexec
std::string Path(getDriver().Dir);
Path += "/../libexec";
getProgramPaths().push_back(Path);
}
TCEToolChain::~TCEToolChain() {
}
bool TCEToolChain::IsMathErrnoDefault() const {
return true;
}
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
bool TCEToolChain::isPICDefault() const {
return false;
}
bool TCEToolChain::isPIEDefault() const {
return false;
}
Completely re-work how the Clang driver interprets PIC and PIE options. There were numerous issues here that were all entangled, and so I've tried to do a general simplification of the logic. 1) The logic was mimicing actual GCC bugs, rather than "features". These have been fixed in trunk GCC, and this fixes Clang as well. Notably, the logic was always intended to be last-match-wins like any other flag. 2) The logic for handling '-mdynamic-no-pic' was preposterously unclear. It also allowed the use of this flag on non-Darwin platforms where it has no actual meaning. Now this option is handled directly based on tests of how llvm-gcc behaves, and it is only supported on Darwin. 3) The APIs for the Driver's ToolChains had the implementation ugliness of dynamic-no-pic leaking through them. They also had the implementation details of the LLVM relocation model flag names leaking through. 4) The actual results of passing these flags was incorrect on Darwin in many cases. For example, Darwin *always* uses PIC level 2 if it uses in PIC level, and Darwin *always* uses PIC on 64-bit regardless of the flags specified, including -fPIE. Darwin never compiles in PIE mode, but it can *link* in PIE mode. 5) Also, PIC was not always being enabled even when PIE was. This isn't a supported mode at all and may have caused some fallout in builds with complex PIC and PIE interactions. The result is (I hope) cleaner and clearer for readers. I've also left comments and tests about some of the truly strage behavior that is observed on Darwin platforms. We have no real testing of Windows platforms and PIC, but I don't have the tools handy to figure that out. Hopefully others can beef up our testing here. Unfortunately, I can't test this for every platform. =/ If folks have dependencies on these flags that aren't covered by tests, they may break. I've audited and ensured that all the changes in behavior of the existing tests are intentional and good. In particular I've tried to make sure the Darwin behavior (which is more suprising than the Linux behavior) also matches that of 'gcc' on my mac. llvm-svn: 168297
2012-11-19 11:52:03 +08:00
bool TCEToolChain::isPICDefaultForced() const {
return false;
}
/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *OpenBSD::buildAssembler() const {
return new tools::openbsd::Assemble(*this);
}
Tool *OpenBSD::buildLinker() const {
return new tools::openbsd::Link(*this);
}
/// Bitrig - Bitrig tool chain which can call as(1) and ld(1) directly.
Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *Bitrig::buildAssembler() const {
return new tools::bitrig::Assemble(*this);
}
Tool *Bitrig::buildLinker() const {
return new tools::bitrig::Link(*this);
}
void Bitrig::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/");
break;
case ToolChain::CST_Libstdcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/stdc++");
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/stdc++/backward");
StringRef Triple = getTriple().str();
if (Triple.startswith("amd64"))
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/stdc++/x86_64" +
Triple.substr(5));
else
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/stdc++/" +
Triple);
break;
}
}
void Bitrig::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lcxxrt");
// Include supc++ to provide Unwind until provided by libcxx.
CmdArgs.push_back("-lgcc");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
break;
}
}
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
// When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
// back to '/usr/lib' if it doesn't exist.
if ((Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::ppc) &&
llvm::sys::fs::exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
else
getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}
ToolChain::CXXStdlibType
FreeBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libstdc++")
return ToolChain::CST_Libstdcxx;
if (Value == "libc++")
return ToolChain::CST_Libcxx;
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
if (getTriple().getOSMajorVersion() >= 10)
return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx;
}
void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/v1");
break;
case ToolChain::CST_Libstdcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/4.2");
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/4.2/backward");
break;
}
}
Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assemble(*this);
}
Tool *FreeBSD::buildLinker() const {
return new tools::freebsd::Link(*this);
}
bool FreeBSD::UseSjLjExceptions() const {
// FreeBSD uses SjLj exceptions on ARM oabi.
switch (getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
return false;
default:
return (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::thumb);
}
}
bool FreeBSD::HasNativeLLVMSupport() const {
return true;
}
bool FreeBSD::isPIEDefault() const {
return getSanitizerArgs().hasZeroBaseShadow();
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
if (getDriver().UseStdLib) {
// When targeting a 32-bit platform, try the special directory used on
// 64-bit hosts, and only fall back to the main library directory if that
// doesn't work.
// FIXME: It'd be nicer to test if this directory exists, but I'm not sure
// what all logic is needed to emulate the '=' prefix here.
switch (Triple.getArch()) {
case llvm::Triple::x86:
getFilePaths().push_back("=/usr/lib/i386");
break;
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIHF:
getFilePaths().push_back("=/usr/lib/eabi");
break;
default:
getFilePaths().push_back("=/usr/lib/oabi");
break;
}
break;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
if (tools::mips::hasMipsAbiArg(Args, "o32"))
getFilePaths().push_back("=/usr/lib/o32");
else if (tools::mips::hasMipsAbiArg(Args, "64"))
getFilePaths().push_back("=/usr/lib/64");
break;
case llvm::Triple::sparc:
getFilePaths().push_back("=/usr/lib/sparc");
break;
default:
break;
}
getFilePaths().push_back("=/usr/lib");
}
}
Tool *NetBSD::buildAssembler() const {
return new tools::netbsd::Assemble(*this);
}
Tool *NetBSD::buildLinker() const {
return new tools::netbsd::Link(*this);
}
ToolChain::CXXStdlibType
NetBSD::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
if (Value == "libstdc++")
return ToolChain::CST_Libstdcxx;
if (Value == "libc++")
return ToolChain::CST_Libcxx;
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
unsigned Major, Minor, Micro;
getTriple().getOSVersion(Major, Minor, Micro);
if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 23) || Major == 0) {
switch (getArch()) {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return ToolChain::CST_Libcxx;
default:
break;
}
}
return ToolChain::CST_Libstdcxx;
}
void NetBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/");
break;
case ToolChain::CST_Libstdcxx:
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/g++");
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/g++/backward");
break;
}
}
/// Minix - Minix tool chain which can call as(1) and ld(1) directly.
Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *Minix::buildAssembler() const {
return new tools::minix::Assemble(*this);
}
Tool *Minix::buildLinker() const {
return new tools::minix::Link(*this);
}
/// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly.
AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: Generic_GCC(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
getFilePaths().push_back("/usr/sfw/lib");
getFilePaths().push_back("/opt/gcc4/lib");
getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");
}
Tool *AuroraUX::buildAssembler() const {
return new tools::auroraux::Assemble(*this);
}
Tool *AuroraUX::buildLinker() const {
return new tools::auroraux::Link(*this);
}
/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly.
Solaris::Solaris(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: Generic_GCC(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
}
Tool *Solaris::buildAssembler() const {
return new tools::solaris::Assemble(*this);
}
Tool *Solaris::buildLinker() const {
return new tools::solaris::Link(*this);
}
/// Distribution (very bare-bones at the moment).
enum Distro {
ArchLinux,
DebianLenny,
DebianSqueeze,
DebianWheezy,
DebianJessie,
Exherbo,
RHEL4,
RHEL5,
RHEL6,
Fedora,
OpenSUSE,
UbuntuHardy,
UbuntuIntrepid,
UbuntuJaunty,
UbuntuKarmic,
UbuntuLucid,
UbuntuMaverick,
UbuntuNatty,
UbuntuOneiric,
UbuntuPrecise,
UbuntuQuantal,
UbuntuRaring,
UbuntuSaucy,
UbuntuTrusty,
UnknownDistro
};
static bool IsRedhat(enum Distro Distro) {
return Distro == Fedora || (Distro >= RHEL4 && Distro <= RHEL6);
}
static bool IsOpenSUSE(enum Distro Distro) {
return Distro == OpenSUSE;
}
static bool IsDebian(enum Distro Distro) {
return Distro >= DebianLenny && Distro <= DebianJessie;
}
static bool IsUbuntu(enum Distro Distro) {
return Distro >= UbuntuHardy && Distro <= UbuntuTrusty;
}
static Distro DetectDistro(llvm::Triple::ArchType Arch) {
std::unique_ptr<llvm::MemoryBuffer> File;
if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) {
StringRef Data = File.get()->getBuffer();
SmallVector<StringRef, 8> Lines;
Data.split(Lines, "\n");
Distro Version = UnknownDistro;
for (unsigned i = 0, s = Lines.size(); i != s; ++i)
if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME="))
Version = llvm::StringSwitch<Distro>(Lines[i].substr(17))
.Case("hardy", UbuntuHardy)
.Case("intrepid", UbuntuIntrepid)
.Case("jaunty", UbuntuJaunty)
.Case("karmic", UbuntuKarmic)
.Case("lucid", UbuntuLucid)
.Case("maverick", UbuntuMaverick)
.Case("natty", UbuntuNatty)
.Case("oneiric", UbuntuOneiric)
.Case("precise", UbuntuPrecise)
.Case("quantal", UbuntuQuantal)
.Case("raring", UbuntuRaring)
.Case("saucy", UbuntuSaucy)
.Case("trusty", UbuntuTrusty)
.Default(UnknownDistro);
return Version;
}
if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) {
StringRef Data = File.get()->getBuffer();
if (Data.startswith("Fedora release"))
return Fedora;
else if (Data.startswith("Red Hat Enterprise Linux") &&
Data.find("release 6") != StringRef::npos)
return RHEL6;
else if ((Data.startswith("Red Hat Enterprise Linux") ||
Data.startswith("CentOS")) &&
Data.find("release 5") != StringRef::npos)
return RHEL5;
else if ((Data.startswith("Red Hat Enterprise Linux") ||
Data.startswith("CentOS")) &&
Data.find("release 4") != StringRef::npos)
return RHEL4;
return UnknownDistro;
}
if (!llvm::MemoryBuffer::getFile("/etc/debian_version", File)) {
StringRef Data = File.get()->getBuffer();
if (Data[0] == '5')
return DebianLenny;
else if (Data.startswith("squeeze/sid") || Data[0] == '6')
return DebianSqueeze;
else if (Data.startswith("wheezy/sid") || Data[0] == '7')
return DebianWheezy;
else if (Data.startswith("jessie/sid") || Data[0] == '8')
return DebianJessie;
return UnknownDistro;
}
if (llvm::sys::fs::exists("/etc/SuSE-release"))
return OpenSUSE;
if (llvm::sys::fs::exists("/etc/exherbo-release"))
return Exherbo;
if (llvm::sys::fs::exists("/etc/arch-release"))
return ArchLinux;
return UnknownDistro;
}
/// \brief Get our best guess at the multiarch triple for a target.
///
/// Debian-based systems are starting to use a multiarch setup where they use
/// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here.
static std::string getMultiarchTriple(const llvm::Triple &TargetTriple,
StringRef SysRoot) {
// For most architectures, just use whatever we have rather than trying to be
// clever.
switch (TargetTriple.getArch()) {
default:
return TargetTriple.str();
// We use the existence of '/lib/<triple>' as a directory to detect some
// common linux triples that don't quite match the Clang triple for both
// 32-bit and 64-bit targets. Multiarch fixes its install triples to these
// regardless of what the actual target triple is.
case llvm::Triple::arm:
case llvm::Triple::thumb:
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabihf"))
return "arm-linux-gnueabihf";
} else {
if (llvm::sys::fs::exists(SysRoot + "/lib/arm-linux-gnueabi"))
return "arm-linux-gnueabi";
}
return TargetTriple.str();
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF) {
if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabihf"))
return "armeb-linux-gnueabihf";
} else {
if (llvm::sys::fs::exists(SysRoot + "/lib/armeb-linux-gnueabi"))
return "armeb-linux-gnueabi";
}
return TargetTriple.str();
case llvm::Triple::x86:
if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu"))
return "i386-linux-gnu";
return TargetTriple.str();
case llvm::Triple::x86_64:
if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu"))
return "x86_64-linux-gnu";
return TargetTriple.str();
case llvm::Triple::arm64:
case llvm::Triple::aarch64:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64-linux-gnu"))
return "aarch64-linux-gnu";
return TargetTriple.str();
case llvm::Triple::aarch64_be:
if (llvm::sys::fs::exists(SysRoot + "/lib/aarch64_be-linux-gnu"))
return "aarch64_be-linux-gnu";
return TargetTriple.str();
case llvm::Triple::mips:
if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu"))
return "mips-linux-gnu";
return TargetTriple.str();
case llvm::Triple::mipsel:
if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu"))
return "mipsel-linux-gnu";
return TargetTriple.str();
case llvm::Triple::ppc:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
return "powerpc-linux-gnuspe";
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu"))
return "powerpc-linux-gnu";
return TargetTriple.str();
case llvm::Triple::ppc64:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu"))
return "powerpc64-linux-gnu";
case llvm::Triple::ppc64le:
if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64le-linux-gnu"))
return "powerpc64le-linux-gnu";
return TargetTriple.str();
}
}
static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) {
if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str());
}
static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
if (isMipsArch(Triple.getArch())) {
// lib32 directory has a special meaning on MIPS targets.
// It contains N32 ABI binaries. Use this folder if produce
// code for N32 ABI only.
if (tools::mips::hasMipsAbiArg(Args, "n32"))
return "lib32";
return Triple.isArch32Bit() ? "lib" : "lib64";
}
// It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
// using that variant while targeting other architectures causes problems
// because the libraries are laid out in shared system roots that can't cope
// with a 'lib32' library search path being considered. So we only enable
// them when we know we may need it.
//
// FIXME: This is a bit of a hack. We should really unify this code for
// reasoning about oslibdir spellings with the lib dir spellings in the
// GCCInstallationDetector, but that is a more significant refactoring.
if (Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::ppc)
return "lib32";
return Triple.isArch32Bit() ? "lib" : "lib64";
}
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
GCCInstallation.init(D, Triple, Args);
Multilibs = GCCInstallation.getMultilibs();
llvm::Triple::ArchType Arch = Triple.getArch();
std::string SysRoot = computeSysRoot();
// Cross-compiling binutils and GCC installations (vanilla and openSUSE at
// least) put various tools in a triple-prefixed directory off of the parent
// of the GCC installation. We use the GCC triple here to ensure that we end
// up with tools that support the same amount of cross compiling as the
// detected GCC installation. For example, if we find a GCC installation
// targeting x86_64, but it is a bi-arch GCC installation, it can also be
// used to target i386.
// FIXME: This seems unlikely to be Linux-specific.
ToolChain::path_list &PPaths = getProgramPaths();
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
GCCInstallation.getTriple().str() + "/bin").str());
Linker = GetProgramPath("ld");
Distro Distro = DetectDistro(Arch);
if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("relro");
}
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)
ExtraOpts.push_back("-X");
const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::Android;
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
const bool IsMips = isMipsArch(Arch);
if (IsMips && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
// and the MIPS ABI require .dynsym to be sorted in different ways.
// .gnu.hash needs symbols to be grouped by hash code whereas the MIPS
// ABI requires a mapping between the GOT and the symbol table.
// Android loader does not support .gnu.hash.
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
if (!IsMips && !IsAndroid) {
if (IsRedhat(Distro) || IsOpenSUSE(Distro) ||
(IsUbuntu(Distro) && Distro >= UbuntuMaverick))
ExtraOpts.push_back("--hash-style=gnu");
if (IsDebian(Distro) || IsOpenSUSE(Distro) || Distro == UbuntuLucid ||
Distro == UbuntuJaunty || Distro == UbuntuKarmic)
ExtraOpts.push_back("--hash-style=both");
}
if (IsRedhat(Distro))
ExtraOpts.push_back("--no-add-needed");
if (Distro == DebianSqueeze || Distro == DebianWheezy ||
Distro == DebianJessie || IsOpenSUSE(Distro) ||
(IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) ||
(IsUbuntu(Distro) && Distro >= UbuntuKarmic))
ExtraOpts.push_back("--build-id");
if (IsOpenSUSE(Distro))
ExtraOpts.push_back("--enable-new-dtags");
// The selection of paths to try here is designed to match the patterns which
// the GCC driver itself uses, as this is part of the GCC-compatible driver.
// This was determined by running GCC in a fake filesystem, creating all
// possible permutations of these directories, and seeing which ones it added
// to the link paths.
path_list &Paths = getFilePaths();
const std::string OSLibDir = getOSLibDir(Triple, Args);
const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot);
// Add the multilib suffixed paths where they are available.
if (GCCInstallation.isValid()) {
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const std::string &LibPath = GCCInstallation.getParentLibPath();
const Multilib &Multilib = GCCInstallation.getMultilib();
// Sourcery CodeBench MIPS toolchain holds some libraries under
// a biarch-like suffix of the GCC installation.
addPathIfExists((GCCInstallation.getInstallPath() +
Multilib.gccSuffix()),
Paths);
// GCC cross compiling toolchains will install target libraries which ship
// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
// any part of the GCC installation in
// <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
// debatable, but is the reality today. We need to search this tree even
// when we have a sysroot somewhere else. It is the responsibility of
// whomever is doing the cross build targeting a sysroot using a GCC
// installation that is *not* within the system root to ensure two things:
//
// 1) Any DSOs that are linked in from this tree or from the install path
// above must be preasant on the system root and found via an
// appropriate rpath.
// 2) There must not be libraries installed into
// <prefix>/<triple>/<libdir> unless they should be preferred over
// those within the system root.
//
// Note that this matches the GCC behavior. See the below comment for where
// Clang diverges from GCC's behavior.
addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
Multilib.osSuffix(),
Paths);
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
// If the GCC installation we found is inside of the sysroot, we want to
// prefer libraries installed in the parent prefix of the GCC installation.
// It is important to *not* use these paths when the GCC installation is
// outside of the system root as that can pick up unintended libraries.
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
// This usually happens when there is an external cross compiler on the
// host system, and a more minimal sysroot available that is the target of
// the cross. Note that GCC does include some of these directories in some
// configurations but this seems somewhere between questionable and simply
// a bug.
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
if (StringRef(LibPath).startswith(SysRoot)) {
addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
addPathIfExists(LibPath + "/../" + OSLibDir, Paths);
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
}
}
// Similar to the logic for GCC above, if we currently running Clang inside
// of the requested system root, add its parent library paths to
// those searched.
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot)) {
addPathIfExists(D.Dir + "/../lib/" + MultiarchTriple, Paths);
addPathIfExists(D.Dir + "/../" + OSLibDir, Paths);
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths);
addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths);
// Try walking via the GCC triple path in case of biarch or multiarch GCC
// installations with strange symlinks.
if (GCCInstallation.isValid()) {
addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
"/../../" + OSLibDir, Paths);
// Add the 'other' biarch variant path
Multilib BiarchSibling;
if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
addPathIfExists(GCCInstallation.getInstallPath() +
BiarchSibling.gccSuffix(), Paths);
}
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
// See comments above on the multilib variant for details of why this is
// included even from outside the sysroot.
const std::string &LibPath = GCCInstallation.getParentLibPath();
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
const Multilib &Multilib = GCCInstallation.getMultilib();
addPathIfExists(LibPath + "/../" + GCCTriple.str() +
"/lib" + Multilib.osSuffix(), Paths);
// See comments above on the multilib variant for details of why this is
// only included from within the sysroot.
if (StringRef(LibPath).startswith(SysRoot))
Fix using Clang as a cross compiler installed on a host machine and not inside of a sysroot targeting a system+sysroot which is "similar" or "compatible" with the host system. This shows up when trying to build system images on largely compatible hardware as-if fully cross compiled. The problem is that previously we *perfectly* mimiced GCC here, and it turns out GCC has a bug that no one has really stumbled across. GCC will try to look in thy system prefix ('/usr/local' f.ex.) into which it is instaled to find libraries installed along side GCC that should be preferred to the base system libraries ('/usr' f.ex.). This seems not unreasonable, but it has a very unfortunate consequence when combined with a '--sysroot' which does *not* contain the GCC installation we're using to complete the toolchain. That results in some of the host system's library directories being searched during the link. Now, it so happens that most folks doing stuff like this use '--with-sysroot' and '--disable-multilib' when configuring GCC. Even better, they're usually not cross-compiling to a target that is similar to the host. As a result, searching the host for libraries doesn't really matter -- most of the time weird directories get appended that don't exist (no arm triple lib directory, etc). Even if you're cross-compiling from 32-bit to 64-bit x86 or vice-versa, disabling multilib makes it less likely that you'll actually find viable libraries on the host. But that's just luck. We shouldn't rely on this, and this patch disables looking in the system prefix containing the GCC installation if that system prefix is *outside* of the sysroot. For empty sysroots, this has no effect. Similarly, when using the GCC *inside* of the sysroot, we still track wherever it is installed within the sysroot and look there for libraries. But now we can use a cross compiler GCC installation outside the system root, and only look for the crtbegin.o in the GCC installation, and look for all the other libraries inside the system root. This should fix PR12478, allowing Clang to be used when building a ChromiumOS image without polluting the image with libraries from the host system. llvm-svn: 154176
2012-04-07 00:32:06 +08:00
addPathIfExists(LibPath, Paths);
}
// Similar to the logic for GCC above, if we are currently running Clang
// inside of the requested system root, add its parent library path to those
// searched.
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot))
addPathIfExists(D.Dir + "/../lib", Paths);
addPathIfExists(SysRoot + "/lib", Paths);
addPathIfExists(SysRoot + "/usr/lib", Paths);
}
bool Linux::HasNativeLLVMSupport() const {
return true;
}
Tool *Linux::buildLinker() const {
return new tools::gnutools::Link(*this);
}
Tool *Linux::buildAssembler() const {
return new tools::gnutools::Assemble(*this);
}
std::string Linux::computeSysRoot() const {
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;
if (!GCCInstallation.isValid() || !isMipsArch(getTriple().getArch()))
return std::string();
// Standalone MIPS toolchains use different names for sysroot folder
// and put it into different places. Here we try to check some known
// variants.
const StringRef InstallDir = GCCInstallation.getInstallPath();
const StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
std::string Path = (InstallDir + "/../../../../" + TripleStr + "/libc" +
Multilib.osSuffix()).str();
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
if (llvm::sys::fs::exists(Path))
return Path;
Path = (InstallDir + "/../../../../sysroot" + Multilib.osSuffix()).str();
if (llvm::sys::fs::exists(Path))
return Path;
return std::string();
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
}
void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string SysRoot = computeSysRoot();
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P.str());
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
// Check for configure-time C include directories.
StringRef CIncludeDirs(C_INCLUDE_DIRS);
if (CIncludeDirs != "") {
SmallVector<StringRef, 5> dirs;
CIncludeDirs.split(dirs, ":");
for (SmallVectorImpl<StringRef>::iterator I = dirs.begin(), E = dirs.end();
I != E; ++I) {
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
StringRef Prefix = llvm::sys::path::is_absolute(*I) ? SysRoot : "";
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + *I);
}
return;
}
// Lacking those, try to detect the correct set of system includes for the
// target triple.
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
// Sourcery CodeBench and modern FSF Mips toolchains put extern C
// system includes under three additional directories.
if (GCCInstallation.isValid() && isMipsArch(getTriple().getArch())) {
addExternCSystemIncludeIfExists(
DriverArgs, CC1Args, GCCInstallation.getInstallPath() + "/include");
addExternCSystemIncludeIfExists(
DriverArgs, CC1Args,
GCCInstallation.getInstallPath() + "/../../../../" +
GCCInstallation.getTriple().str() + "/libc/usr/include");
addExternCSystemIncludeIfExists(
DriverArgs, CC1Args,
GCCInstallation.getInstallPath() + "/../../../../sysroot/usr/include");
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
}
// Implement generic Debian multiarch support.
const StringRef X86_64MultiarchIncludeDirs[] = {
"/usr/include/x86_64-linux-gnu",
// FIXME: These are older forms of multiarch. It's not clear that they're
// in use in any released version of Debian, so we should consider
// removing them.
"/usr/include/i686-linux-gnu/64", "/usr/include/i486-linux-gnu/64"
};
const StringRef X86MultiarchIncludeDirs[] = {
"/usr/include/i386-linux-gnu",
// FIXME: These are older forms of multiarch. It's not clear that they're
// in use in any released version of Debian, so we should consider
// removing them.
"/usr/include/x86_64-linux-gnu/32", "/usr/include/i686-linux-gnu",
"/usr/include/i486-linux-gnu"
};
const StringRef AArch64MultiarchIncludeDirs[] = {
"/usr/include/aarch64-linux-gnu"
};
const StringRef ARMMultiarchIncludeDirs[] = {
"/usr/include/arm-linux-gnueabi"
};
const StringRef ARMHFMultiarchIncludeDirs[] = {
"/usr/include/arm-linux-gnueabihf"
};
const StringRef MIPSMultiarchIncludeDirs[] = {
"/usr/include/mips-linux-gnu"
};
const StringRef MIPSELMultiarchIncludeDirs[] = {
"/usr/include/mipsel-linux-gnu"
};
const StringRef PPCMultiarchIncludeDirs[] = {
"/usr/include/powerpc-linux-gnu"
};
const StringRef PPC64MultiarchIncludeDirs[] = {
"/usr/include/powerpc64-linux-gnu"
};
ArrayRef<StringRef> MultiarchIncludeDirs;
if (getTriple().getArch() == llvm::Triple::x86_64) {
MultiarchIncludeDirs = X86_64MultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::x86) {
MultiarchIncludeDirs = X86MultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::aarch64 ||
getTriple().getArch() == llvm::Triple::aarch64_be ||
getTriple().getArch() == llvm::Triple::arm64) {
MultiarchIncludeDirs = AArch64MultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::arm) {
if (getTriple().getEnvironment() == llvm::Triple::GNUEABIHF)
MultiarchIncludeDirs = ARMHFMultiarchIncludeDirs;
else
MultiarchIncludeDirs = ARMMultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::mips) {
MultiarchIncludeDirs = MIPSMultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::mipsel) {
MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::ppc) {
MultiarchIncludeDirs = PPCMultiarchIncludeDirs;
} else if (getTriple().getArch() == llvm::Triple::ppc64) {
MultiarchIncludeDirs = PPC64MultiarchIncludeDirs;
}
for (ArrayRef<StringRef>::iterator I = MultiarchIncludeDirs.begin(),
E = MultiarchIncludeDirs.end();
I != E; ++I) {
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
if (llvm::sys::fs::exists(SysRoot + *I)) {
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + *I);
break;
}
}
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
// add even when Clang is acting as-if it were a system compiler.
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
Supports Sourcery CodeBench Mips toolchain directories tree. Sourcery CodeBench and modern FSF Mips toolchains require a bit more complicated algorithm to calculate headers, libraries and sysroot paths than implemented by Clang driver now. The main problem is that all these paths depend on a set of command line arguments additionally to a target triple value. For example, let $TC is a toolchain installation directory. If we compile big-endian 32-bit mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2 folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc argument. If we compile little-endian 32-bit soft-float mips code, crtbegin.o is in the $TC/lib/gcc/mips-linux-gnu/4.7.2/soft-float/el folder and the toolchain's linker requires --sysroot=$TC/mips-linux-gnu/libc/soft-float/el argument. 1. Calculate MultiarchSuffix using all necessary command line options and use this MultiarchSuffix to detect crtbegin.o location in the GCCInstallationDetector::ScanLibDirForGCCTriple() routine. 2. If a user does not provide --sysroot argument to the driver explicitly, calculate new sysroot value based on command line options. Then use this calculated sysroot path: a. To populate a file search paths list in the Linux::Linux() constructor. b. To find Mips toolchain specific include headers directories in the Linux::AddClangSystemIncludeArgs() routine. c. To provide -–sysroot argument for a linker. Note: - The FSF's tree slightly differs (folder names) and is not supported yet. - New addExternCSystemIncludeIfExits() routine is a temporary solution. I plan to move path existence check to the addExternCSystemInclude() routine by a separate commit. The patch reviewed by Rafael Espindola. http://llvm-reviews.chandlerc.com/D644 llvm-svn: 179934
2013-04-20 16:15:03 +08:00
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
/// \brief Helper to add the three variant paths for a libstdc++ installation.
/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir,
const ArgList &DriverArgs,
ArgStringList &CC1Args) {
if (!llvm::sys::fs::exists(Base))
return false;
addSystemInclude(DriverArgs, CC1Args, Base);
addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir);
addSystemInclude(DriverArgs, CC1Args, Base + "/backward");
return true;
}
/// \brief Helper to add an extra variant path for an (Ubuntu) multilib
/// libstdc++ installation.
/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix,
Twine TargetArchDir,
Twine IncludeSuffix,
const ArgList &DriverArgs,
ArgStringList &CC1Args) {
if (!addLibStdCXXIncludePaths(Base + Suffix,
TargetArchDir + IncludeSuffix,
DriverArgs, CC1Args))
return false;
addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix
+ IncludeSuffix);
return true;
}
void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx))
return;
// Check if libc++ has been enabled and provide its include paths if so.
if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) {
const std::string LibCXXIncludePathCandidates[] = {
// The primary location is within the Clang installation.
// FIXME: We shouldn't hard code 'v1' here to make Clang future proof to
// newer ABI versions.
getDriver().Dir + "/../include/c++/v1",
// We also check the system as for a long time this is the only place Clang looked.
// FIXME: We should really remove this. It doesn't make any sense.
getDriver().SysRoot + "/usr/include/c++/v1"
};
for (unsigned i = 0; i < llvm::array_lengthof(LibCXXIncludePathCandidates);
++i) {
if (!llvm::sys::fs::exists(LibCXXIncludePathCandidates[i]))
continue;
// Add the first candidate that exists.
addSystemInclude(DriverArgs, CC1Args, LibCXXIncludePathCandidates[i]);
break;
}
return;
}
// We need a detected GCC installation on Linux to provide libstdc++'s
// headers. We handled the libc++ case above.
if (!GCCInstallation.isValid())
return;
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
const GCCVersion &Version = GCCInstallation.getVersion();
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
"/c++/" + Version.Text, TripleStr,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return;
const std::string LibStdCXXIncludePathCandidates[] = {
// Gentoo is weird and places its headers inside the GCC install, so if the
// first attempt to find the headers fails, try these patterns.
InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
Version.MinorStr,
InstallDir.str() + "/include/g++-v" + Version.MajorStr,
// Android standalone toolchain has C++ headers in yet another place.
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
// without a subdirectory corresponding to the gcc version.
LibDir.str() + "/../include/c++",
};
for (unsigned i = 0; i < llvm::array_lengthof(LibStdCXXIncludePathCandidates);
++i) {
if (addLibStdCXXIncludePaths(LibStdCXXIncludePathCandidates[i],
TripleStr + Multilib.includeSuffix(),
DriverArgs, CC1Args))
break;
}
}
bool Linux::isPIEDefault() const {
return getSanitizerArgs().hasZeroBaseShadow();
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
// Path mangling to find libexec
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
if (llvm::sys::fs::exists("/usr/lib/gcc47"))
getFilePaths().push_back("/usr/lib/gcc47");
else
getFilePaths().push_back("/usr/lib/gcc44");
}
Tool *DragonFly::buildAssembler() const {
return new tools::dragonfly::Assemble(*this);
}
Tool *DragonFly::buildLinker() const {
return new tools::dragonfly::Link(*this);
}
/// XCore tool chain
XCore::XCore(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) : ToolChain(D, Triple, Args) {
// ProgramPaths are found via 'PATH' environment variable.
}
Tool *XCore::buildAssembler() const {
return new tools::XCore::Assemble(*this);
}
Tool *XCore::buildLinker() const {
return new tools::XCore::Link(*this);
}
bool XCore::isPICDefault() const {
return false;
}
bool XCore::isPIEDefault() const {
return false;
}
bool XCore::isPICDefaultForced() const {
return false;
}
bool XCore::SupportsProfiling() const {
return false;
}
bool XCore::hasBlocksRuntime() const {
return false;
}
void XCore::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
if (const char *cl_include_dir = getenv("XCC_C_INCLUDE_PATH")) {
SmallVector<StringRef, 4> Dirs;
const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
ArrayRef<StringRef> DirVec(Dirs);
addSystemIncludes(DriverArgs, CC1Args, DirVec);
}
}
void XCore::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
CC1Args.push_back("-nostdsysteminc");
}
void XCore::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
if (const char *cl_include_dir = getenv("XCC_CPLUS_INCLUDE_PATH")) {
SmallVector<StringRef, 4> Dirs;
const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator,'\0'};
StringRef(cl_include_dir).split(Dirs, StringRef(EnvPathSeparatorStr));
ArrayRef<StringRef> DirVec(Dirs);
addSystemIncludes(DriverArgs, CC1Args, DirVec);
}
}
void XCore::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// We don't output any lib args. This is handled by xcc.
}