This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

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;
+}
 

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