Blame SOURCES/0004-PATCH-clang-Prefer-gcc-toolchains-with-libgcc_s.so-w.patch

300695
From d8af49687765744efaae7ba0f0c4c0fcd58a0e31 Mon Sep 17 00:00:00 2001
1ca1ea
From: serge-sans-paille <sguelton@redhat.com>
1ca1ea
Date: Wed, 23 Sep 2020 12:47:30 +0000
300695
Subject: [PATCH 4/6] [PATCH][clang] Prefer gcc toolchains with libgcc_s.so
300695
 when not static linking libgcc
1ca1ea
1ca1ea
Fedora ships cross-compilers on all platforms, so a user could end up
1ca1ea
with a gcc x86_64 cross-compiler installed on an x86_64 system. clang
1ca1ea
maintains a list of supported triples for each target and when all
1ca1ea
else is equal will prefer toolchains with triples that appear earlier
1ca1ea
in the list.
1ca1ea
1ca1ea
The cross-compiler triple on Fedora is x86_64-linux-gnu and this comes
1ca1ea
before the Fedora system compiler's triple: x86_64-redhat-linux in
1ca1ea
the triples list, so the cross compiler is always preferred. This
1ca1ea
is a problem, because the cross compiler is missing libraries, like
1ca1ea
libgcc_s.so, that clang expects to be there so linker invocations
1ca1ea
will fail.
1ca1ea
1ca1ea
This patch fixes this by checking for the existence of libgcc_s.so
1ca1ea
when it is required and taking that into account when selecting a
1ca1ea
toolchain.
1ca1ea
---
300695
 clang/lib/Driver/ToolChains/Gnu.cpp                      | 16 ++++++++++++++--
300695
 clang/lib/Driver/ToolChains/Gnu.h                        |  4 +++-
300695
 .../usr/lib/gcc/x86_64-linux-gnu/7/crtbegin.o            |  0
300695
 .../usr/lib/gcc/x86_64-redhat-linux/7/crtbegin.o         |  0
300695
 .../usr/lib/gcc/x86_64-redhat-linux/7/libgcc_s.so        |  0
300695
 clang/test/Driver/linux-ld.c                             | 12 ++++++++++++
1ca1ea
 6 files changed, 29 insertions(+), 3 deletions(-)
300695
 create mode 100644 clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-linux-gnu/7/crtbegin.o
300695
 create mode 100644 clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/crtbegin.o
300695
 create mode 100644 clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/libgcc_s.so
1ca1ea
300695
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
300695
index 5deeb10..5d51517 100644
300695
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
300695
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
300695
@@ -2539,6 +2539,8 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
1ca1ea
        (TargetArch == llvm::Triple::x86 &&
1ca1ea
         TargetTriple.getOS() != llvm::Triple::Solaris)}};
1ca1ea
 
1ca1ea
+  bool NeedLibgccShared = !Args.hasArg(options::OPT_static_libgcc) &&
1ca1ea
+                          !Args.hasArg(options::OPT_static);
1ca1ea
   for (auto &Suffix : Suffixes) {
1ca1ea
     if (!Suffix.Active)
1ca1ea
       continue;
300695
@@ -2556,8 +2558,17 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
1ca1ea
           continue; // Saw this path before; no need to look at it again.
1ca1ea
       if (CandidateVersion.isOlderThan(4, 1, 1))
1ca1ea
         continue;
1ca1ea
-      if (CandidateVersion <= Version)
1ca1ea
-        continue;
1ca1ea
+
1ca1ea
+      bool CandidateHasLibGccShared = false;
1ca1ea
+      if (CandidateVersion <= Version) {
1ca1ea
+        if (NeedLibgccShared && !HasLibGccShared) {
1ca1ea
+          CandidateHasLibGccShared =
1ca1ea
+                D.getVFS().exists(LI->path() + "/libgcc_s.so");
1ca1ea
+
1ca1ea
+        }
1ca1ea
+        if (HasLibGccShared || !CandidateHasLibGccShared)
1ca1ea
+          continue;
1ca1ea
+      }
1ca1ea
 
1ca1ea
       if (!ScanGCCForMultilibs(TargetTriple, Args, LI->path(),
1ca1ea
                                NeedsBiarchSuffix))
300695
@@ -2571,6 +2582,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
1ca1ea
       GCCInstallPath = (LibDir + "/" + LibSuffix + "/" + VersionText).str();
1ca1ea
       GCCParentLibPath = (GCCInstallPath + "/../" + Suffix.ReversePath).str();
1ca1ea
       IsValid = true;
1ca1ea
+      HasLibGccShared = CandidateHasLibGccShared;
1ca1ea
     }
