ROSE Compiler Framework/Plugin

Overview
Starting from Version 0.9.9.83, ROSE has a new feature to support external plugins. It borrows the design and implementation of Clang Plugins.

The process to isolate the relevant source files and headers in Clang is available at:
 * https://github.com/chunhualiao/Clang-Plugin-Extracted

The interface is very similar to what Clang has, with some simplification and improvements.

With this feature, you can develop your ROSE-based tools as dynamically loadable plugins. Then you can use command line options of ROSE's default translator, rose-compiler (or another ROSE translator), to
 * load shared libraries containing the plugins,
 * specify actions to be executed,
 * as well as pass command line options to each action.

Benefits
The main benefit of using plugins is that you can use a single installed ROSE default translator to execute one or more arbitrary external plugins, in the order they appear on the command line.

This will significantly reduce the overhead of composing ROSE-based transformations, by reusing the costly parsing and unparsing, and freely chaining up the transformation plugins through command line options.

The deployment of plugins are much simpler also. No need to recompile/reinstall ROSE.

For example, we had to call two heavy-weight tools in two command lines: tool_1 input.c; tool_2 input.c;
 * 1) two separated command lines to run two ROSE-based tools, each of which has costly parsing and unparsing.

Now, we can call the default ROSE rose-compiler and chain up two plugins (act1 and act2) instead:
 * 1) sharing one identitiTranslator's parsing/unparsing support,
 * 2) load multiple shared libraries, executing two actions in the order they show up in the command line, also pass multiple options to each of the plugins

rose-compiler -rose:plugin_lib lib.so -rose:plugin_lib lib2.so -rose:plugin_action act -rose:plugin_action act2 \ -rose:plugin_arg_act1 op1 -rose:plugin_arg_act1 op2 -rose:plugin_arg_act2 op3 -rose:plugin_arg_act2 op4

Command Line Interface
rose-compiler --help, excerpt of the plugin section Plugin Mode: -rose:plugin_lib  Specify the file path to a shared library built from plugin source files This option can repeat multiple times to load multiple libraries -rose:plugin_action  Specify the plugin action to be executed This option can repeat multiple times to execute multiple actions in the order shown up in command line -rose:plugin_arg_ Specify one option to be passed to a plugin named act_name This option can repeat multiple times to provide multiple options to a plugin

Examples
 * rose-compiler -rose:plugin_lib /path/libPrintNamesPlugin.so -rose:plugin_action print-names -rose:plugin_arg_print-names pretty-printing
 * load a shared library containing a single plugin, execute the plugin named print-names, also pass an option named "pretty-printing" to the plugin.
 * rose-compiler -rose:plugin_lib lib.so -rose:plugin_lib lib2.so -rose:plugin_action act1 -rose:plugin_action act2 -rose:plugin_arg_act1 op1 -rose:plugin_arg_act1 op2 -rose:plugin_arg_act2 op3 -rose:plugin_arg_act2 op4
 * load multiple shared libraries, executing two actions in the order they show up in the command line, also pass multiple options to each of the plugins

Plugin Super Class
Two interface functions are provided for a ROSE plugin: class PluginAction { public: virtual void process(SgProject*) {}; virtual bool ParseArgs(const std::vector &arg) {return true; }; };
 * ParseArgs: optionally handle command line options passed to this plugin
 * process: process the AST

An Example Plugin
You can find the full example from
 * https://github.com/rose-compiler/rose-plugin

This plugin will just print all defining functions' names of an input source file. // An example ROSE plugin: PrintNamesPlugin.cpp

//Mandatory include headers
 * 1) include "rose.h"
 * 2) include "plugin.h"

// optional headers
 * 1) include "RoseAst.h" // using AST Iterator
 * 2) include

using namespace std; using namespace Rose;

//Step 1. Derive a plugin action from Rose::PluginAction class PrintNamesAction : public Rose::PluginAction { public: PrintNamesAction {} ~PrintNamesAction {}

// This is optional. Need only if your plugin wants to handle options // Provide command line option processing: arg will be the options passed to this plugin bool ParseArgs(const std::vector &arg) {    cout<get_definingDeclaration==fdecl)) cout<get_name< uniquePluginName1("print-names", "print function names");

Compile the plugin
A sample makefile ROSE_INSTALL=/path/to/rose/install
 * Note: copy&paste may not work since tabs will be wrongfully pasted as whitespaces. You need to restore tabs before commands in the Makefile.
 * 1) specify where the installed copy of ROSE is located.
 * 2) Essentially the --prefix path used with configure

Plugin=PrintNamesPlugin Plugin_SOURCE=$(Plugin).cpp
 * 1) Your Plugin source files

TESTCODE=test1.cpp
 * 1) Input testcode for your plugin

comma  := , CXX     = $(shell $(ROSE_INSTALL)/bin/rose-config cxx) CPPFLAGS = $(shell $(ROSE_INSTALL)/bin/rose-config cppflags) -I. CXXFLAGS = $(shell $(ROSE_INSTALL)/bin/rose-config cxxflags) LIBDIRS = $(shell $(ROSE_INSTALL)/bin/rose-config libdirs) LDFLAGS = $(shell $(ROSE_INSTALL)/bin/rose-config ldflags) -L. \          $(addprefix -Wl$(comma)-rpath -Wl$(comma), $(subst :,, $(LIBDIRS)))
 * 1) Standard C++ compiler stuff (see rose-config --help)


 * 1) Makefile Targets
 * 1) Makefile Targets

all: $(Plugin).so

$(Plugin).so: $(Plugin_SOURCE) $(CXX) -g $(Plugin_SOURCE) -fpic -shared $(CPPFLAGS) $(LDFLAGS) -o $@
 * 1) compile the plugin and generate a shared library
 * 2) -g is recommended to be used by default to enable debugging your code

check: $(Plugin).so       $(ROSE_INSTALL)/bin/rose-compiler -c -rose:plugin_lib $(Plugin).so -rose:plugin_action print-names -rose:plugin_arg_print-names op1 -I. -I$(ROSE_INSTALL)/include $(TESTCODE)
 * 1) test the plugin

clean: rm -rf $(Plugin).so *.o rose_* *.dot

Running the plugin
Command line and options:
 * rose-compiler -rose:plugin_lib PrintNamesPlugin.so -rose:plugin_action print-names -rose:plugin_arg_print-names op1 -c input_testPlugins.C

Sample input file: input_testPlugins.C int foo {} int bar; int a, b,c;

Sample output: 1 arguments op1 "foo"