From: Chandler Carruth Date: Wed, 27 Aug 2014 08:41:41 +0000 (+0000) Subject: Significantly fix Clang's header search for Ubuntu (and possibly other X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=08b8fe7867c3ebf729101aa707b381eb53a01626;p=clang Significantly fix Clang's header search for Ubuntu (and possibly other modern Debian-based distributions) due to on-going multiarch madness. It appears that when the multiarch heeader search support went into the clang driver, it went in in a quite bad state. The order of includes completely failed to match the order exhibited by GCC, and in a specific case -- when the GCC triple and the multiarch triple don't match as with i686-linux-gnu and i386-linux-gnu -- we would absolutely fail to find the libstdc++ target-specific header files. I assume that folks who have been using Clang on Ubuntu 32-bit systems have been applying weird patches to hack around this. I can't imagine how else it could have worked. This was originally reported by a 64-bit operating system user who had a 32-bit crosscompiler installed. We tried to use that rather than the bi-arch support of the 64-bit compiler, but failed due to the triple differences. I've corrected all the wrong orderings in the existing tests and added a specific test for the multiarch triple strings that are different in a significant way. This should significantly improve the usability of Clang when checked out vanilla from upstream onto Ubuntu machines with an i686 GCC installation for whatever reason. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216531 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index c7654b7ddb..9ea21b4947 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -3345,32 +3345,39 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 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. +/// \brief Helper to add the variant paths of a libstdc++ installation. /*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine Suffix, - Twine TargetArchDir, + StringRef GCCTriple, + StringRef GCCMultiarchTriple, + StringRef TargetMultiarchTriple, Twine IncludeSuffix, const ArgList &DriverArgs, ArgStringList &CC1Args) { - if (!addLibStdCXXIncludePaths(Base + Suffix, - TargetArchDir + IncludeSuffix, - DriverArgs, CC1Args)) + if (!llvm::sys::fs::exists(Base)) return false; - addSystemInclude(DriverArgs, CC1Args, Base + "/" + TargetArchDir + Suffix - + IncludeSuffix); + addSystemInclude(DriverArgs, CC1Args, Base + Suffix); + + // The vanilla GCC layout of libstdc++ headers uses a triple subdirectory. If + // that path exists or we have neither a GCC nor target multiarch triple, use + // this vanilla search path. + if ((GCCMultiarchTriple.empty() && TargetMultiarchTriple.empty()) || + llvm::sys::fs::exists(Base + Suffix + "/" + GCCTriple + IncludeSuffix)) { + addSystemInclude(DriverArgs, CC1Args, + Base + Suffix + "/" + GCCTriple + IncludeSuffix); + } else { + // Otherwise try to use multiarch naming schemes which have normalized the + // triples and put the triple before the suffix. + // + // GCC surprisingly uses *both* the GCC triple with a multilib suffix and + // the target triple, so we support that here. + addSystemInclude(DriverArgs, CC1Args, + Base + "/" + GCCMultiarchTriple + Suffix + IncludeSuffix); + addSystemInclude(DriverArgs, CC1Args, + Base + "/" + TargetMultiarchTriple + Suffix); + } + + addSystemInclude(DriverArgs, CC1Args, Base + Suffix + "/backward"); return true; } @@ -3414,13 +3421,21 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef TripleStr = GCCInstallation.getTriple().str(); const Multilib &Multilib = GCCInstallation.getMultilib(); + const std::string GCCMultiarchTriple = + getMultiarchTriple(GCCInstallation.getTriple(), getDriver().SysRoot); + const std::string TargetMultiarchTriple = + getMultiarchTriple(getTriple(), getDriver().SysRoot); const GCCVersion &Version = GCCInstallation.getVersion(); + // The primary search for libstdc++ supports multiarch variants. if (addLibStdCXXIncludePaths(LibDir.str() + "/../include", - "/c++/" + Version.Text, TripleStr, + "/c++/" + Version.Text, TripleStr, GCCMultiarchTriple, + TargetMultiarchTriple, Multilib.includeSuffix(), DriverArgs, CC1Args)) return; + // Otherwise, fall back on a bunch of options which don't use multiarch + // layouts for simplicity. 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. @@ -3435,9 +3450,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, }; for (const auto &IncludePath : LibStdCXXIncludePathCandidates) { - if (addLibStdCXXIncludePaths(IncludePath, - TripleStr + Multilib.includeSuffix(), - DriverArgs, CC1Args)) + if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr, + /*GCCMultiarchTriple*/ "", + /*TargetMultiarchTriple*/ "", + Multilib.includeSuffix(), DriverArgs, CC1Args)) break; } } diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index a3b20d6694..2c7ce062c0 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -679,10 +679,10 @@ protected: private: static bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, - Twine TargetArchDir, Twine IncludeSuffix, - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args); - static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, + StringRef GCCTriple, + StringRef GCCMultiarchTriple, + StringRef TargetMultiarchTriple, + Twine IncludeSuffix, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args); diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/lib/i386-linux-gnu/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/lib/i386-linux-gnu/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/lib/x86_64-linux-gnu/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/lib/x86_64-linux-gnu/.keep new file mode 100755 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/c++/4.8/backward/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/c++/4.8/backward/.keep new file mode 100755 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/i386-linux-gnu/c++/4.8/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/i386-linux-gnu/c++/4.8/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/x86_64-linux-gnu/c++/4.8/32/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/include/x86_64-linux-gnu/c++/4.8/32/.keep new file mode 100755 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/i686-linux-gnu/4.8/crtbegin.o b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/i686-linux-gnu/4.8/crtbegin.o new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/x86_64-linux-gnu/4.8/32/crtbegin.o b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/x86_64-linux-gnu/4.8/32/crtbegin.o new file mode 100755 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o new file mode 100755 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/i386-linux-gnu/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/i386-linux-gnu/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/x86_64-linux-gnu/.keep b/test/Driver/Inputs/ubuntu_14.04_multiarch_tree2/usr/lib/x86_64-linux-gnu/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/linux-header-search.cpp b/test/Driver/linux-header-search.cpp index 9635519ad0..309ece28db 100644 --- a/test/Driver/linux-header-search.cpp +++ b/test/Driver/linux-header-search.cpp @@ -46,8 +46,8 @@ // CHECK-UBUNTU-13-04: "{{[^"]*}}clang{{[^"]*}}" "-cc1" // CHECK-UBUNTU-13-04: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-13-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7" -// CHECK-UBUNTU-13-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/backward" // CHECK-UBUNTU-13-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/x86_64-linux-gnu/c++/4.7" +// CHECK-UBUNTU-13-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/backward" // CHECK-UBUNTU-13-04: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-UBUNTU-13-04: "-internal-isystem" "{{.*}}{{/|\\\\}}lib{{(64|32)?}}{{/|\\\\}}clang{{/|\\\\}}{{[0-9]\.[0-9]\.[0-9]}}{{/|\\\\}}include" // CHECK-UBUNTU-13-04: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/x86_64-linux-gnu" @@ -61,9 +61,8 @@ // CHECK-UBUNTU-14-04: "{{[^"]*}}clang{{[^"]*}}" "-cc1" // CHECK-UBUNTU-14-04: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8" -// CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/x86_64-linux-gnu/x32" -// CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward" // CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8/x32" +// CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward" // CHECK-UBUNTU-14-04: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-UBUNTU-14-04: "-internal-isystem" "{{.*}}{{/|\\\\}}lib{{(64|x32)?}}{{/|\\\\}}clang{{/|\\\\}}{{[0-9]\.[0-9]\.[0-9]}}{{/|\\\\}}include" // CHECK-UBUNTU-14-04: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/x86_64-linux-gnu" @@ -77,8 +76,8 @@ // CHECK-UBUNTU-13-04-CROSS: "{{[^"]*}}clang{{[^"]*}}" "-cc1" // CHECK-UBUNTU-13-04-CROSS: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc-cross/arm-linux-gnueabihf/4.7/../../../../include/c++/4.7" -// CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc-cross/arm-linux-gnueabihf/4.7/../../../../include/c++/4.7/backward" // CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc-cross/arm-linux-gnueabihf/4.7/../../../../include/arm-linux-gnueabihf/c++/4.7" +// CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc-cross/arm-linux-gnueabihf/4.7/../../../../include/c++/4.7/backward" // CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "[[SYSROOT]]/usr/local/include" // CHECK-UBUNTU-13-04-CROSS: "-internal-isystem" "{{.*}}{{/|\\\\}}lib{{(64|32)?}}{{/|\\\\}}clang{{/|\\\\}}{{[0-9]\.[0-9]\.[0-9]}}{{/|\\\\}}include" // CHECK-UBUNTU-13-04-CROSS: "-internal-externc-isystem" "[[SYSROOT]]/include" @@ -93,9 +92,8 @@ // CHECK-UBUNTU-13-04-M32: "-triple" "i386-unknown-linux-gnu" // CHECK-UBUNTU-13-04-M32: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7" -// CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/x86_64-linux-gnu/32" -// CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/backward" // CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/x86_64-linux-gnu/c++/4.7/32" +// CHECK-UBUNTU-13-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/backward" // // Test Ubuntu/Debian's Ubuntu 14.04 config variant, with -m32 // and an empty 4.9 directory. @@ -107,9 +105,22 @@ // CHECK-UBUNTU-14-04-M32: "-triple" "i386-unknown-linux-gnu" // CHECK-UBUNTU-14-04-M32: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8" -// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/x86_64-linux-gnu/32" -// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward" // CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8/32" +// CHECK-UBUNTU-14-04-M32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward" +// +// Test Ubuntu/Debian's Ubuntu 14.04 with -m32 and an i686 cross compiler +// installed rather than relying on multilib. Also happens to look like an +// actual i686 Ubuntu system. +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target x86_64-unknown-linux-gnu -m32 \ +// RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \ +// RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-I686 %s +// CHECK-UBUNTU-14-04-I686: "{{[^"]*}}clang{{[^"]*}}" "-cc1" +// CHECK-UBUNTU-14-04-I686: "-triple" "i386-unknown-linux-gnu" +// CHECK-UBUNTU-14-04-I686: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-UBUNTU-14-04-I686: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/i686-linux-gnu/4.8/../../../../include/c++/4.8" +// CHECK-UBUNTU-14-04-I686: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/i686-linux-gnu/4.8/../../../../include/i386-linux-gnu/c++/4.8" +// CHECK-UBUNTU-14-04-I686: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/i686-linux-gnu/4.8/../../../../include/c++/4.8/backward" // // Test Ubuntu/Debian's Ubuntu 14.04 for powerpc64le // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ @@ -120,9 +131,8 @@ // CHECK-UBUNTU-14-04-PPC64LE: "-triple" "powerpc64le-unknown-linux-gnu" // CHECK-UBUNTU-14-04-PPC64LE: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-UBUNTU-14-04-PPC64LE: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/powerpc64le-linux-gnu/4.8/../../../../include/c++/4.8" -// CHECK-UBUNTU-14-04-PPC64LE: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/powerpc64le-linux-gnu/4.8/../../../../include/c++/4.8/powerpc64le-linux-gnu" -// CHECK-UBUNTU-14-04-PPC64LE: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/powerpc64le-linux-gnu/4.8/../../../../include/c++/4.8/backward" // CHECK-UBUNTU-14-04-PPC64LE: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/powerpc64le-linux-gnu/4.8/../../../../include/powerpc64le-linux-gnu/c++/4.8" +// CHECK-UBUNTU-14-04-PPC64LE: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/powerpc64le-linux-gnu/4.8/../../../../include/c++/4.8/backward" // CHECK-UBUNTU-14-04-PPC64LE: "-internal-externc-isystem" "[[SYSROOT]]/usr/include/powerpc64le-linux-gnu" // CHECK-UBUNTU-14-04-PPC64LE: "-internal-externc-isystem" "[[SYSROOT]]/include" // CHECK-UBUNTU-14-04-PPC64LE: "-internal-externc-isystem" "[[SYSROOT]]/usr/include"