如何利用Clang Tooling获取文件的相对包含路径?
解决Clang Tooling生成相对包含路径的问题
要生成枚举定义文件的相对包含路径,你可以从MatchResult里拿到ASTContext,进而获取翻译单元的包含目录列表,再结合完整路径计算相对路径。具体步骤如下:
1. 获取翻译单元的包含目录列表
从MatchResult中提取ASTContext,通过它获取HeaderSearchInfo,进而拿到所有的包含目录:
// 你的MatchFinder::MatchResult对象 const auto& matchResult = ...; const clang::ASTContext& astContext = matchResult.Context; const clang::HeaderSearch& headerSearch = astContext.getHeaderSearchInfo()->getHeaderSearch(); // 收集用户指定的包含目录(可根据需求调整过滤规则) std::vector<std::string> includeDirs; for (const auto& dir : headerSearch.user_dirs()) { if (dir.isValid()) { includeDirs.push_back(dir.getDir()->getName().str()); } } // 若需要包含系统目录,可遍历headerSearch.search_dirs()并过滤
2. 计算相对包含路径
拿到包含目录后,遍历这些目录,找到与枚举定义文件完整路径匹配最长的前缀,截取后得到相对路径:
// 你已有的获取完整路径的代码 const EnumType *enumType = ...; auto defineFileLoc = enumType->getDecl()->getDefinition()->getLocation(); const auto& sourceManager = astContext.getSourceManager(); const auto defineFilePath = sourceManager.getFilename(sourceManager.getExpansionLoc(defineFileLoc)).str(); // 寻找最长匹配的包含目录前缀 std::string relativePath; size_t maxMatchLen = 0; for (const auto& dir : includeDirs) { if (defineFilePath.starts_with(dir)) { size_t matchLen = dir.size(); // 确保匹配的是完整目录(避免部分匹配,比如dir是/a/b,文件是/a/bc/file.h) if (matchLen == defineFilePath.size() || defineFilePath[matchLen] == '/') { if (matchLen > maxMatchLen) { maxMatchLen = matchLen; // 截取相对路径,处理目录末尾的/ relativePath = defineFilePath.substr(matchLen + (dir.back() == '/' ? 0 : 1)); } } } } // 未找到匹配目录时,回退到完整路径 if (relativePath.empty()) { relativePath = defineFilePath; }
3. 跨平台与规范化优化
可以用Clang自带的llvm::sys::path工具类处理路径分隔符、简化路径,避免跨平台问题:
#include "llvm/Support/Path.h" // 规范化路径,统一分隔符并去除冗余的./../ std::string normalizedFile = llvm::sys::path::remove_leading_dots(llvm::sys::path::convert_to_slash(defineFilePath)); for (auto& dir : includeDirs) { dir = llvm::sys::path::remove_leading_dots(llvm::sys::path::convert_to_slash(dir)); }
内容的提问来源于stack exchange,提问作者shaharhoch
相关产品推荐
相关产品推荐

