diff mbox series

[16/49] Add support for in-tree plugins

Message ID 1573867416-55618-17-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series RFC: Add a static analysis framework to GCC | expand

Commit Message

David Malcolm Nov. 16, 2019, 1:23 a.m. UTC
This patch adds support for "in-tree" plugins i.e. GCC plugins that live
in the GCC source tree and are shipped as part of the GCC tarball.

The patch adds Makefile/configure machinery for handling in-tree GCC
plugins, adapted from how we support frontends.

Each in-tree plugin should provide a Make-plugin.in and config-plugin.in,
analogous to the Make-lang.in and config-lang.in provided by a frontend;
they can also supply options via a plugin.opt, analogous to a frontend's
lang.opt.

The patch adds a --enable-plugins=[LIST OF PLUGIN NAMES] configure option,
analogous to --enable-languages.  The default is for no such plugins to be
enabled.

ChangeLog:
	* configure.ac: Handle --enable-plugins.

gcc/ChangeLog:
	* Makefile.in (CONFIG_PLUGINS): New.
	(SUBDIRS, subdirs): Generalize to cover plugins as well as
	languages.
	(plugin_opt_files): New.
	(ALL_OPT_FILES): Add plugin_opt_files.
	(ALL_HOST_PLUGIN_OBJS): New.
	(ALL_HOST_OBJS): Add ALL_HOST_PLUGIN_OBJS.
	(plugin_hooks): New.
	(PLUGIN_MAKEFRAGS): New; include them.
	(Makefile): Add dependency on PLUGIN_MAKEFRAGS.
	(all.cross): Add dependency on plugin.all.cross.
	(start.encap): Add plugin.start.encap.
	(rest.encap): Add plugin.rest.encap.
	(SELFTEST_TARGETS): Add selftest_plugins.
	(info): Add dependency on lang.info.
	(dvi): Add dependency on plugin.dvi.
	(pdf): Add dependency on plugin.pdf.
	(HTMLS_BUILD): Add plugin.html.
	(man): Add plugin.man.
	(mostlyclean): Add plugin.mostlyclean.
	(clean): Add plugin.clean.
	(distclean): Update for renaming of Make-hooks to Make-lang-hooks;
	add Make-plugin-hooks.  Add plugin.distclean dependency.
	(maintainer-clean): Add plugin.maintainer-clean.
	(install-plugin): Add plugin.install-plugin.
	(install-common): Add plugin.install-common.
	(install-info): Add plugin.install-info.
	(install-pdf): Add plugin.install-pdf.
	(install-html): Add plugin.install-html.
	(install-man): Add plugin.install-man.
	(uninstall): Add plugin.uninstall.
	(TAGS): Add plugin.tags.
	* configure.ac (Make-hooks): Rename to Make-lang-hooks.
	(plugin_opt_files): New.
	(plugin_specs_files): New.
	(plugin_tree_files): New.
	(all_plugins): New.
	(all_plugin_makefrags): New.
	(all_selected_plugins): New.
	(plugin_hooks): New.
	("Plugin hooks"): New section.  Iterate through config-plugin.in,
	analogously to config-lang.in.
	(check_plugins): New.
	(selftest_plugins): New.
	(Make-plugin-hooks): Emit.
	* doc/install.texi (--enable-plugins): New option.
---
 configure.ac         |   6 ++
 gcc/Makefile.in      |  98 ++++++++++++++++++++---------
 gcc/configure.ac     | 172 +++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/doc/install.texi |   9 +++
 4 files changed, 251 insertions(+), 34 deletions(-)

Comments

Eric Gallager Dec. 6, 2019, 10:40 p.m. UTC | #1
On 11/15/19, David Malcolm <dmalcolm@redhat.com> wrote:
> This patch adds support for "in-tree" plugins i.e. GCC plugins that live
> in the GCC source tree and are shipped as part of the GCC tarball.

Nick Clifton was asking us to do something like this anyways in his
talk at Cauldron on his annobin plugin; it might be worthwhile to add
support for in-tree plugins regardless of whether the analyzer ends up
being an in-tree plugin itself or not.

