From: Chandler Carruth Date: Wed, 31 Jul 2013 00:37:07 +0000 (+0000) Subject: Find a better compromise with the default library search paths used by X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28803ba0cd8a5d13d104af96aadf72dca4160a7f;p=clang Find a better compromise with the default library search paths used by Clang when linking and using a GCC installation from a GCC cross-compiler. This was desired already by two special case platforms (Android and Mips), and turns out to be generally (if frustratingly) true. I've added a substantial comment to the code clarifying the underlying assumptions of doing actual cross compiles with Clang (or GCC for that matter!) and help avoid further confusion here. The end result is to realize that fully general form of PR12478 cannot be resolved while we support existing cross-compiling GCC toolchains, and linking with them (namely, linking against their libgcc and libstdc++ installs). GCC installs these target libraries under a target-specific prefix but one that may not be available within the actual sysroot in use. When linking in this world, GCC works and Clang should as well, but caveat emptor: DSOs from this tree must be replicated and rpath-fixed to be found at runtime within the sysroot. I've extended the cross compile test cases to cover these issues by pointing them at a sysroot and actually checking the library search paths. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187466 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 62f7834e56..5defac6eed 100644 --- a/lib/Driver/ToolChains.cpp +++ b/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/test/Driver/cross-linux-tools.c b/test/Driver/cross-linux.c similarity index 54% rename from test/Driver/cross-linux-tools.c rename to test/Driver/cross-linux.c index ead2130674..8eb2dd1439 100644 --- a/test/Driver/cross-linux-tools.c +++ b/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"