From: David Chisnall Date: Sat, 9 Nov 2013 14:16:52 +0000 (+0000) Subject: Add support for -fuse-ld=. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a799d7db952e30b479d647fe35c00ee7360d7628;p=clang Add support for -fuse-ld=. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194328 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index ed49006b21..5d54642bec 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -20,6 +20,8 @@ def err_drv_unknown_stdin_type : Error< def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_invalid_linker_name : Error< + "invalid linker name in argument '%0'">; def err_drv_invalid_rtlib_name : Error< "invalid runtime library name in argument '%0'">; def err_drv_unsupported_rtlib_for_platform : Error< diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index faaaee1e93..45a46e267b 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -1434,7 +1434,8 @@ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group; defm profile_use : BooleanFFlag<"profile-use">, Group; def fprofile_use_EQ : Joined<["-"], "fprofile-use=">, Group; -def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group; +def fuse_ld_EQ : Joined<["-", "--"], "fuse-ld=">, Group, + HelpText<"The suffix of the linker to use (e.g. bfd for ld.bfd).">; defm align_functions : BooleanFFlag<"align-functions">, Group; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 12bce286b9..a0d757c46f 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -126,6 +126,9 @@ public: path_list &getProgramPaths() { return ProgramPaths; } const path_list &getProgramPaths() const { return ProgramPaths; } + /// Returns the linker path, respecting the -fuse-ld= argument to determine + /// the linker suffix or name. + std::string GetLinkerPath() const; const SanitizerArgs& getSanitizerArgs() const; diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 9fe03799f1..20e37ff6b8 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -146,6 +146,28 @@ std::string ToolChain::GetProgramPath(const char *Name) const { return D.GetProgramPath(Name, *this); } +std::string ToolChain::GetLinkerPath() const { + if (Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ)) { + StringRef Value = 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 (Value.empty() || Value == "ld") + return GetProgramPath("ld"); + std::string LinkerName = Value.str(); + std::string LD("ld."); + LD += LinkerName; + std::string LinkerPath = GetProgramPath(LD.c_str()); + bool Exists; + if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists) + return LinkerPath; + getDriver().Diag(diag::err_drv_invalid_linker_name) + << A->getAsString(Args); + return ""; + } + return GetProgramPath("ld"); +} + + types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { return types::lookupTypeForExtension(Ext); } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 7c987191d8..378cc4e11d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -5184,7 +5184,7 @@ void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5296,7 +5296,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5447,7 +5447,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5587,7 +5587,7 @@ void bitrig::Link::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5838,7 +5838,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple()); const char *Exec = - Args.MakeArgString(ToolChain.GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -5992,7 +5992,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6503,7 +6503,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -6687,7 +6687,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("ld")); + Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } diff --git a/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.bfd new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold b/test/Driver/Inputs/basic_freebsd_tree/usr/bin/ld.gold new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Driver/fuse_ld.c b/test/Driver/fuse_ld.c new file mode 100644 index 0000000000..241047de7c --- /dev/null +++ b/test/Driver/fuse_ld.c @@ -0,0 +1,14 @@ +// RUN: %clang %s -### 2>&1 | FileCheck %s +// CHECK: ld +// RUN: %clang -fuse-ld=bfd --sysroot=%S/Inputs/basic_freebsd_tree \ +// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK-BFD %s +// CHECK-BFD: ld.bfd +// RUN: %clang -fuse-ld=gold --sysroot=%S/Inputs/basic_freebsd_tree \ +// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK-GOLD %s +// CHECK-GOLD: ld.gold +// RUN: %clang -fuse-ld=plib --sysroot=%S/Inputs/basic_freebsd_tree \ +// RUN: -B%S/Inputs/basic_freebsd_tree %s -### 2>&1 | \ +// RUN: FileCheck -check-prefix=CHECK-PLIB %s +// CHECK-PLIB: error: invalid linker name