>
> The patch adds Makefile/configure machinery for handling in-tree GCC
> plugins, adapted from how we support frontends.
>
> Each in-tree plugin should provide a Make-plugin.in and config-plugin.in,
> analogous to the Make-lang.in and config-lang.in provided by a frontend;
> they can also supply options via a plugin.opt, analogous to a frontend's
> lang.opt.
>
> The patch adds a --enable-plugins=[LIST OF PLUGIN NAMES] configure option,
> analogous to --enable-languages.  The default is for no such plugins to be
> enabled.
>
> ChangeLog:
> 	* configure.ac: Handle --enable-plugins.
>
> gcc/ChangeLog:
> 	* Makefile.in (CONFIG_PLUGINS): New.
> 	(SUBDIRS, subdirs): Generalize to cover plugins as well as
> 	languages.
> 	(plugin_opt_files): New.
> 	(ALL_OPT_FILES): Add plugin_opt_files.
> 	(ALL_HOST_PLUGIN_OBJS): New.
> 	(ALL_HOST_OBJS): Add ALL_HOST_PLUGIN_OBJS.
> 	(plugin_hooks): New.
> 	(PLUGIN_MAKEFRAGS): New; include them.
> 	(Makefile): Add dependency on PLUGIN_MAKEFRAGS.
> 	(all.cross): Add dependency on plugin.all.cross.
> 	(start.encap): Add plugin.start.encap.
> 	(rest.encap): Add plugin.rest.encap.
> 	(SELFTEST_TARGETS): Add selftest_plugins.
> 	(info): Add dependency on lang.info.
> 	(dvi): Add dependency on plugin.dvi.
> 	(pdf): Add dependency on plugin.pdf.
> 	(HTMLS_BUILD): Add plugin.html.
> 	(man): Add plugin.man.
> 	(mostlyclean): Add plugin.mostlyclean.
> 	(clean): Add plugin.clean.
> 	(distclean): Update for renaming of Make-hooks to Make-lang-hooks;
> 	add Make-plugin-hooks.  Add plugin.distclean dependency.
> 	(maintainer-clean): Add plugin.maintainer-clean.
> 	(install-plugin): Add plugin.install-plugin.
> 	(install-common): Add plugin.install-common.
> 	(install-info): Add plugin.install-info.
> 	(install-pdf): Add plugin.install-pdf.
> 	(install-html): Add plugin.install-html.
> 	(install-man): Add plugin.install-man.
> 	(uninstall): Add plugin.uninstall.
> 	(TAGS): Add plugin.tags.
> 	* configure.ac (Make-hooks): Rename to Make-lang-hooks.
> 	(plugin_opt_files): New.
> 	(plugin_specs_files): New.
> 	(plugin_tree_files): New.
> 	(all_plugins): New.
> 	(all_plugin_makefrags): New.
> 	(all_selected_plugins): New.
> 	(plugin_hooks): New.
> 	("Plugin hooks"): New section.  Iterate through config-plugin.in,
> 	analogously to config-lang.in.
> 	(check_plugins): New.
> 	(selftest_plugins): New.
> 	(Make-plugin-hooks): Emit.
> 	* doc/install.texi (--enable-plugins): New option.
> ---
>  configure.ac         |   6 ++
>  gcc/Makefile.in      |  98 ++++++++++++++++++++---------
>  gcc/configure.ac     | 172
> +++++++++++++++++++++++++++++++++++++++++++++++++--
>  gcc/doc/install.texi |   9 +++
>  4 files changed, 251 insertions(+), 34 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index b8ce2ad..9b8b8ab 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2188,6 +2188,12 @@ Supported languages are: ${potential_languages}])
>    ac_configure_args=`echo " $ac_configure_args" | sed -e "s/
> '--enable-languages=[[^ ]]*'//g" -e "s/$/
> '--enable-languages="$enable_languages"'/" `
>  fi
>
> +# Look if the user specified --enable-plugins="..."
> +if test -d ${srcdir}/gcc; then
> +  enable_plugins=`echo "${enable_plugins}" | sed -e 's/[[ 	,]][[ 	,]]*/,/g'
> -e 's/,$//'`
> +  ac_configure_args=`echo " $ac_configure_args" | sed -e "s/
> '--enable-plugins=[[^ ]]*'//g" -e "s/$/
> '--enable-plugins="$enable_plugins"'/" `
> +fi
> +
>  # Handle --disable-<component> generically.
>  for dir in $configdirs $build_configdirs $target_configdirs ; do
>    dirname=`echo $dir | sed -e s/target-//g -e s/build-//g -e s/-/_/g`
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 5feef6a..c0dfbde 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -132,7 +132,7 @@ CROSS=@CROSS@
>  # Variables that exist for you to override.
>  # See below for how to change them for certain systems.
>
> -# List of language subdirectories.
> +# List of language and plugin subdirectories.
>  SUBDIRS =@subdirs@ build
>
>  # Selection of languages to be made.
> @@ -142,6 +142,8 @@ ifeq (@enable_gcov@,yes)
>  LANGUAGES += gcov$(exeext) gcov-dump$(exeext) gcov-tool$(exeext)
>  endif
>
> +CONFIG_PLUGINS = @all_selected_plugins@
> +
>  # Default values for variables overridden in Makefile fragments.
>  # CFLAGS is for the user to override to, e.g., do a cross build with -O2.
>  # TCFLAGS is used for compilations with the GCC just built.
> @@ -570,6 +572,7 @@ lang_checks_parallelized=
>  lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt
> $(srcdir)/common.opt
>  lang_specs_files=@lang_specs_files@
>  lang_tree_files=@lang_tree_files@
> +plugin_opt_files=@plugin_opt_files@
>  target_cpu_default=@target_cpu_default@
>  OBJC_BOEHM_GC=@objc_boehm_gc@
>  extra_modes_file=@extra_modes_file@
> @@ -1186,7 +1189,7 @@ FLAGS_TO_PASS = \
>  # Lists of files for various purposes.
>
>  # All option source files
> -ALL_OPT_FILES=$(lang_opt_files) $(extra_opt_files)
> +ALL_OPT_FILES=$(lang_opt_files) $(plugin_opt_files) $(extra_opt_files)
>
>  # Target specific, C specific object file
>  C_TARGET_OBJS=@c_target_objs@
> @@ -1639,6 +1642,8 @@ OBJS-libcommon-target = $(common_out_object_file)
> prefix.o params.o \
>  # This lists all host objects for the front ends.
>  ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
>
> +ALL_HOST_PLUGIN_OBJS = $(foreach v,$(CONFIG_PLUGINS),$($(v)_OBJS))
> +
>  ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
>    $(OBJS-libcommon-target) main.o c-family/cppspec.o \
>    $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \
> @@ -1655,7 +1660,10 @@ endif
>
>  # This lists all host object files, whether they are included in this
>  # compilation or not.
> -ALL_HOST_OBJS = $(ALL_HOST_FRONTEND_OBJS) $(ALL_HOST_BACKEND_OBJS)
> +ALL_HOST_OBJS = \
> +  $(ALL_HOST_FRONTEND_OBJS) \
> +  $(ALL_HOST_PLUGIN_OBJS) \
> +  $(ALL_HOST_BACKEND_OBJS)
>
>  BACKEND = libbackend.a main.o libcommon-target.a libcommon.a \
>  	$(CPPLIB) $(LIBDECNUMBER)
> @@ -1752,6 +1760,32 @@ s-alltree: Makefile
>  $(foreach file,$(ALL_HOST_FRONTEND_OBJS),$(eval CFLAGS-$(file) +=
> -DIN_GCC_FRONTEND))
>
>  #
> +# Plugin makefile fragments.
> +
> +# The following targets define the interface between us and the
> +# in-tree plugins.
> +#
> +# all.cross, start.encap, rest.encap,
> +# install-common, install-info, install-man,
> +# uninstall,
> +# mostlyclean, clean, distclean, maintainer-clean,
> +#
> +# Each plugin is linked in with a series of hooks.  The name of each
> +# hooked is "plugin.${target_name}" (eg: plugin.info).  Configure computes
> +# and adds these here.  We use double-colon rules for some of the hooks;
> +# double-colon rules should be preferred for any new hooks.
> +
> +# plugin hooks, generated by configure
> +@plugin_hooks@
> +
> +# per-plugin makefile fragments
> +PLUGIN_MAKEFRAGS = @all_plugin_makefrags@
> +
> +ifneq ($(PLUGIN_MAKEFRAGS),)
> +include $(PLUGIN_MAKEFRAGS)
> +endif
> +
> +#
>
>  # -----------------------------
>  # Rebuilding this configuration
> @@ -1793,8 +1827,9 @@ $(foreach file,$(ALL_HOST_FRONTEND_OBJS),$(eval
> CFLAGS-$(file) += -DIN_GCC_FRONT
>  # This is what is done in this makefile. Note that mkconfig.sh has a
>  # move-if-change built-in
>
> -Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS)
> +Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS)
> $(PLUGIN_MAKEFRAGS)
>  	LANGUAGES="$(CONFIG_LANGUAGES)" \
> +	PLUGINS="$(CONFIG_PLUGINS)" \
>  	CONFIG_HEADERS= \
>  	CONFIG_SHELL="$(SHELL)" \
>  	CONFIG_FILES=$@ $(SHELL) config.status
> @@ -1924,12 +1959,13 @@ quickstrap: all
>  all.internal: start.encap rest.encap doc selftest
>  # This is what to compile if making a cross-compiler.
>  all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
> -	libgcc-support lang.all.cross doc selftest @GENINSRC@ srcextra
> +	libgcc-support lang.all.cross plugin.all.cross doc \
> +	selftest @GENINSRC@ srcextra
>  # This is what must be made before installing GCC and converting
> libraries.
>  start.encap: native xgcc$(exeext) cpp$(exeext) specs \
> -	libgcc-support lang.start.encap @GENINSRC@ srcextra
> +	libgcc-support lang.start.encap plugin.start.encap @GENINSRC@ srcextra
>  # These can't be made until after GCC can run.
> -rest.encap: lang.rest.encap
> +rest.encap: lang.rest.encap plugin.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) \
> @@ -1967,11 +2003,12 @@ SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs
> $(srcdir)/testsuite/selftests
>  # driver, frontend, or selftest data change.
>  .PHONY: selftest
>
> -# Potentially run all selftest-<LANG>.  The various <LANG>/Make-lang.in
> can
> -# require the selftests to be run by defining their selftest-<LANG> as
> -# s-selftest-<LANG>.  Otherwise, they should define it as empty.
> +# Potentially run all selftest-<LANG> and selftest-<PLUGIN>.
> +# The various <LANG>/Make-lang.in and <PLUGIN>/Make-plugin.in can
> +# require the selftests to be run by defining their selftest-<NAME> as
> +# s-selftest-<NAME>.  Otherwise, they should define it as empty.
>
> -SELFTEST_TARGETS = @selftest_languages@
> +SELFTEST_TARGETS = @selftest_languages@ @selftest_plugins@
>  selftest: $(SELFTEST_TARGETS)
>
>  # Recompile all the language-independent object files.
> @@ -3157,7 +3194,8 @@ doc: $(BUILD_INFO) $(GENERATED_MANPAGES)
>  INFOFILES = doc/cpp.info doc/gcc.info doc/gccint.info \
>              doc/gccinstall.info doc/cppinternals.info
>
> -info: $(INFOFILES) lang.info @GENINSRC@ srcinfo lang.srcinfo
> +info: $(INFOFILES) lang.info plugin.info @GENINSRC@ srcinfo lang.srcinfo \
> +	plugin.srcinfo
>
>  srcinfo: $(INFOFILES)
>  	-cp -p $^ $(srcdir)/doc
> @@ -3244,7 +3282,7 @@ $(build_htmldir)/gccint/index.html:
> $(TEXI_GCCINT_FILES)
>  $(build_htmldir)/cppinternals/index.html: $(TEXI_CPPINT_FILES)
>
>  dvi:: doc/gcc.dvi doc/gccint.dvi doc/gccinstall.dvi doc/cpp.dvi \
> -      doc/cppinternals.dvi lang.dvi
> +      doc/cppinternals.dvi lang.dvi plugin.dvi

So, right, this reminds me, if we're going to be adding new dvi
files... has anyone gotten `make install-dvi` from the top-level to
work recently? I had a patch for it a few years ago but never
completed it: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00380.html

