This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA/RFC: Enable both gold and ld in a single toolchain


Hi Guys,

  I have created a patch (attached) that enables both GOLD and LD to be
  built and used in a single toolchain.  This allows easy comparison of
  the two linkers with just a single command line switch to choose
  between them.

  I suspect that the patch may not be approved, but I wanted to
  contribute it in case anyone else was interested in this facility.

  In order to build both linkers it is necessary to run the top level
  configure script with the switch:

    --enable-gold=both

  Then once the linkers are built/installed you can add:

    -Luse-gold

  to a gcc command line to use the GOLD linker.  Otherwise the LD linker
  (aka gld) will be used.

  There is one special caveat though.  When installing the two linkers
  it is necessary to install gold before ld as otherwise the ld linker
  will be overwritten.  Ie run:

    make ... install-gold install-ld ...


  The choice of -Luse-gold as the switch to select the gold linker is a
  hack.  One of the requirements for programs and scripts that sit
  between gcc and the linker, (such as collect2 and collect-ld), is that
  gcc must continue to work if they are not there and the linker is
  invoked directly.  Thus any options that are intended for the
  intermediate programs/scripts must be disguised in some fashion.
  
  Collect2 uses environment variables to get its options but this is,
  IMHO, heinous.  So instead I chose to use the -L switch.  This can
  take an arbitrary text argument and it will not cause the linker to
  complain if the argument is not recognised or the so called library
  search path does not actually exist.  In theory it could break a link
  if there really is a sub-directory of the current directory called
  "use-gold" and this directory contains subtly invalid binaries, but
  this is very unlikely to happen.

  Comments welcome, and if the gcc maintainers feel that this feature is
  actually wanted in the mainstream sources I will happy to apply my
  patch and maintain it in the future.

  Tested with i686-pc-linux-gnu, sparc-elf and arm-eabi toolchains, and
  an x86 bootstrap.  (That is bootstrapping without gold enabled, just
  to make sure that I did not break anything).

Cheers
  Nick

./ChangeLog
2010-03-04  Nick Clifton  <nickc@redhat.com>

	* configure.ac (--enable-gold): Accept a value of "both".  If
	this value is given then configure both ld and gold.
        * configure: Regenerate.

gcc/ChangeLog
2010-03-04  Nick Clifton  <nickc@redhat.com>

	* configure.ac (gcc_cv_gold_srcdir): New cached variable -
	contains the location of the gold sources.
        (ORIGINAL_GOLD_FOR_TARGET): New substituted variable - contains
	the name of the locally built gold executable.
        * configure: Regenerate.
        * collect2.c (main): Detect the -Luse-gold switch and select the
	gold linker, if found.
        * exec-tool.in: Detect the -Luse-gold switch and select the gold
	linker, if found.  Add support for -v switch.  Report problems
	locating linker executable.

gold/ChangeLog
2010-03-04  Nick Clifton  <nickc@redhat.com>

	* Makefile.am (install-exec-local): Also install the executable
	as a binary named 'gold'.
        * Makefile.in: Regenerate.

Index: gold/Makefile.am
===================================================================
RCS file: /cvs/src/src/gold/Makefile.am,v
retrieving revision 1.60
diff -c -3 -p -r1.60 Makefile.am
*** gold/Makefile.am	3 Feb 2010 05:36:55 -0000	1.60
--- gold/Makefile.am	4 Mar 2010 15:08:22 -0000
*************** install-exec-local: ld-new$(EXEEXT)
*** 185,190 ****
--- 185,197 ----
  	  ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
  	    || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \
  	fi
+ 	n=`echo gold | sed '$(transform)'`; \
+ 	$(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(bindir)/$${n}$(EXEEXT); \
+ 	if test "$(bindir)" != "$(tooldir)/bin"; then \
+ 	  rm -f $(DESTDIR)$(tooldir)/bin/gold$(EXEEXT); \
+ 	  ln $(DESTDIR)$(bindir)/$${n}$(EXEEXT) $(DESTDIR)$(tooldir)/bin/gold$(EXEEXT) >/dev/null 2>/dev/null \
+ 	    || $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/gold$(EXEEXT); \
+ 	fi
  
  # We want install to imply install-info as per GNU standards, despite
  # the cygnus option.
Index: configure.ac
===================================================================
--- configure.ac	(revision 157226)
+++ configure.ac	(working copy)
@@ -320,7 +320,7 @@
 [  --enable-gold           use gold instead of ld],
 ENABLE_GOLD=$enableval,
 ENABLE_GOLD=no)
-if test "${ENABLE_GOLD}" = "yes"; then
+if test "${ENABLE_GOLD}" = "yes" -o "${ENABLE_GOLD}" = "both"; then
   # Check for ELF target.
   is_elf=no
   case "${target}" in
@@ -340,7 +340,11 @@
     # Check for target supported by gold.
     case "${target}" in
       i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*)