1ca1ea
   }
1ca1ea
 }
300695
diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
300695
index 90d3baf..9d0cea2 100644
300695
--- a/clang/lib/Driver/ToolChains/Gnu.h
300695
+++ b/clang/lib/Driver/ToolChains/Gnu.h
1ca1ea
@@ -190,6 +190,7 @@ public:
1ca1ea
   /// Driver, and has logic for fuzzing that where appropriate.
1ca1ea
   class GCCInstallationDetector {
1ca1ea
     bool IsValid;
1ca1ea
+    bool HasLibGccShared;
1ca1ea
     llvm::Triple GCCTriple;
1ca1ea
     const Driver &D;
1ca1ea
 
300695
@@ -216,7 +217,8 @@ public:
300695
     const std::string GentooConfigDir = "/etc/env.d/gcc";
1ca1ea
 
1ca1ea
   public:
1ca1ea
-    explicit GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
1ca1ea
+    explicit GCCInstallationDetector(const Driver &D)
1ca1ea
+        : IsValid(false), HasLibGccShared(false), D(D) {}
1ca1ea
     void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args,
1ca1ea
               ArrayRef<std::string> ExtraTripleAliases = None);
1ca1ea
 
300695
diff --git a/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-linux-gnu/7/crtbegin.o b/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-linux-gnu/7/crtbegin.o
1ca1ea
new file mode 100644
300695
index 0000000..e69de29
300695
diff --git a/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/crtbegin.o b/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/crtbegin.o
1ca1ea
new file mode 100644
300695
index 0000000..e69de29
300695
diff --git a/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/libgcc_s.so b/clang/test/Driver/Inputs/fedora_28_tree/usr/lib/gcc/x86_64-redhat-linux/7/libgcc_s.so
1ca1ea
new file mode 100644
300695
index 0000000..e69de29
300695
diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c
300695
index 24d3c78..071bb9b 100644
300695
--- a/clang/test/Driver/linux-ld.c
300695
+++ b/clang/test/Driver/linux-ld.c
1ca1ea
@@ -784,6 +784,18 @@
1ca1ea
 // CHECK-FEDORA-31-RISCV64: "{{.*}}/usr/lib/gcc/riscv64-redhat-linux/9{{/|\\\\}}crtend.o"
1ca1ea
 // CHECK-FEDORA-31-RISCV64: "{{.*}}/usr/lib/gcc/riscv64-redhat-linux/9{{/|\\\\}}crtn.o"
1ca1ea
 //
1ca1ea
+// Check that clang does not select the cross compiler by default on Fedora 28.
1ca1ea
+//
1ca1ea
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
1ca1ea
+// RUN:     --target=x86_64-unknown-linux-gnu \
1ca1ea
+// RUN:     --gcc-toolchain="" \
1ca1ea
+// RUN:     --sysroot=%S/Inputs/fedora_28_tree \
1ca1ea
+// RUN:   | FileCheck --check-prefix=CHECK-FEDORA-28-X86_64 %s
1ca1ea
+//
1ca1ea
+// CHECK-FEDORA-28-X86_64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
1ca1ea
+// CHECK-FEDORA-28-X86_64: "[[SYSROOT]]/usr/lib/gcc/x86_64-redhat-linux/7/crtbegin.o"
1ca1ea
+// CHECK-FEDORA-28-X86_64: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-redhat-linux/7"
1ca1ea
+//
1ca1ea
 // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
1ca1ea
 // RUN:     --target=arm-unknown-linux-gnueabi -rtlib=platform \
1ca1ea
 // RUN:     --gcc-toolchain="" \
1ca1ea
-- 
300695
1.8.3.1
1ca1ea