Skip to content

Commit dbe3755

Browse files
Teemperorvgvassilev
authored andcommitted
[cxxmodules] Load core C++ modules on startup
ROOT seems to expect hat the core modules declarations are already loaded on startup. Those modules include Core and RIO which are initailized very early on startup and reference each other. One problem that arises from this is that Core references RIO in TDirectory but RIO is loaded after Core, so while loading Core we fail reading RIO reflection information for TKey because we only have at this point only a forward declaration of the refernenced TKey class from RIO. One easy fix is to preload those two modules (which are anyway always loaded at some point) so that they can reference each other at this early stage of initialization.
1 parent 27e52a6 commit dbe3755

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

core/metacling/src/TCling.cxx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,77 @@ inline bool TCling::TUniqueString::Append(const std::string& str)
10871087
return notPresent;
10881088
}
10891089

1090+
////////////////////////////////////////////////////////////////////////////////
1091+
/// Loads the basic C++ modules that we require to run any ROOT program.
1092+
/// This is just supposed to make the declarations in their headers available
1093+
/// to the interpreter.
1094+
static void LoadCoreModules(cling::Interpreter &interp)
1095+
{
1096+
clang::CompilerInstance &CI = *interp.getCI();
1097+
// Without modules, this function is just a no-op.
1098+
if (!CI.getLangOpts().Modules)
1099+
return;
1100+
1101+
clang::HeaderSearch &headerSearch = CI.getPreprocessor().getHeaderSearchInfo();
1102+
clang::ModuleMap &moduleMap = headerSearch.getModuleMap();
1103+
// List of core modules we need to load.
1104+
std::vector<std::string> neededCoreModuleNames = {"Core", "RIO"};
1105+
std::vector<std::string> missingCoreModuleNames;
1106+
1107+
std::vector<clang::Module *> coreModules;
1108+
1109+
// Lookup the core modules in the modulemap by name.
1110+
for (std::string moduleName : neededCoreModuleNames) {
1111+
clang::Module *module = moduleMap.findModule(moduleName);
1112+
if (module) {
1113+
coreModules.push_back(module);
1114+
} else {
1115+
// If we can't find a module, we record that to report it later.
1116+
missingCoreModuleNames.push_back(moduleName);
1117+
}
1118+
}
1119+
1120+
// If we couldn't find some modules, so let's print an error message.
1121+
if (!missingCoreModuleNames.empty()) {
1122+
std::string MissingModuleNameList;
1123+
for (const std::string &name : missingCoreModuleNames) {
1124+
MissingModuleNameList += " " + name;
1125+
}
1126+
1127+
Error("TCling::LoadCoreModules",
1128+
"Internal error, couldn't find core "
1129+
"C++ modules in modulemap:%s\n",
1130+
MissingModuleNameList.c_str());
1131+
}
1132+
1133+
// Collect all submodules in the found core modules.
1134+
for (size_t i = 0; i < coreModules.size(); ++i) {
1135+
for (clang::Module *subModule : coreModules[i]->submodules())
1136+
coreModules.push_back(subModule);
1137+
}
1138+
1139+
// Now we collect all header files from the previously collected modules.
1140+
std::vector<StringRef> moduleHeaders;
1141+
for (clang::Module *module : coreModules) {
1142+
ROOT::TMetaUtils::foreachHeaderInModule(
1143+
*module, [&moduleHeaders](const clang::Module::Header &h) { moduleHeaders.push_back(h.NameAsWritten); });
1144+
}
1145+
1146+
// Turn the list of found header files into C++ code that includes all of
1147+
// them. This will be wrapped into an `import` declaration by clang, so we
1148+
// only make those modules available, not actually textually include those
1149+
// headers.
1150+
std::stringstream declarations;
1151+
for (StringRef H : moduleHeaders) {
1152+
declarations << "#include \"" << H.str() << "\"\n";
1153+
}
1154+
auto result = interp.declare(declarations.str());
1155+
1156+
if (result != cling::Interpreter::CompilationResult::kSuccess) {
1157+
Error("TCling::LoadCoreModules", "Couldn't parse core headers: %s\n", declarations.str().c_str());
1158+
}
1159+
}
1160+
10901161
////////////////////////////////////////////////////////////////////////////////
10911162
/// Initialize the cling interpreter interface.
10921163

@@ -1226,6 +1297,9 @@ TCling::TCling(const char *name, const char *title)
12261297
"using namespace std;");
12271298
}
12281299

1300+
// Setup core C++ modules if we have any to setup.
1301+
LoadCoreModules(*fInterpreter);
1302+
12291303
// We are now ready (enough is loaded) to init the list of opaque typedefs.
12301304
fNormalizedCtxt = new ROOT::TMetaUtils::TNormalizedCtxt(fInterpreter->getLookupHelper());
12311305
fLookupHelper = new ROOT::TMetaUtils::TClingLookupHelper(*fInterpreter, *fNormalizedCtxt, TClingLookupHelper__ExistingTypeCheck, TClingLookupHelper__AutoParse);

0 commit comments

Comments
 (0)