>
>  doc/%.dvi: %.texi
>  	$(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
> @@ -3256,7 +3294,7 @@ doc/gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
>  PDFFILES = doc/gcc.pdf doc/gccint.pdf doc/gccinstall.pdf doc/cpp.pdf \
>             doc/cppinternals.pdf
>
> -pdf:: $(PDFFILES) lang.pdf
> +pdf:: $(PDFFILES) lang.pdf plugin.pdf
>
>  doc/%.pdf: %.texi
>  	$(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
> @@ -3275,7 +3313,7 @@ HTMLS_INSTALL=$(build_htmldir)/cpp
> $(build_htmldir)/gcc \
>  # List the html file targets.
>  HTMLS_BUILD=$(build_htmldir)/cpp/index.html $(build_htmldir)/gcc/index.html
> \
>         $(build_htmldir)/gccinstall/index.html
> $(build_htmldir)/gccint/index.html \
> -       $(build_htmldir)/cppinternals/index.html lang.html
> +       $(build_htmldir)/cppinternals/index.html lang.html plugin.html
>
>  html:: $(HTMLS_BUILD)
>
> @@ -3297,7 +3335,8 @@ MANFILES = doc/gcov.1 doc/cpp.1 doc/gcc.1 doc/gfdl.7
> doc/gpl.7 \
>
>  generated-manpages: man
>
> -man: $(MANFILES) lang.man @GENINSRC@ srcman lang.srcman
> +man: $(MANFILES) lang.man plugin.man @GENINSRC@ srcman lang.srcman \
> +	plugin.srcman
>
>  srcman: $(MANFILES)
>  	-cp -p $^ $(srcdir)/doc
> @@ -3351,7 +3390,7 @@ gpl.pod: gpl_v3.texi
>  # We remove as much from the language subdirectories as we can
>  # (less duplicated code).
>
> -mostlyclean: lang.mostlyclean
> +mostlyclean: lang.mostlyclean plugin.mostlyclean
>  	-rm -f $(MOSTLYCLEANFILES)
>  	-rm -f *$(objext) c-family/*$(objext)
>  	-rm -f *$(coverageexts)
> @@ -3388,7 +3427,7 @@ mostlyclean: lang.mostlyclean
>
>  # Delete all files made by compilation
>  # that don't exist in the distribution.
> -clean: mostlyclean lang.clean
> +clean: mostlyclean lang.clean plugin.clean
>  	-rm -f libgcc.a libgcc_eh.a libgcov.a
>  	-rm -f libgcc_s*
>  	-rm -f libunwind*
> @@ -3409,11 +3448,11 @@ clean: mostlyclean lang.clean
>
>  # Delete all files that users would normally create
>  # while building and installing GCC.
> -distclean: clean lang.distclean
> +distclean: clean lang.distclean plugin.distclean
>  	-rm -f auto-host.h auto-build.h
>  	-rm -f cstamp-h
>  	-rm -f config.status config.run config.cache config.bak
> -	-rm -f Make-lang Make-hooks Make-host Make-target
> +	-rm -f Make-lang Make-lang-hooks Make-plugin-hooks Make-host Make-target
>  	-rm -f Makefile *.oaux
>  	-rm -f gthr-default.h
>  	-rm -f TAGS */TAGS
> @@ -3435,7 +3474,7 @@ distclean: clean lang.distclean
>  maintainer-clean:
>  	@echo 'This command is intended for maintainers to use; it'
>  	@echo 'deletes files that may need special tools to rebuild.'
> -	$(MAKE) lang.maintainer-clean distclean
> +	$(MAKE) lang.maintainer-clean plugin.maintainer-clean distclean
>  	-rm -f cpp.??s cpp.*aux
>  	-rm -f gcc.??s gcc.*aux
>  	-rm -f $(gcc_docdir)/*.info $(gcc_docdir)/*.1 $(gcc_docdir)/*.7
> $(gcc_docdir)/*.dvi $(gcc_docdir)/*.pdf
> @@ -3546,7 +3585,7 @@ install-gengtype: installdirs gengtype$(exeext)
> gtype.state
>  	$(INSTALL_PROGRAM) gengtype$(exeext)
> $(DESTDIR)$(plugin_bindir)/gengtype$(exeext)
>
>  # Install the headers needed to build a plugin.
> -install-plugin: installdirs lang.install-plugin s-header-vars
> install-gengtype
> +install-plugin: installdirs lang.install-plugin plugin.install-plugin
> s-header-vars install-gengtype
>  # We keep the directory structure for files in config or c-family and .def
>  # files. All other files are flattened to a single directory.
>  	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
> @@ -3573,7 +3612,7 @@ install-plugin: installdirs lang.install-plugin
> s-header-vars install-gengtype
>  	$(INSTALL_DATA) b-header-vars
> $(DESTDIR)$(plugin_includedir)/b-header-vars
>
>  # Install the compiler executables built during cross compilation.
> -install-common: native lang.install-common installdirs
> +install-common: native lang.install-common plugin.install-common
> installdirs
>  	for file in $(COMPILERS); do \
>  	  if [ -f $$file ] ; then \
>  	    rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
> @@ -3648,7 +3687,8 @@ install-info:: doc installdirs \
>  	$(DESTDIR)$(infodir)/cppinternals.info \
>  	$(DESTDIR)$(infodir)/gccinstall.info \
>  	$(DESTDIR)$(infodir)/gccint.info \
> -	lang.install-info
> +	lang.install-info \
> +	plugin.install-info
>
>  $(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
>  	rm -f $@
> @@ -3667,7 +3707,7 @@ $(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
>
>  pdf__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
>
> -install-pdf: $(PDFFILES) lang.install-pdf
> +install-pdf: $(PDFFILES) lang.install-pdf plugin.install-pdf
>  	@$(NORMAL_INSTALL)
>  	test -z "$(pdfdir)/gcc" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
>  	@list='$(PDFFILES)'; for p in $$list; do \
> @@ -3679,7 +3719,7 @@ install-pdf: $(PDFFILES) lang.install-pdf
>
>  html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
>
> -install-html: $(HTMLS_BUILD) lang.install-html
> +install-html: $(HTMLS_BUILD) lang.install-html plugin.install-html
>  	@$(NORMAL_INSTALL)
>  	test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
>  	@list='$(HTMLS_INSTALL)'; for p in $$list; do \
> @@ -3697,7 +3737,7 @@ install-html: $(HTMLS_BUILD) lang.install-html
>  	done
>
>  # Install the man pages.
> -install-man: lang.install-man \
> +install-man: lang.install-man plugin.install-man \
>  	$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext) \
>  	$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext) \
>  	$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext) \
> @@ -3857,7 +3897,7 @@ install-gcc-ar: installdirs gcc-ar$(exeext)
> gcc-nm$(exeext) gcc-ranlib$(exeext)
>  	fi
>
>  # Cancel installation by deleting the installed files.
> -uninstall: lang.uninstall
> +uninstall: lang.uninstall plugin.uninstall
>  	-rm -rf $(DESTDIR)$(libsubdir)
>  	-rm -rf $(DESTDIR)$(libexecsubdir)
>  	-rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
> @@ -4164,7 +4204,7 @@ paranoia: paranoia.o real.o $(LIBIBERTY)
>  # These exist for maintenance purposes.
>
>  # Update the tags table.
> -TAGS: lang.tags
> +TAGS: lang.tags plugin.tags
>  	(cd $(srcdir);					\
>  	incs= ;						\
>  	list='$(SUBDIRS)'; for dir in $$list; do	\
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 62f4b26..537d3d8 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -6300,7 +6300,7 @@ all_selected_languages=
>  # The other mechanism is a set of hooks for each of the main targets
>  # like `clean', `install', etc.
>
> -language_hooks="Make-hooks"
> +language_hooks="Make-lang-hooks"
>
>  for lang in ${srcdir}/*/config-lang.in
>  do
> @@ -6409,8 +6409,8 @@ done
>  # We link each language in with a set of hooks, reached indirectly via
>  # lang.${target}.  Only do so for selected languages.
>
> -rm -f Make-hooks
> -touch Make-hooks
> +rm -f Make-lang-hooks
> +touch Make-lang-hooks
>  target_list="all.cross start.encap rest.encap tags \
>  	install-common install-man install-info install-pdf install-html dvi \
>  	pdf html uninstall info man srcextra srcman srcinfo \
> @@ -6423,7 +6423,160 @@ do
>  	do
>  		x="$x $lang.$t"
>  	done
> -	echo "lang.$t: $x" >> Make-hooks
> +	echo "lang.$t: $x" >> Make-lang-hooks
> +done
> +
> +# --------------
> +# Plugin hooks
> +# --------------
> +
> +# Make empty files to contain the specs and options for each plugin.
> +# Then add #include lines to for a compiler that has specs and/or options.
> +
> +plugin_opt_files=
> +plugin_specs_files=
> +plugin_tree_files=
> +# These (without "all_") are set in each config-plugin.in.
> +# `plugin' must be a single word so is spelled singularly.
> +all_plugins=
> +# List of plugin makefile fragments.
> +all_plugin_makefrags=
> +
> +# These are the plugins that are set in --enable-plugins,
> +# and are available in the GCC tree.
> +all_selected_plugins=
> +
> +# Add the plugin fragments.
> +# Plugins are added via two mechanisms.  Some information must be
> +# recorded in makefile variables, these are defined in config-plugin.in.
> +# We accumulate them and plug them into the main Makefile.
> +# The other mechanism is a set of hooks for each of the main targets
> +# like `clean', `install', etc.
> +
> +plugin_hooks="Make-plugin-hooks"
> +
> +for plugin in ${srcdir}/*/config-plugin.in
> +do
> +changequote(,)dnl
> +	test "$plugin" = "${srcdir}/*/config-plugin.in" && continue
> +
> +        plugin_alias=`sed -n -e
> 's,^plugin=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^plugin=\([^
> ]*\).*$,\1,p' $plugin`
> +        if test "x$plugin_alias" = x
> +        then
> +              echo "$plugin doesn't set \$plugin." 1>&2
> +              exit 1
> +        fi
> +        subdir="`echo $plugin | sed -e
> 's,^.*/\([^/]*\)/config-plugin.in$,\1,'`"
> +        subdirs="$subdirs $subdir"
> +
> +	# $gcc_subdir is where the gcc integration files are to be found
> +	# for a plugin, both for internal compiler purposes (compiler
> +	# sources implementing front-end to GCC tree converters), and for
> +	# build infrastructure purposes (Make-plugin.in, etc.)
> +	#
> +	# This will be <subdir> (relative to $srcdir) if a line like
> +	# gcc_subdir="<subdir>" or gcc_subdir=<subdir>
> +	# is found in <plugindir>/config-plugin.in, and will remain <plugindir>
> +	# otherwise.
> +	#
> +	# Except for the plugin alias (fetched above), the regular
> +	# "config-plugin.in" contents are always retrieved from $gcc_subdir,
> +	# so a <plugindir>/config-plugin.in setting gcc_subdir typically sets
> +	# only this and the plugin alias.
> +
> +        gcc_subdir=`sed -n -e
> 's,^gcc_subdir=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^gcc_subdir=\([^
> ]*\).*$,\1,p' $plugin`
> +        if [ "$gcc_subdir" = "" ]; then
> +           gcc_subdir="$subdir"
> +        fi
> +
> +        case ",$enable_plugins," in
> +        *,$plugin_alias,*)
> +            all_selected_plugins="$all_selected_plugins $plugin_alias"
> +            if test -f $srcdir/$gcc_subdir/plugin-specs.h; then
> +                plugin_specs_files="$plugin_specs_files
> $srcdir/$gcc_subdir/plugin-specs.h"
> +	    fi
> +	    ;;
> +        esac
> +changequote([,])dnl
> +
> +	plugin=
> +	boot_plugin=
> +	compilers=
> +	outputs=
> +	gtfiles=
> +	subdir_requires=
> +	. ${srcdir}/$gcc_subdir/config-plugin.in
> +	if test "x$plugin" = x
> +	then
> +		echo "${srcdir}/$gcc_subdir/config-plugin.in doesn't set \$plugin." 1>&2
> +		exit 1
> +	fi
> +
> +	ok=:
> +        case ",$enable_plugins," in
> +        	*,$plugin_alias,*) ;;
> +		*)
> +			for i in $subdir_requires; do
> +				test -f "${srcdir}/$i/config-plugin.in" && continue
> +				ok=false
> +				break
> +			done
> +		;;
> +	esac
> +	$ok || continue
> +
> +	all_plugin_makefrags="$all_plugin_makefrags
> \$(srcdir)/$gcc_subdir/Make-plugin.in"
> +	if test -f $srcdir/$gcc_subdir/plugin.opt; then
> +	    plugin_opt_files="$plugin_opt_files $srcdir/$gcc_subdir/plugin.opt"
> +	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/plugin.opt"
> +	fi
> +	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
> +	    plugin_tree_files="$plugin_tree_files
> $srcdir/$gcc_subdir/$subdir-tree.def"
> +	fi
> +	all_plugins="$all_plugins $plugin"
> +	all_compilers="$all_compilers $compilers"
> +	all_outputs="$all_outputs $outputs"
> +	all_gtfiles="$all_gtfiles [[$subdir]] $gtfiles"
> +	case ",$enable_plugins," in
> +		*,analyzer,*)
> +		    AC_DEFINE(ENABLE_ANALYZER, 1, [Define to enable static analyzer.])
> +		    enable_analyzer=yes
> +		    AC_SUBST(enable_analyzer)
> +		    ;;
> +		*) ;;
> +	esac
> +done
> +
> +check_plugins=
> +for plugin in $all_selected_plugins
> +do
> +	check_plugins="$check_plugins check-$plugin"
> +done
> +
> +selftest_plugins=
> +for plugin in $all_selected_plugins
> +do
> +	selftest_plugins="$selftest_plugins selftest-$plugin"
> +done
> +
> +# We link each plugin in with a set of hooks, reached indirectly via
> +# plugin.${target}.  Only do so for selected plugins.
> +
> +rm -f Make-plugin-hooks
> +touch Make-plugin-hooks
> +target_list="all.cross start.encap rest.encap tags \
> +	install-common install-man install-info install-pdf install-html dvi \
> +	pdf html uninstall info man srcextra srcman srcinfo \
> +	mostlyclean clean distclean maintainer-clean install-plugin"
> +
> +for t in $target_list
> +do
> +	x=
> +	for plugin in $all_selected_plugins
> +	do
> +		x="$x $plugin.$t"
> +	done
> +	echo "plugin.$t: $x" >> Make-plugin-hooks
>  done
>
>  # --------
> @@ -6481,7 +6634,10 @@ AC_SUBST(all_compilers)
>  AC_SUBST(all_gtfiles)
>  AC_SUBST(all_lang_makefrags)
>  AC_SUBST(all_languages)
> +AC_SUBST(all_plugin_makefrags)
>  AC_SUBST(all_selected_languages)
> +AC_SUBST(all_plugins)
> +AC_SUBST(all_selected_plugins)
>  AC_SUBST(build_exeext)
>  AC_SUBST(build_install_headers_dir)
>  AC_SUBST(build_xm_file_list)
> @@ -6490,6 +6646,8 @@ AC_SUBST(build_xm_defines)
>  AC_SUBST(build_file_translate)
>  AC_SUBST(check_languages)
>  AC_SUBST(selftest_languages)
> +AC_SUBST(check_plugins)
> +AC_SUBST(selftest_plugins)
>  AC_SUBST(cpp_install_dir)
>  AC_SUBST(xmake_file)
>  AC_SUBST(tmake_file)
> @@ -6515,6 +6673,9 @@ AC_SUBST(install)
>  AC_SUBST(lang_opt_files)
>  AC_SUBST(lang_specs_files)
>  AC_SUBST(lang_tree_files)
> +AC_SUBST(plugin_opt_files)
> +AC_SUBST(plugin_specs_files)
> +AC_SUBST(plugin_tree_files)
>  AC_SUBST(local_prefix)
>  AC_SUBST(md_file)
>  AC_SUBST(objc_boehm_gc)
> @@ -6540,6 +6701,7 @@ AC_SUBST(d_target_objs)
>  AC_SUBST(target_cpu_default)
>
>  AC_SUBST_FILE(language_hooks)
> +AC_SUBST_FILE(plugin_hooks)
>
>  # Echo link setup.
>  if test x${build} = x${host} ; then
> @@ -6742,7 +6904,7 @@ AC_MSG_RESULT($ld_pushpopstate_support)
>  # AC_CONFIG_SUBDIRS($subdirs)
>
>  # Create the Makefile
> -# and configure language subdirectories
> +# and configure language and plugin subdirectories
>  AC_CONFIG_FILES($all_outputs)
>
>  AC_CONFIG_COMMANDS([default],
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index dd36a1e..c27807f 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1707,6 +1707,15 @@ specified languages with the stage-1 compiler by
> using @command{make
>  stage1-bubble all-target}, or run the testsuite on the stage-1 compiler
>  for the specified languages using @command{make stage1-start check-gcc}.
>
> +@item --enable-plugins=@var{plugin1},@var{plugin2},@dots{}
> +Specify that a particular subset of in-tree plugins should be built.
> +For a list of valid values for @var{pluginN} you can issue the following
> +command in the @file{gcc} directory of your GCC source tree:@*
> +@smallexample
> +grep ^plugin= */config-plugin.in
> +@end smallexample
> +If you do not pass this flag, then no in-tree plugins will be built.
> +
>  @item --disable-libada
>  Specify that the run-time libraries and tools used by GNAT should not
>  be built.  This can be useful for debugging, or for compatibility with
> --
> 1.8.5.3
>
>
Jeff Law Dec. 7, 2019, 2:39 p.m. UTC | #2
On Fri, 2019-11-15 at 20:23 -0500, David Malcolm wrote:
> This patch adds support for "in-tree" plugins i.e. GCC plugins that
> live
> in the GCC source tree and are shipped as part of the GCC tarball.
> 
> The patch adds Makefile/configure machinery for handling in-tree GCC
> plugins, adapted from how we support frontends.
> 
> Each in-tree plugin should provide a Make-plugin.in and config-
> plugin.in,
> analogous to the Make-lang.in and config-lang.in provided by a
> frontend;
> they can also supply options via a plugin.opt, analogous to a
> frontend's
> lang.opt.
> 
> The patch adds a --enable-plugins=[LIST OF PLUGIN NAMES] configure
> option,
> analogous to --enable-languages.  The default is for no such plugins
> to be
> enabled.
> 
> ChangeLog:
> 	* configure.ac: Handle --enable-plugins.
> 
> gcc/ChangeLog:
> 	* Makefile.in (CONFIG_PLUGINS): New.
> 	(SUBDIRS, subdirs): Generalize to cover plugins as well as
> 	languages.
> 	(plugin_opt_files): New.
> 	(ALL_OPT_FILES): Add plugin_opt_files.
> 	(ALL_HOST_PLUGIN_OBJS): New.
> 	(ALL_HOST_OBJS): Add ALL_HOST_PLUGIN_OBJS.
> 	(plugin_hooks): New.
> 	(PLUGIN_MAKEFRAGS): New; include them.
> 	(Makefile): Add dependency on PLUGIN_MAKEFRAGS.
> 	(all.cross): Add dependency on plugin.all.cross.
> 	(start.encap): Add plugin.start.encap.
> 	(rest.encap): Add plugin.rest.encap.
> 	(SELFTEST_TARGETS): Add selftest_plugins.
> 	(info): Add dependency on lang.info.
> 	(dvi): Add dependency on plugin.dvi.
> 	(pdf): Add dependency on plugin.pdf.
> 	(HTMLS_BUILD): Add plugin.html.
> 	(man): Add plugin.man.
> 	(mostlyclean): Add plugin.mostlyclean.
> 	(clean): Add plugin.clean.
> 	(distclean): Update for renaming of Make-hooks to Make-lang-
> hooks;
> 	add Make-plugin-hooks.  Add plugin.distclean dependency.
> 	(maintainer-clean): Add plugin.maintainer-clean.
> 	(install-plugin): Add plugin.install-plugin.
> 	(install-common): Add plugin.install-common.
> 	(install-info): Add plugin.install-info.
> 	(install-pdf): Add plugin.install-pdf.
> 	(install-html): Add plugin.install-html.
> 	(install-man): Add plugin.install-man.
> 	(uninstall): Add plugin.uninstall.
> 	(TAGS): Add plugin.tags.
> 	* configure.ac (Make-hooks): Rename to Make-lang-hooks.
> 	(plugin_opt_files): New.
> 	(plugin_specs_files): New.
> 	(plugin_tree_files): New.
> 	(all_plugins): New.
> 	(all_plugin_makefrags): New.
> 	(all_selected_plugins): New.
> 	(plugin_hooks): New.
> 	("Plugin hooks"): New section.  Iterate through config-
> plugin.in,
> 	analogously to config-lang.in.
> 	(check_plugins): New.
> 	(selftest_plugins): New.
> 	(Make-plugin-hooks): Emit.
> 	* doc/install.texi (--enable-plugins): New option.
So do we want to push on the concept of in-tree plugins for somethign
like annobin?  If not, given the general desire to not use plugins for
teh analyzer, would we still want this?

jeff
David Malcolm Dec. 8, 2019, 2:32 p.m. UTC | #3
On Sat, 2019-12-07 at 07:39 -0700, Jeff Law wrote:
> On Fri, 2019-11-15 at 20:23 -0500, David Malcolm wrote:
> > This patch adds support for "in-tree" plugins i.e. GCC plugins that
> > live
> > in the GCC source tree and are shipped as part of the GCC tarball.
> > 
> > The patch adds Makefile/configure machinery for handling in-tree
> > GCC
> > plugins, adapted from how we support frontends.
> > 
> > Each in-tree plugin should provide a Make-plugin.in and config-
> > plugin.in,
> > analogous to the Make-lang.in and config-lang.in provided by a
> > frontend;
> > they can also supply options via a plugin.opt, analogous to a
> > frontend's
> > lang.opt.
> > 
> > The patch adds a --enable-plugins=[LIST OF PLUGIN NAMES] configure
> > option,
> > analogous to --enable-languages.  The default is for no such
> > plugins
> > to be
> > enabled.
> > 
> > ChangeLog:
> > 	* configure.ac: Handle --enable-plugins.
> > 
> > gcc/ChangeLog:
> > 	* Makefile.in (CONFIG_PLUGINS): New.
> > 	(SUBDIRS, subdirs): Generalize to cover plugins as well as
> > 	languages.
> > 	(plugin_opt_files): New.
> > 	(ALL_OPT_FILES): Add plugin_opt_files.
> > 	(ALL_HOST_PLUGIN_OBJS): New.
> > 	(ALL_HOST_OBJS): Add ALL_HOST_PLUGIN_OBJS.
> > 	(plugin_hooks): New.
> > 	(PLUGIN_MAKEFRAGS): New; include them.
> > 	(Makefile): Add dependency on PLUGIN_MAKEFRAGS.
> > 	(all.cross): Add dependency on plugin.all.cross.
> > 	(start.encap): Add plugin.start.encap.
> > 	(rest.encap): Add plugin.rest.encap.
> > 	(SELFTEST_TARGETS): Add selftest_plugins.
> > 	(info): Add dependency on lang.info.
> > 	(dvi): Add dependency on plugin.dvi.
> > 	(pdf): Add dependency on plugin.pdf.
> > 	(HTMLS_BUILD): Add plugin.html.
> > 	(man): Add plugin.man.
> > 	(mostlyclean): Add plugin.mostlyclean.
> > 	(clean): Add plugin.clean.
> > 	(distclean): Update for renaming of Make-hooks to Make-lang-
> > hooks;
> > 	add Make-plugin-hooks.  Add plugin.distclean dependency.
> > 	(maintainer-clean): Add plugin.maintainer-clean.
> > 	(install-plugin): Add plugin.install-plugin.
> > 	(install-common): Add plugin.install-common.
> > 	(install-info): Add plugin.install-info.
> > 	(install-pdf): Add plugin.install-pdf.
> > 	(install-html): Add plugin.install-html.
> > 	(install-man): Add plugin.install-man.
> > 	(uninstall): Add plugin.uninstall.
> > 	(TAGS): Add plugin.tags.
> > 	* configure.ac (Make-hooks): Rename to Make-lang-hooks.
> > 	(plugin_opt_files): New.
> > 	(plugin_specs_files): New.
> > 	(plugin_tree_files): New.
> > 	(all_plugins): New.
> > 	(all_plugin_makefrags): New.
> > 	(all_selected_plugins): New.
> > 	(plugin_hooks): New.
> > 	("Plugin hooks"): New section.  Iterate through config-
> > plugin.in,
> > 	analogously to config-lang.in.
> > 	(check_plugins): New.
> > 	(selftest_plugins): New.
> > 	(Make-plugin-hooks): Emit.
> > 	* doc/install.texi (--enable-plugins): New option.
> So do we want to push on the concept of in-tree plugins for somethign
> like annobin?  If not, given the general desire to not use plugins
> for
> teh analyzer, would we still want this?
> 
> jeff

As this becomes orthogonal to the analyzer work, I've dropped this
patch from v3 of the kit, but someone else is welcome to pick this up
and run with it.

Dave
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index b8ce2ad..9b8b8ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2188,6 +2188,12 @@  Supported languages are: ${potential_languages}])
   ac_configure_args=`echo " $ac_configure_args" | sed -e "s/ '--enable-languages=[[^ ]]*'//g" -e "s/$/ '--enable-languages="$enable_languages"'/" `
 fi
 
