//--- Command main program----------------------------------------------------- int main ( int argc, char** argv ) //----------------------------------------------------------------------------- { fs::path pwd = fs::initial_path(); fs::path out; Strings_t libs; std::string pkgName; std::string userModule; // declare a group of options that will be allowed only on command line po::options_description generic("Generic options"); generic.add_options() ("help,h", "produce this help message") ("package-name,p", po::value<string>(), "name of the package for which we create the configurables file") ("input-libraries,i", po::value<string>(), "libraries to extract the component configurables from") ("input-cfg,c", po::value<string>(), "path to the cfg file holding the description of the Configurable base " "classes, the python module holding the Configurable definitions, etc...") ("output-dir,o", po::value<string>()->default_value("../genConf"), "output directory for genconf files.") ("debug-level,d", po::value<int>()->default_value(0), "debug level") ("load-library,l", po::value< Strings_t >()->composing(), "preloading library") ("user-module,m", po::value<string>(), "user-defined module to be imported by the genConf-generated one") ; // declare a group of options that will be allowed both on command line // _and_ in configuration file po::options_description config("Configuration"); config.add_options() ("configurable-module", po::value<string>()->default_value("AthenaCommon"), "Name of the module holding the configurable classes") ("configurable-default-name", po::value<string>()->default_value("Configurable.DefaultName"), "Default name for the configurable instance") ("configurable-algorithm", po::value<string>()->default_value("ConfigurableAlgorithm"), "Name of the configurable base class for Algorithm components") ("configurable-algtool", po::value<string>()->default_value("ConfigurableAlgTool"), "Name of the configurable base class for AlgTool components") ("configurable-auditor", po::value<string>()->default_value("ConfigurableAuditor"), "Name of the configurable base class for Auditor components") ("configurable-service", po::value<string>()->default_value("ConfigurableService"), "Name of the configurable base class for Service components") ; po::options_description cmdline_options; cmdline_options.add(generic).add(config); po::options_description config_file_options; config_file_options.add(config); po::options_description visible("Allowed options"); visible.add(generic).add(config); po::variables_map vm; try { po::store( po::command_line_parser(argc, argv). options(cmdline_options).run(), vm ); po::notify(vm); // try to read configuration from the optionally given configuration file if( vm.count("input-cfg") ) { string cfgFileName = vm["input-cfg"].as<string>(); cfgFileName = fs::system_complete( fs::path( cfgFileName ) ).string(); std::ifstream ifs( cfgFileName.c_str() ); po::store( parse_config_file( ifs, config_file_options ), vm ); } po::notify(vm); } catch ( po::error& err ) { cout << "ERR0R: error detected while parsing command options: "<< err.what() << endl; return EXIT_FAILURE; } //--- Process command options ----------------------------------------------- if( vm.count("help")) { cout << visible << endl; return EXIT_FAILURE; } if( vm.count("package-name") ) { pkgName = vm["package-name"].as<string>(); } else { cout << "ERROR: 'package-name' required" << endl; cout << visible << endl; return EXIT_FAILURE; } if( vm.count("user-module") ) { userModule = vm["user-module"].as<string>(); cout << "INFO: will import user module " << userModule << endl; } if( vm.count("input-libraries") ) { // re-shape the input arguments: // - removes spurious spaces, // - split into tokens. Strings_t inputLibs; { string tmp = vm["input-libraries"].as<string>(); boost::trim(tmp); boost::split( inputLibs, tmp, boost::is_any_of(" "), boost::token_compress_on ); } // libs.reserve( inputLibs.size() ); for ( Strings_t::const_iterator iLib = inputLibs.begin(); iLib != inputLibs.end(); ++iLib ) { std::string lib = fs::path(*iLib).stem().string(); if ( 0 == lib.find("lib") ) { lib = lib.substr(3); // For *NIX remove "lib" } // remove duplicates if ( !lib.empty() && std::find( libs.begin(), libs.end(), lib ) == libs.end() ) { libs.push_back( lib ); } } //> end loop over input-libraries if ( libs.empty() ) { cout << "ERROR: input component library(ies) required !\n" << "ERROR: 'input-libraries' argument was [" << vm["input-libraries"].as<string>() << "]" << endl; return EXIT_FAILURE; } } else { cout << "ERROR: input component library(ies) required" << endl; cout << visible << endl; return EXIT_FAILURE; } if( vm.count("output-dir") ) { out = fs::system_complete( fs::path( vm["output-dir"].as<string>() ) ); } if ( vm.count("debug-level") ) { PluginService::SetDebug( vm["debug-level"].as<int>() ); } if ( vm.count("load-library") ) { Strings_t lLib_list = vm["load-library"].as< Strings_t >(); for (Strings_t::const_iterator lLib=lLib_list.begin(); lLib != lLib_list.end(); ++lLib) { // load done through ROOT::Reflex helper class SharedLibrary tmplib(*lLib) ; tmplib.Load() ; } } if ( !fs::exists( out ) ) { try { fs::create_directory(out); } catch ( fs::filesystem_error &err ) { cout << "ERR0R: error creating directory: "<< err.what() << endl; return EXIT_FAILURE; } } cout << ":::::: libraries : [ "; copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") ); cout << "] ::::::" << endl; configGenerator py( pkgName, out.string() ); py.setConfigurableModule (vm["configurable-module"].as<string>()); py.setConfigurableDefaultName(vm["configurable-default-name"].as<string>()); py.setConfigurableAlgorithm (vm["configurable-algorithm"].as<string>()); py.setConfigurableAlgTool (vm["configurable-algtool"].as<string>()); py.setConfigurableAuditor (vm["configurable-auditor"].as<string>()); py.setConfigurableService (vm["configurable-service"].as<string>()); int sc = EXIT_FAILURE; try { sc = py.genConfig( libs, userModule ); } catch ( exception& e ) { cout << "ERROR: Could not generate Configurable(s) !\n" << "ERROR: Got exception: " << e.what() << endl; return EXIT_FAILURE; } if ( EXIT_SUCCESS == sc ) { // create an empty __init__.py file in the output dir fstream initPy( ( out / fs::path( "__init__.py" ) ).string().c_str(), std::ios_base::out|std::ios_base::trunc ); initPy << "## Hook for " << pkgName << " genConf module\n" << flush; } cout << ":::::: libraries : [ "; copy( libs.begin(), libs.end(), ostream_iterator<string>(cout, " ") ); cout << "] :::::: [DONE]" << endl; return sc; }
//----------------------------------------------------------------------------- int configGenerator::genConfig( const Strings_t& libs, const string& userModule ) //----------------------------------------------------------------------------- { //--- Disable checking StatusCode ------------------------------------------- StatusCode::disableChecking(); const Strings_t::const_iterator endLib = libs.end(); const std::string gaudiSvc = "GaudiCoreSvc"; const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib ); //--- Instantiate ApplicationMgr -------------------------------------------- if ( !isGaudiSvc && createAppMgr() ) { cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl; return EXIT_FAILURE; } //--- Iterate over component factories -------------------------------------- Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS); if ( !factories ) { cout << "ERROR: No PluginSvc factory namespace could be found" << endl; return EXIT_FAILURE; } ISvcLocator* svcLoc = Gaudi::svcLocator(); IInterface* dummySvc = new Service( "DummySvc", svcLoc ); dummySvc->addRef(); bool allGood = true; // iterate over all the requested libraries for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) { std::cout << ":::: processing library: " << *iLib << "..." << std::endl; // reset state m_importGaudiHandles = false; m_pyBuf.str(""); m_dbBuf.str(""); // Scan the pluginSvc namespace and store the "background" of already // alive components, so we can extract our signal later on set<string> bkgNames; if ( !isGaudiSvc ) { for ( Member_Iterator it = factories.FunctionMember_Begin(); it != factories.FunctionMember_End(); ++it ) { string ident = getId(*it); if ( PluginService::Debug() > 0 ) { cout << "::: " << ident << endl; } bkgNames.insert( ident ); } } const set<string>::const_iterator bkgNamesEnd = bkgNames.end(); //--- Load component library ---------------------------------------------- System::ImageHandle handle; unsigned long err = System::loadDynamicLib( *iLib, &handle ); if ( err != 1 ) { cout << "ERROR: " << System::getLastErrorString() << endl; allGood = false; continue; } for ( Member_Iterator it = factories.FunctionMember_Begin(); it != factories.FunctionMember_End(); ++it ) { const string ident = getId(*it); if ( bkgNames.find(ident) != bkgNamesEnd ) { if ( PluginService::Debug() > 0 ) { cout << "\t==> skipping [" << ident << "]..." << endl; } continue; } // Atlas contributed code (patch #1247) // Skip the generation of configurables if the component does not come // from the same library we are processing (i.e. we found a symbol that // is coming from a library loaded by the linker). // Windows implementation is empty. if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) { cout << "WARNING: library [" << *iLib << "] requested factory " << "from another library [" << DsoUtils::dsoName(*it) << "]" << " ==> [" << ident << "] !!" << endl; continue; } const string rtype = it->TypeOf().ReturnType().Name(); string type; bool known = true; if ( ident == "ApplicationMgr" ) type = "ApplicationMgr"; else if ( rtype == "IInterface*" ) type = "IInterface"; else if ( rtype == "IAlgorithm*" ) type = "Algorithm"; else if ( rtype == "IService*" ) type = "Service"; else if ( rtype == "IAlgTool*" ) type = "AlgTool"; else if ( rtype == "IAuditor*" ) type = "Auditor"; else if ( rtype == "IConverter*" ) type = "Converter"; else if ( rtype == "DataObject*" ) type = "DataObject"; else type = "Unknown", known = false; string name = ident; // handle possible problems with templated components boost::trim(name); cout << " - component: " << name << endl; if ( type == "IInterface" ) { /// not enough information... /// skip it continue; } if ( type == "Converter" || type == "DataObject" ) { /// no Properties, so don't bother create Configurables... continue; } //if ( type == "ApplicationMgr" ) { /// @FIXME: no Configurable for this component. yet... /// continue; //} if ( !known ) { cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n" << "WARNING: component [" << ident << "] is skipped !" << endl; allGood = false; continue; } string cname = "DefaultName"; vector<void*> args; args.reserve( 3 ); if ( type == "AlgTool" ) { args.resize( 3 ); args[0] = &cname; args[1] = &type; args[2] = dummySvc; } else { args.resize( 2 ); args[0] = &cname; args[1] = svcLoc; } IProperty* prop = 0; try { if ( type == "Algorithm" ) { prop = makeInstance<IAlgorithm>(*it,args); } else if ( type == "Service") { prop = makeInstance<IService>(*it,args); } else if ( type == "AlgTool") { prop = makeInstance<IAlgTool>(*it,args); } else if ( type == "Auditor") { prop = makeInstance<IAuditor>(*it,args); } else if ( type == "ApplicationMgr") { //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop)); svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop)); } else { prop = makeInstance<IInterface>(*it,args); } } catch ( exception& e ) { cout << "ERROR: Error instantiating " << name << " from " << *iLib << endl; cout << "ERROR: Got exception: " << e.what() << endl; allGood = false; continue; } catch ( ... ) { cout << "ERROR: Error instantiating " << name << " from " << *iLib << endl; allGood = false; continue; } if( prop ) { if (genComponent( *iLib, name, type, prop->getProperties() )) { allGood = false; } prop->release(); } else { cout << "ERROR: could not cast IInterface* object to an IProperty* !\n" << "ERROR: return type from PluginSvc is [" << rtype << "]...\n" << "ERROR: NO Configurable will be generated for [" << name << "] !" << endl; allGood = false; } } //> end loop over factories /// /// write-out files for this library /// const std::string pyName = ( fs::path(m_outputDirName) / fs::path(*iLib+"Conf.py") ).string(); const std::string dbName = ( fs::path(m_outputDirName) / fs::path(*iLib+"_confDb.py") ).string(); std::fstream py( pyName.c_str(), std::ios_base::out|std::ios_base::trunc ); std::fstream db( dbName.c_str(), std::ios_base::out|std::ios_base::trunc ); genHeader ( py, db ); if (!userModule.empty()) py << "from " << userModule << " import *" <<endl; genBody ( py, db ); genTrailer( py, db ); } //> end loop over libraries dummySvc->release(); dummySvc = 0; return allGood ? EXIT_SUCCESS : EXIT_FAILURE; }
//----------------------------------------------------------------------------- int configGenerator::genConfig( const Strings_t& libs, const string& userModule ) //----------------------------------------------------------------------------- { //--- Disable checking StatusCode ------------------------------------------- StatusCode::disableChecking(); const Strings_t::const_iterator endLib = libs.end(); const std::string gaudiSvc = "GaudiCoreSvc"; const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib ); //--- Instantiate ApplicationMgr -------------------------------------------- if ( !isGaudiSvc && createAppMgr() ) { cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl; return EXIT_FAILURE; } //--- Iterate over component factories -------------------------------------- using Gaudi::PluginService::Details::Registry; Registry& registry = Registry::instance(); std::set<std::string> bkgNames = registry.loadedFactories(); ISvcLocator* svcLoc = Gaudi::svcLocator(); IInterface* dummySvc = new Service( "DummySvc", svcLoc ); dummySvc->addRef(); bool allGood = true; // iterate over all the requested libraries for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) { std::cout << ":::: processing library: " << *iLib << "..." << std::endl; // reset state m_importGaudiHandles = false; m_pyBuf.str(""); m_dbBuf.str(""); //--- Load component library ---------------------------------------------- System::ImageHandle handle; unsigned long err = System::loadDynamicLib( *iLib, &handle ); if ( err != 1 ) { cout << "ERROR: " << System::getLastErrorString() << endl; allGood = false; continue; } std::set<std::string> factories = registry.loadedFactories(); for ( std::set<std::string>::iterator it = factories.begin(); it != factories.end(); ++it ) { const string ident = *it; if ( bkgNames.find(ident) != bkgNames.end() ) { if ( Gaudi::PluginService::Details::logger().level() <= 1 ) { cout << "\t==> skipping [" << ident << "]..." << endl; } continue; } const Registry::FactoryInfo info = registry.getInfo(*it); const string rtype = info.rtype; // do not generate configurables for the Reflex-compatible aliases if (info.properties.find("ReflexName") != info.properties.end()) continue; // Atlas contributed code (patch #1247) // Skip the generation of configurables if the component does not come // from the same library we are processing (i.e. we found a symbol that // is coming from a library loaded by the linker). if ( !DsoUtils::inDso( info.ptr, DsoUtils::libNativeName(*iLib) ) ) { cout << "WARNING: library [" << *iLib << "] exposes factory [" << ident << "] which is declared in [" << DsoUtils::dsoName(info.ptr) << "] !!" << endl; continue; } string type; bool known = true; if ( ident == "ApplicationMgr" ) type = "ApplicationMgr"; else if ( rtype == typeid(IInterface*).name() ) type = "IInterface"; else if ( rtype == typeid(IAlgorithm*).name() ) type = "Algorithm"; else if ( rtype == typeid(IService* ).name() ) type = "Service"; else if ( rtype == typeid(IAlgTool* ).name() ) type = "AlgTool"; else if ( rtype == typeid(IAuditor* ).name() ) type = "Auditor"; else if ( rtype == typeid(IConverter*).name() ) type = "Converter"; else if ( rtype == typeid(DataObject*).name() ) type = "DataObject"; else type = "Unknown", known = false; string name = ident; // handle possible problems with templated components boost::trim(name); if ( type == "IInterface" ) { /// not enough information... /// skip it continue; } if ( type == "Converter" || type == "DataObject" ) { /// no Properties, so don't bother create Configurables... continue; } if ( !known ) { cout << "WARNING: Unknown (return) type [" << System::typeinfoName(rtype.c_str()) << "] !!" << " Component [" << ident << "] is skipped !" << endl; continue; } cout << " - component: " << info.className << " ("; if (info.className != name) cout << name << ": "; cout << type << ")" << endl; string cname = "DefaultName"; SmartIF<IProperty> prop; try { if ( type == "Algorithm" ) { prop = SmartIF<IAlgorithm>(Algorithm::Factory::create(ident, cname, svcLoc)); } else if ( type == "Service") { prop = SmartIF<IService>(Service::Factory::create(ident, cname, svcLoc)); } else if ( type == "AlgTool") { prop = SmartIF<IAlgTool>(AlgTool::Factory::create(ident, cname, type, dummySvc)); // FIXME: AlgTool base class increase artificially by 1 the refcount. prop->release(); } else if ( type == "Auditor") { prop = SmartIF<IAuditor>(Auditor::Factory::create(ident, cname, svcLoc)); } else if ( type == "ApplicationMgr") { prop = SmartIF<ISvcLocator>(svcLoc); } else { continue; // unknown } } catch ( exception& e ) { cout << "ERROR: Error instantiating " << name << " from " << *iLib << endl; cout << "ERROR: Got exception: " << e.what() << endl; allGood = false; continue; } catch ( ... ) { cout << "ERROR: Error instantiating " << name << " from " << *iLib << endl; allGood = false; continue; } if( prop ) { if (genComponent( *iLib, name, type, prop->getProperties() )) { allGood = false; } prop.reset(); } else { cout << "ERROR: could not cast IInterface* object to an IProperty* !\n" << "ERROR: return type from PluginSvc is [" << rtype << "]...\n" << "ERROR: NO Configurable will be generated for [" << name << "] !" << endl; allGood = false; } } //> end loop over factories /// /// write-out files for this library /// const std::string pyName = ( fs::path(m_outputDirName) / fs::path(*iLib+"Conf.py") ).string(); const std::string dbName = ( fs::path(m_outputDirName) / fs::path(*iLib+".confdb") ).string(); std::fstream py( pyName.c_str(), std::ios_base::out|std::ios_base::trunc ); std::fstream db( dbName.c_str(), std::ios_base::out|std::ios_base::trunc ); genHeader ( py, db ); if (!userModule.empty()) py << "from " << userModule << " import *" <<endl; genBody ( py, db ); genTrailer( py, db ); } //> end loop over libraries dummySvc->release(); dummySvc = 0; return allGood ? EXIT_SUCCESS : EXIT_FAILURE; }