Message ID | 1319095480-15406-1-git-send-email-andi@firstfloor.org |
---|---|
State | New |
Headers | show |
On Thu, Oct 20, 2011 at 9:24 AM, Andi Kleen <andi@firstfloor.org> wrote: > From: Andi Kleen <ak@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. It's only a single wrapper which just adds a --plugin > argument before calling the respective binutils utilities. Thanks for doing this. How do they end up being used? I suppose Makefiles will need to call gcc-ar then instead of ar? In which case I wonder if ... > 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. ;) ... using something like gcc --ar would be more convenient (as you can then trivially share the find-the-files logic)? Did you consider factoring out the find-the-file logic to a shared file that you can re-use? Thanks, Richard. > I didn't add any documentation because the syntax is exactly the same as > the native ar/ranlib/nm. > > Passed bootstrap and test suite on x86_64-linux. > > gcc/: > 2011-10-19 Andi Kleen <ak@linux.intel.com> > > * Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib. > (native): Add gcc-ar. > (AR_OBJS, AR_LIBS, gcc-ar, gcc-ar.o): Add. > (install): Depend on install-gcc-ar. > (install-gcc-ar): Add. > (uninstall): Uninstall gcc-ar/nm/ranlib. > * gcc-ar.c: Add new file. > --- > gcc/Makefile.in | 28 +++++++++++++-- > gcc/gcc-ar.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 134 insertions(+), 3 deletions(-) > create mode 100644 gcc/gcc-ar.c > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 6b28ef5..7816243 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) > > ifeq ($(enable_plugin),yes) > native: gengtype$(exeext) > @@ -2049,6 +2051,17 @@ 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_OBJS = gcc-ar.o > +AR_LIBS = @COLLECT2_LIBS@ > +gcc-ar$(exeext): $(AR_OBJS) $(LIBDEPS) > + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ > + $(AR_OBJS) $(LIBS) $(AR_LIBS) > + > +gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H) > + $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \ > + -DTARGET_MACHINE=\"$(target_noncanonical)\" \ > + -c $(srcdir)/gcc-ar.c $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@ > + > COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o > COLLECT2_LIBS = @COLLECT2_LIBS@ > collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) > @@ -4576,7 +4589,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 +4914,12 @@ install-collect2: collect2 installdirs > install-lto-wrapper: lto-wrapper$(exeext) > $(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext) > > +# XXX hardlink if system supports it > +install-gcc-ar: > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ar$(exeext) > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-nm$(exeext) > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ranlib$(exeext) > + > # Cancel installation by deleting the installed files. > uninstall: lang.uninstall > -rm -rf $(DESTDIR)$(libsubdir) > @@ -4915,6 +4934,9 @@ 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* > + -rm -f $(DESTDIR)$(bindir)/gcc-ar$(exeext) > + -rm -f $(DESTDIR)$(bindir)/gcc-nm$(exeext) > + -rm -f $(DESTDIR)$(bindir)/gcc-ranlib$(exeext) > # > # 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..2c51e9a > --- /dev/null > +++ b/gcc/gcc-ar.c > @@ -0,0 +1,109 @@ > +/* Wrapper for ar/ranlib/nm to pass the LTO plugin. The same executable > + handles all. > + 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" > + > +static const char *personas[] = > + { > + "ar", > + "ranlib", > + "nm", > + NULL > + }; > + > +static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX; > + > +static const char dir_separator[] = { DIR_SEPARATOR, 0 }; > + > +int > +main(int ac, char **av) > +{ > + char *nprefix; > + const char *exe_name; > + char *plugin; > + int len, k, status, err; > + const char *err_msg; > + const char **nargv; > + bool is_ar = false; > + > + /* Determine which utility */ > + len = strlen (av[0]); > + for (k = 0; personas[k]; k++) > + { > + int w = strlen (personas[k]); > + if (len >= w && !strcmp (av[0] + len - w, personas[k])) > + break; > + } > + if (personas[k] == NULL) > + { > + fprintf (stderr, "Unknown executable name %s\n", av[0]); > + exit (1); > + } > + is_ar = !strcmp (personas[k], "ar"); > + > + exe_name = personas[k]; > +#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"); > + plugin = concat (nprefix ? nprefix : standard_libexec_prefix, > + 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 > >
> On Thu, Oct 20, 2011 at 9:24 AM, Andi Kleen <andi@firstfloor.org> wrote: > > From: Andi Kleen <ak@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. It's only a single wrapper which just adds a --plugin > > argument before calling the respective binutils utilities. > > Thanks for doing this. How do they end up being used? I suppose > Makefiles will need to call gcc-ar then instead of ar? In which case Yes, it is what other compilers provide at the moment, too. In longer run, I would like to see binutils plugin machinery to be able to resolve this by itself for all installed compilers in the system. This is bit tricky: 1) binutils already has default plugin search path. We need to arrange our plugin to install there 2) it is not realistic to expect exactly one linker plugin on the system. LLVM/Open64/ICC eventually will want to provide their own plugins on that search path 3) Either we will need to install plugin for every GCC release installed or we will need to make our plugin resonably backward compatible. This is probably not that big deal since the symbol table is rather simple part of LTO machinery. We broke compatibility in between 4.5/4.6 and 4.7, but we probably could get more serious here. > I wonder if ... > > > 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. > > ;) > > ... using something like gcc --ar would be more convenient (as you > can then trivially share the find-the-files logic)? Did you consider > factoring out the find-the-file logic to a shared file that you can re-use? Hmm, these alternatives would work with me. Bit ugly feature about gcc --ar is the fact that all options after --ar are passed to real ar and must be in the ar's syntax. That one is different from ours (and different from nm or ranlib's), so the formal description of how command line options works would get bit tricky. Honza
On Thu, Oct 20, 2011 at 10:56 AM, Jan Hubicka <hubicka@ucw.cz> wrote: >> On Thu, Oct 20, 2011 at 9:24 AM, Andi Kleen <andi@firstfloor.org> wrote: >> > From: Andi Kleen <ak@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. It's only a single wrapper which just adds a --plugin >> > argument before calling the respective binutils utilities. >> >> Thanks for doing this. How do they end up being used? I suppose >> Makefiles will need to call gcc-ar then instead of ar? In which case > > Yes, it is what other compilers provide at the moment, too. > > In longer run, I would like to see binutils plugin machinery to be able > to resolve this by itself for all installed compilers in the system. This > is bit tricky: > 1) binutils already has default plugin search path. We need to arrange our > plugin to install there > 2) it is not realistic to expect exactly one linker plugin on the system. > LLVM/Open64/ICC eventually will want to provide their own plugins on > that search path > 3) Either we will need to install plugin for every GCC release installed > or we will need to make our plugin resonably backward compatible. > This is probably not that big deal since the symbol table is rather simple > part of LTO machinery. We broke compatibility in between 4.5/4.6 and 4.7, > but we probably could get more serious here. > >> I wonder if ... >> >> > 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. >> >> ;) >> >> ... using something like gcc --ar would be more convenient (as you >> can then trivially share the find-the-files logic)? Did you consider >> factoring out the find-the-file logic to a shared file that you can re-use? > > Hmm, these alternatives would work with me. > Bit ugly feature about gcc --ar is the fact that all options after --ar are > passed to real ar and must be in the ar's syntax. That one is different from > ours (and different from nm or ranlib's), so the formal description of how > command line options works would get bit tricky. Yeah, maybe use it as `gcc --ar`, thus make it print the found ar plus the plugin argument ... At least somehow sharing the file finding code would be nice, but I don't want to block the patch in its current form if sharing it does complicate things more than it simplifies them by not duplicating code. Richard. > Honza >
On Thu, Oct 20, 2011 at 10:45:31AM +0200, Richard Guenther wrote: > > 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. It's only a single wrapper which just adds a --plugin > > argument before calling the respective binutils utilities. > > Thanks for doing this. How do they end up being used? I suppose > Makefiles will need to call gcc-ar then instead of ar? In which case > I wonder if ... Basically you use make AR=gcc-ar RANLIB=gcc-ranlib NM=gcc-nm For most makefiles just specifying ar is enough. > > > 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. > > ;) > > ... using something like gcc --ar would be more convenient (as you That's essentially what the old proposal did (gcc -print-plugin-name) plus a wrapper. You can see the old discussion here http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02471.html > can then trivially share the find-the-files logic)? Did you consider > factoring out the find-the-file logic to a shared file that you can re-use? I did this first (with collect2), but it was quite messy. Still have it as a branch. Then I settled on this simpler method which works for me at least. collect2 does not fully match what gcc.c does I think, so there's already some divergence. -Andi
On Thu, 20 Oct 2011, Andi Kleen wrote: > 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. Certainly it needs to work for the installed prefix being different from the configured prefix, which means using make_relative_prefix. > +install-gcc-ar: > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ar$(exeext) > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-nm$(exeext) > + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ranlib$(exeext) Programs should be installed under names that: * begin with $(target_noncanonical)-; * only have copies / links without that prefix in the case of a native compiler; * respect $(program_transform_name), for any program installed in bindir (see GCC_INSTALL_NAME etc.). The logic for installing the Go driver in go/Make-lang.in is probably the most modern version of the code to install a program in bindir, minus the cruft in some of the older bits of code. Also, the GNU Coding Standards specify that the program's behavior should not depend on the name by which it is run. Thus, you do need to build separate programs for each case (they might use a single source file built with separate defines).
On Thu, 20 Oct 2011, Andi Kleen wrote: > collect2 does not fully match what gcc.c does I think, so there's > already some divergence. collect2 is always called from within the gcc driver, so it can rely on environment variables set by the driver. As I understand it, these wrappers are not called from within the driver - they are called in the same environment as the driver itself is called in.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 6b28ef5..7816243 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) ifeq ($(enable_plugin),yes) native: gengtype$(exeext) @@ -2049,6 +2051,17 @@ 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_OBJS = gcc-ar.o +AR_LIBS = @COLLECT2_LIBS@ +gcc-ar$(exeext): $(AR_OBJS) $(LIBDEPS) + +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \ + $(AR_OBJS) $(LIBS) $(AR_LIBS) + +gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H) + $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \ + -DTARGET_MACHINE=\"$(target_noncanonical)\" \ + -c $(srcdir)/gcc-ar.c $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@ + COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) @@ -4576,7 +4589,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 +4914,12 @@ install-collect2: collect2 installdirs install-lto-wrapper: lto-wrapper$(exeext) $(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext) +# XXX hardlink if system supports it +install-gcc-ar: + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ar$(exeext) + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-nm$(exeext) + $(INSTALL_PROGRAM) gcc-ar$(exeext) $(DESTDIR)$(bindir)/gcc-ranlib$(exeext) + # Cancel installation by deleting the installed files. uninstall: lang.uninstall -rm -rf $(DESTDIR)$(libsubdir) @@ -4915,6 +4934,9 @@ 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* + -rm -f $(DESTDIR)$(bindir)/gcc-ar$(exeext) + -rm -f $(DESTDIR)$(bindir)/gcc-nm$(exeext) + -rm -f $(DESTDIR)$(bindir)/gcc-ranlib$(exeext) # # 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..2c51e9a --- /dev/null +++ b/gcc/gcc-ar.c @@ -0,0 +1,109 @@ +/* Wrapper for ar/ranlib/nm to pass the LTO plugin. The same executable + handles all. + 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" + +static const char *personas[] = + { + "ar", + "ranlib", + "nm", + NULL + }; + +static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX; + +static const char dir_separator[] = { DIR_SEPARATOR, 0 }; + +int +main(int ac, char **av) +{ + char *nprefix; + const char *exe_name; + char *plugin; + int len, k, status, err; + const char *err_msg; + const char **nargv; + bool is_ar = false; + + /* Determine which utility */ + len = strlen (av[0]); + for (k = 0; personas[k]; k++) + { + int w = strlen (personas[k]); + if (len >= w && !strcmp (av[0] + len - w, personas[k])) + break; + } + if (personas[k] == NULL) + { + fprintf (stderr, "Unknown executable name %s\n", av[0]); + exit (1); + } + is_ar = !strcmp (personas[k], "ar"); + + exe_name = personas[k]; +#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"); + plugin = concat (nprefix ? nprefix : standard_libexec_prefix, + 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; +}
From: Andi Kleen <ak@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. It's only a single wrapper which just adds 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. Passed bootstrap and test suite on x86_64-linux. gcc/: 2011-10-19 Andi Kleen <ak@linux.intel.com> * Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib. (native): Add gcc-ar. (AR_OBJS, AR_LIBS, gcc-ar, gcc-ar.o): Add. (install): Depend on install-gcc-ar. (install-gcc-ar): Add. (uninstall): Uninstall gcc-ar/nm/ranlib. * gcc-ar.c: Add new file. --- gcc/Makefile.in | 28 +++++++++++++-- gcc/gcc-ar.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 gcc/gcc-ar.c