+# Look if the user specified --enable-plugins="..."
+if test -d ${srcdir}/gcc; then
+  enable_plugins=`echo "${enable_plugins}" | sed -e 's/[[ 	,]][[ 	,]]*/,/g' -e 's/,$//'`
+  ac_configure_args=`echo " $ac_configure_args" | sed -e "s/ '--enable-plugins=[[^ ]]*'//g" -e "s/$/ '--enable-plugins="$enable_plugins"'/" `
+fi
+
 # Handle --disable-<component> generically.
 for dir in $configdirs $build_configdirs $target_configdirs ; do
   dirname=`echo $dir | sed -e s/target-//g -e s/build-//g -e s/-/_/g`
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5feef6a..c0dfbde 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -132,7 +132,7 @@  CROSS=@CROSS@
 # Variables that exist for you to override.
 # See below for how to change them for certain systems.
 
-# List of language subdirectories.
+# List of language and plugin subdirectories.
 SUBDIRS =@subdirs@ build
 
 # Selection of languages to be made.
@@ -142,6 +142,8 @@  ifeq (@enable_gcov@,yes)
 LANGUAGES += gcov$(exeext) gcov-dump$(exeext) gcov-tool$(exeext)
 endif
 
+CONFIG_PLUGINS = @all_selected_plugins@
+
 # Default values for variables overridden in Makefile fragments.
 # CFLAGS is for the user to override to, e.g., do a cross build with -O2.
 # TCFLAGS is used for compilations with the GCC just built.
@@ -570,6 +572,7 @@  lang_checks_parallelized=
 lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt $(srcdir)/common.opt
 lang_specs_files=@lang_specs_files@
 lang_tree_files=@lang_tree_files@
+plugin_opt_files=@plugin_opt_files@
 target_cpu_default=@target_cpu_default@
 OBJC_BOEHM_GC=@objc_boehm_gc@
 extra_modes_file=@extra_modes_file@
@@ -1186,7 +1189,7 @@  FLAGS_TO_PASS = \
 # Lists of files for various purposes.
 
 # All option source files
-ALL_OPT_FILES=$(lang_opt_files) $(extra_opt_files)
+ALL_OPT_FILES=$(lang_opt_files) $(plugin_opt_files) $(extra_opt_files)
 
 # Target specific, C specific object file
 C_TARGET_OBJS=@c_target_objs@
@@ -1639,6 +1642,8 @@  OBJS-libcommon-target = $(common_out_object_file) prefix.o params.o \
 # This lists all host objects for the front ends.
 ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
 
+ALL_HOST_PLUGIN_OBJS = $(foreach v,$(CONFIG_PLUGINS),$($(v)_OBJS))
+
 ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
   $(OBJS-libcommon-target) main.o c-family/cppspec.o \
   $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \
@@ -1655,7 +1660,10 @@  endif
 
 # This lists all host object files, whether they are included in this
 # compilation or not.
-ALL_HOST_OBJS = $(ALL_HOST_FRONTEND_OBJS) $(ALL_HOST_BACKEND_OBJS)
+ALL_HOST_OBJS = \
+  $(ALL_HOST_FRONTEND_OBJS) \
+  $(ALL_HOST_PLUGIN_OBJS) \
+  $(ALL_HOST_BACKEND_OBJS)
 
 BACKEND = libbackend.a main.o libcommon-target.a libcommon.a \
 	$(CPPLIB) $(LIBDECNUMBER)
@@ -1752,6 +1760,32 @@  s-alltree: Makefile
 $(foreach file,$(ALL_HOST_FRONTEND_OBJS),$(eval CFLAGS-$(file) += -DIN_GCC_FRONTEND))
 
 #
+# Plugin makefile fragments.
+
+# The following targets define the interface between us and the
+# in-tree plugins.
+#
+# all.cross, start.encap, rest.encap,
+# install-common, install-info, install-man,
+# uninstall,
+# mostlyclean, clean, distclean, maintainer-clean,
+#
+# Each plugin is linked in with a series of hooks.  The name of each
+# hooked is "plugin.${target_name}" (eg: plugin.info).  Configure computes
+# and adds these here.  We use double-colon rules for some of the hooks;
+# double-colon rules should be preferred for any new hooks.
+
+# plugin hooks, generated by configure
+@plugin_hooks@
+
+# per-plugin makefile fragments
+PLUGIN_MAKEFRAGS = @all_plugin_makefrags@
+
+ifneq ($(PLUGIN_MAKEFRAGS),)
+include $(PLUGIN_MAKEFRAGS)
+endif
+
+#
 
 # -----------------------------
 # Rebuilding this configuration
@@ -1793,8 +1827,9 @@  $(foreach file,$(ALL_HOST_FRONTEND_OBJS),$(eval CFLAGS-$(file) += -DIN_GCC_FRONT
 # This is what is done in this makefile. Note that mkconfig.sh has a
 # move-if-change built-in
 
-Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS)
+Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS) $(PLUGIN_MAKEFRAGS)
 	LANGUAGES="$(CONFIG_LANGUAGES)" \
+	PLUGINS="$(CONFIG_PLUGINS)" \
 	CONFIG_HEADERS= \
 	CONFIG_SHELL="$(SHELL)" \
 	CONFIG_FILES=$@ $(SHELL) config.status
@@ -1924,12 +1959,13 @@  quickstrap: all
 all.internal: start.encap rest.encap doc selftest
 # This is what to compile if making a cross-compiler.
 all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
-	libgcc-support lang.all.cross doc selftest @GENINSRC@ srcextra
+	libgcc-support lang.all.cross plugin.all.cross doc \
+	selftest @GENINSRC@ srcextra
 # This is what must be made before installing GCC and converting libraries.
 start.encap: native xgcc$(exeext) cpp$(exeext) specs \
-	libgcc-support lang.start.encap @GENINSRC@ srcextra
+	libgcc-support lang.start.encap plugin.start.encap @GENINSRC@ srcextra
 # These can't be made until after GCC can run.
-rest.encap: lang.rest.encap
+rest.encap: lang.rest.encap plugin.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) \
@@ -1967,11 +2003,12 @@  SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
 # driver, frontend, or selftest data change.
 .PHONY: selftest
 
-# Potentially run all selftest-<LANG>.  The various <LANG>/Make-lang.in can
-# require the selftests to be run by defining their selftest-<LANG> as
-# s-selftest-<LANG>.  Otherwise, they should define it as empty.
+# Potentially run all selftest-<LANG> and selftest-<PLUGIN>.
+# The various <LANG>/Make-lang.in and <PLUGIN>/Make-plugin.in can
+# require the selftests to be run by defining their selftest-<NAME> as
+# s-selftest-<NAME>.  Otherwise, they should define it as empty.
 
-SELFTEST_TARGETS = @selftest_languages@
+SELFTEST_TARGETS = @selftest_languages@ @selftest_plugins@
 selftest: $(SELFTEST_TARGETS)
 
 # Recompile all the language-independent object files.
@@ -3157,7 +3194,8 @@  doc: $(BUILD_INFO) $(GENERATED_MANPAGES)
 INFOFILES = doc/cpp.info doc/gcc.info doc/gccint.info \
             doc/gccinstall.info doc/cppinternals.info
 
-info: $(INFOFILES) lang.info @GENINSRC@ srcinfo lang.srcinfo
+info: $(INFOFILES) lang.info plugin.info @GENINSRC@ srcinfo lang.srcinfo \
+	plugin.srcinfo
 
 srcinfo: $(INFOFILES)
 	-cp -p $^ $(srcdir)/doc
@@ -3244,7 +3282,7 @@  $(build_htmldir)/gccint/index.html: $(TEXI_GCCINT_FILES)
 $(build_htmldir)/cppinternals/index.html: $(TEXI_CPPINT_FILES)
 
 dvi:: doc/gcc.dvi doc/gccint.dvi doc/gccinstall.dvi doc/cpp.dvi \
-      doc/cppinternals.dvi lang.dvi
+      doc/cppinternals.dvi lang.dvi plugin.dvi
 
 doc/%.dvi: %.texi
 	$(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
@@ -3256,7 +3294,7 @@  doc/gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
 PDFFILES = doc/gcc.pdf doc/gccint.pdf doc/gccinstall.pdf doc/cpp.pdf \
            doc/cppinternals.pdf
 
-pdf:: $(PDFFILES) lang.pdf
+pdf:: $(PDFFILES) lang.pdf plugin.pdf
 
 doc/%.pdf: %.texi
 	$(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
@@ -3275,7 +3313,7 @@  HTMLS_INSTALL=$(build_htmldir)/cpp $(build_htmldir)/gcc \
 # List the html file targets.
 HTMLS_BUILD=$(build_htmldir)/cpp/index.html $(build_htmldir)/gcc/index.html \
        $(build_htmldir)/gccinstall/index.html $(build_htmldir)/gccint/index.html \
-       $(build_htmldir)/cppinternals/index.html lang.html
+       $(build_htmldir)/cppinternals/index.html lang.html plugin.html
 
 html:: $(HTMLS_BUILD)
 
@@ -3297,7 +3335,8 @@  MANFILES = doc/gcov.1 doc/cpp.1 doc/gcc.1 doc/gfdl.7 doc/gpl.7 \
 
 generated-manpages: man
 
-man: $(MANFILES) lang.man @GENINSRC@ srcman lang.srcman
+man: $(MANFILES) lang.man plugin.man @GENINSRC@ srcman lang.srcman \
+	plugin.srcman
 
 srcman: $(MANFILES)
 	-cp -p $^ $(srcdir)/doc
@@ -3351,7 +3390,7 @@  gpl.pod: gpl_v3.texi
 # We remove as much from the language subdirectories as we can
 # (less duplicated code).
 
-mostlyclean: lang.mostlyclean
+mostlyclean: lang.mostlyclean plugin.mostlyclean
 	-rm -f $(MOSTLYCLEANFILES)
 	-rm -f *$(objext) c-family/*$(objext)
 	-rm -f *$(coverageexts)
@@ -3388,7 +3427,7 @@  mostlyclean: lang.mostlyclean
 
 # Delete all files made by compilation
 # that don't exist in the distribution.
-clean: mostlyclean lang.clean
+clean: mostlyclean lang.clean plugin.clean
 	-rm -f libgcc.a libgcc_eh.a libgcov.a
 	-rm -f libgcc_s*
 	-rm -f libunwind*
@@ -3409,11 +3448,11 @@  clean: mostlyclean lang.clean
 
 # Delete all files that users would normally create
 # while building and installing GCC.
-distclean: clean lang.distclean
+distclean: clean lang.distclean plugin.distclean
 	-rm -f auto-host.h auto-build.h
 	-rm -f cstamp-h
 	-rm -f config.status config.run config.cache config.bak
-	-rm -f Make-lang Make-hooks Make-host Make-target
+	-rm -f Make-lang Make-lang-hooks Make-plugin-hooks Make-host Make-target
 	-rm -f Makefile *.oaux
 	-rm -f gthr-default.h
 	-rm -f TAGS */TAGS
@@ -3435,7 +3474,7 @@  distclean: clean lang.distclean
 maintainer-clean:
 	@echo 'This command is intended for maintainers to use; it'
 	@echo 'deletes files that may need special tools to rebuild.'
-	$(MAKE) lang.maintainer-clean distclean
+	$(MAKE) lang.maintainer-clean plugin.maintainer-clean distclean
 	-rm -f cpp.??s cpp.*aux
 	-rm -f gcc.??s gcc.*aux
 	-rm -f $(gcc_docdir)/*.info $(gcc_docdir)/*.1 $(gcc_docdir)/*.7 $(gcc_docdir)/*.dvi $(gcc_docdir)/*.pdf
@@ -3546,7 +3585,7 @@  install-gengtype: installdirs gengtype$(exeext) gtype.state
 	$(INSTALL_PROGRAM) gengtype$(exeext) $(DESTDIR)$(plugin_bindir)/gengtype$(exeext)
 
 # Install the headers needed to build a plugin.
-install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
+install-plugin: installdirs lang.install-plugin plugin.install-plugin s-header-vars install-gengtype
 # We keep the directory structure for files in config or c-family and .def
 # files. All other files are flattened to a single directory.
 	$(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
@@ -3573,7 +3612,7 @@  install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
 	$(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
 
 # Install the compiler executables built during cross compilation.
-install-common: native lang.install-common installdirs
+install-common: native lang.install-common plugin.install-common installdirs
 	for file in $(COMPILERS); do \
 	  if [ -f $$file ] ; then \
 	    rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
@@ -3648,7 +3687,8 @@  install-info:: doc installdirs \
 	$(DESTDIR)$(infodir)/cppinternals.info \
 	$(DESTDIR)$(infodir)/gccinstall.info \
 	$(DESTDIR)$(infodir)/gccint.info \
-	lang.install-info
+	lang.install-info \
+	plugin.install-info
 
 $(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
 	rm -f $@
@@ -3667,7 +3707,7 @@  $(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
 
 pdf__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
 
-install-pdf: $(PDFFILES) lang.install-pdf
+install-pdf: $(PDFFILES) lang.install-pdf plugin.install-pdf
 	@$(NORMAL_INSTALL)
 	test -z "$(pdfdir)/gcc" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
 	@list='$(PDFFILES)'; for p in $$list; do \
@@ -3679,7 +3719,7 @@  install-pdf: $(PDFFILES) lang.install-pdf
 
 html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
 
-install-html: $(HTMLS_BUILD) lang.install-html
+install-html: $(HTMLS_BUILD) lang.install-html plugin.install-html
 	@$(NORMAL_INSTALL)
 	test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
 	@list='$(HTMLS_INSTALL)'; for p in $$list; do \
@@ -3697,7 +3737,7 @@  install-html: $(HTMLS_BUILD) lang.install-html
 	done
 
 # Install the man pages.
-install-man: lang.install-man \
+install-man: lang.install-man plugin.install-man \
 	$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext) \
 	$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext) \
 	$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext) \
@@ -3857,7 +3897,7 @@  install-gcc-ar: installdirs gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
 	fi
 
 # Cancel installation by deleting the installed files.
-uninstall: lang.uninstall
+uninstall: lang.uninstall plugin.uninstall
 	-rm -rf $(DESTDIR)$(libsubdir)
 	-rm -rf $(DESTDIR)$(libexecsubdir)
 	-rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
@@ -4164,7 +4204,7 @@  paranoia: paranoia.o real.o $(LIBIBERTY)
 # These exist for maintenance purposes.
 
 # Update the tags table.
-TAGS: lang.tags
+TAGS: lang.tags plugin.tags
 	(cd $(srcdir);					\
 	incs= ;						\
 	list='$(SUBDIRS)'; for dir in $$list; do	\
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 62f4b26..537d3d8 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -6300,7 +6300,7 @@  all_selected_languages=
 # The other mechanism is a set of hooks for each of the main targets
 # like `clean', `install', etc.
 
-language_hooks="Make-hooks"
+language_hooks="Make-lang-hooks"
 
 for lang in ${srcdir}/*/config-lang.in
 do
@@ -6409,8 +6409,8 @@  done
 # We link each language in with a set of hooks, reached indirectly via
 # lang.${target}.  Only do so for selected languages.
 
-rm -f Make-hooks
-touch Make-hooks
+rm -f Make-lang-hooks
+touch Make-lang-hooks
 target_list="all.cross start.encap rest.encap tags \
 	install-common install-man install-info install-pdf install-html dvi \
 	pdf html uninstall info man srcextra srcman srcinfo \
@@ -6423,7 +6423,160 @@  do
 	do
 		x="$x $lang.$t"
 	done
-	echo "lang.$t: $x" >> Make-hooks
+	echo "lang.$t: $x" >> Make-lang-hooks
+done
+
+# --------------
+# Plugin hooks
+# --------------
+
+# Make empty files to contain the specs and options for each plugin.
+# Then add #include lines to for a compiler that has specs and/or options.
+
+plugin_opt_files=
+plugin_specs_files=
+plugin_tree_files=
+# These (without "all_") are set in each config-plugin.in.
+# `plugin' must be a single word so is spelled singularly.
+all_plugins=
+# List of plugin makefile fragments.
+all_plugin_makefrags=
+
+# These are the plugins that are set in --enable-plugins,
+# and are available in the GCC tree.
+all_selected_plugins=
+
+# Add the plugin fragments.
+# Plugins are added via two mechanisms.  Some information must be
+# recorded in makefile variables, these are defined in config-plugin.in.
+# We accumulate them and plug them into the main Makefile.
+# The other mechanism is a set of hooks for each of the main targets
+# like `clean', `install', etc.
+
+plugin_hooks="Make-plugin-hooks"
+
+for plugin in ${srcdir}/*/config-plugin.in
+do
+changequote(,)dnl
+	test "$plugin" = "${srcdir}/*/config-plugin.in" && continue
+
+        plugin_alias=`sed -n -e 's,^plugin=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^plugin=\([^   ]*\).*$,\1,p' $plugin`
+        if test "x$plugin_alias" = x
+        then
+              echo "$plugin doesn't set \$plugin." 1>&2
+              exit 1
+        fi
+        subdir="`echo $plugin | sed -e 's,^.*/\([^/]*\)/config-plugin.in$,\1,'`"
+        subdirs="$subdirs $subdir"
+
+	# $gcc_subdir is where the gcc integration files are to be found
+	# for a plugin, both for internal compiler purposes (compiler
+	# sources implementing front-end to GCC tree converters), and for
+	# build infrastructure purposes (Make-plugin.in, etc.)
+	#
+	# This will be <subdir> (relative to $srcdir) if a line like 
+	# gcc_subdir="<subdir>" or gcc_subdir=<subdir>
+	# is found in <plugindir>/config-plugin.in, and will remain <plugindir>
+	# otherwise.
+	#
+	# Except for the plugin alias (fetched above), the regular
+	# "config-plugin.in" contents are always retrieved from $gcc_subdir,
+	# so a <plugindir>/config-plugin.in setting gcc_subdir typically sets
+	# only this and the plugin alias.
+
+        gcc_subdir=`sed -n -e 's,^gcc_subdir=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^gcc_subdir=\([^   ]*\).*$,\1,p' $plugin`
+        if [ "$gcc_subdir" = "" ]; then
+           gcc_subdir="$subdir"
+        fi
+
+        case ",$enable_plugins," in
+        *,$plugin_alias,*)
+            all_selected_plugins="$all_selected_plugins $plugin_alias"
+            if test -f $srcdir/$gcc_subdir/plugin-specs.h; then
+                plugin_specs_files="$plugin_specs_files $srcdir/$gcc_subdir/plugin-specs.h"
+	    fi
+	    ;;
+        esac
+changequote([,])dnl
+
+	plugin=
+	boot_plugin=
+	compilers=
+	outputs=
+	gtfiles=
+	subdir_requires=
+	. ${srcdir}/$gcc_subdir/config-plugin.in
+	if test "x$plugin" = x
+	then
+		echo "${srcdir}/$gcc_subdir/config-plugin.in doesn't set \$plugin." 1>&2
+		exit 1
+	fi
+
+	ok=:
+        case ",$enable_plugins," in
+        	*,$plugin_alias,*) ;;
+		*)
+			for i in $subdir_requires; do
+				test -f "${srcdir}/$i/config-plugin.in" && continue
+				ok=false
+				break
+			done
+		;;
+	esac
+	$ok || continue
+
+	all_plugin_makefrags="$all_plugin_makefrags \$(srcdir)/$gcc_subdir/Make-plugin.in"
+	if test -f $srcdir/$gcc_subdir/plugin.opt; then
+	    plugin_opt_files="$plugin_opt_files $srcdir/$gcc_subdir/plugin.opt"
+	    all_opt_files="$all_opt_files $srcdir/$gcc_subdir/plugin.opt"
+	fi
+	if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
+	    plugin_tree_files="$plugin_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
+	fi
+	all_plugins="$all_plugins $plugin"
+	all_compilers="$all_compilers $compilers"
+	all_outputs="$all_outputs $outputs"
+	all_gtfiles="$all_gtfiles [[$subdir]] $gtfiles"
+	case ",$enable_plugins," in
+		*,analyzer,*)
+		    AC_DEFINE(ENABLE_ANALYZER, 1, [Define to enable static analyzer.])
+		    enable_analyzer=yes
+		    AC_SUBST(enable_analyzer)
+		    ;;
+		*) ;;
+	esac
+done
+
+check_plugins=
+for plugin in $all_selected_plugins
+do
+	check_plugins="$check_plugins check-$plugin"
+done
+
+selftest_plugins=
+for plugin in $all_selected_plugins
+do
+	selftest_plugins="$selftest_plugins selftest-$plugin"
+done
+
+# We link each plugin in with a set of hooks, reached indirectly via
+# plugin.${target}.  Only do so for selected plugins.
+
+rm -f Make-plugin-hooks
+touch Make-plugin-hooks
+target_list="all.cross start.encap rest.encap tags \
+	install-common install-man install-info install-pdf install-html dvi \
+	pdf html uninstall info man srcextra srcman srcinfo \
+	mostlyclean clean distclean maintainer-clean install-plugin"
+
+for t in $target_list
+do
+	x=
+	for plugin in $all_selected_plugins
+	do
+		x="$x $plugin.$t"
+	done
+	echo "plugin.$t: $x" >> Make-plugin-hooks
 done
 
 # --------
@@ -6481,7 +6634,10 @@  AC_SUBST(all_compilers)
 AC_SUBST(all_gtfiles)
 AC_SUBST(all_lang_makefrags)
 AC_SUBST(all_languages)
+AC_SUBST(all_plugin_makefrags)
 AC_SUBST(all_selected_languages)
+AC_SUBST(all_plugins)
+AC_SUBST(all_selected_plugins)
 AC_SUBST(build_exeext)
 AC_SUBST(build_install_headers_dir)
 AC_SUBST(build_xm_file_list)
@@ -6490,6 +6646,8 @@  AC_SUBST(build_xm_defines)
 AC_SUBST(build_file_translate)
 AC_SUBST(check_languages)
 AC_SUBST(selftest_languages)
+AC_SUBST(check_plugins)
+AC_SUBST(selftest_plugins)
 AC_SUBST(cpp_install_dir)
 AC_SUBST(xmake_file)
 AC_SUBST(tmake_file)
@@ -6515,6 +6673,9 @@  AC_SUBST(install)
 AC_SUBST(lang_opt_files)
 AC_SUBST(lang_specs_files)
 AC_SUBST(lang_tree_files)
+AC_SUBST(plugin_opt_files)
+AC_SUBST(plugin_specs_files)
+AC_SUBST(plugin_tree_files)
 AC_SUBST(local_prefix)
 AC_SUBST(md_file)
 AC_SUBST(objc_boehm_gc)
@@ -6540,6 +6701,7 @@  AC_SUBST(d_target_objs)
 AC_SUBST(target_cpu_default)
 
 AC_SUBST_FILE(language_hooks)
+AC_SUBST_FILE(plugin_hooks)
 
 # Echo link setup.
 if test x${build} = x${host} ; then
@@ -6742,7 +6904,7 @@  AC_MSG_RESULT($ld_pushpopstate_support)
 # AC_CONFIG_SUBDIRS($subdirs)
 
 # Create the Makefile
-# and configure language subdirectories
+# and configure language and plugin subdirectories
 AC_CONFIG_FILES($all_outputs)
 
 AC_CONFIG_COMMANDS([default],
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index dd36a1e..c27807f 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1707,6 +1707,15 @@  specified languages with the stage-1 compiler by using @command{make
 stage1-bubble all-target}, or run the testsuite on the stage-1 compiler
 for the specified languages using @command{make stage1-start check-gcc}.
 
+@item --enable-plugins=@var{plugin1},@var{plugin2},@dots{}
+Specify that a particular subset of in-tree plugins should be built.
+For a list of valid values for @var{pluginN} you can issue the following
+command in the @file{gcc} directory of your GCC source tree:@*
+@smallexample
+grep ^plugin= */config-plugin.in
+@end smallexample
+If you do not pass this flag, then no in-tree plugins will be built.
+
 @item --disable-libada
 Specify that the run-time libraries and tools used by GNAT should not
 be built.  This can be useful for debugging, or for compatibility with