Support inclusion of precompiled header from header search paths.
This commit is contained in:
parent
a757a424a3
commit
e10447fe92
@ -13,6 +13,7 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
@ -20,6 +21,7 @@ namespace llvm {
|
||||
|
||||
namespace clang {
|
||||
class HeaderSearchOptions;
|
||||
class FileManager;
|
||||
}
|
||||
|
||||
namespace cling {
|
||||
@ -66,6 +68,23 @@ namespace cling {
|
||||
llvm::StringRef Delim = platform::kEnvDelim,
|
||||
bool Verbose = false);
|
||||
|
||||
|
||||
///\brief Look for given file that can be reachable from current working
|
||||
/// directory or any user supplied include paths in Args. This is useful
|
||||
/// to look for a file (precompiled header) before a Preprocessor instance
|
||||
/// has been created.
|
||||
///
|
||||
/// \param [in] Args - The argv vector to look for '-I' & '/I' flags
|
||||
/// \param [in/out] File - File to look for, may mutate to an absolute path
|
||||
/// \param [in] FM - File manger to resolve current dir with (can be null)
|
||||
/// \param [in] FileType - File type for logging or nullptr for no logging
|
||||
///
|
||||
/// \return true if File is reachable and is a regular file
|
||||
///
|
||||
bool LookForFile(const std::vector<const char*>& Args, std::string& File,
|
||||
const clang::FileManager* FM = nullptr,
|
||||
const char* FileType = nullptr);
|
||||
|
||||
///\brief Adds multiple include paths separated by a delimter into the
|
||||
/// given HeaderSearchOptions. This adds the paths but does no further
|
||||
/// processing. See Interpreter::AddIncludePaths or CIFactory::createCI
|
||||
|
@ -666,44 +666,48 @@ static void stringifyPreprocSetting(PreprocessorOptions& PPOpts,
|
||||
std::unique_ptr<CompilerInstance> CI(new CompilerInstance());
|
||||
CI->createFileManager();
|
||||
|
||||
llvm::StringRef PCHFileName
|
||||
std::string& PCHFileName
|
||||
= Invocation->getPreprocessorOpts().ImplicitPCHInclude;
|
||||
if (!PCHFileName.empty()) {
|
||||
// Load target options etc from PCH.
|
||||
struct PCHListener: public ASTReaderListener {
|
||||
CompilerInvocation& m_Invocation;
|
||||
if (cling::utils::LookForFile(argvCompile, PCHFileName,
|
||||
&CI->getFileManager(),
|
||||
COpts.Verbose ? "Precompiled header" : nullptr)) {
|
||||
// Load target options etc from PCH.
|
||||
struct PCHListener: public ASTReaderListener {
|
||||
CompilerInvocation& m_Invocation;
|
||||
|
||||
PCHListener(CompilerInvocation& I): m_Invocation(I) {}
|
||||
PCHListener(CompilerInvocation& I): m_Invocation(I) {}
|
||||
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool /*Complain*/,
|
||||
bool /*AllowCompatibleDifferences*/) override {
|
||||
*m_Invocation.getLangOpts() = LangOpts;
|
||||
return false;
|
||||
}
|
||||
bool ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
bool /*Complain*/,
|
||||
bool /*AllowCompatibleDifferences*/) override {
|
||||
*m_Invocation.getLangOpts() = LangOpts;
|
||||
return false;
|
||||
}
|
||||
bool ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
bool /*Complain*/,
|
||||
bool /*AllowCompatibleDifferences*/) override {
|
||||
m_Invocation.getTargetOpts() = TargetOpts;
|
||||
return false;
|
||||
}
|
||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||
bool /*Complain*/,
|
||||
std::string &/*SuggestedPredefines*/) override {
|
||||
// Import selected options, e.g. don't overwrite ImplicitPCHInclude.
|
||||
PreprocessorOptions& myPP = m_Invocation.getPreprocessorOpts();
|
||||
insertBehind(myPP.Macros, PPOpts.Macros);
|
||||
insertBehind(myPP.Includes, PPOpts.Includes);
|
||||
insertBehind(myPP.MacroIncludes, PPOpts.MacroIncludes);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PCHListener listener(*Invocation);
|
||||
ASTReader::readASTFileControlBlock(PCHFileName,
|
||||
CI->getFileManager(),
|
||||
CI->getPCHContainerReader(),
|
||||
false /*FindModuleFileExtensions*/,
|
||||
listener);
|
||||
m_Invocation.getTargetOpts() = TargetOpts;
|
||||
return false;
|
||||
}
|
||||
bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
|
||||
bool /*Complain*/,
|
||||
std::string &/*SuggestedPredefines*/) override {
|
||||
// Import selected options, e.g. don't overwrite ImplicitPCHInclude.
|
||||
PreprocessorOptions& myPP = m_Invocation.getPreprocessorOpts();
|
||||
insertBehind(myPP.Macros, PPOpts.Macros);
|
||||
insertBehind(myPP.Includes, PPOpts.Includes);
|
||||
insertBehind(myPP.MacroIncludes, PPOpts.MacroIncludes);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
PCHListener listener(*Invocation);
|
||||
ASTReader::readASTFileControlBlock(PCHFileName,
|
||||
CI->getFileManager(),
|
||||
CI->getPCHContainerReader(),
|
||||
false /*FindModuleFileExtensions*/,
|
||||
listener);
|
||||
}
|
||||
}
|
||||
|
||||
Invocation->getFrontendOpts().DisableFree = true;
|
||||
|
@ -9,9 +9,11 @@
|
||||
|
||||
#include "cling/Utils/Paths.h"
|
||||
#include "cling/Utils/Output.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Lex/HeaderSearchOptions.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
namespace cling {
|
||||
namespace utils {
|
||||
@ -150,6 +152,65 @@ void LogNonExistantDirectory(llvm::StringRef Path) {
|
||||
cling::log() << " ignoring nonexistent directory \"" << Path << "\"\n";
|
||||
}
|
||||
|
||||
static void LogFileStatus(const char* Prefix, const char* FileType,
|
||||
llvm::StringRef Path) {
|
||||
cling::log() << Prefix << " " << FileType << " '" << Path << "'\n";
|
||||
}
|
||||
|
||||
bool LookForFile(const std::vector<const char*>& Args, std::string& Path,
|
||||
const clang::FileManager* FM, const char* FileType) {
|
||||
if (llvm::sys::fs::is_regular_file(Path)) {
|
||||
if (FileType)
|
||||
LogFileStatus("Using", FileType, Path);
|
||||
return true;
|
||||
}
|
||||
if (FileType)
|
||||
LogFileStatus("Ignoring", FileType, Path);
|
||||
|
||||
SmallString<1024> FilePath;
|
||||
if (FM) {
|
||||
FilePath.assign(Path);
|
||||
if (FM->FixupRelativePath(FilePath) &&
|
||||
llvm::sys::fs::is_regular_file(FilePath)) {
|
||||
if (FileType)
|
||||
LogFileStatus("Using", FileType, FilePath.str());
|
||||
Path = FilePath.str();
|
||||
return true;
|
||||
}
|
||||
// Don't write same same log entry twice when FilePath == Path
|
||||
if (FileType && !FilePath.str().equals(Path))
|
||||
LogFileStatus("Ignoring", FileType, FilePath);
|
||||
}
|
||||
else if (llvm::sys::path::is_absolute(Path))
|
||||
return false;
|
||||
|
||||
for (std::vector<const char*>::const_iterator It = Args.begin(),
|
||||
End = Args.end(); It < End; ++It) {
|
||||
const char* Arg = *It;
|
||||
// TODO: Suppport '-iquote' and MSVC equivalent
|
||||
if (!::strncmp("-I", Arg, 2) || !::strncmp("/I", Arg, 2)) {
|
||||
if (!Arg[2]) {
|
||||
if (++It >= End)
|
||||
break;
|
||||
FilePath.assign(*It);
|
||||
}
|
||||
else
|
||||
FilePath.assign(Arg + 2);
|
||||
|
||||
llvm::sys::path::append(FilePath, Path.c_str());
|
||||
if (llvm::sys::fs::is_regular_file(FilePath)) {
|
||||
if (FileType)
|
||||
LogFileStatus("Using", FileType, FilePath.str());
|
||||
Path = FilePath.str();
|
||||
return true;
|
||||
}
|
||||
if (FileType)
|
||||
LogFileStatus("Ignoring", FileType, FilePath);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SplitPaths(llvm::StringRef PathStr,
|
||||
llvm::SmallVectorImpl<llvm::StringRef>& Paths,
|
||||
SplitMode Mode, llvm::StringRef Delim, bool Verbose) {
|
||||
|
@ -1,6 +1,10 @@
|
||||
// RUN: mkdir -p %T/Rel/Path
|
||||
// RUN: rm -f CompGen.h.pch
|
||||
// RUN: rm -f %T/Rel/Path/Relative.pch
|
||||
// RUN: clang -x c++-header -fexceptions -fcxx-exceptions -std=c++14 -pthread %S/Inputs/CompGen.h -o CompGen.h.pch
|
||||
// RUN: clang -x c++-header -fexceptions -fcxx-exceptions -std=c++14 -pthread %S/Inputs/CompGen.h -o %T/Rel/Path/Relative.pch
|
||||
// RUN: cat %s | %cling -I%p -Xclang -include-pch -Xclang CompGen.h.pch 2>&1 | FileCheck %s
|
||||
// RUN: cat %s | %cling -I%p -I%T/Rel/Path -include-pch Relative.pch 2>&1 | FileCheck %s
|
||||
|
||||
//.storeState "a"
|
||||
.x TriggerCompGen.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user