原题
我按照教程创建了一个名为ast_extract
的工具来分析libpng的源代码:
llvm::cl::OptionCategory ASTExtractCategory("ASTExtract tool options");
llvm::Expected<clang::tooling::CommonOptionsParser> optionParser = clang::tooling::CommonOptionsParser::create(argc, argv, ASTExtractCategory);
clang::tooling::ClangTool tool(optionParser->getCompilations(), optionParser->getCompilations().getAllFiles());
字符串
但是,该工具遇到无法找到“stddef. h”文件的问题,如以下错误消息所示:
我可以通过添加一个额外的参数来暂时解决这个问题,比如ast_extract --extra-arg='-I/data/tfk/llvm/lib/clang/17/include'
。但是,当使用Bash时,我可以简单地从compile_commands.json
复制命令行,而不会遇到任何问题:
clang -c -DHAVE_CONFIG_H -I. -g -O2 -fPIC -DPIC -o .libs/pngmem.o pngmem.c
型
如何修改ast_extract
工具以消除对额外参数的需要?
更新
感谢scott!通过将以下规则合并到CMakeLists.txt中,我成功地实现了上述第一个解决方案
# Install the compiler header files that libtool cannot find (such as stddef.h)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR})
install(TARGETS ast_extract DESTINATION bin)
install(DIRECTORY ${LLVM_INCLUDE_DIR}/../lib/clang/${LLVM_VERSION_MAJOR}/include DESTINATION lib/clang/${LLVM_VERSION_MAJOR})
message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}")
message(STATUS "CLANG_INCLUDE_DIRS: ${CLANG_INCLUDE_DIRS}")
型
尽管我尽了最大努力来减少硬编码,但到stddef. h(${LLVM_INCLUDE_DIR}/../lib/clang/${LLVM_VERSION_MAJOR}/include
)的路径似乎有些麻烦。
我很好奇是否有一个CMake变量直接对应所需的路径?
1条答案
按热度按时间dluptydi1#
简而言之,不同之处在于
bash
调用的clang
在文件系统中附近有其编译器头文件(包括stddef.h
),而LibTooling可执行文件则没有。解析C需要的不仅仅是一个能够读取C语法的程序,它还需要某些头文件,这些头文件在逻辑上是编译器的一部分,而不是C库的一部分;
stddef.h
是前者之一,而(比如)stdio.h
是后者之一。如果你使用LibTooling来创建一个解析C++的可执行文件,如果没有编译器头文件,它是不完整的,就像一个视频游戏的可执行文件缺少它的艺术资产一样。(就像一个视频游戏可以将它的艺术打包到可执行文件中一样,一个LibTooling可执行文件可以将编译器头嵌入其中,但是不幸的是,LibTooling API并没有设置成容易做到这一点。)那么,LibTooling程序如何找到它的编译器头文件呢?有几个API接受类似
argv
的数组,包括您代码中使用的clang::tooling::CommonOptionsParser::create
。这些API安排在该数组中查找与argv[0]
相关的编译器头文件,实际上是在$(argv[0])/../lib/clang/$(version)/include
中。因此,您需要确保目录存在,并且填充了所有必需的文件。解决方案:正确的方法是让你的工具有一个“安装”步骤或类似的步骤,将Clang编译器头文件沿着复制到可执行文件将运行的位置。你需要复制
lib/clang/$(version)/include
中的每个文件。然而,由于这有点烦人,我通常会让我的
Makefile
传递一个-D
开关,该开关提供我正在使用的Clang安装目录的路径,然后在我的C++代码中,我只需将shell传递的argv[0]
替换为$(clang_install_dir)/bin/clang
,有效地欺骗Clang API来模拟clang
本身。然后API将找到与clang
相同的编译器头。这当然意味着我的工具只在该位置安装了clang
的兼容版本时才能工作,所以它适合于实验和一次性开发,但是如果其他人要安装和使用它,那么工具就不应该这样做。作为参考,还有其他几个与此主题有关的问题和讨论,尽管没有一个问题和足够完整的答案使其适合作为重复目标:
其中一些提供了不同的解决方法,包括传递一个额外的
-I
参数,这可以像您注意到的那样工作,但通常不是一个好的解决方案。