Home | History | Annotate | Download | only in docs
      1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
      2           "http://www.w3.org/TR/html4/strict.dtd">
      3 <html>
      4 <head>
      5 <title>Clang Plugins</title>
      6 <link type="text/css" rel="stylesheet" href="../menu.css">
      7 <link type="text/css" rel="stylesheet" href="../content.css">
      8 </head>
      9 <body>
     10 
     11 <!--#include virtual="../menu.html.incl"-->
     12 
     13 <div id="content">
     14 
     15 <h1>Clang Plugins</h1>
     16 <p>Clang Plugins make it possible to run extra user defined actions during
     17 a compilation. This document will provide a basic walkthrough of how to write
     18 and run a Clang Plugin.</p>
     19 
     20 <!-- ======================================================================= -->
     21 <h2 id="intro">Introduction</h2>
     22 <!-- ======================================================================= -->
     23 
     24 <p>Clang Plugins run FrontendActions over code. See the
     25 <a href="RAVFrontendAction.html">FrontendAction tutorial</a> on how to write a
     26 FrontendAction using the RecursiveASTVisitor. In this tutorial, we'll
     27 demonstrate how to write a simple clang plugin.
     28 </p>
     29 
     30 <!-- ======================================================================= -->
     31 <h2 id="pluginactions">Writing a PluginASTAction</h2>
     32 <!-- ======================================================================= -->
     33 
     34 <p>The main difference from writing normal FrontendActions is that you can
     35 handle plugin command line options. The
     36 PluginASTAction base class declares a ParseArgs method which you have to
     37 implement in your plugin.
     38 </p>
     39 <pre>
     40   bool ParseArgs(const CompilerInstance &amp;CI,
     41                  const std::vector&lt;std::string>&amp; args) {
     42     for (unsigned i = 0, e = args.size(); i != e; ++i) {
     43       if (args[i] == "-some-arg") {
     44         // Handle the command line argument.
     45       }
     46     }
     47     return true;
     48   }
     49 </pre>
     50 
     51 <!-- ======================================================================= -->
     52 <h2 id="registerplugin">Registering a plugin</h2>
     53 <!-- ======================================================================= -->
     54 
     55 <p>A plugin is loaded from a dynamic library at runtime by the compiler. To register
     56 a plugin in a library, use FrontendPluginRegistry::Add:</p>
     57 <pre>
     58   static FrontendPluginRegistry::Add&lt;MyPlugin> X("my-plugin-name", "my plugin description");
     59 </pre>
     60 
     61 <!-- ======================================================================= -->
     62 <h2 id="example">Putting it all together</h2>
     63 <!-- ======================================================================= -->
     64 
     65 <p>Let's look at an example plugin that prints top-level function names.
     66 This example is also checked into the clang repository; please also take a look
     67 at the latest <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/PrintFunctionNames.cpp?view=markup">checked in version of PrintFunctionNames.cpp</a>.</p>
     68 <pre>
     69 #include "clang/Frontend/FrontendPluginRegistry.h"
     70 #include "clang/AST/ASTConsumer.h"
     71 #include "clang/AST/AST.h"
     72 #include "clang/Frontend/CompilerInstance.h"
     73 #include "llvm/Support/raw_ostream.h"
     74 using namespace clang;
     75 
     76 namespace {
     77 
     78 class PrintFunctionsConsumer : public ASTConsumer {
     79 public:
     80   virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
     81     for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
     82       const Decl *D = *i;
     83       if (const NamedDecl *ND = dyn_cast&lt;NamedDecl>(D))
     84         llvm::errs() &lt;&lt; "top-level-decl: \"" &lt;&lt; ND->getNameAsString() &lt;&lt; "\"\n";
     85     }
     86 
     87     return true;
     88   }
     89 };
     90 
     91 class PrintFunctionNamesAction : public PluginASTAction {
     92 protected:
     93   ASTConsumer *CreateASTConsumer(CompilerInstance &amp;CI, llvm::StringRef) {
     94     return new PrintFunctionsConsumer();
     95   }
     96 
     97   bool ParseArgs(const CompilerInstance &amp;CI,
     98                  const std::vector&lt;std::string>&amp; args) {
     99     for (unsigned i = 0, e = args.size(); i != e; ++i) {
    100       llvm::errs() &lt;&lt; "PrintFunctionNames arg = " &lt;&lt; args[i] &lt;&lt; "\n";
    101 
    102       // Example error handling.
    103       if (args[i] == "-an-error") {
    104         DiagnosticsEngine &amp;D = CI.getDiagnostics();
    105         unsigned DiagID = D.getCustomDiagID(
    106           DiagnosticsEngine::Error, "invalid argument '" + args[i] + "'");
    107         D.Report(DiagID);
    108         return false;
    109       }
    110     }
    111     if (args.size() &amp;&amp; args[0] == "help")
    112       PrintHelp(llvm::errs());
    113 
    114     return true;
    115   }
    116   void PrintHelp(llvm::raw_ostream&amp; ros) {
    117     ros &lt;&lt; "Help for PrintFunctionNames plugin goes here\n";
    118   }
    119 
    120 };
    121 
    122 }
    123 
    124 static FrontendPluginRegistry::Add&lt;PrintFunctionNamesAction>
    125 X("print-fns", "print function names");
    126 </pre>
    127 
    128 <!-- ======================================================================= -->
    129 <h2 id="running">Running the plugin</h2>
    130 <!-- ======================================================================= -->
    131 
    132 <p>To run a plugin, the dynamic library containing the plugin registry must be
    133 loaded via the -load command line option. This will load all plugins that are
    134 registered, and you can select the plugins to run by specifying the -plugin
    135 option. Additional parameters for the plugins can be passed with -plugin-arg-&lt;plugin-name>.</p>
    136 
    137 <p>Note that those options must reach clang's cc1 process. There are two
    138 ways to do so:</p>
    139 <ul>
    140 <li>
    141 Directly call the parsing process by using the -cc1 option; this has the
    142 downside of not configuring the default header search paths, so you'll need to
    143 specify the full system path configuration on the command line.
    144 </li>
    145 <li>
    146 Use clang as usual, but prefix all arguments to the cc1 process with -Xclang.
    147 </li>
    148 </ul>
    149 <p>For example, to run the print-function-names plugin over a source file in clang,
    150 first build the plugin, and then call clang with the plugin from the source tree:</p>
    151 <pre>
    152   $ export BD=/path/to/build/directory
    153   $ (cd $BD &amp;&amp; make PrintFunctionNames )
    154   $ clang++ -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
    155         -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE \
    156         -I$BD/tools/clang/include -Itools/clang/include -I$BD/include -Iinclude \
    157         tools/clang/tools/clang-check/ClangCheck.cpp -fsyntax-only \
    158         -Xclang -load -Xclang $BD/lib/PrintFunctionNames.so -Xclang \
    159         -plugin -Xclang print-fns
    160 </pre>
    161 
    162 <p>Also see the print-function-name plugin example's
    163 <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/README.txt?view=markup">README</a></p>
    164 
    165 
    166 
    167 </div>
    168 </body>
    169 </html>
    170 
    171