Libtooling не может найти stddef.h и другие заголовки

Я пишу инструмент для анализа проектов исходного кода семейства C, в основном следуя этим двум учебникам 1 2 на clang 3.4 (ствол 192426) на ubuntu 12.04.

На основе официального руководства, он говорит, что я мог бы пройти compile_commands.json на -p, однако, если я набираю только $ ./main -p [path of compile_commands.json], он будет жаловаться на отсутствие позиционных аргументов. Похоже, мне все равно нужно передать все имена файлов в качестве аргументов, что нецелесообразно, если проект действительно огромен. Я предпочитаю, чтобы он мог просто анализировать все файлы, указанные в compile_commands.json, без запроса, но не могу узнать, как включить это.

Так как я не могу найти учебник для CommonOptionsParser, чтобы выполнить любую настройку, я использую CompilationDatabase. Существует фиктивный посетитель, возвращающий true для VisitStmt, VisitDecl и VisitType, поэтому я пропущу это. Функция main довольно проста:

int main(int argc, const char **argv) {
    string errorMsg = "";
    CompilationDatabase *cd = CompilationDatabase::autoDetectFromDirectory (argv[1], errorMsg);
    ClangTool Tool(*cd, cd->getAllFiles());

    int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>());

    return result;
}

Я выбираю opencv для синтаксического анализа, так как с помощью cmake gaurantee правильность compile_commands.json (справа?). Однако появляется много ошибок (прилагается в конце). LibTooling жалуется, что не может найти stdarg.h, stddef.h и emmintrin.h. Это FAQ для clang, но он говорит, почему это произойдет, но не сказал, как решить это при использовании libtooling. Передайте все аргументы для clang -###, поскольку clang может решить это, но как передать эти аргументы при использовании libtooling?

# include <stdarg.h>
          ^
1 error generated.
Error while processing /home/jcwu/repos/opencv/3rdparty/openexr/IlmImf/ImfCompressionAttribute.cpp.
In file included from /home/jcwu/repos/opencv/3rdparty/libjpeg/jmemansi.c:16:
/home/jcwu/repos/opencv/3rdparty/libjpeg/jinclude.h:35:10: fatal error: 'stddef.h' file not found
#include <stddef.h>
         ^
1 error generated.
Error while processing /home/jcwu/repos/opencv/3rdparty/libjpeg/jmemansi.c.
error: no suitable precompiled header file found in directory '/home/jcwu/repos/opencv/modules/legacy/precomp.hpp.gch'
1 error generated.
Error while processing /home/jcwu/repos/opencv/modules/legacy/src/hmmobs.cpp.
In file included from /home/jcwu/repos/opencv/3rdparty/libwebp/enc/quant.c:17:
In file included from /home/jcwu/repos/opencv/3rdparty/libwebp/enc/../dsp/../enc/vp8enci.h:17:
/usr/include/string.h:34:10: fatal error: 'stddef.h' file not found
#include <stddef.h>
         ^
1 error generated.
Error while processing /home/jcwu/repos/opencv/3rdparty/libwebp/enc/quant.c.
In file included from /home/jcwu/repos/opencv/modules/imgproc/opencv_test_imgproc_pch_dephelp.cxx:1:
In file included from /home/jcwu/repos/opencv/modules/imgproc/test/test_precomp.hpp:12:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/iostream:40:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/ostream:40:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/ios:39:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/iosfwd:42:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/postypes.h:42:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/cwchar:46:
/usr/include/wchar.h:40:11: fatal error: 'stdarg.h' file not found
# include <stdarg.h>

==== Обновление ====

Считать исходный код CommonOptionsParser.cpp. Он использует FixedCompilationDatabase, чтобы угадать CompilationDatabase по аргументам после -, а затем передать аргументы до - для пользовательских (только -p в CommonOptionParser) опций. В моем случае требуется compile_commands.json, поэтому я могу пропустить с помощью CommonOptionsParser.

Поэтому моя проблема сводится к тому, как передать эти параметры из "clang - ###" в LibTooling, когда у меня есть compile_commands.json? Должен ли я вызвать команду оболочки для каждого файла, который я хочу проанализировать?

==== Обновление ====

