如何在基于libtooling的工具中获取编译命令

Posted

技术标签:

【中文标题】如何在基于libtooling的工具中获取编译命令【英文标题】:How to obtain the compilation command in a tool based on libtooling 【发布时间】:2020-02-11 10:11:17 【问题描述】:

我已经构建了一个自定义工具(基于 libtooling)来转换源代码。我使用了 clang 自己的教程并设法运行了我自己的自定义 FrontendAction。我现在需要解析提供给工具(在命令行上)的编译标志以自定义转换。然而,无论我做什么,CompilationDatabase 似乎总是返回一个空的编译命令列表。

这是示例代码:

#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

【问题讨论】:

【参考方案1】:

编译数据库

您的编译数据库 (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的工具中获取编译命令的主要内容,如果未能解决你的问题,请参考以下文章

命令 libtool 失败,退出代码为 1

错误:libtool - 编译 MPI 程序时

OS X 安装命令行看图工具 chafa 以及其依赖libtool

如何从 automake/libtool 库中获取符号列表?

C++学习(三五九)GNU构建系统Autotools(autoconf automake libtool autoscan autoheader aclocal automake m4)

libtool:存档中的对象名称冲突(NETCDF + MinGW)