4 #pragma warning ( disable : 4273 )
14 #pragma warning(disable:279)
16 #if !defined(_WIN32) && !defined(_MSC_VER)
21 #include "boost/program_options.hpp"
23 #if defined(__ICC) && !defined(_WIN32) && (_MSC_VER == 0)
28 #include "boost/filesystem/operations.hpp"
29 #include "boost/filesystem/exception.hpp"
30 #include "boost/filesystem/convenience.hpp"
31 #include "boost/algorithm/string/split.hpp"
32 #include "boost/algorithm/string/classification.hpp"
33 #include "boost/algorithm/string/trim.hpp"
34 #include "boost/algorithm/string/case_conv.hpp"
35 #include "boost/algorithm/string/replace.hpp"
36 #include "boost/format.hpp"
37 #include "boost/regex.hpp"
72 namespace po = boost::program_options;
73 namespace fs = boost::filesystem;
80 typedef std::vector<std::string>
Strings_t;
84 const std::string py_tab =
" ";
88 const boost::regex pythonIdentifier(
"^[a-zA-Z_][a-zA-Z0-9_]*$");
122 const string& outputDirName ) :
123 m_pkgName ( pkgName ),
124 m_outputDirName ( outputDirName ),
126 m_importGaudiHandles( false ),
146 m_configurable[
"DefaultName" ] = defaultName;
152 m_configurable[
"Algorithm" ] = cfgAlgorithm;
158 m_configurable[
"AlgTool" ] = cfgAlgTool;
164 m_configurable[
"Auditor" ] = cfgAuditor;
170 m_configurable[
"Service" ] = cfgService;
171 m_configurable[
"ApplicationMgr" ] = cfgService;
175 int genComponent(
const std::string& libName,
176 const std::string& componentName,
177 const std::string& componentType,
178 const vector<Property*>& properties );
180 void genHeader( std::ostream& pyOut, std::ostream& dbOut );
182 std::ostream& dbOut ) {
183 pyOut << m_pyBuf.str() << flush;
184 dbOut << m_dbBuf.str() << flush;
186 void genTrailer( std::ostream& pyOut,
187 std::ostream& dbOut );
190 void pythonizeValue(
const Property* prop,
195 void pythonizeName(
string& name );
208 std::string userModule;
211 po::options_description
generic(
"Generic options");
212 generic.add_options()
214 "produce this help message")
217 "name of the package for which we create the configurables file")
218 (
"input-libraries,i",
220 "libraries to extract the component configurables from")
223 "path to the cfg file holding the description of the Configurable base "
224 "classes, the python module holding the Configurable definitions, etc...")
226 po::value<string>()->default_value(
"../genConf"),
227 "output directory for genconf files.")
229 po::value<int>()->default_value(0),
232 po::value< Strings_t >()->composing(),
233 "preloading library")
236 "user-defined module to be imported by the genConf-generated one")
238 "do not generate the (empty) __init__.py")
243 po::options_description config(
"Configuration");
245 (
"configurable-module",
246 po::value<string>()->default_value(
"AthenaCommon"),
247 "Name of the module holding the configurable classes")
248 (
"configurable-default-name",
249 po::value<string>()->default_value(
"Configurable.DefaultName"),
250 "Default name for the configurable instance")
251 (
"configurable-algorithm",
252 po::value<string>()->default_value(
"ConfigurableAlgorithm"),
253 "Name of the configurable base class for Algorithm components")
254 (
"configurable-algtool",
255 po::value<string>()->default_value(
"ConfigurableAlgTool"),
256 "Name of the configurable base class for AlgTool components")
257 (
"configurable-auditor",
258 po::value<string>()->default_value(
"ConfigurableAuditor"),
259 "Name of the configurable base class for Auditor components")
260 (
"configurable-service",
261 po::value<string>()->default_value(
"ConfigurableService"),
262 "Name of the configurable base class for Service components")
265 po::options_description cmdline_options;
266 cmdline_options.add(
generic).add(config);
268 po::options_description config_file_options;
269 config_file_options.add(config);
271 po::options_description visible(
"Allowed options");
272 visible.add(
generic).add(config);
274 po::variables_map vm;
277 po::store( po::command_line_parser(argc, argv).
278 options(cmdline_options).run(),
284 if( vm.count(
"input-cfg") ) {
285 string cfgFileName = vm[
"input-cfg"].as<
string>();
286 cfgFileName = fs::system_complete(
fs::path( cfgFileName ) ).string();
287 std::ifstream ifs( cfgFileName.c_str() );
288 po::store( parse_config_file( ifs, config_file_options ), vm );
293 catch ( po::error& err ) {
294 cout <<
"ERROR: error detected while parsing command options: "<< err.what() << endl;
299 if( vm.count(
"help")) {
300 cout << visible << endl;
304 if( vm.count(
"package-name") ) {
305 pkgName = vm[
"package-name"].as<
string>();
308 cout <<
"ERROR: 'package-name' required" << endl;
309 cout << visible << endl;
313 if( vm.count(
"user-module") ) {
314 userModule = vm[
"user-module"].as<
string>();
315 cout <<
"INFO: will import user module " << userModule << endl;
318 if( vm.count(
"input-libraries") ) {
324 string tmp = vm[
"input-libraries"].as<
string>();
326 boost::split( inputLibs, tmp,
327 boost::is_any_of(
" "),
328 boost::token_compress_on );
332 libs.reserve( inputLibs.size() );
333 for ( Strings_t::const_iterator iLib = inputLibs.begin();
334 iLib != inputLibs.end();
336 std::string lib =
fs::path(*iLib).stem().string();
337 if ( 0 == lib.find(
"lib") ) {
342 std::find( libs.begin(), libs.end(), lib ) == libs.end() ) {
343 libs.push_back( lib );
346 if ( libs.empty() ) {
347 cout <<
"ERROR: input component library(ies) required !\n"
348 <<
"ERROR: 'input-libraries' argument was ["
349 << vm[
"input-libraries"].as<
string>()
356 cout <<
"ERROR: input component library(ies) required" << endl;
357 cout << visible << endl;
361 if( vm.count(
"output-dir") ) {
362 out = fs::system_complete(
fs::path( vm[
"output-dir"].as<string>() ) );
365 if ( vm.count(
"debug-level") ) {
369 if ( vm.count(
"load-library") ) {
371 for (Strings_t::const_iterator lLib=lLib_list.begin();
372 lLib != lLib_list.end();
378 cout <<
"WARNING: failed to load: "<< *lLib << endl;
384 if ( !fs::exists( out ) ) {
386 fs::create_directory(out);
388 catch ( fs::filesystem_error &err ) {
389 cout <<
"ERROR: error creating directory: "<< err.what() << endl;
394 cout <<
":::::: libraries : [ ";
395 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout,
" ") );
396 cout <<
"] ::::::" << endl;
400 py.setConfigurableDefaultName(vm[
"configurable-default-name"].as<string>());
401 py.setConfigurableAlgorithm (vm[
"configurable-algorithm"].as<string>());
402 py.setConfigurableAlgTool (vm[
"configurable-algtool"].as<string>());
403 py.setConfigurableAuditor (vm[
"configurable-auditor"].as<string>());
404 py.setConfigurableService (vm[
"configurable-service"].as<string>());
406 int sc = EXIT_FAILURE;
408 sc = py.genConfig( libs, userModule );
410 catch ( exception& e ) {
411 cout <<
"ERROR: Could not generate Configurable(s) !\n"
412 <<
"ERROR: Got exception: " << e.what() << endl;
416 if ( EXIT_SUCCESS == sc && ! vm.count(
"no-init")) {
418 fstream initPy( ( out /
fs::path(
"__init__.py" ) ).
string().c_str(),
419 std::ios_base::out|std::ios_base::trunc );
420 initPy <<
"## Hook for " << pkgName <<
" genConf module\n" << flush;
423 cout <<
":::::: libraries : [ ";
424 copy( libs.begin(), libs.end(), ostream_iterator<string>(cout,
" ") );
425 cout <<
"] :::::: [DONE]" << endl;
437 const Strings_t::const_iterator endLib = libs.end();
439 const std::string gaudiSvc =
"GaudiCoreSvc";
440 const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
444 cout <<
"ERROR: ApplicationMgr can not be created. Check environment" << endl;
450 Registry&
registry = Registry::instance();
452 std::set<std::string> bkgNames = registry.loadedFactories();
461 for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
463 std::cout <<
":::: processing library: " << *iLib <<
"..." << std::endl;
466 m_importGaudiHandles =
false;
479 std::set<std::string>
factories = registry.loadedFactories();
481 for ( std::set<std::string>::iterator it = factories.begin();
482 it != factories.end(); ++it ) {
483 const string ident = *it;
484 if ( bkgNames.find(ident) != bkgNames.end() ) {
486 cout <<
"\t==> skipping [" << ident <<
"]..." << endl;
491 const Registry::FactoryInfo info = registry.getInfo(*it);
492 const string rtype = info.rtype;
495 if (info.properties.find(
"ReflexName") != info.properties.end())
503 cout <<
"WARNING: library [" << *iLib <<
"] exposes factory ["
504 << ident <<
"] which is declared in ["
505 << DsoUtils::dsoName(info.ptr) <<
"] !!" << endl;
511 if ( ident ==
"ApplicationMgr" ) type =
"ApplicationMgr";
512 else if ( rtype ==
typeid(
IInterface*).name() ) type =
"IInterface";
513 else if ( rtype ==
typeid(
IAlgorithm*).name() ) type =
"Algorithm";
514 else if ( rtype ==
typeid(
IService* ).name() ) type =
"Service";
515 else if ( rtype ==
typeid(
IAlgTool* ).name() ) type =
"AlgTool";
516 else if ( rtype ==
typeid(
IAuditor* ).name() ) type =
"Auditor";
517 else if ( rtype ==
typeid(
IConverter*).name() ) type =
"Converter";
518 else if ( rtype ==
typeid(
DataObject*).name() ) type =
"DataObject";
519 else type =
"Unknown", known =
false;
524 if ( type ==
"IInterface" ) {
530 if ( type ==
"Converter" || type ==
"DataObject" ) {
537 <<
" Component [" << ident <<
"] is skipped !"
542 cout <<
" - component: " << info.className <<
" (";
543 if (info.className != name)
544 cout << name <<
": ";
545 cout << type <<
")" << endl;
547 string cname =
"DefaultName";
550 if ( type ==
"Algorithm" ) {
553 else if ( type ==
"Service") {
556 else if ( type ==
"AlgTool") {
557 prop =
SmartIF<IAlgTool>(AlgTool::Factory::create(ident, cname, type, dummySvc));
561 else if ( type ==
"Auditor") {
564 else if ( type ==
"ApplicationMgr") {
571 catch ( exception& e ) {
572 cout <<
"ERROR: Error instantiating " << name
573 <<
" from " << *iLib << endl;
574 cout <<
"ERROR: Got exception: " << e.what() << endl;
579 cout <<
"ERROR: Error instantiating " << name
580 <<
" from " << *iLib << endl;
585 if (genComponent( *iLib, name, type, prop->getProperties() )) {
590 cout <<
"ERROR: could not cast IInterface* object to an IProperty* !\n"
591 <<
"ERROR: return type from PluginSvc is [" << rtype <<
"]...\n"
592 <<
"ERROR: NO Configurable will be generated for ["
602 const std::string pyName = (
fs::path(m_outputDirName) /
603 fs::path(*iLib+
"Conf.py") ).
string();
604 const std::string dbName = (
fs::path(m_outputDirName) /
605 fs::path(*iLib+
".confdb") ).
string();
607 std::fstream py( pyName.c_str(),
608 std::ios_base::out|std::ios_base::trunc );
609 std::fstream db( dbName.c_str(),
610 std::ios_base::out|std::ios_base::trunc );
612 genHeader ( py, db );
613 if (!userModule.empty())
614 py <<
"from " << userModule <<
" import *" <<endl;
616 genTrailer( py, db );
623 return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
630 std::string::size_type pos = 0, nxtpos = 0;
633 while ( std::string::npos != pos ){
635 nxtpos = m_configurable[
"Module"].find_first_of(
',',pos);
638 mod = m_configurable[
"Module"].substr(pos,nxtpos-pos);
639 std::ostringstream
import;
644 if ( std::string::npos == nxtpos ) {
646 s <<
indent <<
import.str() <<
"\n" << flush;
647 pos = std::string::npos;
651 <<
indent << py_tab <<
import.str() <<
"\n"
652 <<
indent <<
"except ImportError:\n"
669 <<
"\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
670 if ( m_importGaudiHandles ) {
671 py <<
"from GaudiKernel.GaudiHandles import *\n";
674 genImport(py,
boost::format(
"from %1%.Configurable import *"));
677 db <<
"## -*- ascii -*- \n"
678 <<
"# db file automatically generated by genconf on: "
689 db <<
"## " << m_pkgName <<
"\n"
696 const std::string& componentName,
697 const std::string& componentType,
698 const vector<Property*>& properties )
701 string cname = componentName;
702 pythonizeName(cname);
705 PropertyDoc_t propDoc;
708 m_pyBuf <<
"class " << cname
709 <<
"( " << m_configurable[componentType] <<
" ) :"
711 m_pyBuf <<
" __slots__ = { \n";
712 for ( vector<Property*>::const_iterator it = properties.begin() ;
713 it != properties.end(); ++it ) {
715 const string pname = (*it)->name();
717 if (!boost::regex_match(pname, pythonIdentifier)) {
718 std::cout <<
"ERROR: invalid property name \"" << pname
719 <<
"\" in component " << cname
720 <<
" (invalid Python identifier)" << std::endl;
722 m_pyBuf <<
" #ERROR-invalid identifier '" << pname <<
"'\n"
727 string pvalue, ptype;
728 pythonizeValue( (*it), pvalue, ptype );
729 m_pyBuf <<
" '" << pname <<
"' : " << pvalue <<
", # " << ptype <<
"\n";
731 if ( (*it)->documentation() !=
"none" ) {
732 propDoc[
pname] = (*it)->documentation();
737 m_pyBuf <<
" _propertyDocDct = { \n";
738 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
739 iProp != propDoc.end();
741 m_pyBuf << std::setw(5)
742 <<
"'" << iProp->first <<
"' : "
743 <<
"\"\"\" " << iProp->second <<
" \"\"\",\n";
748 <<
" def __init__(self, name = " << m_configurable[
"DefaultName"]
750 <<
" super(" << cname <<
", self).__init__(name)\n"
751 <<
" for n,v in kwargs.items():\n"
752 <<
" setattr(self, n, v)\n"
753 <<
" def getDlls( self ):\n"
754 <<
" return '" << libName <<
"'\n"
755 <<
" def getType( self ):\n"
756 <<
" return '" << componentName <<
"'\n"
757 <<
" pass # class " << cname <<
"\n"
761 const string pyName = (
fs::path(m_outputDirName) /
762 fs::path(libName+
"Conf.py") ).
string();
767 << m_pkgName <<
"." << modName <<
" "
768 << libName <<
" " << cname
778 static string in(
"<>&*,: ().");
779 static string out(
"__rp__s___");
780 boost::algorithm::replace_all(name,
", ",
",");
781 for ( string::iterator
i = name.begin();
i != name.end(); ++
i ) {
782 if ( in.find(*
i) != string::npos ) *
i = out[in.find(*
i)];
788 string& pvalue,
string& ptype )
791 const std::string cvalue = p->
toString();
793 if ( ti ==
typeid(
bool) ) {
794 pvalue = ( cvalue ==
"0" || cvalue ==
"False" || cvalue ==
"false" )
799 else if ( ti ==
typeid(
char) || ti ==
typeid(
signed char)
800 || ti ==
typeid(
unsigned char) ||
801 ti ==
typeid(short) || ti ==
typeid(
unsigned short) ||
802 ti ==
typeid(int) || ti ==
typeid(
unsigned int) ||
803 ti ==
typeid(long) || ti ==
typeid(
unsigned long) ) {
807 else if ( ti ==
typeid(
long long) || ti ==
typeid(
unsigned long long) ) {
808 pvalue = cvalue +
"L";
811 else if ( ti ==
typeid(
float) || ti ==
typeid(double) ) {
813 pvalue = boost::to_lower_copy(cvalue);
814 if ( pvalue ==
"nan" ) {
815 pvalue =
"float('nan')";
816 std::cout <<
"WARNING: default value for ["
817 << p->
name() <<
"] is NaN !!"
819 }
else if ( std::string::npos == pvalue.find(
".") &&
820 std::string::npos == pvalue.find(
"e") ) {
821 pvalue = cvalue +
".0";
825 else if ( ti ==
typeid(
string) ) {
827 pvalue =
"'"+cvalue+
"'";
831 m_importGaudiHandles =
true;
837 ptype =
"GaudiHandle";
840 m_importGaudiHandles =
true;
846 ptype =
"GaudiHandleArray";
849 std::ostringstream v_str;
850 v_str.setf(std::ios::fixed);
852 pvalue = v_str.str();
866 propMgr->setProperty(
"JobOptionsType",
"NONE" );
867 propMgr->setProperty(
"AppName",
"");
868 propMgr->setProperty(
"OutputLevel",
"7");
const GaudiHandleArrayBase & value() const
int genConfig(const Strings_t &modules, const string &userModule)
main entry point of this class:
GAUDI_API long argc()
Number of arguments passed to the commandline (==numCmdLineArgs()); just to match argv call...
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
The data converters are responsible to translate data from one representation into another...
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
virtual std::string toString() const =0
value -> string
std::vector< std::string > Strings_t
const std::string & name() const
property name
-*- C++ -*- /////////////////////////////
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
int genComponent(const std::string &libName, const std::string &componentName, const std::string &componentType, const vector< Property * > &properties)
void pythonizeValue(const Property *prop, string &pvalue, string &ptype)
handle the "marshalling" of Properties
static Time current(void)
Returns the current time.
void pythonizeName(string &name)
Translates a valid C++ typename into a valid python one.
void setConfigurableDefaultName(const std::string &defaultName)
customize the default name for configurable instances
std::vector< fs::path > LibPathNames_t
void setConfigurableAlgTool(const std::string &cfgAlgTool)
customize the configurable base class for AlgTool component
void * ImageHandle
Definition of an image handle.
GaudiUtils::HashMap< std::string, std::string > m_configurable
Configurable customization.
stringstream m_pyBuf
buffer of auto-generated configurables
GAUDIPS_API Logger & logger()
Return the current logger instance.
void setConfigurableModule(const std::string &moduleName)
customize the Module name where configurable base classes are defined
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
int main(int argc, char **argv)
GAUDI_API ISvcLocator * svcLocator()
bool isValid() const
Allow for check if smart pointer is valid.
General service interface definition.
Definition of the basic interface.
virtual const std::string pythonRepr() const
Python representation of handle, i.e.
void genHeader(std::ostream &pyOut, std::ostream &dbOut)
stringstream m_dbBuf
buffer of generated configurables informations for the "Db" file The "Db" file is holding information...
configGenerator(const string &pkgName, const string &outputDirName)
The IAlgorithm is the interface implemented by the Algorithm base class.
void setConfigurableAlgorithm(const std::string &cfgAlgorithm)
customize the configurable base class for Algorithm component
GAUDI_API std::string path(const AIDA::IBaseHistogram *aida)
get the path in THS for AIDA histogram
Base class of array's of various gaudihandles.
string m_outputDirName
absolute path to the directory where genconf will store auto-generated files (Configurables and Confi...
Property base class allowing Property* collections to be "homogeneous".
virtual unsigned long release()=0
Release Interface instance.
void genImport(std::ostream &s, const boost::format &frmt, std::string indent)
bool m_importGaudiHandles
switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the compon...
void setConfigurableService(const std::string &cfgService)
customize the configurable base class for Service component
GAUDI_API const std::string & moduleName()
Get the name of the (executable/DLL) file without file-type.
const GaudiHandleBase & value() const
In-memory database of the loaded factories.
string m_pkgName
name of the package we are processing
virtual unsigned long addRef()=0
Increment the reference count of Interface instance.
static GAUDI_API void disableChecking()
const std::type_info * type_info() const
property type-info
void genTrailer(std::ostream &pyOut, std::ostream &dbOut)
GAUDI_API const std::string getLastErrorString()
Get last system error as string.
Base class to handles to be used in lieu of naked pointers to various Gaudi components.
Base class for all services.
A DataObject is the base class of any identifiable object on any data store.
The IAuditor is the interface implmented by the AlgAuditor base class.
void reset(TYPE *ptr=0)
Set the internal pointer to the passed one disposing of the old one.
virtual const std::string pythonRepr() const
Python representation of array of handles, i.e.
std::string libNativeName(const std::string &libName)
void genBody(std::ostream &pyOut, std::ostream &dbOut)
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
GAUDI_API IAppMgrUI * createApplicationMgr(const std::string &dllname, const std::string &factname)
virtual void toStream(std::ostream &out) const =0
value -> stream
GAUDI_API unsigned long loadDynamicLib(const std::string &name, ImageHandle *handle)
Load dynamic link library.
void setConfigurableAuditor(const std::string &cfgAuditor)
customize the configurable base class for AlgTool component