Добавить файл памяти в Clang CompilerInstance
Я пытаюсь создать инструмент с помощью clang, и мне было интересно, возможно ли добавить файл включения из памяти в CompilerInstance
препроцессор.
Моя цель - добавить #include <my_globals.hpp>
в мои файлы и динамически включить этот файл с соответствующим содержанием. Итак, у меня есть ASTFrontendAction
как это:
class MyFrontendAction : public ASTFrontendAction
{
virtual bool BeginInvocation(CompilerInstance &ci) override{
auto buffer = llvm::MemoryBuffer::getMemBufferCopy(...);
ci.createFileManager();
ci.createSourceManager(ci.getFileManager());
ci.createPreprocessor(clang::TU_Complete);
auto& pp = ci.getPreprocessor();
auto& preprocessorOpts = pp.getPreprocessorOpts();
preprocessorOpts.clearRemappedFiles();
preprocessorOpts.addRemappedFile("my_globals.hpp", buffer.release());
// this seams not to work
auto& hsi = pp.getHeaderSearchInfo();
auto& headerSearchOptions = hsi.getHeaderSearchOpts();
headerSearchOptions.Verbose = true; // this option is used during job
}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& ci, StringRef file) override{/* do my parsing */}
};
Разбор работает до тех пор, пока я не включаю свой заголовочный файл. Если я это сделаю, я получу my_globals.hpp file not found
,
Итак addRemappedFile
не делает этот файл видимым для препроцессора. Я мог бы добавить какой-нибудь путь поиска, но как я могу указать, что этот файл не имеет пути?
Может ли кто-нибудь дать мне подсказку, как я могу решить это.
1 ответ
Я отвечу на свой вопрос, может быть, это будет полезно. В то время как PPCallbacks
вызываются всякий раз, когда препроцессор касается файла, я не нашел способа изменить содержимое. Таким образом, мое решение состоит в том, чтобы предоставить свой собственный FileSystem
class MyFs : public FileSystem{
... openFileForRead(const Twine& Path) overwrite
{
// in here I create my own File that will contain the data
// all other functions and when the path is not what I expect I forward it to a FileSystrem
}
};
class MyFrontendAction : public ASTFrontendAction
{
virtual bool BeginInvocation(CompilerInstance &ci) override{
ci.createFileManager(); // now I have a default FS
llvm::IntrusiveRefCntPtr<vfs::FileSystem> fs(new MyFs(ci.getFileManager().getVirtualFileSystem()));
ci.setVirtualFileSystem(fs);
ci.setFileManager(new clang::FileManager(clang::FileSystemOptions{}, fs));
auto& fm = ci.getFileManager();
ci.createSourceManager(fm);
return true;
}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance& ci, StringRef file) override{/* do my parsing */}
};