]> granicus.if.org Git - clang/commitdiff
Accept absolute paths in the -fuse-ld option.
authorPeter Zotov <whitequark@whitequark.org>
Wed, 9 Mar 2016 05:18:16 +0000 (05:18 +0000)
committerPeter Zotov <whitequark@whitequark.org>
Wed, 9 Mar 2016 05:18:16 +0000 (05:18 +0000)
This patch extends the -fuse-ld option to accept a full path to an executable
and use it verbatim to invoke the linker. There are generally two reasons
to desire this.

The first reason relates to the sad truth is that Clang is retargetable,
Binutils are not.

While any Clang from a binary distribution is sufficient to compile code
for a wide range of architectures and prefixed BFD linkers (e.g.
installed as /usr/bin/arm-none-linux-gnueabi-ld) as well as cross-compiled
libc's (for non-bare-metal targets) are widely available, including on all
Debian derivatives, it is impossible to use them together because
the -fuse-ld= option allows to specify neither a linker prefix nor
a full path to one.

The second reason is linker development, both when porting existing linkers
to new architectures and when working on a new linker such as LLD.

Differential Revision: http://reviews.llvm.org/D17952

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262996 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/ToolChain.cpp
test/Driver/fuse-ld.c

index 97eee59d127288b03ab9e0b29b2bdc69f1a910e0..c1305f1b790cb97cdb90e7ed4979b1220a2c2340 100644 (file)
@@ -342,19 +342,26 @@ std::string ToolChain::GetProgramPath(const char *Name) const {
 
 std::string ToolChain::GetLinkerPath() const {
   if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
-    StringRef Suffix = A->getValue();
-
-    // If we're passed -fuse-ld= with no argument, or with the argument ld,
-    // then use whatever the default system linker is.
-    if (Suffix.empty() || Suffix == "ld")
-      return GetProgramPath("ld");
-
-    llvm::SmallString<8> LinkerName("ld.");
-    LinkerName.append(Suffix);
-
-    std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
-    if (llvm::sys::fs::exists(LinkerPath))
-      return LinkerPath;
+    StringRef UseLinker = A->getValue();
+
+    if (llvm::sys::path::is_absolute(UseLinker)) {
+      // If we're passed -fuse-ld= with what looks like an absolute path,
+      // don't attempt to second-guess that.
+      if (llvm::sys::fs::exists(UseLinker))
+        return UseLinker;
+    } else {
+      // If we're passed -fuse-ld= with no argument, or with the argument ld,
+      // then use whatever the default system linker is.
+      if (UseLinker.empty() || UseLinker == "ld")
+        return GetProgramPath("ld");
+
+      llvm::SmallString<8> LinkerName("ld.");
+      LinkerName.append(UseLinker);
+
+      std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
+      if (llvm::sys::fs::exists(LinkerPath))
+        return LinkerPath;
+    }
 
     getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
     return "";
index bd25b8deb3289f4fada7c1964969c25d8a18973e..ca89eb997165a0aa4c39061b1ca38b03ce610d7b 100644 (file)
@@ -1,3 +1,9 @@
+// RUN: %clang %s -### \
+// RUN:     -fuse-ld=/usr/local/bin/or1k-linux-ld 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ABSOLUTE-LD
+// CHECK-ABSOLUTE-LD: /usr/local/bin/or1k-linux-ld
+
+
 // RUN: %clang %s -### \
 // RUN:     -target x86_64-unknown-freebsd 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-FREEBSD-LD