diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -350,9 +350,21 @@ // // Note that this matches the GCC behavior. See the below comment for where // Clang diverges from GCC's behavior. - addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" + - OSLibDir + SelectedMultilib.osSuffix(), - Paths); + // + // On Exherbo, the GCC installation will reside in e.g. + // /usr/x86_64-pc-linux-gnu/lib/gcc/armv7-unknown-linux-gnueabihf/9.2.0 + // while the matching lib path is + // /usr/armv7-unknown-linux-gnueabihf/lib + if (Distro == Distro::Exherbo) + addPathIfExists(D, + LibPath + "/../../" + GCCTriple.str() + "/lib/../" + + OSLibDir + SelectedMultilib.osSuffix(), + Paths); + else + addPathIfExists(D, + LibPath + "/../" + GCCTriple.str() + "/lib/../" + + OSLibDir + SelectedMultilib.osSuffix(), + Paths); // 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. @@ -844,6 +856,39 @@ if (getTriple().isAndroid()) MultiarchIncludeDirs = AndroidMultiarchIncludeDirs; + // Exherbo's multiarch layout is /usr//include and not + // /usr/include/ + const Distro Distro(D.getVFS()); + const StringRef ExherboMultiarchIncludeDirs[] = {"/usr/" + getTriple().str() + + "/include"}; + const StringRef ExherboX86_64MuslMultiarchIncludeDirs[] = { + "/usr/x86_64-pc-linux-musl/include"}; + const StringRef ExherboX86_64MultiarchIncludeDirs[] = { + "/usr/x86_64-pc-linux-gnu/include"}; + const StringRef ExherboI686MuslMultiarchIncludeDirs[] = { + "/usr/i686-pc-linux-musl/include"}; + const StringRef ExherboI686MultiarchIncludeDirs[] = { + "/usr/i686-pc-linux-gnu/include"}; + if (Distro == Distro::Exherbo) { + switch (getTriple().getArch()) { + case llvm::Triple::x86_64: + if (getTriple().isMusl()) + MultiarchIncludeDirs = ExherboX86_64MuslMultiarchIncludeDirs; + else + MultiarchIncludeDirs = ExherboX86_64MultiarchIncludeDirs; + break; + case llvm::Triple::x86: + if (getTriple().isMusl()) + MultiarchIncludeDirs = ExherboI686MuslMultiarchIncludeDirs; + else + MultiarchIncludeDirs = ExherboI686MultiarchIncludeDirs; + break; + default: + MultiarchIncludeDirs = ExherboMultiarchIncludeDirs; + break; + } + } + for (StringRef Dir : MultiarchIncludeDirs) { if (D.getVFS().exists(SysRoot + Dir)) { addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + Dir); @@ -917,12 +962,30 @@ StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef TripleStr = GCCInstallation.getTriple().str(); + const Driver &D = getDriver(); const Multilib &Multilib = GCCInstallation.getMultilib(); - const std::string GCCMultiarchTriple = getMultiarchTriple( - getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot); + const std::string GCCMultiarchTriple = + getMultiarchTriple(D, GCCInstallation.getTriple(), D.SysRoot); const std::string TargetMultiarchTriple = - getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot); + getMultiarchTriple(D, getTriple(), D.SysRoot); const GCCVersion &Version = GCCInstallation.getVersion(); + const Distro Distro(D.getVFS()); + + // On Exherbo the consecutive addLibStdCXXIncludePaths call would evaluate to: + // LibDir = /usr/lib/gcc//9.2.0/../../.. + // = /usr/lib/ + // LibDir + "/../include" = /usr/include + // addLibStdCXXIncludePaths would then check if "/usr/include/c++/" + // exists, and add that as include path when what we want is + // "/usr//include/c++/" + // Note that "/../../" is needed and not just "/../" as /usr/include points to + // /usr/host/include + if (Distro == Distro::Exherbo && + addLibStdCXXIncludePaths( + LibDir.str() + "/../../" + TripleStr + "/include", + "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple, + TargetMultiarchTriple, Multilib.includeSuffix(), DriverArgs, CC1Args)) + return; // The primary search for libstdc++ supports multiarch variants. if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",