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"
39 #include <boost/log/core.hpp>
40 #include <boost/log/trivial.hpp>
41 #include <boost/log/expressions.hpp>
42 #include <boost/log/utility/setup/console.hpp>
43 #include <boost/log/utility/setup/common_attributes.hpp>
45 #include "GaudiKernel/System.h"
46 #include "GaudiKernel/ISvcLocator.h"
47 #include "GaudiKernel/IProperty.h"
48 #include "GaudiKernel/IAppMgrUI.h"
49 #include "GaudiKernel/IAlgorithm.h"
50 #include "GaudiKernel/IAlgTool.h"
51 #include "GaudiKernel/IAuditor.h"
52 #include "GaudiKernel/IAppMgrUI.h"
53 #include "GaudiKernel/Service.h"
54 #include "GaudiKernel/Bootstrap.h"
55 #include "GaudiKernel/SmartIF.h"
56 #include "GaudiKernel/HashMap.h"
57 #include "GaudiKernel/GaudiHandle.h"
58 #include "GaudiKernel/DataObjectDescriptor.h"
60 #include "GaudiKernel/Auditor.h"
61 #include "GaudiKernel/Service.h"
62 #include "GaudiKernel/AlgTool.h"
63 #include "GaudiKernel/Algorithm.h"
65 #include "GaudiKernel/Time.h"
67 #include <Gaudi/PluginService.h>
80 namespace fs = boost::filesystem;
82 #define LOG_ERROR BOOST_LOG_TRIVIAL(error)
83 #define LOG_WARNING BOOST_LOG_TRIVIAL(warning)
84 #define LOG_INFO BOOST_LOG_TRIVIAL(info)
85 #define LOG_DEBUG BOOST_LOG_TRIVIAL(debug)
92 typedef std::vector<std::string>
Strings_t;
96 const std::string py_tab =
" ";
100 const boost::regex pythonIdentifier(
"^[a-zA-Z_][a-zA-Z0-9_]*$");
136 const string& outputDirName ) :
137 m_pkgName ( pkgName ),
138 m_outputDirName ( outputDirName ),
140 m_importGaudiHandles( false ),
141 m_importDataObjectDescriptors( false ),
161 m_configurable[
"DefaultName" ] = defaultName;
167 m_configurable[
"Algorithm" ] = cfgAlgorithm;
173 m_configurable[
"AlgTool" ] = cfgAlgTool;
179 m_configurable[
"Auditor" ] = cfgAuditor;
185 m_configurable[
"Service" ] = cfgService;
186 m_configurable[
"ApplicationMgr" ] = cfgService;
190 int genComponent(
const std::string& libName,
191 const std::string& componentName,
192 const std::string& componentType,
195 void genHeader( std::ostream& pyOut, std::ostream& dbOut );
197 std::ostream& dbOut ) {
198 pyOut << m_pyBuf.str() << flush;
199 dbOut << m_dbBuf.str() << flush;
201 void genTrailer( std::ostream& pyOut,
202 std::ostream& dbOut );
205 void pythonizeValue(
const Property* prop,
210 void pythonizeName(
string&
name );
218 namespace keywords = boost::log::keywords;
219 namespace expr = boost::log::expressions;
221 logging::add_console_log
226 <<
"[" << std::setw(7) << std::left
227 << logging::trivial::severity
228 <<
"] " << expr::smessage
234 logging::trivial::severity >= level
245 ? boost::log::trivial::info
246 : boost::log::trivial::warning);
252 std::string userModule;
255 po::options_description
generic(
"Generic options");
256 generic.add_options()
258 "produce this help message")
261 "name of the package for which we create the configurables file")
262 (
"input-libraries,i",
264 "libraries to extract the component configurables from")
267 "path to the cfg file holding the description of the Configurable base "
268 "classes, the python module holding the Configurable definitions, etc...")
270 po::value<string>()->default_value(
"../genConf"),
271 "output directory for genconf files.")
273 po::value<int>()->default_value(0),
276 po::value< Strings_t >()->composing(),
277 "preloading library")
280 "user-defined module to be imported by the genConf-generated one")
282 "do not generate the (empty) __init__.py")
287 po::options_description
config(
"Configuration");
289 (
"configurable-module",
290 po::value<string>()->default_value(
"AthenaCommon"),
291 "Name of the module holding the configurable classes")
292 (
"configurable-default-name",
293 po::value<string>()->default_value(
"Configurable.DefaultName"),
294 "Default name for the configurable instance")
295 (
"configurable-algorithm",
296 po::value<string>()->default_value(
"ConfigurableAlgorithm"),
297 "Name of the configurable base class for Algorithm components")
298 (
"configurable-algtool",
299 po::value<string>()->default_value(
"ConfigurableAlgTool"),
300 "Name of the configurable base class for AlgTool components")
301 (
"configurable-auditor",
302 po::value<string>()->default_value(
"ConfigurableAuditor"),
303 "Name of the configurable base class for Auditor components")
304 (
"configurable-service",
305 po::value<string>()->default_value(
"ConfigurableService"),
306 "Name of the configurable base class for Service components")
309 po::options_description cmdline_options;
310 cmdline_options.add(
generic).add(config);
312 po::options_description config_file_options;
313 config_file_options.add(config);
315 po::options_description visible(
"Allowed options");
316 visible.add(
generic).add(config);
318 po::variables_map vm;
321 po::store( po::command_line_parser(argc, argv).
322 options(cmdline_options).run(),
328 if( vm.count(
"input-cfg") ) {
329 string cfgFileName = vm[
"input-cfg"].as<
string>();
330 cfgFileName = fs::system_complete(
fs::path( cfgFileName ) ).string();
331 std::ifstream ifs( cfgFileName );
332 po::store( parse_config_file( ifs, config_file_options ), vm );
337 catch ( po::error& err ) {
339 <<
"error detected while parsing command options: "
345 if( vm.count(
"help")) {
346 cout << visible << endl;
350 if( vm.count(
"package-name") ) {
351 pkgName = vm[
"package-name"].as<
string>();
355 cout << visible << endl;
359 if( vm.count(
"user-module") ) {
360 userModule = vm[
"user-module"].as<
string>();
361 LOG_INFO <<
"INFO: will import user module " << userModule;
364 if( vm.count(
"input-libraries") ) {
370 string tmp = vm[
"input-libraries"].as<
string>();
372 boost::split( inputLibs, tmp,
373 boost::is_any_of(
" "),
374 boost::token_compress_on );
378 libs.reserve( inputLibs.size() );
379 for ( Strings_t::const_iterator iLib = inputLibs.begin();
380 iLib != inputLibs.end();
382 std::string lib =
fs::path(*iLib).stem().string();
383 if ( 0 == lib.find(
"lib") ) {
388 std::find( libs.begin(), libs.end(), lib ) == libs.end() ) {
389 libs.push_back( lib );
392 if ( libs.empty() ) {
393 LOG_ERROR <<
"input component library(ies) required !\n";
394 LOG_ERROR <<
"'input-libraries' argument was ["
395 << vm[
"input-libraries"].as<
string>()
401 LOG_ERROR <<
"input component library(ies) required";
402 cout << visible << endl;
406 if( vm.count(
"output-dir") ) {
407 out = fs::system_complete(
fs::path( vm[
"output-dir"].as<string>() ) );
410 if ( vm.count(
"debug-level") ) {
414 if ( vm.count(
"load-library") ) {
416 for (Strings_t::const_iterator lLib=lLib_list.begin();
417 lLib != lLib_list.end();
429 if ( !fs::exists( out ) ) {
431 fs::create_directory(out);
433 catch ( fs::filesystem_error &err ) {
434 LOG_ERROR <<
"error creating directory: "<< err.what();
440 std::ostringstream
msg;
441 msg <<
":::::: libraries : [ ";
442 copy( libs.begin(), libs.end(), ostream_iterator<string>(
msg,
" ") );
449 py.setConfigurableDefaultName(vm[
"configurable-default-name"].as<string>());
450 py.setConfigurableAlgorithm (vm[
"configurable-algorithm"].as<string>());
451 py.setConfigurableAlgTool (vm[
"configurable-algtool"].as<string>());
452 py.setConfigurableAuditor (vm[
"configurable-auditor"].as<string>());
453 py.setConfigurableService (vm[
"configurable-service"].as<string>());
455 int sc = EXIT_FAILURE;
457 sc = py.genConfig( libs, userModule );
459 catch ( exception& e ) {
460 cout <<
"ERROR: Could not generate Configurable(s) !\n"
461 <<
"ERROR: Got exception: " << e.what() << endl;
465 if ( EXIT_SUCCESS == sc && ! vm.count(
"no-init")) {
467 fstream initPy( ( out /
fs::path(
"__init__.py" ) ).
string(),
468 std::ios_base::out|std::ios_base::trunc );
469 initPy <<
"## Hook for " << pkgName <<
" genConf module\n" << flush;
473 std::ostringstream
msg;
474 msg <<
":::::: libraries : [ ";
475 copy( libs.begin(), libs.end(), ostream_iterator<string>(
msg,
" ") );
476 msg <<
"] :::::: [DONE]";
489 const Strings_t::const_iterator endLib = libs.end();
491 const std::string gaudiSvc =
"GaudiCoreSvc";
492 const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
496 cout <<
"ERROR: ApplicationMgr can not be created. Check environment" << endl;
502 Registry&
registry = Registry::instance();
504 std::set<std::string> bkgNames = registry.loadedFactories();
513 for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
515 LOG_INFO <<
":::: processing library: " << *iLib <<
"...";
518 m_importGaudiHandles =
false;
519 m_importDataObjectDescriptors =
false;
532 std::set<std::string>
factories = registry.loadedFactories();
534 for ( std::set<std::string>::iterator it = factories.begin();
535 it != factories.end(); ++it ) {
536 const string ident = *it;
537 if ( bkgNames.find(ident) != bkgNames.end() ) {
539 LOG_INFO <<
"\t==> skipping [" << ident <<
"]...";
544 const Registry::FactoryInfo info = registry.getInfo(*it);
545 const string rtype = info.rtype;
548 if (info.properties.find(
"ReflexName") != info.properties.end())
556 LOG_WARNING <<
"library [" << *iLib <<
"] exposes factory ["
557 << ident <<
"] which is declared in ["
558 << DsoUtils::dsoName(info.ptr) <<
"] !!";
564 if ( ident ==
"ApplicationMgr" ) type =
"ApplicationMgr";
565 else if ( rtype ==
typeid(
IInterface*).
name() ) type =
"IInterface";
566 else if ( rtype ==
typeid(
IAlgorithm*).
name() ) type =
"Algorithm";
567 else if ( rtype ==
typeid(
IService* ).
name() ) type =
"Service";
568 else if ( rtype ==
typeid(
IAlgTool* ).
name() ) type =
"AlgTool";
569 else if ( rtype ==
typeid(
IAuditor* ).
name() ) type =
"Auditor";
570 else if ( rtype ==
typeid(
IConverter*).
name() ) type =
"Converter";
571 else if ( rtype ==
typeid(
DataObject*).
name() ) type =
"DataObject";
572 else type =
"Unknown", known =
false;
577 if ( type ==
"IInterface" ) {
583 if ( type ==
"Converter" || type ==
"DataObject" ) {
590 <<
" Component [" << ident <<
"] is skipped !";
594 LOG_INFO <<
" - component: " << info.className
595 <<
" (" << (info.className != name ? (name +
": ")
599 string cname =
"DefaultName";
602 if ( type ==
"Algorithm" ) {
605 else if ( type ==
"Service") {
608 else if ( type ==
"AlgTool") {
609 prop =
SmartIF<IAlgTool>(AlgTool::Factory::create(ident, cname, type, dummySvc));
613 else if ( type ==
"Auditor") {
616 else if ( type ==
"ApplicationMgr") {
623 catch ( exception& e ) {
624 LOG_ERROR <<
"Error instantiating " << name
625 <<
" from " << *iLib;
626 LOG_ERROR <<
"Got exception: " << e.what();
631 LOG_ERROR <<
"Error instantiating " << name
632 <<
" from " << *iLib;
637 if (genComponent( *iLib, name, type, prop->
getProperties() )) {
642 LOG_ERROR <<
"could not cast IInterface* object to an IProperty* !";
643 LOG_ERROR <<
"return type from PluginSvc is [" << rtype <<
"]...";
644 LOG_ERROR <<
"NO Configurable will be generated for ["
653 const std::string pyName = (
fs::path(m_outputDirName) /
654 fs::path(*iLib+
"Conf.py") ).
string();
655 const std::string dbName = (
fs::path(m_outputDirName) /
656 fs::path(*iLib+
".confdb") ).
string();
658 std::fstream py( pyName, std::ios_base::out|std::ios_base::trunc );
659 std::fstream db( dbName, std::ios_base::out|std::ios_base::trunc );
661 genHeader ( py, db );
662 if (!userModule.empty())
663 py <<
"from " << userModule <<
" import *" <<endl;
665 genTrailer( py, db );
672 return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
679 std::string::size_type pos = 0, nxtpos = 0;
682 while ( std::string::npos != pos ){
684 nxtpos = m_configurable[
"Module"].find_first_of(
',',pos);
687 mod = m_configurable[
"Module"].substr(pos,nxtpos-pos);
688 std::ostringstream
import;
693 if ( std::string::npos == nxtpos ) {
695 s <<
indent <<
import.str() <<
"\n" << flush;
696 pos = std::string::npos;
700 <<
indent << py_tab <<
import.str() <<
"\n"
701 <<
indent <<
"except ImportError:\n"
718 <<
"\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
719 if ( m_importGaudiHandles ) {
720 py <<
"from GaudiKernel.GaudiHandles import *\n";
723 if ( m_importDataObjectDescriptors ) {
724 py <<
"from GaudiKernel.DataObjectDescriptor import *\n";
727 genImport(py,
boost::format(
"from %1%.Configurable import *"));
730 db <<
"## -*- ascii -*- \n"
731 <<
"# db file automatically generated by genconf on: "
742 db <<
"## " << m_pkgName <<
"\n"
749 const std::string& componentName,
750 const std::string& componentType,
754 string cname = componentName;
755 pythonizeName(cname);
758 PropertyDoc_t propDoc;
761 m_pyBuf <<
"class " << cname
762 <<
"( " << m_configurable[componentType] <<
" ) :"
764 m_pyBuf <<
" __slots__ = { \n";
765 for ( vector<Property*>::const_iterator it = properties.begin() ;
766 it != properties.end(); ++it ) {
768 const string pname = (*it)->name();
770 if (!boost::regex_match(pname, pythonIdentifier)) {
771 std::cout <<
"ERROR: invalid property name \"" << pname
772 <<
"\" in component " << cname
773 <<
" (invalid Python identifier)" << std::endl;
775 m_pyBuf <<
" #ERROR-invalid identifier '" << pname <<
"'\n"
780 string pvalue, ptype;
781 pythonizeValue( (*it), pvalue, ptype );
782 m_pyBuf <<
" '" << pname <<
"' : " << pvalue <<
", # " << ptype <<
"\n";
784 if ( (*it)->documentation() !=
"none" ) {
785 propDoc[
pname] = (*it)->documentation();
790 m_pyBuf <<
" _propertyDocDct = { \n";
791 for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
792 iProp != propDoc.end();
794 m_pyBuf << std::setw(5)
795 <<
"'" << iProp->first <<
"' : "
796 <<
"\"\"\" " << iProp->second <<
" \"\"\",\n";
801 <<
" def __init__(self, name = " << m_configurable[
"DefaultName"]
803 <<
" super(" << cname <<
", self).__init__(name)\n"
804 <<
" for n,v in kwargs.items():\n"
805 <<
" setattr(self, n, v)\n"
806 <<
" def getDlls( self ):\n"
807 <<
" return '" << libName <<
"'\n"
808 <<
" def getType( self ):\n"
809 <<
" return '" << componentName <<
"'\n"
810 <<
" pass # class " << cname <<
"\n"
814 const string pyName = (
fs::path(m_outputDirName) /
815 fs::path(libName+
"Conf.py") ).
string();
820 << m_pkgName <<
"." << modName <<
" "
821 << libName <<
" " << cname
831 static string in(
"<>&*,: ().");
832 static string out(
"__rp__s___");
833 boost::algorithm::replace_all(name,
", ",
",");
834 for ( string::iterator
i = name.begin();
i != name.end(); ++
i ) {
835 if ( in.find(*
i) != string::npos ) *
i = out[in.find(*
i)];
841 string& pvalue,
string& ptype )
844 const std::string cvalue = p->
toString();
846 if ( ti ==
typeid(
bool) ) {
847 pvalue = ( cvalue ==
"0" || cvalue ==
"False" || cvalue ==
"false" )
852 else if ( ti ==
typeid(
char) || ti ==
typeid(
signed char)
853 || ti ==
typeid(
unsigned char) ||
854 ti ==
typeid(short) || ti ==
typeid(
unsigned short) ||
855 ti ==
typeid(int) || ti ==
typeid(
unsigned int) ||
856 ti ==
typeid(long) || ti ==
typeid(
unsigned long) ) {
860 else if ( ti ==
typeid(
long long) || ti ==
typeid(
unsigned long long) ) {
861 pvalue = cvalue +
"L";
864 else if ( ti ==
typeid(
float) || ti ==
typeid(double) ) {
866 pvalue = boost::to_lower_copy(cvalue);
867 if ( pvalue ==
"nan" ) {
868 pvalue =
"float('nan')";
869 std::cout <<
"WARNING: default value for ["
870 << p->
name() <<
"] is NaN !!"
872 }
else if ( std::string::npos == pvalue.find(
".") &&
873 std::string::npos == pvalue.find(
"e") ) {
874 pvalue = cvalue +
".0";
878 else if ( ti ==
typeid(
string) ) {
880 pvalue =
"'"+cvalue+
"'";
884 m_importGaudiHandles =
true;
890 ptype =
"GaudiHandle";
893 m_importGaudiHandles =
true;
899 ptype =
"GaudiHandleArray";
902 m_importDataObjectDescriptors =
true;
908 ptype =
"DataDescriptor";
911 m_importDataObjectDescriptors =
true;
917 ptype =
"DataDescriptorCollection";
920 std::ostringstream v_str;
921 v_str.setf(std::ios::fixed);
923 pvalue = v_str.str();
928 #include "GaudiKernel/IMessageSvc.h"
937 if ( !propMgr || !appUI )
return EXIT_FAILURE;
939 propMgr->setProperty(
"AppName",
"");
940 propMgr->setProperty(
"OutputLevel",
"7");
943 msgSvc->setProperty(
"setWarning",
"['DefaultName', 'PropertyMgr']");
944 msgSvc->setProperty(
"Format",
"%T %0W%M");
const GaudiHandleArrayBase & value() const
int genConfig(const Strings_t &modules, const string &userModule)
main entry point of this class:
virtual std::string pythonRepr() const
Python representation of handle, i.e.
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...
virtual const std::vector< Property * > & getProperties() const =0
Get list of properties.
virtual std::string toString() const =0
value -> string
std::vector< std::string > Strings_t
const std::string & name() const
property name
-*- C++ -*- /////////////////////////////
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.
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
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
virtual const DataObjectDescriptor & value() const
const DataObjectDescriptorCollection & value() const
GAUDIPS_API Logger & logger()
Return the current logger instance.
std::vector< fs::path > LibPathNames_t
GAUDI_API const std::string & moduleName()
Get the name of the (executable/DLL) file without file-type.
void setConfigurableAlgTool(const std::string &cfgAlgTool)
customize the configurable base class for AlgTool component
void * ImageHandle
Definition of an image handle.
const std::string pythonRepr() const
GaudiUtils::HashMap< std::string, std::string > m_configurable
Configurable customization.
stringstream m_pyBuf
buffer of auto-generated configurables
void setConfigurableModule(const std::string &moduleName)
customize the Module name where configurable base classes are defined
SmartIF< IFace > as() const
return a new SmartIF instance to another interface
int main(int argc, char **argv)
GAUDI_API ISvcLocator * svcLocator()
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
General service interface definition.
Definition of the basic interface.
virtual StatusCode setProperty(const Property &p)=0
Set the property by property.
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
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
void init_logging(boost::log::trivial::severity_level level)
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".
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
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
const GaudiHandleBase & value() const
GAUDI_API const std::string getLastErrorString()
Get last system error as string.
In-memory database of the loaded factories.
string m_pkgName
name of the package we are processing
GAUDI_API unsigned long loadDynamicLib(const std::string &name, ImageHandle *handle)
Load dynamic link library.
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 reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
void genTrailer(std::ostream &pyOut, std::ostream &dbOut)
bool m_importDataObjectDescriptors
Base class to handles to be used in lieu of naked pointers to various Gaudi components.
virtual StatusCode configure()=0
Configure the job.
The IProperty is the basic interface for all components which have properties that can be set or get...
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.
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)
const std::string pythonRepr() const
virtual void toStream(std::ostream &out) const =0
value -> stream
void setConfigurableAuditor(const std::string &cfgAuditor)
customize the configurable base class for AlgTool component
std::string pythonRepr() const override
Python representation of array of handles, i.e.