clang::HeaderSearch 忽略搜索路径
clang::HeaderSearch search path ignored
我试图让 clang::CompilerInstance
解析包含包含的源文件,但我不知道如何让它真正找到包含的 header。这是我的设置:
std::unique_ptr<clang::CompilerInstance> ci(new clang::CompilerInstance());
ci->createDiagnostics();
LLVMInitializeARMTarget();
LLVMInitializeARMTargetMC();
LLVMInitializeARMAsmPrinter();
LLVMInitializeARMAsmParser();
std::shared_ptr<clang::TargetOptions> options(new clang::TargetOptions);
options->Triple = "arm-v7m-unknown-none-eabi";
options->CPU = "cortex-m3";
clang::TargetInfo *targetInfo = clang::TargetInfo::CreateTargetInfo(ci->getDiagnostics(), options);
ci->setTarget(targetInfo);
ci->createFileManager();
ci->createSourceManager(ci->getFileManager());
NSURL *sysrootURL = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:@"Compiler/basalt"];
NSURL *includeURL = [sysrootURL URLByAppendingPathComponent:@"include"];
ci->createPreprocessor(clang::TranslationUnitKind::TU_Complete);
ci->getPreprocessorOpts().UsePredefines = false;
// Header searcher
llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> hso(new clang::HeaderSearchOptions());
hso->UseBuiltinIncludes = false;
hso->UseStandardSystemIncludes = false;
hso->UseStandardCXXIncludes = false;
hso->Sysroot = [[includeURL path] UTF8String];
clang::HeaderSearch headerSearch(hso, ci->getSourceManager(), ci->getDiagnostics(), ci->getLangOpts(), targetInfo);
headerSearch.AddSearchPath(clang::DirectoryLookup(ci->getFileManager().getDirectory([[includeURL path] UTF8String]), clang::SrcMgr::C_System, false), true);
clang::InitializePreprocessor(ci->getPreprocessor(), ci->getPreprocessorOpts(), ci->getFrontendOpts());
// Main file
const clang::FileEntry *file = ci->getFileManager().getFile([[[_url URLByAppendingPathComponent:@"src/main.c"] path] UTF8String]);
ci->getSourceManager().setMainFileID(ci->getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User));
ci->getPreprocessor().EnterMainSourceFile();
ci->getDiagnosticClient().BeginSourceFile(ci->getLangOpts(), &ci->getPreprocessor());
clang::Token tok;
do {
ci->getPreprocessor().Lex(tok);
if(ci->getDiagnostics().hasErrorOccurred())
break;
ci->getPreprocessor().DumpToken(tok);
std::cerr << std::endl;
} while(tok.isNot(clang::tok::eof));
ci->getDiagnosticClient().EndSourceFile();
路径肯定是100%正确的,反复检查过。这一切都有效,直到我抛出的源代码包含类似 #include <foobar.h>
的东西,在这种情况下它会失败并显示 error 'foobar.h' file not found
,即使 foobar.h 确实存在。我觉得我在这里遗漏了一些非常明显的东西。任何指向正确方向的指针?
首先,停止使用 CompilerInstance - 所有权语义非常糟糕,几乎无法使用(除非他们在 3.6 中用 unique_ptr
修复了这个问题)。自己制作组件更容易。
其次,是的,你必须自己做。这是我自己使用 Clang 的项目的逐字摘录:
clang::HeaderSearch hs(/*params*/);
// WHY AM I DOING THIS MYSELF CLANG
// CAN'T YOU READ YOUR OWN CONSTRUCTOR PARAMETERS AND OPTIONS STRUCTS?
std::vector<clang::DirectoryLookup> lookups;
for (auto entry : opts.HeaderSearchOptions->UserEntries) {
auto lookup = clang::DirectoryLookup(FileManager.getDirectory(entry.Path), clang::SrcMgr::CharacteristicKind::C_System, false);
if (!lookup.getDir())
throw SpecificError<ClangCouldNotInterpretPath>(a, where, "Clang could not interpret path " + entry.Path);
lookups.push_back(lookup);
}
hs.SetSearchPaths(lookups, 0, 0, true);
我试图让 clang::CompilerInstance
解析包含包含的源文件,但我不知道如何让它真正找到包含的 header。这是我的设置:
std::unique_ptr<clang::CompilerInstance> ci(new clang::CompilerInstance());
ci->createDiagnostics();
LLVMInitializeARMTarget();
LLVMInitializeARMTargetMC();
LLVMInitializeARMAsmPrinter();
LLVMInitializeARMAsmParser();
std::shared_ptr<clang::TargetOptions> options(new clang::TargetOptions);
options->Triple = "arm-v7m-unknown-none-eabi";
options->CPU = "cortex-m3";
clang::TargetInfo *targetInfo = clang::TargetInfo::CreateTargetInfo(ci->getDiagnostics(), options);
ci->setTarget(targetInfo);
ci->createFileManager();
ci->createSourceManager(ci->getFileManager());
NSURL *sysrootURL = [[[NSBundle mainBundle] resourceURL] URLByAppendingPathComponent:@"Compiler/basalt"];
NSURL *includeURL = [sysrootURL URLByAppendingPathComponent:@"include"];
ci->createPreprocessor(clang::TranslationUnitKind::TU_Complete);
ci->getPreprocessorOpts().UsePredefines = false;
// Header searcher
llvm::IntrusiveRefCntPtr<clang::HeaderSearchOptions> hso(new clang::HeaderSearchOptions());
hso->UseBuiltinIncludes = false;
hso->UseStandardSystemIncludes = false;
hso->UseStandardCXXIncludes = false;
hso->Sysroot = [[includeURL path] UTF8String];
clang::HeaderSearch headerSearch(hso, ci->getSourceManager(), ci->getDiagnostics(), ci->getLangOpts(), targetInfo);
headerSearch.AddSearchPath(clang::DirectoryLookup(ci->getFileManager().getDirectory([[includeURL path] UTF8String]), clang::SrcMgr::C_System, false), true);
clang::InitializePreprocessor(ci->getPreprocessor(), ci->getPreprocessorOpts(), ci->getFrontendOpts());
// Main file
const clang::FileEntry *file = ci->getFileManager().getFile([[[_url URLByAppendingPathComponent:@"src/main.c"] path] UTF8String]);
ci->getSourceManager().setMainFileID(ci->getSourceManager().createFileID(file, clang::SourceLocation(), clang::SrcMgr::C_User));
ci->getPreprocessor().EnterMainSourceFile();
ci->getDiagnosticClient().BeginSourceFile(ci->getLangOpts(), &ci->getPreprocessor());
clang::Token tok;
do {
ci->getPreprocessor().Lex(tok);
if(ci->getDiagnostics().hasErrorOccurred())
break;
ci->getPreprocessor().DumpToken(tok);
std::cerr << std::endl;
} while(tok.isNot(clang::tok::eof));
ci->getDiagnosticClient().EndSourceFile();
路径肯定是100%正确的,反复检查过。这一切都有效,直到我抛出的源代码包含类似 #include <foobar.h>
的东西,在这种情况下它会失败并显示 error 'foobar.h' file not found
,即使 foobar.h 确实存在。我觉得我在这里遗漏了一些非常明显的东西。任何指向正确方向的指针?
首先,停止使用 CompilerInstance - 所有权语义非常糟糕,几乎无法使用(除非他们在 3.6 中用 unique_ptr
修复了这个问题)。自己制作组件更容易。
其次,是的,你必须自己做。这是我自己使用 Clang 的项目的逐字摘录:
clang::HeaderSearch hs(/*params*/);
// WHY AM I DOING THIS MYSELF CLANG
// CAN'T YOU READ YOUR OWN CONSTRUCTOR PARAMETERS AND OPTIONS STRUCTS?
std::vector<clang::DirectoryLookup> lookups;
for (auto entry : opts.HeaderSearchOptions->UserEntries) {
auto lookup = clang::DirectoryLookup(FileManager.getDirectory(entry.Path), clang::SrcMgr::CharacteristicKind::C_System, false);
if (!lookup.getDir())
throw SpecificError<ClangCouldNotInterpretPath>(a, where, "Clang could not interpret path " + entry.Path);
lookups.push_back(lookup);
}
hs.SetSearchPaths(lookups, 0, 0, true);