Clang Plugins
本文为译文,点击 此处查看原文。
Clang Plugins
可以在编译期间运行额外的用户定义的操作。本文档将提供如何编写和运行一个 Clang Plugins
的基本步骤。
1. 介绍
Clang Plugins
在代码上运行FrontendActions
。请参阅关于如何使用RecursiveASTVisitor
编写一个FrontendAction
的FrontendAction教程。在本教程中,我们将演示如何编写一个简单的clang plugin
。
2. 编写一个PluginASTAction
编写PluginASTAction
与编写普通FrontendActions
的主要区别在于,您可以处理plugin命令行选项
。PluginASTAction
基类声明了一个ParseArgs
方法,您必须在您的 plugin 中实现这个方法。
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string>& args) {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
if (args[i] == "-some-arg") {
// 处理命令行参数
}
}
return true;
}
3. 注册一个plugin
编译器在运行时从一个动态库加载一个 plugin。要在库中注册一个 plugin,使用FrontendPluginRegistry::Add<>
:
static FrontendPluginRegistry::Add<MyPlugin> X("my-plugin-name", "my plugin description");
4. 定义pragmas
Plugins 还可以通过声明一个PragmaHandler
来定义 pragmas 并使用PragmaHandlerRegistry::Add<>
来注册它:
// Define a pragma handler for #pragma example_pragma
class ExamplePragmaHandler : public PragmaHandler {
public:
ExamplePragmaHandler() : PragmaHandler("example_pragma") { }
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &PragmaTok) {
// Handle the pragma
}
};
static PragmaHandlerRegistry::Add<ExamplePragmaHandler> Y("example_pragma","example pragma description");
5. 把它们放在一起
让我们看一个示例plugin,它打印顶级函数名。这个例子被检入clang存储库;请查看PrintFunctionNames.cpp的最新版本。
6. 运行此plugin
6.1 使用cc1命令行
要运行一个 plugin,必须通过-load
命令行选项加载包含这个 plugin 注册表的动态库。这将加载所有已注册的 plugin,您可以通过指定-plugin
选项来选择要运行的 plugin。plugin的附加参数可以通过-plugin-arg-<plugin-name>
来传递。
注意,这些选项必须到达 clang 的cc1
过程。有两种方法可以做到这一点:
- 使用
-cc1
选项直接调用解析过程;这样做的缺点是没有配置默认的头文件搜索路径,因此需要在命令行上指定完整的系统路径配置。 - 像往常一样使用 clang,但是在
cc1
过程的所有参数前面加上-Xclang
。
例如,要在 clang 中一个源文件上运行 print-function-names
plugin,首先构建此 plugin,然后从源文件树中使用 plugin 调用 clang:
$ export BD=/path/to/build/directory
$ (cd $BD && make PrintFunctionNames )
$ clang++ -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE \
-I$BD/tools/clang/include -Itools/clang/include -I$BD/include -Iinclude \
tools/clang/tools/clang-check/ClangCheck.cpp -fsyntax-only \
-Xclang -load -Xclang $BD/lib/PrintFunctionNames.so -Xclang \
-plugin -Xclang print-fns
还请参阅 print-function-name
plugin示例的README。
6.2 使用clang命令行
在 clang 命令行上使用-fplugin=plugin
将 plugin 作为一个参数传递给 cc1
命令行上的-load
。如果 plugin 类实现了getActionType
方法,那么此 plugin 将自动运行。例如,在 main AST action 之后自动运行此 plugin(即与使用-add-plugin
相同):
// Automatically run the plugin after the main AST action
PluginASTAction::ActionType getActionType() override {
return AddAfterMainAction;
}