From: Andi Kleen <a...@linux.intel.com>

Slim LTO requires running ar/nm/ranlib with the LTO plugin. The most
convenient way to get this into existing Makefiles is using small
wrappers that pass the plugin. This matches how other compilers
(LLVM, icc) do this too.

My previous attempt at using shell scripts for this
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02471.html
was not approved. Here's another attempt using wrappers written
in C.  This adds wrappers add a --plugin argument before calling the
respective binutils utilities.

The logic gcc.c uses to find the files is very complicated. I didn't
try to replicate it 100% and left out some magic. I would be interested
if this simple method works for everyone or if more code needs
to be added. This only needs to support LTO supporting hosts of course.

I didn't add any documentation because the syntax is exactly the same as
the native ar/ranlib/nm.

v2: Address review comments. Makefile follows go now, use own binaries
for each sub program.

Passed bootstrap and test suite on x86_64-linux.

gcc/:
2011-10-19  Andi Kleen  <a...@linux.intel.com>

        * Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib.
        (native): Add gcc-ar, gcc-nm, gcc-ranlib.
        (AR_LIBS, gcc-ar, gcc-ar.o, gcc-ranlib, gcc-ranlib.o,
         gcc-nm, gcc-nm.o, gcc-ranlib.c, gcc-nm.c): Add.
        (install): Depend on install-gcc-ar.
        (install-gcc-ar): Add.
        (uninstall): Uninstall gcc-ar, gcc-nm, gcc-ranlib.
        * gcc-ar.c: Add new file.
---
 gcc/Makefile.in |   71 +++++++++++++++++++++++++++++++++++++++--
 gcc/gcc-ar.c    |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+), 3 deletions(-)
 create mode 100644 gcc/gcc-ar.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6b28ef5..1b9987a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1545,7 +1545,8 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h 
insn-codes.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
  xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
  $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
- $(SPECS) collect2$(exeext) lto-wrapper$(exeext) \
+ $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
+ gcc-ranlib$(exeext) \
  gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
  gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a \
  libcommon-target.a libcommon.a libgcc.mk
@@ -1791,7 +1792,8 @@ rest.encap: lang.rest.encap
 # This is what is made with the host's compiler
 # whether making a cross compiler or not.
 native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
-       $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext)
+       $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \
+       gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
 
 ifeq ($(enable_plugin),yes)
 native: gengtype$(exeext)
@@ -2049,6 +2051,46 @@ sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) 
coretypes.h $(BASIC_BLOCK
 ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_H)
 sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
 
+AR_LIBS = @COLLECT2_LIBS@
+
+gcc-ar$(exeext): gcc-ar.o $(LIBDEPS)
+       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
+               $(LIBS) $(AR_LIBS)
+
+gcc-nm$(exeext): gcc-nm.o $(LIBDEPS)
+       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
+               $(LIBS) $(AR_LIBS)
+
+gcc-ranlib$(exeext): gcc-ranlib.o $(LIBDEPS)
+       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
+               $(LIBS) $(AR_LIBS)
+
+CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
+       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
+
+gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
+       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
+
+gcc-ranlib.o: gcc-ranlib.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
+       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
+
+gcc-nm.o: gcc-nm.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+# ??? the implicit rules dont trigger if the source file has a different name
+# so copy instead
+gcc-ranlib.c: gcc-ar.c
+       cp $^ $@
+
+gcc-nm.c: gcc-ar.c
+       cp $^ $@
+
 COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o
 COLLECT2_LIBS = @COLLECT2_LIBS@
 collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
@@ -4576,7 +4618,7 @@ maintainer-clean:
 # broken is small.
 install: install-common $(INSTALL_HEADERS) \
     install-cpp install-man install-info install-@POSUB@ \
-    install-driver install-lto-wrapper
+    install-driver install-lto-wrapper install-gcc-ar
 
 ifeq ($(enable_plugin),yes)
 install: install-plugin
@@ -4901,6 +4943,23 @@ install-collect2: collect2 installdirs
 install-lto-wrapper: lto-wrapper$(exeext)
        $(INSTALL_PROGRAM) lto-wrapper$(exeext) 
