blob: 7c5c65ccf1d4573b971c11dd3963991c2fb9e103 [file] [log] [blame]
Sean Silva93ca0212012-12-13 01:10:46 +00001=============
2Clang Plugins
3=============
4
Dmitri Gribenko97555a12012-12-15 21:10:51 +00005Clang Plugins make it possible to run extra user defined actions during a
6compilation. This document will provide a basic walkthrough of how to write and
7run a Clang Plugin.
Sean Silva93ca0212012-12-13 01:10:46 +00008
9Introduction
10============
11
12Clang Plugins run FrontendActions over code. See the :doc:`FrontendAction
Dmitri Gribenko97555a12012-12-15 21:10:51 +000013tutorial <RAVFrontendAction>` on how to write a ``FrontendAction`` using the
14``RecursiveASTVisitor``. In this tutorial, we'll demonstrate how to write a
15simple clang plugin.
Sean Silva93ca0212012-12-13 01:10:46 +000016
Dmitri Gribenko97555a12012-12-15 21:10:51 +000017Writing a ``PluginASTAction``
18=============================
Sean Silva93ca0212012-12-13 01:10:46 +000019
Dmitri Gribenko97555a12012-12-15 21:10:51 +000020The main difference from writing normal ``FrontendActions`` is that you can
21handle plugin command line options. The ``PluginASTAction`` base class declares
22a ``ParseArgs`` method which you have to implement in your plugin.
Sean Silva93ca0212012-12-13 01:10:46 +000023
Dmitri Gribenko97555a12012-12-15 21:10:51 +000024.. code-block:: c++
Sean Silva93ca0212012-12-13 01:10:46 +000025
Dmitri Gribenko97555a12012-12-15 21:10:51 +000026 bool ParseArgs(const CompilerInstance &CI,
27 const std::vector<std::string>& args) {
28 for (unsigned i = 0, e = args.size(); i != e; ++i) {
29 if (args[i] == "-some-arg") {
30 // Handle the command line argument.
Sean Silva93ca0212012-12-13 01:10:46 +000031 }
Dmitri Gribenko97555a12012-12-15 21:10:51 +000032 }
33 return true;
34 }
Sean Silva93ca0212012-12-13 01:10:46 +000035
36Registering a plugin
37====================
38
39A plugin is loaded from a dynamic library at runtime by the compiler. To
Dmitri Gribenko97555a12012-12-15 21:10:51 +000040register a plugin in a library, use ``FrontendPluginRegistry::Add<>``:
Sean Silva93ca0212012-12-13 01:10:46 +000041
Dmitri Gribenko97555a12012-12-15 21:10:51 +000042.. code-block:: c++
Sean Silva93ca0212012-12-13 01:10:46 +000043
Dmitri Gribenko97555a12012-12-15 21:10:51 +000044 static FrontendPluginRegistry::Add<MyPlugin> X("my-plugin-name", "my plugin description");
Sean Silva93ca0212012-12-13 01:10:46 +000045
46Putting it all together
47=======================
48
Dmitri Gribenko97555a12012-12-15 21:10:51 +000049Let's look at an example plugin that prints top-level function names. This
50example is also checked into the clang repository; please also take a look at
51the latest `checked in version of PrintFunctionNames.cpp
52<http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/PrintFunctionNames.cpp?view=markup>`_.
Sean Silva93ca0212012-12-13 01:10:46 +000053
Dmitri Gribenko97555a12012-12-15 21:10:51 +000054.. code-block:: c++
Sean Silva93ca0212012-12-13 01:10:46 +000055
56 #include "clang/Frontend/FrontendPluginRegistry.h"
57 #include "clang/AST/ASTConsumer.h"
58 #include "clang/AST/AST.h"
59 #include "clang/Frontend/CompilerInstance.h"
60 #include "llvm/Support/raw_ostream.h"
61 using namespace clang;
62
63 namespace {
64
65 class PrintFunctionsConsumer : public ASTConsumer {
66 public:
67 virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
68 for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
69 const Decl *D = *i;
70 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
71 llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
72 }
73
74 return true;
75 }
76 };
77
78 class PrintFunctionNamesAction : public PluginASTAction {
79 protected:
80 ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
81 return new PrintFunctionsConsumer();
82 }
83
84 bool ParseArgs(const CompilerInstance &CI,
85 const std::vector<std::string>& args) {
86 for (unsigned i = 0, e = args.size(); i != e; ++i) {
87 llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
88
89 // Example error handling.
90 if (args[i] == "-an-error") {
91 DiagnosticsEngine &D = CI.getDiagnostics();
92 unsigned DiagID = D.getCustomDiagID(
93 DiagnosticsEngine::Error, "invalid argument '" + args[i] + "'");
94 D.Report(DiagID);
95 return false;
96 }
97 }
98 if (args.size() && args[0] == "help")
99 PrintHelp(llvm::errs());
100
101 return true;
102 }
103 void PrintHelp(llvm::raw_ostream& ros) {
104 ros << "Help for PrintFunctionNames plugin goes here\n";
105 }
106
107 };
108
109 }
110
111 static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
112 X("print-fns", "print function names");
113
114Running the plugin
115==================
116
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000117To run a plugin, the dynamic library containing the plugin registry must be
118loaded via the :option:`-load` command line option. This will load all plugins
119that are registered, and you can select the plugins to run by specifying the
120:option:`-plugin` option. Additional parameters for the plugins can be passed with
121:option:`-plugin-arg-<plugin-name>`.
Sean Silva93ca0212012-12-13 01:10:46 +0000122
123Note that those options must reach clang's cc1 process. There are two
124ways to do so:
125
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000126* Directly call the parsing process by using the :option:`-cc1` option; this
127 has the downside of not configuring the default header search paths, so
128 you'll need to specify the full system path configuration on the command
129 line.
130* Use clang as usual, but prefix all arguments to the cc1 process with
131 :option:`-Xclang`.
Sean Silva93ca0212012-12-13 01:10:46 +0000132
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000133For example, to run the ``print-function-names`` plugin over a source file in
134clang, first build the plugin, and then call clang with the plugin from the
135source tree:
Sean Silva93ca0212012-12-13 01:10:46 +0000136
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000137.. code-block:: console
Sean Silva93ca0212012-12-13 01:10:46 +0000138
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000139 $ export BD=/path/to/build/directory
140 $ (cd $BD && make PrintFunctionNames )
141 $ clang++ -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
Sean Silva93ca0212012-12-13 01:10:46 +0000142 -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE \
143 -I$BD/tools/clang/include -Itools/clang/include -I$BD/include -Iinclude \
144 tools/clang/tools/clang-check/ClangCheck.cpp -fsyntax-only \
145 -Xclang -load -Xclang $BD/lib/PrintFunctionNames.so -Xclang \
146 -plugin -Xclang print-fns
147
148Also see the print-function-name plugin example's
149`README <http://llvm.org/viewvc/llvm-project/cfe/trunk/examples/PrintFunctionNames/README.txt?view=markup>`_
Dmitri Gribenko97555a12012-12-15 21:10:51 +0000150