diff --git a/CMakeLists.txt b/CMakeLists.txt index 957825e88ddac..1ddabfa148268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,7 +343,7 @@ endif() if(runtime_cxxmodules) # Dummy target that does nothing, we don't need a PCH for modules. - add_custom_target(onepcm) + add_custom_target(onepcm DEPENDS TreePlayer TMVA Graf) else() add_custom_command(OUTPUT etc/allDict.cxx.pch COMMAND ${CMAKE_COMMAND} -E env ROOTIGNOREPREFIX=1 ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/etc/dictpch/makepch.py etc/allDict.cxx.pch ${__allIncludes} -I${CMAKE_BINARY_DIR}/include diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 551386c572ff9..b053b82e9ff33 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -1088,8 +1088,9 @@ inline bool TCling::TUniqueString::Append(const std::string& str) return notPresent; } +//////////////////////////////////////////////////////////////////////////////// ///\returns true if the module was loaded. -static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp) { +static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp, bool Complain = true) { clang::CompilerInstance &CI = *interp.getCI(); assert(CI.getLangOpts().Modules && "Function only relevant when C++ modules are turned on!"); @@ -1103,57 +1104,34 @@ static bool LoadModule(const std::string &ModuleName, cling::Interpreter &interp clang::IdentifierInfo *II = PP.getIdentifierInfo(M->Name); SourceLocation ValidLoc = M->DefinitionLoc; bool success = !CI.getSema().ActOnModuleImport(ValidLoc, ValidLoc, std::make_pair(II, ValidLoc)).isInvalid(); - // Also make the module visible in the preprocessor to export its macros. - PP.makeModuleVisible(M, ValidLoc); - return success; + if (success) { + // Also make the module visible in the preprocessor to export its macros. + PP.makeModuleVisible(M, ValidLoc); + return success; + } + if (Complain) { + if (M->IsSystem) + Error("TCling::LoadModule", "Module %s failed to load", M->Name.c_str()); + else + Info("TCling::LoadModule", "Module %s failed to load", M->Name.c_str()); + } } + if (Complain) + Error ("TCling::LoadModule", "Module %s not found!", ModuleName.c_str()); return false; } //////////////////////////////////////////////////////////////////////////////// -/// Loads the basic C++ modules that we require to run any ROOT program. -/// This is just supposed to make the declarations in their headers available -/// to the interpreter. -static void LoadCoreModules(cling::Interpreter &interp) +/// Loads the C++ modules that we require to run any ROOT program. This is just +/// supposed to make a C++ module from a modulemap available to the interpreter. +static void LoadModules(const std::vector &modules, cling::Interpreter &interp) { - clang::CompilerInstance &CI = *interp.getCI(); // Without modules, this function is just a no-op. - if (!CI.getLangOpts().Modules) + if (!interp.getCI()->getLangOpts().Modules) return; - clang::HeaderSearch &headerSearch = CI.getPreprocessor().getHeaderSearchInfo(); - clang::ModuleMap &moduleMap = headerSearch.getModuleMap(); - // List of core modules we can load, but it's ok if they are missing because - // the system doesn't have these modules. - if (clang::Module *LIBCM = moduleMap.findModule("libc")) - if (!LoadModule(LIBCM->Name, interp)) - Error("TCling::LoadCoreModules", "Cannot load module %s", LIBCM->Name.c_str()); - - if (clang::Module *STLM = moduleMap.findModule("stl")) - if (!LoadModule(STLM->Name, interp)) - Error("TCling::LoadCoreModules", "Cannot load module %s", STLM->Name.c_str()); - - // ROOT_Types is a module outside core because we need C and -no-rtti compatibility. - // Preload it as it is an integral part of module Core. - if (!LoadModule(moduleMap.findModule("ROOT_Types")->Name, interp)) - Error("TCling::LoadCoreModules", "Cannot load module ROOT_Types"); - - if (!LoadModule(moduleMap.findModule("Core")->Name, interp)) - Error("TCling::LoadCoreModules", "Cannot load module Core"); - - if (!LoadModule(moduleMap.findModule("RIO")->Name, interp)) - Error("TCling::LoadCoreModules", "Cannot load module RIO"); - - // Check that the gROOT macro was exported by any core module. - assert(interp.getMacro("gROOT") && "Couldn't load gROOT macro?"); - - // C99 decided that it's a very good idea to name a macro `I` (the letter I). - // This seems to screw up nearly all the template code out there as `I` is - // common template parameter name and iterator variable name. - // Let's follow the GCC recommendation and undefine `I` in case any of the - // core modules have defined it: - // https://www.gnu.org/software/libc/manual/html_node/Complex-Numbers.html - interp.declare("#ifdef I\n #undef I\n #endif\n"); + for (const auto &modName : modules) + LoadModule(modName, interp); } static bool FileExists(const char *file) @@ -1230,9 +1208,10 @@ TCling::TCling(const char *name, const char *title) // Activate C++ modules support. If we are running within rootcling, it's up // to rootcling to set this flag depending on whether it wants to produce - // C++ modules. + // C++ modules. Unless we are running in stage 2 where rootcling will require + // TCling's interpreter information. TString vfsArg; - if (useCxxModules && !fromRootCling) { + if (useCxxModules && getenv("ROOT_MODULES")) { // We only set this flag, rest is done by the CIFactory. interpArgs.push_back("-fmodules"); // We should never build modules during runtime, so let's enable the @@ -1292,6 +1271,20 @@ TCling::TCling(const char *name, const char *title) static llvm::raw_fd_ostream fMPOuts (STDOUT_FILENO, /*ShouldClose*/false); fMetaProcessor = new cling::MetaProcessor(*fInterpreter, fMPOuts); + // Setup core C++ modules if we have any to setup. + LoadModules({"libc", "stl", "ROOT_Types", "Core", "RIO"}, *fInterpreter); + + // Check that the gROOT macro was exported by any core module. + assert(fInterpreter->getMacro("gROOT") && "Couldn't load gROOT macro?"); + + // C99 decided that it's a very good idea to name a macro `I` (the letter I). + // This seems to screw up nearly all the template code out there as `I` is + // common template parameter name and iterator variable name. + // Let's follow the GCC recommendation and undefine `I` in case any of the + // core modules have defined it: + // https://www.gnu.org/software/libc/manual/html_node/Complex-Numbers.html + fInterpreter->declare("#ifdef I\n #undef I\n #endif\n"); + // For the list to also include string, we have to include it now. // rootcling does parts already if needed, e.g. genreflex does not want using // namespace std. @@ -1300,6 +1293,7 @@ TCling::TCling(const char *name, const char *title) "#include \n" "using std::string;"); } else { + LoadModules({"TreePlayer", "TMVA", "Graf"}, *fInterpreter); fInterpreter->declare("#include \"Rtypes.h\"\n" + gClassDefInterpMacro + "\n" + gInterpreterClassDef + "\n" @@ -1309,9 +1303,6 @@ TCling::TCling(const char *name, const char *title) "using namespace std;"); } - // Setup core C++ modules if we have any to setup. - LoadCoreModules(*fInterpreter); - // We are now ready (enough is loaded) to init the list of opaque typedefs. fNormalizedCtxt = new ROOT::TMetaUtils::TNormalizedCtxt(fInterpreter->getLookupHelper()); fLookupHelper = new ROOT::TMetaUtils::TClingLookupHelper(*fInterpreter, *fNormalizedCtxt, TClingLookupHelper__ExistingTypeCheck, TClingLookupHelper__AutoParse);