]> granicus.if.org Git - clang/commitdiff
Find a better compromise with the default library search paths used by
authorChandler Carruth <chandlerc@gmail.com>
Wed, 31 Jul 2013 00:37:07 +0000 (00:37 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 31 Jul 2013 00:37:07 +0000 (00:37 +0000)
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

lib/Driver/ToolChains.cpp
test/Driver/cross-linux.c [moved from test/Driver/cross-linux-tools.c with 54% similarity]

index 62f7834e56fd88fd9ccee4575cba5c2a1747f100..5defac6eedbbe85b69651497a123fff48dd19708 100644 (file)
@@ -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 <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 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
+    //     <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/../" + 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);
similarity index 54%
rename from test/Driver/cross-linux-tools.c
rename to test/Driver/cross-linux.c
index ead2130674e96436ad840f835108af3eaddfda35..8eb2dd143917d30d28c3f40bfbe2892ea2ef9658 100644 (file)
 // 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"