如何在基于libtooling的工具中获取编译命令
How to obtain the compilation command in a tool based on libtooling
我已经构建了一个用于转换源代码的自定义工具(基于 libtooling)。我使用了 clang 自己的教程并设法 运行 我自己的自定义 FrontendAction。我现在需要解析提供给工具(在命令行上)的编译标志以自定义转换。然而,无论我做什么,CompilationDatabase 似乎总是 return 一个空的编译命令列表。
这是示例代码:
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
static cl::OptionCategory MyToolCategory("CustomTool");
static cl::extrahelp MoreHelp("\nMore help text...");
int main(int argc, const char **argv)
{
CommonOptionsParser op(argc, argv, MyToolCategory); // Parse the command-line arguments
CompilationDatabase &Compilations = op.getCompilations();
for (const auto &cmd: Compilations.getAllCompileCommands()) { //<---- this list is always empty!!!
std::cout << "filename: " << cmd.Filename;
// Do stuff with compile flags
}
ClangTool Tool(Compilations, op.getSourcePathList()); // Create a new Clang Tool instance (a LibTooling environment)
return Tool.run(newFrontendActionFactory<MyASTFrontendAction>().get()); // Run custom Frontendaction
}
我是这样调用工具的:
./custom-tool sample.c -- -I/some/include/path -std=gnu11
我希望能够获得命令行标志 -I/some/include/path
和 -std=gnu11
。
编译数据库
您的编译数据库 (compile_commands.json) 为空或不存在。所有编译命令在技术上都是数据库中的所有命令,因此是空的。
clang 如何使用我提供的选项
Clang 在 CompilationDatabase
对象周围创建一个临时包装器,将这些选项添加到已询问此 CompilationDatabase
的任何文件,即使该文件不在数据库本身中,并且即使它不存在。
那我怎样才能得到那个信息呢
您可以遍历源列表并请求(又名 getCompileCommands
)数据库为该特定文件提供命令,而不是迭代编译命令。
工作演示
#include "clang/Tooling/CommonOptionsParser.h"
using namespace clang;
using namespace tooling;
using namespace llvm;
static cl::OptionCategory MyToolCategory("CustomTool");
static cl::extrahelp MoreHelp("\nMore help text...");
void print(const std::vector<CompileCommand> &Commands) {
if (Commands.empty()) {
return;
}
for (auto opt : Commands[0].CommandLine) {
llvm::errs() << "\t" << opt << "\n";
}
}
int main(int argc, const char **argv) {
CommonOptionsParser OP(argc, argv,
MyToolCategory);
CompilationDatabase &Compilations = OP.getCompilations();
for (const auto &File :
OP.getSourcePathList()) {
llvm::errs() << "filename: " << File << "\n";
llvm::errs() << "opts:\n";
auto Commands = Compilations.getCompileCommands(File);
print(Commands);
}
auto CommandsForFakeFile = Compilations.getCompileCommands("baloney.c");
llvm::errs() << "fake filename: baloney.c\n";
print(CommandsForFakeFile);
return 0;
}
上面的代码生成以下输出:
> ./myTool test.cpp -- -I/some/include/path -std=gnu11
filename: test.cpp
opts:
$PATH_TO_MYTOOL_EXEC/clang-tool
-I/some/include/path
-std=gnu11
test.cpp
fake filename: baloney.c
$PATH_TO_MYTOOL_EXEC/clang-tool
-I/some/include/path
-std=gnu11
baloney.c
希望这些信息对您有用!祝您使用 Clang 愉快!
我已经构建了一个用于转换源代码的自定义工具(基于 libtooling)。我使用了 clang 自己的教程并设法 运行 我自己的自定义 FrontendAction。我现在需要解析提供给工具(在命令行上)的编译标志以自定义转换。然而,无论我做什么,CompilationDatabase 似乎总是 return 一个空的编译命令列表。
这是示例代码:
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
static cl::OptionCategory MyToolCategory("CustomTool");
static cl::extrahelp MoreHelp("\nMore help text...");
int main(int argc, const char **argv)
{
CommonOptionsParser op(argc, argv, MyToolCategory); // Parse the command-line arguments
CompilationDatabase &Compilations = op.getCompilations();
for (const auto &cmd: Compilations.getAllCompileCommands()) { //<---- this list is always empty!!!
std::cout << "filename: " << cmd.Filename;
// Do stuff with compile flags
}
ClangTool Tool(Compilations, op.getSourcePathList()); // Create a new Clang Tool instance (a LibTooling environment)
return Tool.run(newFrontendActionFactory<MyASTFrontendAction>().get()); // Run custom Frontendaction
}
我是这样调用工具的:
./custom-tool sample.c -- -I/some/include/path -std=gnu11
我希望能够获得命令行标志 -I/some/include/path
和 -std=gnu11
。
编译数据库
您的编译数据库 (compile_commands.json) 为空或不存在。所有编译命令在技术上都是数据库中的所有命令,因此是空的。
clang 如何使用我提供的选项
Clang 在 CompilationDatabase
对象周围创建一个临时包装器,将这些选项添加到已询问此 CompilationDatabase
的任何文件,即使该文件不在数据库本身中,并且即使它不存在。
那我怎样才能得到那个信息呢
您可以遍历源列表并请求(又名 getCompileCommands
)数据库为该特定文件提供命令,而不是迭代编译命令。
工作演示
#include "clang/Tooling/CommonOptionsParser.h"
using namespace clang;
using namespace tooling;
using namespace llvm;
static cl::OptionCategory MyToolCategory("CustomTool");
static cl::extrahelp MoreHelp("\nMore help text...");
void print(const std::vector<CompileCommand> &Commands) {
if (Commands.empty()) {
return;
}
for (auto opt : Commands[0].CommandLine) {
llvm::errs() << "\t" << opt << "\n";
}
}
int main(int argc, const char **argv) {
CommonOptionsParser OP(argc, argv,
MyToolCategory);
CompilationDatabase &Compilations = OP.getCompilations();
for (const auto &File :
OP.getSourcePathList()) {
llvm::errs() << "filename: " << File << "\n";
llvm::errs() << "opts:\n";
auto Commands = Compilations.getCompileCommands(File);
print(Commands);
}
auto CommandsForFakeFile = Compilations.getCompileCommands("baloney.c");
llvm::errs() << "fake filename: baloney.c\n";
print(CommandsForFakeFile);
return 0;
}
上面的代码生成以下输出:
> ./myTool test.cpp -- -I/some/include/path -std=gnu11
filename: test.cpp
opts:
$PATH_TO_MYTOOL_EXEC/clang-tool
-I/some/include/path
-std=gnu11
test.cpp
fake filename: baloney.c
$PATH_TO_MYTOOL_EXEC/clang-tool
-I/some/include/path
-std=gnu11
baloney.c
希望这些信息对您有用!祝您使用 Clang 愉快!