如何在CMake项目中使用ASTMatcher扫描全局变量(含依赖头文件)
I've built an ASTMatcher to hunt down global variables in my project. It works perfectly when scanning individual .cpp or .h files on its own, but it can't pick up variables from headers that are included via my project's CMakeLists.txt. Can I fix this using scan-build or by adding specific command-line arguments to my tool?
The tool does correctly scan its own source files and output valid global variable data (example below), but it throws runtime errors when running against the full project. I used the LibASTMatchers Tutorial as a reference for development.
Example Output:
{ "GlobalVar":[ { "name" : "MyToolCategory", "type" : "int", "loc" : "D:\\LLVM\\llvm\\tools\\clang\\tools\\extra\\match-global-variable\\MatchGlobalVariable.cpp:22:33" }, { "name" : "MoreHelp", "type" : "int", "loc" : "D:\\LLVM\\llvm\\tools\\clang\\tools\\extra\\match-global-variable\\MatchGlobalVariable.cpp:30:22" }, { "name" : "GlobalVarMatcher", "type" : "int", "loc" : "D:\\LLVM\\llvm\\tools\\clang\\tools\\extra\\match-global-variable\\MatchGlobalVariable.cpp:51:20" }, { "name" : "GlobalVar", "type" : "int", "loc" : "D:\\LLVM\\llvm\\tools\\clang\\tools\\extra\\match-global-variable\\MatchGlobalVariable.cpp:55:12" } ] }
Absolutely—you can fix this by making sure your ASTMatcher has access to the full compilation context that CMake sets up, either with scan-build or by leveraging a compilation database. Here's how to approach it:
1. Use scan-build to integrate your tool with CMake's build pipeline
scan-build is made to wrap build commands and feed Clang-based tools all the necessary compilation flags. This is the easiest way to ensure your tool sees every header CMake specifies:
- First, confirm your tool is built as a standalone
clang-tool(since you're using LibASTMatchers, this is probably your setup). - Run
scan-buildwith your tool instead of the default analyzer. For example:
If it's a standalone executable, you can wrap the build command to use your tool:scan-build -load path/to/your/MatchGlobalVariable.so -plugin MatchGlobalVariable cmake --build .
This forces your tool to process every file exactly as CMake compiles it—including all headers added viascan-build --use-analyzer=/path/to/your/MatchGlobalVariable makeinclude_directoriesortarget_include_directoriesin your CMakeLists. The key here is thatscan-buildcaptures all the-Iinclude flags and preprocessor defines CMake uses, so your tool knows where to find those headers.
2. Generate a compilation database for your tool to use
If scan-build isn't your preference, you can have CMake generate a compile_commands.json file. This file contains all the compilation flags for every source file in your project, which your tool can use to parse files with the correct context:
- Enable compilation database generation in CMake:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. - Modify your ASTMatcher tool to read from
compile_commands.jsonusing Clang'sJSONCompilationDatabaseAPI. When you run your tool against the project, it will use the exact include paths and flags CMake would use, so it can resolve and parse all the headers specified in your build config.
3. Fix runtime errors by ensuring full header traversal
The runtime errors you're seeing are almost certainly because your tool isn't resolving headers correctly (missing include paths, preprocessor defines, etc.). Using either scan-build or the compilation database will fix this by providing the right flags.
One quick check: make sure your ASTMatcher is configured to traverse into included headers. By default, some matchers might skip included files unless you explicitly enable it. In your tool's code, verify that your ASTFrontendAction and ASTConsumer are set up to process all parts of the translation unit—including headers that are part of the project's include paths.
For example, when setting up your ClangTool, don't limit it to only source files; let it process the full set of files from the compilation database, which includes the relevant headers.
内容的提问来源于stack exchange,提问作者ys z

