[cfe-dev] Adding -fuse-ld= support to clang

Rafael EspĂ­ndola rafael.espindola at gmail.com
Sat May 18 08:59:32 PDT 2013


On 18 May 2013 11:00, David Chisnall <David.Chisnall at cl.cam.ac.uk> wrote:
> Hi Everyone,
>
> In FreeBSD, we are about to start the process of migrating from (ancient) BFD ld to MCLinker, so we're going to need support for multiple linkers for a while.  It turns out that gcc already has an option to select linkers, so I have attempted to remain compatible in the attached patch.  This adds a -fuse-ld={name} option, which takes a string as an argument.  The toolchains then request a linker and get either ld.{name}, ld-{name}, or {name} as the linker.
>
> Does anyone have objections to committing this as-is, or would anyone like to recommend a better approach?

Looks fairly reasonable, but
* Instead of running touch, add the file to the install tree in svn.
* Test both ld.name and ld-name.
* If there is both ld.name and ld-name, make sure and test we select
the same one as gcc.

> David
>
> Index: include/clang/Basic/DiagnosticDriverKinds.td
> ===================================================================
> --- include/clang/Basic/DiagnosticDriverKinds.td        (revision 182184)
> +++ include/clang/Basic/DiagnosticDriverKinds.td        (working copy)
> @@ -26,6 +26,8 @@
>    "unsupported runtime library '%0' for platform '%1'">;
>  def err_drv_invalid_stdlib_name : Error<
>    "invalid library name in argument '%0'">;
> +def err_drv_invalid_linker_name : Error<
> +  "invalid linker name in argument '%0'">;
>  def err_drv_invalid_opt_with_multiple_archs : Error<
>    "option '%0' cannot be used with multiple -arch options">;
>  def err_drv_invalid_output_with_multiple_archs : Error<
> Index: include/clang/Driver/Options.td
> ===================================================================
> --- include/clang/Driver/Options.td     (revision 182184)
> +++ include/clang/Driver/Options.td     (working copy)
> @@ -744,6 +744,8 @@
>  def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
>  def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
>    HelpText<"Use .init_array instead of .ctors">;
> +def fuse_ld_EQ : Joined<["-", "--"], "fuse-ld=">, Group<f_Group>,
> +  HelpText<"The linker to use.">;
>  def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
>  def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
>    HelpText<"Set the default symbol visibility for all global declarations">;
> Index: include/clang/Driver/ToolChain.h
> ===================================================================
> --- include/clang/Driver/ToolChain.h    (revision 182184)
> +++ include/clang/Driver/ToolChain.h    (working copy)
> @@ -136,6 +136,9 @@
>
>    std::string GetFilePath(const char *Name) const;
>    std::string GetProgramPath(const char *Name) const;
> +  /// Returns the linker path, respecting the -fuse-ld= argument to determine
> +  /// the linker suffix or name.
> +  std::string GetLinkerPath() const;
>
>    // Platform defaults information
>
> Index: lib/Driver/ToolChain.cpp
> ===================================================================
> --- lib/Driver/ToolChain.cpp    (revision 182184)
> +++ lib/Driver/ToolChain.cpp    (working copy)
> @@ -132,6 +132,36 @@
>
>  }
>
> +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 GetFilePath("ld");
> +    std::string LinkerName = Value.str();
> +    std::string LD("ld.");
> +    LD += LinkerName;
> +    std::string LinkerPath = GetFilePath(LD.c_str());
> +    bool Exists;
> +    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
> +      return LinkerPath;
> +    LD = std::string("ld-") + LinkerName;
> +    LinkerPath = GetFilePath(LD.c_str());
> +    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
> +      return LinkerPath;
> +    LinkerPath = GetFilePath(LinkerName.c_str());
> +    if (!llvm::sys::fs::exists(LinkerPath, Exists) && Exists)
> +      return LinkerPath;
> +    getDriver().Diag(diag::err_drv_invalid_linker_name)
> +      << A->getAsString(Args);
> +    // Fall through and run the system linker - we could do a hard error here,
> +    // but we may as well try and see if it works.
> +  }
> +  return GetFilePath("ld");
> +}
> +
> +
>  std::string ToolChain::GetProgramPath(const char *Name) const {
>    return D.GetProgramPath(Name, *this);
>  }
> Index: lib/Driver/Tools.cpp
> ===================================================================
> --- lib/Driver/Tools.cpp        (revision 182184)
> +++ lib/Driver/Tools.cpp        (working copy)
> @@ -5219,8 +5219,7 @@
>                                getToolChain().GetFilePath("crtendS.o")));
>    }
>
> -  const char *Exec =
> -    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
> +  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
>    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
>  }
>
> @@ -5361,8 +5360,7 @@
>                                getToolChain().GetFilePath("crtendS.o")));
>    }
>
> -  const char *Exec =
> -    Args.MakeArgString(getToolChain().GetProgramPath("ld"));
> +  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
>    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
>  }
>
> @@ -5612,8 +5610,7 @@
>
>    addProfileRT(ToolChain, Args, CmdArgs, ToolChain.getTriple());
>
> -  const char *Exec =
> -    Args.MakeArgString(ToolChain.GetProgramPath("ld"));
> +  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
>    C.addCommand(new Command(JA, *this, Exec, CmdArgs));
>  }
>
> @@ -5762,7 +5759,7 @@
>
>    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));
>  }
>
> @@ -6247,7 +6244,7 @@
>           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));
>  }
>
> @@ -6430,8 +6427,7 @@
>
>    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));
>  }
>
> Index: test/Driver/fuse_ld.c
> ===================================================================
> --- test/Driver/fuse_ld.c       (revision 0)
> +++ test/Driver/fuse_ld.c       (working copy)
> @@ -0,0 +1,7 @@
> +// RUN: rm -f ld.foo
> +// RUN: %clang %s -target i386-unknown-freebsd -fuse-ld=foo -### 2>&1 | FileCheck -check-prefix=MISSING %s
> +// RUN: touch ld.foo
> +// RUN: %clang %s -B. -target i386-unknown-freebsd -fuse-ld=foo -### 2>&1 | FileCheck -check-prefix=FOUND %s
> +
> +// CHECK-MISSING: error: invalid linker name in argument '-fuse-ld=foo'
> +// CHECK-FOUND: "./ld.foo"
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev




More information about the cfe-dev mailing list