[Driver][Gnu] Support -shared -static: pass -shared to ld and use crtbeginS.o
authorFangrui Song <i@maskray.me>
Tue, 19 Oct 2021 08:09:40 +0000 (01:09 -0700)
committerFangrui Song <i@maskray.me>
Tue, 19 Oct 2021 08:09:41 +0000 (01:09 -0700)
This mode never works (mismatching crtbeginT.o and crtendS.o) and probably
unsupported by GCC on glibc based Linux distro (incorrect crtbeginT.o causes
linker error) but makes sense (-shared means building a shared object, -static
means avoid shared object dependencies) and can be used on musl based Linux
distro.

mingw supports this mode as well.

clang/lib/Driver/ToolChains/Gnu.cpp
clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtbeginS.o [new file with mode: 0644]
clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtendS.o [new file with mode: 0644]
clang/test/Driver/linux-ld.c

index fe5bda5..80e379c 100644 (file)
@@ -473,17 +473,16 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     return;
   }
 
+  if (Args.hasArg(options::OPT_shared))
+    CmdArgs.push_back("-shared");
+
   if (IsStatic) {
     if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
         Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb)
       CmdArgs.push_back("-Bstatic");
     else
       CmdArgs.push_back("-static");
-  } else if (Args.hasArg(options::OPT_shared)) {
-    CmdArgs.push_back("-shared");
-  }
-
-  if (!IsStatic) {
+  } else {
     if (Args.hasArg(options::OPT_rdynamic))
       CmdArgs.push_back("-export-dynamic");
 
@@ -534,10 +533,10 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       }
       if (P.empty()) {
         const char *crtbegin;
-        if (IsStatic)
-          crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
-        else if (Args.hasArg(options::OPT_shared))
+        if (Args.hasArg(options::OPT_shared))
           crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
+        else if (IsStatic)
+          crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
         else if (IsPIE || IsStaticPIE)
           crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
         else
diff --git a/clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtbeginS.o b/clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtbeginS.o
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtendS.o b/clang/test/Driver/Inputs/basic_linux_tree/usr/lib/gcc/x86_64-unknown-linux/10.2.0/crtendS.o
new file mode 100644 (file)
index 0000000..e69de29
index cc50558..102deda 100644 (file)
 // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/lib"
 // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/usr/lib"
 // CHECK-LD-64-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group"
-//
+
+// RUN: %clang -### %s --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -shared -static \
+// RUN:   --gcc-toolchain= --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s
+// CHECK-LD-SHARED-STATIC: "-shared" "-static"
+// CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtbeginS.o"
+// CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtendS.o"
+
 // Check that flags can be combined. The -static dominates.
 // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
 // RUN:     --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \