This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
plugin directory
- From: Basile STARYNKEVITCH <basile at starynkevitch dot net>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 01 Dec 2009 17:09:22 +0100
- Subject: plugin directory
Hello All
In explained in http://gcc.gnu.org/ml/gcc/2009-11/msg00655.html &
http://gcc.gnu.org/ml/gcc-patches/2009-11/msg01403.html why it would be useful to query programmatically the plugin
directory, and to accept short plugin names for plugins (hence to suggest installing them in a well defined place, the
`gcc -print-file-name=plugin`/libexec directory, using shell backquotes).
Up to now, the `gcc -print-file-name=plugin`/ directory contains only the include/ for compiling plugins.
It could be used for other goals.
More specifically,
* passing -fplugin=foo is easier that -fplugin=/some/complex/path/to/foo.so
* without a convention & suggestion to install common plugin in a well defined directory, various Linux (or other)
distributions would install common plugins in different places, and that will make a user nightmare: the same plugin
available on Debian & Fedora would have to be invoked differently (because it would have been installed at different
places).
* some complex plugins, in particular MELT, need to get some resources from the file system. It would make them easier
to use if these resources are installed under the plugin/ directory. This requires an API to query that directory. In
practice, the plugin directory is specified by spec strings in gcc.c and passed to cc1 with -iplugindir option. In turn,
cc1 uses that directory to load plugins with short names and offer a way to plugin to query that.
The attached patch (a major improvement to http://gcc.gnu.org/ml/gcc-patches/2009-11/msg01403.html which did not work)
to trunk rev 154873 did bootstrap on Linux/amd64 and did try to load a plugin using its short name.
### gcc/ChangeLog ###
2009-12-01 Basile Starynkevitch <basile@starynkevitch.net>
* plugins.texi (Invoking plugins): Plugins can have short names.
(Plugin API): Mention plugin_directory_name function.
* gcc.c: (find_file_spec_function) Added new declaration.
(cc1_options): Added stuff for plugin directory.
(static_spec_func): Added find-file.
(find_file_spec_function): new function to call find_file from spec files.
* testsuite/gcc.dg/plugin/plugdir-test-1.c: Added new test.
* testsuite/gcc.dg/plugin/plugdir_plugin.c: Added new test.
* testsuite/gcc.dg/plugin/plugin.exp: Added test for plugin directory.
* gcc-plugin.h (plugin_directory_name): Added new declaration.
* common.opt (iplugindir): Added new option.
* plugin.c (add_new_plugin): Updated comment. Handle short names.
(plugin_directory_name): Added new function.
####
Ok for trunk?
Regards.
PS. The MELT plugin needs such stuff, but can very painfully live without. The MELT plugin also need more libiberty
functions (notably pex_execute & make_temp_file) and has to circumvent them painfully by duplicating their functionalities.
--
Basile STARYNKEVITCH http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mines, sont seulement les miennes} ***
Index: gcc/doc/plugins.texi
===================================================================
--- gcc/doc/plugins.texi (revision 154873)
+++ gcc/doc/plugins.texi (working copy)
@@ -22,7 +22,14 @@ The plugin arguments are parsed by GCC and passed
plugins as key-value pairs. Multiple plugins can be invoked by
specifying multiple @option{-fplugin} arguments.
+A plugin can be simply given by its short name (no dots or
+slashes). When simply passing @option{-fplugin=NAME}, the plugin is
+loaded from @file{libexec/} inside the @file{plugin} directory, so
+@option{-fplugin=NAME} is the same as @option{-fplugin=`gcc
+-print-file-name=plugin`/libexec/NAME.so}, using backquote shell
+syntax to query the @file{plugin} directory.
+
@section Plugin API
Plugins are activated by the compiler at specific events as defined in
@@ -348,6 +355,9 @@ On most systems, you can query this @code{plugin}
invoking @command{gcc -print-file-name=plugin} (replace if needed
@command{gcc} with the appropriate program path).
+Inside plugins, this @code{plugin} directory name can be queried by
+calling @code{plugin_directory_name ()}.
+
The following GNU Makefile excerpt shows how to build a simple plugin:
@smallexample
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c (revision 154873)
+++ gcc/gcc.c (working copy)
@@ -402,6 +402,7 @@ static const char *if_exists_else_spec_function (i
static const char *replace_outfile_spec_function (int, const char **);
static const char *version_compare_spec_function (int, const char **);
static const char *include_spec_function (int, const char **);
+static const char *find_file_spec_function (int, const char **);
static const char *print_asm_header_spec_function (int, const char **);
static const char *compare_debug_dump_opt_spec_function (int, const char **);
static const char *compare_debug_self_opt_spec_function (int, const char **);
@@ -902,6 +903,7 @@ static const char *cc1_options =
%{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
%{fsyntax-only:-o %j} %{-param*}\
%{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\
+ %{fplugin*:-iplugindir %:find-file(plugin) -fplugin%*}\
%{coverage:-fprofile-arcs -ftest-coverage}";
static const char *asm_options =
@@ -1722,6 +1724,7 @@ static const struct spec_function static_spec_func
{ "replace-outfile", replace_outfile_spec_function },
{ "version-compare", version_compare_spec_function },
{ "include", include_spec_function },
+ { "find-file", find_file_spec_function },
{ "print-asm-header", print_asm_header_spec_function },
{ "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
{ "compare-debug-self-opt", compare_debug_self_opt_spec_function },
@@ -8764,6 +8767,20 @@ include_spec_function (int argc, const char **argv
return NULL;
}
+/* %:find-file spec function. */
+static const char *
+find_file_spec_function (int argc, const char**argv)
+{
+ const char *file;
+
+ if (argc != 1)
+ abort ();
+
+ file = find_file (argv[0]);
+ return file;
+}
+
+
/* %:print-asm-header spec function. Print a banner to say that the
following output is from the assembler. */
Index: gcc/testsuite/gcc.dg/plugin/plugdir-test-1.c
===================================================================
--- gcc/testsuite/gcc.dg/plugin/plugdir-test-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/plugin/plugdir-test-1.c (revision 0)
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int main (int argc, char **argv)
+{
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/plugin/plugdir_plugin.c
===================================================================
--- gcc/testsuite/gcc.dg/plugin/plugdir_plugin.c (revision 0)
+++ gcc/testsuite/gcc.dg/plugin/plugdir_plugin.c (revision 0)
@@ -0,0 +1,42 @@
+/* This test plugin just displays the plugin directory. */
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+
+int plugin_is_GPL_compatible;
+
+
+static void
+start_callback (void *gcc_data, void *user_data)
+{
+ inform (UNKNOWN_LOCATION, "plugin directory is %s",
+ plugin_directory_name ());
+}
+
+/* The initialization routine exposed to and called by GCC. The spec of this
+ function is defined in gcc/gcc-plugin.h.
+
+ PLUGIN_NAME - name of the plugin (useful for error reporting)
+ ARGC - the size of the ARGV array
+ ARGV - an array of key-value argument pair
+
+ Returns 0 if initialization finishes successfully.
+
+ Note that this function needs to be named exactly "plugin_init". */
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ register_callback ("plugdir", PLUGIN_START_UNIT, &start_callback, NULL);
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/plugin/plugin.exp
===================================================================
--- gcc/testsuite/gcc.dg/plugin/plugin.exp (revision 154873)
+++ gcc/testsuite/gcc.dg/plugin/plugin.exp (working copy)
@@ -51,6 +51,7 @@ set plugin_test_list [list \
{ ggcplug.c ggcplug-test-1.c } \
{ one_time_plugin.c one_time-test-1.c } \
{ start_unit_plugin.c start_unit-test-1.c } \
+ { plugdir_plugin.c plugdir-test-1.c } \
{ finish_unit_plugin.c finish_unit-test-1.c } \
]
Index: gcc/gcc-plugin.h
===================================================================
--- gcc/gcc-plugin.h (revision 154873)
+++ gcc/gcc-plugin.h (working copy)
@@ -137,4 +137,8 @@ extern void register_callback (const char *plugin_
plugin_callback_func callback,
void *user_data);
+/* Retrieve the plugin directory name, as returned by the
+ -fprint-file-name=plugin argument to the gcc program. */
+extern const char* plugin_directory_name (void);
+
#endif /* GCC_PLUGIN_H */
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (revision 154873)
+++ gcc/common.opt (working copy)
@@ -1525,6 +1525,11 @@ gxcoff+
Common JoinedOrMissing Negative(gcoff)
Generate debug information in extended XCOFF format
+
+iplugindir
+Common Joined Separate Var(plugindir_string)
+-iplugindir <dir> Set <dir> to be the plugin directory
+
o
Common Joined Separate
-o <file> Place output into <file>
Index: gcc/plugin.c
===================================================================
--- gcc/plugin.c (revision 154873)
+++ gcc/plugin.c (working copy)
@@ -121,17 +121,36 @@ get_plugin_base_name (const char *full_name)
}
-/* Create a plugin_name_args object for the give plugin and insert it to
- the hash table. This function is called when -fplugin=/path/to/NAME.so
- option is processed. */
+/* Create a plugin_name_args object for the give plugin and insert it
+ to the hash table. This function is called when
+ -fplugin=/path/to/NAME.so or -fplugin=NAME option is processed. */
void
add_new_plugin (const char* plugin_name)
{
struct plugin_name_args *plugin;
void **slot;
- char *base_name = get_plugin_base_name (plugin_name);
+ char *base_name;
+ bool name_is_short = true;
+ const char *pc;
+ /* Replace short names by their full path when relevant. */
+ for (pc = plugin_name; *pc && name_is_short; pc++)
+ if (*pc == '.' || *pc == '/')
+ name_is_short = false;
+
+ if (name_is_short)
+ {
+ base_name = CONST_CAST (char*, plugin_name);
+ plugin_name = concat (plugin_directory_name (), "/libexec/",
+ plugin_name, ".so", NULL);
+ if (access (plugin_name, R_OK))
+ fatal_error ("file %s expanded from plugin short name %s is not accessible: %m",
+ plugin_name, base_name);
+ }
+ else
+ base_name = get_plugin_base_name (plugin_name);
+
/* If this is the first -fplugin= option we encounter, create
'plugin_name_args_tab' hash table. */
if (!plugin_name_args_tab)
@@ -686,4 +705,12 @@ plugin_default_version_check (struct plugin_gcc_ve
return false;
return true;
}
+
+/* Retrieve the plugin directory. The driver should have passed it as
+ -iplugindir <dir> */
+const char*
+plugin_directory_name (void)
+{
+ return plugindir_string;
+}