-        configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
+        if test "${ENABLE_GOLD}" = "both"; then
+          configdirs="${configdirs} gold"
+	else
+          configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`"
+	fi
         ;;
     esac
   fi
@@ -2653,7 +2657,9 @@
 esac
 
 case "$enable_bootstrap:$ENABLE_GOLD: $configdirs :,$stage1_languages," in
+  yes:both:*\ gold\ *:*,c++,* | \
   yes:yes:*\ gold\ *:*,c++,*) ;;
+  yes:both:*\ gold\ *:* | \
   yes:yes:*\ gold\ *:*)
     AC_MSG_ERROR([in a combined tree, bootstrapping with --enable-gold requires c++ in stage1_languages])
     ;;
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 157226)
+++ gcc/configure.ac	(working copy)
@@ -1923,6 +1923,17 @@
         AC_PATH_PROG(gcc_cv_ld, $LD_FOR_TARGET)
 fi])
 
+gcc_cv_ld_gold_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gold
+
+AS_VAR_SET_IF(gcc_cv_gold,, [
+if test -f $gcc_cv_ld_gold_srcdir/configure.ac \
+     && test -f ../gold/Makefile \
+     && test x$build = x$host; then
+	gcc_cv_gold=../gold/ld-new$build_exeext
+else
+        gcc_cv_gold=''
+fi])
+
 ORIGINAL_PLUGIN_LD_FOR_TARGET=$gcc_cv_ld
 PLUGIN_LD=`basename $gcc_cv_ld`
 AC_ARG_WITH(plugin-ld,
@@ -1941,6 +1952,9 @@
   *) AC_CONFIG_FILES(collect-ld:exec-tool.in, [chmod +x collect-ld]) ;;
 esac 
 
+ORIGINAL_GOLD_FOR_TARGET=$gcc_cv_gold
+AC_SUBST(ORIGINAL_GOLD_FOR_TARGET)
+
 AC_MSG_CHECKING(what linker to use)
 if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext; then
 	# Single tree build which includes ld.  We want to prefer it
Index: gcc/exec-tool.in
===================================================================
--- gcc/exec-tool.in	(revision 157226)
+++ gcc/exec-tool.in	(working copy)
@@ -21,11 +21,13 @@
 
 ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@"
 ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@"
+ORIGINAL_GOLD_FOR_TARGET="@ORIGINAL_GOLD_FOR_TARGET@"
 ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@"
 ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@"
 exeext=@host_exeext@
 fast_install=@enable_fast_install@
 objdir=@objdir@
+version="1.1"
 
 invoked=`basename "$0"`
 case "$invoked" in
@@ -35,15 +37,47 @@
     dir=gas
     ;;
   collect-ld)
-    # when using a linker plugin, gcc will always pass '-plugin' as the
-    # first option to the linker.
-    if test x"$1" = "x-plugin"; then
-      original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
-    else
-      original=$ORIGINAL_LD_FOR_TARGET
+    prog=ld-new$exeext
+    # Look for the magic library paths "-Luse-gold" and
+    # "-Luse-ld".  If present then select the indicated
+    # linker.  Otherwise if -plugin is specified then
+    # choose a plugin-capable linker, otherwise use the
+    # default.
+    case "${1+$@} " in
+      *-Luse-gold\ *)
+        original=$ORIGINAL_GOLD_FOR_TARGET
+	dir=gold
+        ;;
+      *-Luse-ld\ *)
+        original=$ORIGINAL_LD_FOR_TARGET
+        dir=ld
+        ;;
+      *-plugin\ *)
+        original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
+        dir=ld
+	;;
+      *)
+        original=$ORIGINAL_LD_FOR_TARGET
+        dir=ld
+	;;
+    esac
+
+    # If the selected linker has not been configured then
+    # try using the others, in the order PLUGIN-LD, LD, GOLD.
+    if test x"$original" == x; then
+      if test x"$ORIGINAL_PLUGIN_LD_FOR_TARGET" != x; then
+        original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
+        dir=ld
+      elif test x"$ORIGINAL_LD_FOR_TARGET" != x; then
+        original=$ORIGINAL_LD_FOR_TARGET
+        dir=ld
+      elif test x"$ORIGINAL_GOLD_FOR_TARGET" != x; then
+        original=$ORIGINAL_GOLD_FOR_TARGET
+        dir=gold
+      # Otherwise do nothing - the case statement below
+      # will issue an error message for us.
+      fi
     fi
-    prog=ld-new$exeext
-    dir=ld
     ;;
   nm)
     original=$ORIGINAL_NM_FOR_TARGET
@@ -52,36 +86,65 @@
     ;;
 esac
 
-case "$original" in
-  ../*)
-    # compute absolute path of the location of this script
+case x"$original" in
+  x../*)
+    # Compute absolute path to the location of this script.
     tdir=`dirname "$0"`
     scriptdir=`cd "$tdir" && pwd`
 
     if test -x $scriptdir/../$dir/$prog; then
-      test "$fast_install" = yes || exec $scriptdir/../$dir/$prog ${1+"$@"}
+      if test "$fast_install" = yes; then
+        # If libtool did everything it needs to do, there's a fast path.
+        lt_prog=$scriptdir/../$dir/$objdir/lt-$prog 
 
-      # if libtool did everything it needs to do, there's a fast path
-      lt_prog=$scriptdir/../$dir/$objdir/lt-$prog 
-      test -x $lt_prog && exec $lt_prog ${1+"$@"}
-
-      # libtool has not relinked ld-new yet, but we cannot just use the
-      # previous stage (because then the relinking would just never happen!).
-      # So we take extra care to use prev-ld/ld-new *on recursive calls*.
-      test x"$LT_RCU" = x"1" && exec $scriptdir/../prev-$dir/$prog ${1+"$@"}
-
-      LT_RCU=1; export LT_RCU
-      $scriptdir/../$dir/$prog ${1+"$@"}
-      result=$?
-      exit $result
-
+	if test -x $lt_prog; then
+	  original=$lt_prog
+        else
+          # Libtool has not relinked ld-new yet, but we cannot just use the
+          # previous stage (because then the relinking would just never happen!).
+          # So we take extra care to use prev-ld/ld-new *on recursive calls*.
+          if test x"$LT_RCU" = x"1"; then
+	    original=$scriptdir/../prev-$dir/$prog
+          else
+            LT_RCU=1; export LT_RCU
+            case "${1+$@} " in
+              *-v\ *)
+               echo "$invoked version $version"
+               echo $scriptdir/../$dir/$prog ${1+"$@"}
+               ;;
+            esac
+            $scriptdir/../$dir/$prog ${1+"$@"}
+            result=$?
+            exit $result
+          fi
+        fi
+      else
+	original=$scriptdir/../$dir/$prog
+      fi
     else
-      exec $scriptdir/../prev-$dir/$prog ${1+"$@"}
+      original=$scriptdir/../prev-$dir/$prog
     fi
     ;;
-  *)
-    exec "$original" ${1+"$@"}
+  x)
+    echo "$invoked: executable not configured"
+    exit -1
     ;;
 esac
 
+# If -v has been used then display our version number
+# and then echo the command we are about to invoke.
+case "${1+$@} " in
+  *-v\ *)
+    echo "$invoked version $version"
+    echo $original ${1+"$@"}
+    ;;
+esac
 
+if test -x $original; then
+  exec "$original" ${1+"$@"}
+else
+  echo "$invoked: unable to locate executable: $original"
+  exit -1
+fi
+
+
Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c	(revision 157226)
+++ gcc/collect2.c	(working copy)
@@ -1111,6 +1111,7 @@
 main (int argc, char **argv)
 {
   static const char *const ld_suffix	= "ld";
+  static const char *const gold_suffix  = "gold";
   static const char *const plugin_ld_suffix = PLUGIN_LD;
   static const char *const real_ld_suffix = "real-ld";
   static const char *const collect_ld_suffix = "collect-ld";
@@ -1130,6 +1131,8 @@
 
   const char *const full_ld_suffix =
     concat(target_machine, "-", ld_suffix, NULL);
+  const char *const full_gold_suffix =
+    concat (target_machine, "-", gold_suffix, NULL);
   const char *const full_plugin_ld_suffix =
     concat(target_machine, "-", plugin_ld_suffix, NULL);
   const char *const full_nm_suffix =
@@ -1146,6 +1149,7 @@
     concat (target_machine, "-", gstrip_suffix, NULL);
 #else
   const char *const full_ld_suffix	= ld_suffix;
+  const char *const full_gold_suffix	= gold_suffix;
   const char *const full_plugin_ld_suffix = plugin_ld_suffix;
   const char *const full_nm_suffix	= nm_suffix;
   const char *const full_gnm_suffix	= gnm_suffix;
@@ -1168,6 +1172,7 @@
   char **ld1_argv;
   const char **ld1;
   bool use_plugin = false;
+  bool use_gold = false;
 
   /* The kinds of symbols we will have to consider when scanning the
      outcome of a first pass link.  This is ALL to start with, then might
@@ -1256,6 +1261,8 @@
 	    use_verbose = true;
 	    lto_mode = LTO_MODE_NONE;
 	  }
+	else if (! strcmp (argv[i], "-Luse-gold"))
+	  use_gold = true;
 #ifdef COLLECT_EXPORT_LIST
 	/* since -brtl, -bexport, -b64 are not position dependent
 	   also check for them here */
@@ -1356,6 +1363,8 @@
     ld_file_name = find_a_file (&cpath,
 				use_plugin
 				? plugin_ld_suffix
+				: use_gold
+				? gold_suffix
 				: ld_suffix);
   /* Search the ordinary system bin directories
      for `ld' (if native linking) or `TARGET-ld' (if cross).  */
@@ -1363,6 +1372,8 @@
     ld_file_name = find_a_file (&path,
 				use_plugin
 				? full_plugin_ld_suffix
+				: use_gold
+				? full_gold_suffix
 				: full_ld_suffix);
 
 #ifdef REAL_NM_FILE_NAME

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]