Я думаю, что изменить compile_commands.json может быть проще. Я не уверен, почему compile_commands.json, сгенерированный CMake, не будет корректно содержать папку с файлами системных заголовков, так как Makefile, сгенерированный этим CMakeList.txt, может скомпилироваться правильно, почему compile_commands.json пропускает много вещей.

Ответ 1

Я столкнулся с аналогичной проблемой, используя привязки python.

[<Diagnostic severity 4, location <SourceLocation file '/usr/include/stdio.h', line 33, column 11>, spelling "'stddef.h' file not found">]

В разделе "Советы" в

http://clang.llvm.org/docs/LibTooling.html

они упоминают, что по умолчанию включает путь

$(dirname /path/to/tool)/../lib/clang/3.3/include

Идея здесь, кажется, заключается в том, что ожидается, что ваш инструмент будет выполняться из каталога bin, который также содержит сам исполняемый файл clang. Как правило, это будет системный каталог, поэтому один из них будет иметь каталог lib, который содержит каталог clang/3.4/includ e. Поэтому я вручную включил $(which clang)../lib/clang/3.4/include в синтаксический анализатор. В python это выглядит примерно так:

translation_unit = index.parse("test.cc",["-I/home/archgoon/usr/local/lib/clang/3.4/include"])

В результате translation_unit.diagnostics был пустым.

Ответ 2

В моем случае я получал ошибку, установив clang-tidy, но не clang также на Ubuntu.

Ответ 3

Кто-то ответил мне, что база данных компиляции должна быть автономной. Сначала мне нужно убедиться, что compile_commands.json генерируется с использованием clang, и я мог бы использовать clang для создания opencv.

Я установил эти переменные среды

export CC=/home/jcwu/repos/llvm-release/Release/bin/clang 
export CXX=/home/jcwu/repos/llvm-release/Release/bin/clang++ 
export C_INCLUDE_PATH=/usr/local/include:/home/jcwu/repos/llvm-release/Release/lib/clang/3.4/include:/usr/include/x86_64-linux-gnu:/usr/include  # these are from clang -v -c files.cpp 
export CPLUS_INCLUDE_PATH=/usr/local/include:/home/jcwu/repos/llvm-release/Release/lib/clang/3.4/include:/usr/include/x86_64-linux-gnu:/usr/include 

то регенерировать compile_commands.json, он может найти stddef.h, но появляется новая проблема

[ 31%] Building CXX object modules/ts/CMakeFiles/opencv_ts.dir/src/ts.cpp.o 
In file included from /home/jcwu/repos/opencv/modules/ts/src/ts.cpp:116: 
/usr/include/setjmp.h:60:12: error: conflicting types for '__sigsetjmp' 
extern int __sigsetjmp (struct __jmp_buf_tag __env[1], int __savemask) __THROWNL; 
           ^ 
/usr/include/pthread.h:727:12: note: previous declaration is here 
extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROW; 
           ^ 
1 error generated. 
make[2]: *** [modules/ts/CMakeFiles/opencv_ts.dir/src/ts.cpp.o] Error 1 
make[1]: *** [modules/ts/CMakeFiles/opencv_ts.dir/all] Error 2 
make: *** [all] Error 2 

Я не могу использовать clang для создания opencv из-за конфликта типов или двух файлов системных заголовков. Хавн не понял, как это решить.

Ответ 4

Я столкнулся с подобной проблемой, которую паника stddef.h не обнаружила, когда я вызываю clang-tidy против compile_commands.json. В моем случае причина в том, что clang-tidy был основан на llvm версии 7, а версия clang++ была основана на llvm версии 4.0, после изменения clang-tidy на правильную версию проблемы исчезли.

Ответ 5

Пожалуйста, используйте соответствующую версию clang для ваших инструментов и первый аргумент команды compile (и используйте правильный путь).

Например:

  std::vector<std::string> Args {"/home/theuser/.local/llvm-8.0.0/bin/clang-8", "-c", "a.cpp"};
  llvm::IntrusiveRefCntPtr<clang::FileManager> fileManager(new clang::FileManager(clang::FileSystemOptions()));
  clang::tooling::ToolInvocation invoker(Args, new BlankAction(), fileManager.get());
  invoker.run();

Если вы используете библиотеку clang 8.0 для сборки этого инструмента, он будет успешным. Если вы используете другие версии (clang 3.6 и т.д.), Это может привести к этой ошибке.