diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index 62f7834e56fd..5defac6eedbb 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -2281,33 +2281,48 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) GCCInstallation.getBiarchSuffix()), Paths); + // Sourcery CodeBench MIPS toolchain holds some libraries under + // the parent prefix of the GCC installation. + // FIXME: It would be cleaner to model this as a variant of multilib. IE, + // instead of 'lib64' it would be 'lib/el'. + std::string MultilibSuffix; + appendMipsTargetSuffix(MultilibSuffix, Arch, Args); + + // GCC cross compiling toolchains will install target libraries which ship + // as part of the toolchain under // rather than as + // any part of the GCC installation in + // //gcc//. 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 targetting 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 + // // 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/../" + Multilib + + MultilibSuffix, + 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. // 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. // 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. + // the cross. Note that GCC does include some of these directories in some + // configurations but this seems somewhere between questionable and simply + // a bug. if (StringRef(LibPath).startswith(SysRoot)) { - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib, - Paths); addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); addPathIfExists(LibPath + "/../" + Multilib, Paths); } - // On Android, libraries in the parent prefix of the GCC installation are - // preferred to the ones under sysroot. - if (IsAndroid) { - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths); - } - // Sourcery CodeBench MIPS toolchain holds some libraries under - // the parent prefix of the GCC installation. - if (IsMips) { - std::string Suffix; - appendMipsTargetSuffix(Suffix, Arch, Args); - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + - Multilib + Suffix, - Paths); - } } addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths); @@ -2327,10 +2342,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) if (!GCCInstallation.getBiarchSuffix().empty()) addPathIfExists(GCCInstallation.getInstallPath(), Paths); - if (StringRef(LibPath).startswith(SysRoot)) { - addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths); + // See comments above on the multilib variant for details of why this is + // included even from outside the sysroot. + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", 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)) addPathIfExists(LibPath, Paths); - } } addPathIfExists(SysRoot + "/lib", Paths); addPathIfExists(SysRoot + "/usr/lib", Paths); diff --git a/clang/test/Driver/cross-linux-tools.c b/clang/test/Driver/cross-linux.c similarity index 54% rename from clang/test/Driver/cross-linux-tools.c rename to clang/test/Driver/cross-linux.c index ead2130674e9..8eb2dd143917 100644 --- a/clang/test/Driver/cross-linux-tools.c +++ b/clang/test/Driver/cross-linux.c @@ -27,31 +27,69 @@ // RUN: %clang -### -o %t %s 2>&1 -no-integrated-as \ // RUN: --gcc-toolchain=%S/Inputs/multilib_32bit_linux_tree/usr \ // RUN: --target=i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-MULTI32-I386 %s // CHECK-MULTI32-I386: "-cc1" "-triple" "i386-unknown-linux" // CHECK-MULTI32-I386: "{{.*}}/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0/../../../../i386-unknown-linux/bin{{/|\\}}as" "--32" -// CHECK-MULTI32-I386: "{{.*}}/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0/../../../../i386-unknown-linux/bin{{/|\\}}ld" {{.*}} "-m" "elf_i386" +// CHECK-MULTI32-I386: "[[gcc_install:.*/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0]]/../../../../i386-unknown-linux/bin{{/|\\}}ld" +// CHECK-MULTI32-I386: "--sysroot=[[sysroot:.*/Inputs/basic_linux_tree]]" +// CHECK-MULTI32-I386: "-m" "elf_i386" +// CHECK-MULTI32-I386: "[[gcc_install]]/crtbegin.o" +// CHECK-MULTI32-I386: "-L[[gcc_install]]" +// CHECK-MULTI32-I386: "-L[[gcc_install]]/../../../../i386-unknown-linux/lib/../lib32" +// CHECK-MULTI32-I386: "-L[[gcc_install]]/../../../../i386-unknown-linux/lib" +// CHECK-MULTI32-I386: "-L[[sysroot]]/lib" +// CHECK-MULTI32-I386: "-L[[sysroot]]/usr/lib" // // RUN: %clang -### -o %t %s 2>&1 -no-integrated-as \ // RUN: --gcc-toolchain=%S/Inputs/multilib_32bit_linux_tree/usr \ // RUN: --target=x86_64-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-MULTI32-X86-64 %s // CHECK-MULTI32-X86-64: "-cc1" "-triple" "x86_64-unknown-linux" // CHECK-MULTI32-X86-64: "{{.*}}/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0/../../../../i386-unknown-linux/bin{{/|\\}}as" "--64" -// CHECK-MULTI32-X86-64: "{{.*}}/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0/../../../../i386-unknown-linux/bin{{/|\\}}ld" {{.*}} "-m" "elf_x86_64" +// CHECK-MULTI32-X86-64: "[[gcc_install:.*/Inputs/multilib_32bit_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0]]/../../../../i386-unknown-linux/bin{{/|\\}}ld" +// CHECK-MULTI32-X86-64: "--sysroot=[[sysroot:.*/Inputs/basic_linux_tree]]" +// CHECK-MULTI32-X86-64: "-m" "elf_x86_64" +// CHECK-MULTI32-X86-64: "[[gcc_install]]/64/crtbegin.o" +// CHECK-MULTI32-X86-64: "-L[[gcc_install]]/64" +// CHECK-MULTI32-X86-64: "-L[[gcc_install]]/../../../../i386-unknown-linux/lib/../lib64" +// CHECK-MULTI32-X86-64: "-L[[gcc_install]]" +// CHECK-MULTI32-X86-64: "-L[[gcc_install]]/../../../../i386-unknown-linux/lib" +// CHECK-MULTI32-X86-64: "-L[[sysroot]]/lib" +// CHECK-MULTI32-X86-64: "-L[[sysroot]]/usr/lib" // // RUN: %clang -### -o %t %s 2>&1 -no-integrated-as \ // RUN: --gcc-toolchain=%S/Inputs/multilib_64bit_linux_tree/usr \ // RUN: --target=i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-MULTI64-I386 %s // CHECK-MULTI64-I386: "-cc1" "-triple" "i386-unknown-linux" // CHECK-MULTI64-I386: "{{.*}}/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0/../../../../x86_64-unknown-linux/bin{{/|\\}}as" "--32" -// CHECK-MULTI64-I386: "{{.*}}/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0/../../../../x86_64-unknown-linux/bin{{/|\\}}ld" {{.*}} "-m" "elf_i386" +// CHECK-MULTI64-I386: "[[gcc_install:.*/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0]]/../../../../x86_64-unknown-linux/bin{{/|\\}}ld" +// CHECK-MULTI64-I386: "--sysroot=[[sysroot:.*/Inputs/basic_linux_tree]]" +// CHECK-MULTI64-I386: "-m" "elf_i386" +// CHECK-MULTI64-I386: "[[gcc_install]]/32/crtbegin.o" +// CHECK-MULTI64-I386: "-L[[gcc_install]]/32" +// CHECK-MULTI64-I386: "-L[[gcc_install]]/../../../../x86_64-unknown-linux/lib/../lib32" +// CHECK-MULTI64-I386: "-L[[gcc_install]]" +// CHECK-MULTI64-I386: "-L[[gcc_install]]/../../../../x86_64-unknown-linux/lib" +// CHECK-MULTI64-I386: "-L[[sysroot]]/lib" +// CHECK-MULTI64-I386: "-L[[sysroot]]/usr/lib" // // RUN: %clang -### -o %t %s 2>&1 -no-integrated-as \ // RUN: --gcc-toolchain=%S/Inputs/multilib_64bit_linux_tree/usr \ // RUN: --target=x86_64-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-MULTI64-X86-64 %s // CHECK-MULTI64-X86-64: "-cc1" "-triple" "x86_64-unknown-linux" // CHECK-MULTI64-X86-64: "{{.*}}/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0/../../../../x86_64-unknown-linux/bin{{/|\\}}as" "--64" -// CHECK-MULTI64-X86-64: "{{.*}}/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0/../../../../x86_64-unknown-linux/bin{{/|\\}}ld" {{.*}} "-m" "elf_x86_64" +// CHECK-MULTI64-X86-64: "[[gcc_install:.*/Inputs/multilib_64bit_linux_tree/usr/lib/gcc/x86_64-unknown-linux/4.6.0]]/../../../../x86_64-unknown-linux/bin{{/|\\}}ld" +// CHECK-MULTI64-X86-64: "--sysroot=[[sysroot:.*/Inputs/basic_linux_tree]]" +// CHECK-MULTI64-X86-64: "-m" "elf_x86_64" +// CHECK-MULTI64-X86-64: "[[gcc_install]]/crtbegin.o" +// CHECK-MULTI64-X86-64: "-L[[gcc_install]]" +// CHECK-MULTI64-X86-64: "-L[[gcc_install]]/../../../../x86_64-unknown-linux/lib/../lib64" +// CHECK-MULTI64-X86-64: "-L[[gcc_install]]/../../../../x86_64-unknown-linux/lib" +// CHECK-MULTI64-X86-64: "-L[[sysroot]]/lib" +// CHECK-MULTI64-X86-64: "-L[[sysroot]]/usr/lib"