LibTooling
(库工具)LibTooling
是个支持基于Clang
编写独立工具
的库.
为LLVM
设置Clang
工具,在此
用LibTooling
构建的工具(如Clang
插件)通过代码运行FrontendActions
.
这里演示运行Clang
的快速检查一堆代码语法
的SyntaxOnlyAction
的不同方法.
如果想对,如对ClangAST
的某些部分单元测试
的代码
运行FrontendAction
,则runToolOnCode
就是你找的.如:
#include "clang/Tooling/Tooling.h"
TEST(runToolOnCode, CanSyntaxCheckCode) {
//`runToolOnCode`返回在给定代码上是否正确`操作`运行.
EXPECT_TRUE(runToolOnCode(std::make_unique<clang::SyntaxOnlyAction>(), "class X {};"));
}
一旦对FrontendAction
运行了单元测试,使其不可中断,就可创建独立工具了.作为独立运行clang
的工具,首先要确定要为指定文件
使用哪些命令行参数
.
为此,创建了一个编译数据库
.有很多种创建编译数据库
的方法,可根据命令行选项
来支持所有这些方法.
CommonOptionsParser
类,负责解析
与编译数据库和输入
相关的命令行参数
,以便所有工具
可共享实现.
可从构建目录
或命令行
读取编译数据库
.使用CommonOptionsParser
可显式
指定编译命令行
,用-p
命令行选项指定构建路径
,及用源文件路径
自动定位编译数据库
.
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
using namespace clang::tooling;
//对`所有命令行选项`,应用自定义分类,以便只显示他们.
static llvm::cl::OptionCategory MyToolCategory("my-tool options");
int main(int argc, const char **argv) {
//`CommonOptionsParser`构造器解析参数,并创建`编译数据库`.如果出现错误,它终止程序.
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
//使用`OptionsParser.getCompilations()`和`OptionsParser.getSourcePathList()`提取`编译数据库`和输入文件路径列表.
}
ClangTool
一旦有了编译数据库
,就可创建一个ClangTool
并在一些代码
上运行FrontendAction
.如,要对"a.cc"
和"b.cc"
文件运行SyntaxOnlyAction
,可这样写:
//可在同一进程中运行多个源的`clang`工具.
std::vector<std::string> Sources;
Sources.push_back("a.cc");
Sources.push_back("b.cc");
//把创建的`编译数据库`和要运行的`源码`交给`工具构造器`.
ClangTool Tool(OptionsParser.getCompilations(), Sources);
//`ClangTool`要为运行的每个`翻译单元`提供一个新的`FrontendAction`.因此,它以`FrontendActionFactory`作为参数.
//要从给定的`FrontendAction`类型创建`FrontendActionFactory`,调用`newFrontendActionFactory()`.
int result = Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
现在,合并
前面两个步骤
到第一个实际工具
中.此例工具
的更高级版本
也签入到tools/clang-check/ClangCheck.cpp
的clang
树中.
//声明`clang::SyntaxOnlyAction`.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
//声明`llvm::cl::extrahelp`.
#include "llvm/Support/CommandLine.h"
using namespace clang::tooling;
using namespace llvm;
static cl::OptionCategory MyToolCategory("my-tool options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
//之后可添加此指定工具的帮助消息.
static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) {
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
}
检出并构建clang
时,已构建``clang-check
,并在构建
目录中的bin/clang-check
中.
可通过在"--"
分隔符后,指定``llvm
仓库中的文件运行clang-check
的所有必需参数
:
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check tools/clang/tools/clang-check/ClangCheck.cpp -- \
clang++ -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS \
-Itools/clang/include -I$BD/include -Iinclude \
-Itools/clang/lib/Headers -c
或,还可按把编译命令数据库
输出到其构建目录
中,来配置cmake
:
# 或从UI设置CMAKE_EXPORT_COMPILE_COMMANDS.
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
这在目录中创建叫compile_commands.json
的文件.现在,你可通过按第一个参数
指定构建路径
,并按进一步的位置
参数指定一些源文件
,来对项目中的文件运行clang-check
:
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check -p $BD tools/clang/tools/clang-check/ClangCheck.cpp
Clang
工具需要其内置头文件
,并按Clang
方式搜索
它们.因此,默认在$(dirname/path/to/tool)/
中查找内置头文件
.
相对工具二进制文件的/lib/clang/3.3/include
.对在构建clang-resource-headers
后,从llvm
的顶级二进制目录运行的工具,或如果该工具
从clang
二进制文件旁边的clang
安装的二进制目录
运行,则开箱即用.
提示:如果工具找不到stddef.h
或类似头文件
,请使用-v
调用该工具
并查看它所查找的搜索路径
.
有关要链接的库列表
,请查看工具的CMake
文件之一(如clang-check/CMakeList.txt
)这里.