Как получить команду компиляции в инструменте, основанном на libtooling - PullRequest
1 голос
/ 11 февраля 2020

Я создал собственный инструмент (на основе 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 Ответ

1 голос
/ 13 февраля 2020

База данных компиляции

Ваша база данных компиляции ( compile_commands. json) либо пуста, либо не существует. Все команды компиляции являются технически всеми командами в базе данных и, таким образом, являются пустыми.

Как clang использует параметры, которые я предоставляю

Clang создает оболочку ad-ho c вокруг объекта CompilationDatabase, который добавляет эти опции к любому файлу, о котором спрашивался этот CompilationDatabase, даже если этот файл отсутствует в самой базе данных, и даже если он не существует.

Как можно Затем я получаю эту информацию

Вместо того, чтобы повторять команды компиляции, вы можете перебирать исходный список и запрашивать (также известную как getCompileCommands) базу данных, чтобы дать команды для этого конкретного файла.

Работа demo

#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!

...