diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index ee5e2fa8fd57c..9dc24e3f17865 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -2035,6 +2035,7 @@ void TROOT::InitInterpreter() // Enable autoloading fInterpreter->EnableAutoLoading(); + fInterpreter->SetupModules(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/meta/inc/TInterpreter.h b/core/meta/inc/TInterpreter.h index 999439b08f154..1b9297fdfbb6a 100644 --- a/core/meta/inc/TInterpreter.h +++ b/core/meta/inc/TInterpreter.h @@ -162,6 +162,7 @@ class TInterpreter : public TNamed { void (*histaddFunc)(const char* line)) = 0; virtual void Reset() = 0; virtual void ResetAll() = 0; + virtual bool SetupModules() = 0; virtual void ResetGlobals() = 0; virtual void ResetGlobalVar(void *obj) = 0; virtual void RewindDictionary() = 0; diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 09c01e6795d38..073c8964bc6e7 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -3768,6 +3768,12 @@ void TCling::UpdateListOfDataMembers(TClass* cl) const { } +bool TCling::SetupModules() { + if (!fInterpreter->getCI()->getLangOpts().Modules) + return false; + return fInterpreter->setupModules(); +} + //////////////////////////////////////////////////////////////////////////////// /// Create list of pointers to method arguments for TMethod m. diff --git a/core/metacling/src/TCling.h b/core/metacling/src/TCling.h index c9c2aaf7c56b7..519f7ede1c798 100644 --- a/core/metacling/src/TCling.h +++ b/core/metacling/src/TCling.h @@ -234,6 +234,7 @@ class TCling : public TInterpreter { void CreateListOfMethodArgs(TFunction* m) const; void UpdateListOfMethods(TClass* cl) const; void UpdateListOfDataMembers(TClass* cl) const; + virtual bool SetupModules(); virtual DeclId_t GetDataMember(ClassInfo_t *cl, const char *name) const; virtual DeclId_t GetDataMemberAtAddr(const void *addr) const; diff --git a/interpreter/cling/include/cling/Interpreter/Interpreter.h b/interpreter/cling/include/cling/Interpreter/Interpreter.h index 0c23a90519130..5f677a7d3ea29 100644 --- a/interpreter/cling/include/cling/Interpreter/Interpreter.h +++ b/interpreter/cling/include/cling/Interpreter/Interpreter.h @@ -648,6 +648,8 @@ namespace cling { int getDefaultOptLevel() const { return m_OptLevel; } void setDefaultOptLevel(int optLevel) { m_OptLevel = optLevel; } + bool setupModules(); + clang::CompilerInstance* getCI() const; clang::CompilerInstance* getCIOrNull() const; clang::Sema& getSema() const; diff --git a/interpreter/cling/lib/Interpreter/Interpreter.cpp b/interpreter/cling/lib/Interpreter/Interpreter.cpp index 04073542f8c76..2b2a36b13fd6c 100644 --- a/interpreter/cling/lib/Interpreter/Interpreter.cpp +++ b/interpreter/cling/lib/Interpreter/Interpreter.cpp @@ -60,6 +60,9 @@ #include #include +#include +#include +#include using namespace clang; @@ -1473,6 +1476,78 @@ namespace cling { m_DynamicLookupEnabled = value; } + bool Interpreter::setupModules() { + clang::CompilerInstance* CI = getCI(); + std::stringstream declarations; + if (CI->getLangOpts().Modules && CI->getLangOpts().CurrentModule.empty()) { + + clang::HeaderSearch &headerSearch = CI->getPreprocessor().getHeaderSearchInfo(); + clang::ModuleMap &moduleMap = headerSearch.getModuleMap(); + + llvm::SetVector modules; + auto& PP = getParser().getPreprocessor(); + + for (auto MI = moduleMap.module_begin(), end = moduleMap.module_end(); MI != end; MI++) { + clang::Module* Module = MI->second; + HeaderSearchOptions &HSOpts = + PP.getHeaderSearchInfo().getHeaderSearchOpts(); + + std::string ModuleFileName; + bool LoadFromPrebuiltModulePath = false; + // We try to load the module from the prebuilt module paths. If not + // successful, we then try to find it in the module cache. + if (!HSOpts.PrebuiltModulePaths.empty()) { + // Load the module from the prebuilt module path. + ModuleFileName = PP.getHeaderSearchInfo().getModuleFileName( + Module->Name, "", /*UsePrebuiltPath*/ true); + if (!ModuleFileName.empty()) + LoadFromPrebuiltModulePath = true; + } + if (!LoadFromPrebuiltModulePath && Module) { + // Load the module from the module cache. + ModuleFileName = PP.getHeaderSearchInfo().getModuleFileName(Module); + } + bool Exists = false; + { + std::ifstream f(ModuleFileName); + Exists = f.good(); + } + if (Exists) + modules.insert(Module); + } + + for (size_t i = 0; i < modules.size(); ++i) { + clang::Module *M = modules[i]; + for (clang::Module *subModule : M->submodules()) modules.insert(subModule); + } + + // Now we collect all header files from the previously collected modules. + std::set moduleHeaders; + for (clang::Module *module : modules) { + for (int i = 0; i < 4; i++) { + auto &headerList = module->Headers[i]; + for (const clang::Module::Header &moduleHeader : headerList) { + moduleHeaders.insert(moduleHeader.NameAsWritten); + } + } + } + + for (StringRef H : moduleHeaders) { + if (H == "GL/glew.h") + continue; + if (H == "GL/glxew.h") + continue; + if (H.endswith(".inc")) + continue; + if (H == "TException.h") + continue; + declarations << "#include \"" << H.str() << "\"\n"; + } + } + + return declare(declarations.str()) == CompilationResult::kSuccess; + } + Interpreter::ExecutionResult Interpreter::executeTransaction(Transaction& T) { assert(!isInSyntaxOnlyMode() && "Running on what?");