$(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext)
 
+install-gcc-ar:
+       set -e ; \
+       for i in ar nm ranlib ; do \
+         install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) 
;\
+         target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed 
'$(program_transform_name)'`$(exeext) ; \
+         binname=gcc-$$i$(exeext) ; \
+         rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+         rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+         $(INSTALL_PROGRAM) $$binname $(DESTDIR)$(bindir)/$$install_name ;\
+         if test -f $(DESTDIR)$(bindir)$$target_install_name ; then \
+           :; \
+         else \
+           ( cd $(DESTDIR)$(bindir) && \
+             $(LN) $$install_name $$target_install_name ) ; \
+         fi ; \
+       done
+
 # Cancel installation by deleting the installed files.
 uninstall: lang.uninstall
        -rm -rf $(DESTDIR)$(libsubdir)
@@ -4915,6 +4974,12 @@ uninstall: lang.uninstall
        -rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
        -rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
        -rm -f $(DESTDIR)$(infodir)/cppinternals.info* 
$(DESTDIR)$(infodir)/gccint.info*
+       for i in ar nm ranlib ; do \
+         install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) 
;\
+         target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed 
'$(program_transform_name)'`$(exeext) ; \
+         rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+         rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+       done
 #
 # These targets are for the dejagnu testsuites. The file site.exp
 # contains global variables that all the testsuites will use.
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
new file mode 100644
index 0000000..fc7e4a2
--- /dev/null
+++ b/gcc/gcc-ar.c
@@ -0,0 +1,96 @@
+/* Wrapper for ar/ranlib/nm to pass the LTO plugin.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by Andi Kleen.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include "config.h"
+#include "system.h"
+#include "libiberty.h"
+
+#ifndef PERSONALITY
+#error "Please set personality"
+#endif
+
+static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX;
+static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX;
+
+static const char dir_separator[] = { DIR_SEPARATOR, 0 };
+
+int 
+main(int ac, char **av)
+{
+  const char *nprefix;
+  const char *exe_name;
+  char *plugin;
+  int k, status, err;
+  const char *err_msg;
+  const char **nargv;
+  bool is_ar = !strcmp (PERSONALITY, "ar");
+
+  exe_name = PERSONALITY;
+#ifdef CROSS_DIRECTORY_STRUCTURE
+  exe_name = concat (target_machine, "-", exe_name, NULL);
+#endif
+
+  /* Find plugin */
+  /* XXX implement more magic from gcc.c? */
+  nprefix = getenv ("GCC_EXEC_PREFIX");
+  if (!nprefix)
+    nprefix = standard_libexec_prefix;
+
+  nprefix = make_relative_prefix (av[0], 
+                                 standard_bin_prefix, 
+                                 nprefix);
+  plugin = concat (nprefix,
+                  dir_separator,
+                   DEFAULT_TARGET_MACHINE, 
+                  dir_separator,
+                  DEFAULT_TARGET_VERSION,
+                  dir_separator,
+                  LTOPLUGINSONAME,
+                  NULL);
+  if (access (plugin, X_OK))
+    {
+      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
+      exit (1);
+    }
+
+  /* Create new command line with plugin */
+  nargv = XCNEWVEC (const char *, ac + 4);
+  nargv[0] = exe_name;
+  nargv[1] = "--plugin";
+  nargv[2] = plugin;
+  if (is_ar && av[1] && av[1][0] != '-')
+    av[1] = concat("-", av[1], NULL);
+  for (k = 1; k < ac; k++)
+    nargv[2 + k] = av[k];
+  nargv[2 + k] = NULL;
+
+  /* Run utility */
+  /* ??? the const is misplaced in pex_one's argv? */
+  err_msg = pex_one (PEX_LAST|PEX_SEARCH, 
+                    exe_name, 
+                    CONST_CAST2 (char * const *, const char **, nargv),
+                    concat("gcc-", exe_name, NULL), 
+                    NULL,NULL,  &status, &err);
+  if (err_msg) 
+    fprintf(stderr, "Error running %s: %s\n", exe_name, err_msg);
+
+  return err;
+}
-- 
1.7.5.4

Reply via email to