From: vsr Date: Thu, 10 Nov 2016 16:06:34 +0000 (+0300) Subject: Convert to Unix CR style. X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2FV6_7_BR;p=tools%2Fyacsgen.git Convert to Unix CR style. --- diff --git a/module_generator/gener.py b/module_generator/gener.py index 79a1622..5e5f543 100755 --- a/module_generator/gener.py +++ b/module_generator/gener.py @@ -1,996 +1,996 @@ -# Copyright (C) 2009-2012 EDF R&D -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - -import os, shutil, glob, socket -import traceback -import warnings - -try: - from string import Template -except: - from compat import Template, set - -class Invalid(Exception): - pass - -debug=0 - -from mod_tmpl import resMakefile, makecommon, configure, paco_configure -from mod_tmpl import mainMakefile, autogen, application -from mod_tmpl import check_sphinx -from cata_tmpl import catalog, interface, idl, idlMakefile, parallel_interface -from cata_tmpl import xml, xml_interface, xml_service -from cata_tmpl import idlMakefilePaCO_BUILT_SOURCES, idlMakefilePaCO_nodist_salomeinclude_HEADERS -from cata_tmpl import idlMakefilePACO_salomepython_DATA, idlMakefilePACO_salomeidl_DATA -from cata_tmpl import idlMakefilePACO_INCLUDES -from cata_tmpl import cataOutStream, cataInStream, cataOutparam, cataInparam -from cata_tmpl import cataOutParallelStream, cataInParallelStream -from cata_tmpl import cataService, cataCompo -from aster_tmpl import check_aster -from salomemodules import salome_modules -from yacstypes import corbaTypes, corbaOutTypes, moduleTypes, idlTypes, corba_in_type, corba_out_type -from yacstypes import ValidTypes, PyValidTypes, calciumTypes, DatastreamParallelTypes -from yacstypes import ValidImpl, ValidImplTypes, ValidStreamTypes, ValidParallelStreamTypes, ValidDependencies -from gui_tmpl import pyguimakefile, pysalomeapp, cppguimakefile, cppsalomeapp -from doc_tmpl import docmakefile, docconf, docsalomeapp - -def makedirs(namedir): - """Create a new directory named namedir. If a directory already exists copy it to namedir.bak""" - if os.path.exists(namedir): - dirbak = namedir+".bak" - if os.path.exists(dirbak): - shutil.rmtree(dirbak) - os.rename(namedir, dirbak) - os.listdir(dirbak) #needed to update filesystem on special machines (cluster with NFS, for example) - os.makedirs(namedir) - -class Module(object): - """ - A :class:`Module` instance represents a SALOME module that contains components given as a list of - component instances (:class:`CPPComponent` or :class:`PYComponent` or :class:`F77Component` or :class:`ASTERComponent`) - with the parameter *components*. - - :param name: gives the name of the module. The SALOME source module - will be located in the directory. - :type name: str - :param components: gives the list of components of the module. - :param prefix: is the path of the installation directory. - :param layout: If given and has the value "monodir", all components - will be generated in a single directory. The default is to generate each component in its - own directory. - :param doc: can be used to add an online documentation to the module. It must be a list of file names (sources, images, ...) that will be - used to build a sphinx documentation (see http://sphinx.pocoo.org, for more information). If not given, the Makefile.am - and the conf.py (sphinx configuration) files are generated. In this case, the file name extension of source files must be .rst. - See small examples in Examples/pygui1 and Examples/cppgui1. - :param gui: can be used to add a GUI to the module. It must be a list of file names (sources, images, qt designer files, ...). - If not given, the Makefile.am and SalomeApp.xml are generated. All image files are put in the resources directory of the module. - The GUI can be implemented in C++ (file name extension '.cxx') or in Python (file name extension '.py'). - See small examples in Examples/pygui1 and Examples/cppgui1. - - For example, the following call defines a module named "mymodule" with 2 components c1 and c2 (they must have been - defined before) that will be installed in the "install" directory:: - - >>> m = module_generator.Module('mymodule', components=[c1,c2], - prefix="./install") - - """ - def __init__(self, name, components=None, prefix="",layout="multidir", doc=None, gui=None): - self.name = name - self.components = components or [] - self.prefix = prefix or "%s_INSTALL" % name - self.layout=layout - self.doc = doc - self.gui = gui - try: - self.validate() - except Invalid,e: - if debug: - traceback.print_exc() - print "Error in module %s: %s" % (name,e) - raise SystemExit - - def validate(self): - # Test Module name, canot have a "-" in the name - if self.name.find("-") != -1: - raise Invalid("Module name %s is not valid, remove character - in the module name" % self.name) - lcompo = set() - for compo in self.components: - if compo.name in lcompo: - raise Invalid("%s is already defined as a component of the module" % compo.name) - lcompo.add(compo.name) - compo.validate() - if self.gui and self.layout != "multidir": - raise Invalid("A module with GUI can not be generated if layout is not multidir") - -class Component(object): - def __init__(self, name, services=None, impl="PY", libs="", rlibs="", - includes="", kind="lib", sources=None, - inheritedclass="",compodefs="", - idls=None,interfacedefs="",inheritedinterface="",addedmethods=""): - self.name = name - self.impl = impl - self.kind = kind - self.services = services or [] - self.libs = libs - self.rlibs = rlibs - self.includes = includes - self.sources = sources or [] - self.inheritedclass=inheritedclass - self.compodefs=compodefs - self.idls=idls - self.interfacedefs=interfacedefs - self.inheritedinterface=inheritedinterface - self.addedmethods=addedmethods - - def validate(self): - if self.impl not in ValidImpl: - raise Invalid("%s is not a valid implementation. It should be one of %s" % (self.impl, ValidImpl)) - - lnames = set() - for serv in self.services: - serv.impl = self.impl - if serv.name in lnames: - raise Invalid("%s is already defined as a service of the module" % serv.name) - lnames.add(serv.name) - serv.validate() - - for src in self.sources: - if not os.path.exists(src): - raise Invalid("Source file %s does not exist" % src) - - def getImpl(self): - return "SO", "" - - def getMakefileItems(self,gen): - return {} - - def setPrerequisites(self, prerequisites_file): - self.prerequisites = prerequisites_file - -class Service(object): - """ - A :class:`Service` instance represents a component service with dataflow and datastream ports. - - :param name: gives the name of the service. - :type name: str - :param inport: gives the list of input dataflow ports. - :param outport: gives the list of output dataflow ports. An input or output dataflow port is defined - by a 2-tuple (port name, data type name). The list of supported basic data types is: "double", "long", "string", - "dblevec", "stringvec", "intvec", "file" and "pyobj" only for Python services. Depending on the implementation - language, it is also possible to use some types from SALOME modules (see :ref:`yacstypes`). - :param ret: gives the type of the return parameter - :param instream: gives the list of input datastream ports. - :param outstream: gives the list of output datastream ports. An input or output datastream port is defined - by a 3-tuple (port name, data type name, mode name). The list of possible data types is: "CALCIUM_double", "CALCIUM_integer", - "CALCIUM_real", "CALCIUM_string", "CALCIUM_complex", "CALCIUM_logical", "CALCIUM_long". The mode can be "I" (iterative mode) - or "T" (temporal mode). - :param defs: gives the source code to insert in the definition section of the component. It can be C++ includes - or Python imports - :type defs: str - :param body: gives the source code to insert in the service call. It can be any C++ - or Python code that fits well in the body of the service method. - :type body: str - - For example, the following call defines a minimal Python service with one input dataflow port (name "a", type double) - and one input datastream port:: - - >>> s1 = module_generator.Service('myservice', inport=[("a","double"),], - instream=[("aa","CALCIUM_double","I")], - body="print a") - - - """ - def __init__(self, name, inport=None, outport=None, ret="void", instream=None, outstream=None, - parallel_instream=None, parallel_outstream=None, defs="", body="", impl_type="sequential"): - self.name = name - self.inport = inport or [] - self.outport = outport or [] - self.ret = ret - self.instream = instream or [] - self.outstream = outstream or [] - self.parallel_instream = parallel_instream or [] - self.parallel_outstream = parallel_outstream or [] - self.defs = defs - self.body = body - self.impl = "" - self.impl_type = impl_type - - def validate(self): - lports = set() - for port in self.inport: - name, typ = self.validatePort(port) - if name in lports: - raise Invalid("%s is already defined as a service parameter" % name) - lports.add(name) - - for port in self.outport: - name, typ = self.validatePort(port) - if name in lports: - raise Invalid("%s is already defined as a service parameter" % name) - lports.add(name) - - lports = set() - for port in self.instream: - name, typ, dep = self.validateStream(port) - if name in lports: - raise Invalid("%s is already defined as a stream port" % name) - lports.add(name) - - for port in self.outstream: - name, typ, dep = self.validateStream(port) - if name in lports: - raise Invalid("%s is already defined as a stream port" % name) - lports.add(name) - - for port in self.parallel_instream: - name, typ = self.validateParallelStream(port) - if name in lports: - raise Invalid("%s is already defined as a stream port" % name) - lports.add(name) - - for port in self.parallel_outstream: - name, typ = self.validateParallelStream(port) - if name in lports: - raise Invalid("%s is already defined as a stream port" % name) - lports.add(name) - - self.validateImplType() - - def validatePort(self, port): - try: - name, typ = port - except: - raise Invalid("%s is not a valid definition of an data port (name,type)" % (port,)) - - if self.impl in ("PY", "ASTER"): - validtypes = PyValidTypes - else: - validtypes = ValidTypes - - if typ not in validtypes: - raise Invalid("%s is not a valid type. It should be one of %s" % (typ, validtypes)) - return name, typ - - def validateImplType(self): - if self.impl_type not in ValidImplTypes: - raise Invalid("%s is not a valid impl type. It should be one of %s" % (self.impl_type, ValidImplTypes)) - - def validateStream(self, port): - try: - name, typ, dep = port - except: - raise Invalid("%s is not a valid definition of a stream port (name,type,dependency)" % (port,)) - if typ not in ValidStreamTypes: - raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidStreamTypes)) - if dep not in ValidDependencies: - raise Invalid("%s is not a valid dependency. It should be one of %s" % (dep, ValidDependencies)) - return name, typ, dep - - def validateParallelStream(self, port): - try: - name, typ = port - except: - raise Invalid("%s is not a valid definition of a parallel stream port (name,type)" % (port,)) - if typ not in ValidParallelStreamTypes: - raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidParallelStreamTypes)) - return name, typ - -class Generator(object): - """ - A :class:`Generator` instance take a :class:`Module` instance as its first parameter and can be used to generate the - SALOME source module, builds it, installs it and includes it in a SALOME application. - - :param module: gives the :class:`Module` instance that will be used for the generation. - :param context: If given , its content is used to specify the prerequisites - environment file (key *"prerequisites"*) and the SALOME KERNEL installation directory (key *"kernel"*). - :type context: dict - - For example, the following call creates a generator for the module m:: - - >>> g = module_generator.Generator(m,context) - """ - def __init__(self, module, context=None): - self.module = module - self.context = context or {} - self.kernel = self.context["kernel"] - self.gui = self.context.get("gui") - self.makeflags = self.context.get("makeflags") - self.aster = "" - if self.module.gui and not self.gui: - raise Invalid("To generate a module with GUI, you need to set the 'gui' parameter in the context dictionnary") - for component in self.module.components: - component.setPrerequisites(self.context.get("prerequisites")) - - def generate(self): - """Generate a SALOME source module""" - module = self.module - namedir = module.name+"_SRC" - force = self.context.get("force") - update = self.context.get("update") - paco = self.context.get("paco") - if os.path.exists(namedir): - if force: - shutil.rmtree(namedir) - elif not update: - raise Invalid("The directory %s already exists" % namedir) - if update: - makedirs(namedir) - else: - os.makedirs(namedir) - - srcs = {} - makefile = "SUBDIRS=" - makefileItems={"header":""" -include $(top_srcdir)/adm_local/make_common_starter.am -AM_CFLAGS=$(SALOME_INCLUDES) -fexceptions -""", - "salomepython_PYTHON":[], - "dist_salomescript_SCRIPTS":[], - "salomeres_DATA":[], - "lib_LTLIBRARIES":[], - "salomeinclude_HEADERS":[], - "body":"", - } - - #get the list of SALOME modules used and put it in used_modules attribute - def get_dependent_modules(mod,modules): - modules[mod]=1 - if not salome_modules[mod].has_key("depends"):return - for m in salome_modules[mod]["depends"]: - if modules.has_key(m):continue - get_dependent_modules(m,modules) - - modules = {} - for compo in module.components: - for serv in compo.services: - for name, typ in serv.inport + serv.outport + [ ("return",serv.ret) ] : - mod = moduleTypes[typ] - if mod: - get_dependent_modules(mod,modules) - - self.used_modules = modules.keys() - - for compo in module.components: - #for components files - fdict=compo.makeCompo(self) - if self.module.layout=="multidir": - srcs[compo.name] = fdict - #for src/Makefile.am - makefile = makefile + " " + compo.name - else: - srcs.update(fdict) - #for src/Makefile.am - mdict=compo.getMakefileItems(self) - makefileItems["salomepython_PYTHON"]=makefileItems["salomepython_PYTHON"]+mdict.get("salomepython_PYTHON",[]) - makefileItems["dist_salomescript_SCRIPTS"]=makefileItems["dist_salomescript_SCRIPTS"]+mdict.get("dist_salomescript_SCRIPTS",[]) - makefileItems["salomeres_DATA"]=makefileItems["salomeres_DATA"]+mdict.get("salomeres_DATA",[]) - makefileItems["lib_LTLIBRARIES"]=makefileItems["lib_LTLIBRARIES"]+mdict.get("lib_LTLIBRARIES",[]) - makefileItems["salomeinclude_HEADERS"]=makefileItems["salomeinclude_HEADERS"]+mdict.get("salomeinclude_HEADERS",[]) - makefileItems["body"]=makefileItems["body"]+mdict.get("body","")+'\n' - - if module.gui: - GUIname=module.name+"GUI" - fdict=self.makeGui(namedir) - srcs[GUIname] = fdict - #for src/Makefile.am - makefile = makefile + " " + GUIname - - if self.module.layout == "multidir": - srcs["Makefile.am"] = makefile+'\n' - else: - srcs["Makefile.am"] = self.makeMakefile(makefileItems) - - docsubdir="" - if module.doc: - docsubdir="doc" - - #for catalog files - catalogfile = "%sCatalog.xml" % module.name - - need_boost=0 - if module.gui: - need_boost=1 - for compo in module.components: - if hasattr(compo,"calciumextendedinterface") and compo.calciumextendedinterface: - need_boost=1 - break - - #add makefile definitions to make_common_starter.am - other_includes="" - common_starter = makecommon.substitute(other_includes=other_includes) - for mod in self.used_modules: - common_starter = common_starter + salome_modules[mod]["makefiledefs"] + '\n' - - adm_local={"make_common_starter.am": common_starter, "check_aster.m4":check_aster} - if module.doc: - adm_local["check_sphinx.m4"]=check_sphinx - - self.makeFiles({"autogen.sh":autogen, - "Makefile.am":mainMakefile.substitute(docsubdir=docsubdir), - "README":"", "NEWS":"", "AUTHORS":"", "ChangeLog":"", - "src":srcs, - "resources":{"Makefile.am":resMakefile.substitute(module=module.name), catalogfile:self.makeCatalog()}, - "adm_local":adm_local, - }, namedir) - - #add checks for modules in configure.ac - configure_modules="" - for mod in self.used_modules: - configure_modules = configure_modules + salome_modules[mod]["configdefs"] + '\n' - - #for configure.ac - configure_makefiles = [] - if self.module.layout=="multidir": - for compo in module.components: - configure_makefiles.append(" src/"+compo.name+"/Makefile") - - if module.gui: - configure_makefiles.append(" src/%sGUI/Makefile" % module.name) - if module.doc: - configure_makefiles.append(" doc/Makefile") - - other_check="" - other_summary="" - other_require="" - - if need_boost: - other_check=other_check+"""CHECK_BOOST -""" - other_summary=other_summary+"""echo " Boost ................. : $boost_ok" -""" - - if module.gui: - other_check=other_check + """CHECK_SALOME_GUI -CHECK_QT -""" - other_summary=other_summary+'''echo " SALOME GUI ............. : $SalomeGUI_ok" -echo " Qt ..................... : $qt_ok" -''' - other_require=other_require + """ - if test "x$SalomeGUI_ok" = "xno"; then - AC_MSG_ERROR([SALOME GUI is required],1) - fi - if test "x$qt_ok" = "xno"; then - AC_MSG_ERROR([Qt library is required],1) - fi -""" - if module.doc: - other_check=other_check+"CHECK_SPHINX\n" - other_summary=other_summary+'''echo " Sphinx ................. : $sphinx_ok"\n''' - other_require=other_require + """ - if test "x$sphinx_ok" = "xno"; then - AC_MSG_ERROR([Sphinx documentation generator is required],1) - fi -""" - - files={} - #for idl files - idlfile = "%s.idl" % module.name - paco_config="" - PACO_BUILT_SOURCES="" - PACO_SALOMEINCLUDE_HEADERS="" - PACO_INCLUDES="" - PACO_salomepython_DATA="" - PACO_salomeidl_DATA="" - - if paco: - PACO_BUILT_SOURCES = idlMakefilePaCO_BUILT_SOURCES.substitute(module=module.name) - PACO_SALOMEINCLUDE_HEADERS = idlMakefilePaCO_nodist_salomeinclude_HEADERS.substitute(module=module.name) - PACO_salomepython_DATA = idlMakefilePACO_salomepython_DATA.substitute(module=module.name) - PACO_salomeidl_DATA = idlMakefilePACO_salomeidl_DATA.substitute(module=module.name) - PACO_INCLUDES = idlMakefilePACO_INCLUDES - paco_config=paco_configure - - files["configure.ac"]=configure.substitute(module=module.name.lower(), - makefiles='\n'.join(configure_makefiles), - paco_configure=paco_config, - modules=configure_modules, - other_check=other_check, - other_summary=other_summary, - other_require=other_require, - ) - - #if components have other idls - other_idls="" - other_sks="" - for compo in module.components: - if compo.idls: - for idl in compo.idls: - for fidl in glob.glob(idl): - other_idls=other_idls+os.path.basename(fidl) +" " - other_sks=other_sks+os.path.splitext(os.path.basename(fidl))[0]+"SK.cc " - - idlfiles={"Makefile.am": idlMakefile.substitute(module=module.name, - PACO_BUILT_SOURCES=PACO_BUILT_SOURCES, - PACO_SALOMEINCLUDE_HEADERS=PACO_SALOMEINCLUDE_HEADERS, - PACO_INCLUDES=PACO_INCLUDES, - PACO_salomepython_DATA=PACO_salomepython_DATA, - PACO_salomeidl_DATA=PACO_salomeidl_DATA, - other_idls=other_idls,other_sks=other_sks, - ), - idlfile : self.makeidl(), - } - if paco: - idlfiles["%s.xml" % module.name]=self.makexml() - - files["idl"]=idlfiles - - self.makeFiles(files,namedir) - - os.chmod(os.path.join(namedir, "autogen.sh"), 0777) - #copy source files if any in created tree - for compo in module.components: - for src in compo.sources: - if self.module.layout=="multidir": - shutil.copyfile(src, os.path.join(namedir, "src", compo.name, os.path.basename(src))) - else: - shutil.copyfile(src, os.path.join(namedir, "src", os.path.basename(src))) - - if compo.idls: - #copy provided idl files in idl directory - for idl in compo.idls: - for fidl in glob.glob(idl): - shutil.copyfile(fidl, os.path.join(namedir, "idl", os.path.basename(fidl))) - - checks= ("check_Kernel.m4", "check_omniorb.m4", "ac_linker_options.m4", "ac_cxx_option.m4", - "python.m4", "enable_pthreads.m4", "check_f77.m4", "acx_pthread.m4", "check_paco++.m4", - "check_mpi.m4", "check_lam.m4", "check_openmpi.m4", "check_mpich.m4") - if need_boost: - checks=checks+("check_boost.m4",) - for m4file in checks: - shutil.copyfile(os.path.join(self.kernel, "salome_adm", "unix", "config_files", m4file), - os.path.join(namedir, "adm_local", m4file)) - - if self.module.gui: - for m4file in ("check_GUI.m4", "check_qt.m4", "check_opengl.m4"): - shutil.copyfile(os.path.join(self.gui, "adm_local", "unix", "config_files", m4file), - os.path.join(namedir, "adm_local", m4file)) - - self.makeDoc(namedir) - return - - def makeDoc(self,namedir): - if not self.module.doc: - return - rep=os.path.join(namedir,"doc") - os.makedirs(rep) - for docs in self.module.doc: - for doc in glob.glob(docs): - name = os.path.basename(doc) - shutil.copyfile(doc, os.path.join(rep, name)) - - d={} - - others="" - if not self.module.gui: - #without gui but with doc: create a small SalomeApp.xml in doc directory - if not os.path.exists(os.path.join(namedir, "doc", "SalomeApp.xml")): - #create a minimal SalomeApp.xml - salomeapp=docsalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) - d["SalomeApp.xml"]=salomeapp - others="SalomeApp.xml" - - if not os.path.exists(os.path.join(namedir, "doc", "Makefile.am")): - #create a minimal makefile.am - d["Makefile.am"]=docmakefile.substitute(others=others) - - if not os.path.exists(os.path.join(namedir, "doc", "conf.py")): - #create a minimal conf.py - d["conf.py"]=docconf.substitute(module=self.module.name) - - self.makeFiles(d,os.path.join(namedir,"doc")) - - def makeGui(self,namedir): - if not self.module.gui: - return - ispython=False - iscpp=False - #Force creation of intermediate directories - os.makedirs(os.path.join(namedir, "src", self.module.name+"GUI")) - - for srcs in self.module.gui: - for src in glob.glob(srcs): - shutil.copyfile(src, os.path.join(namedir, "src", self.module.name+"GUI", os.path.basename(src))) - if src[-3:]==".py":ispython=True - if src[-4:]==".cxx":iscpp=True - if ispython and iscpp: - raise Invalid("Module GUI must be pure python or pure C++ but not mixed") - if ispython: - return self.makePyGUI(namedir) - if iscpp: - return self.makeCPPGUI(namedir) - raise Invalid("Module GUI must be in python or C++ but it is none of them") - - def makePyGUI(self,namedir): - d={} - if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "Makefile.am")): - #create a minimal makefile.am - sources=[] - other=[] - for srcs in self.module.gui: - for src in glob.glob(srcs): - if src[-3:]==".py": - sources.append(os.path.basename(src)) - else: - other.append(os.path.basename(src)) - makefile=pyguimakefile.substitute(sources=" ".join(sources),other_sources=" ".join(other)) - d["Makefile.am"]=makefile - - if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "SalomeApp.xml")): - #create a minimal SalomeApp.xml - salomeapp=pysalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) - d["SalomeApp.xml"]=salomeapp - - return d - - def makeCPPGUI(self,namedir): - d={} - if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "Makefile.am")): - #create a minimal makefile.am - sources=[] - other=[] - ui_files=[] - for srcs in self.module.gui: - for src in glob.glob(srcs): - if src[-4:]==".cxx": - sources.append(os.path.basename(src)) - elif src[-2:]==".h": - sources.append(os.path.basename(src)[:-2]+"_moc.cxx") - elif src[-3:]==".ui": - ui_files.append("ui_"+os.path.basename(src)[:-3]+".h") - elif src[-3:]==".ts": - other.append(os.path.basename(src)[:-3]+".qm") - elif src[-13:]=="SalomeApp.xml": - pass # This file is already included in the cppguimakefile template! - else: - other.append(os.path.basename(src)) - - makefile=cppguimakefile.substitute(sources=" ".join(sources),other_sources=" ".join(other), - module=self.module.name, uisources= " ".join(ui_files)) - d["Makefile.am"]=makefile - - if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "SalomeApp.xml")): - #create a minimal SalomeApp.xml - salomeapp=cppsalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) - d["SalomeApp.xml"]=salomeapp - - return d - - def makeMakefile(self,makefileItems): - makefile="" - if makefileItems.has_key("header"): - makefile=makefile + makefileItems["header"]+'\n' - if makefileItems.has_key("lib_LTLIBRARIES"): - makefile=makefile+"lib_LTLIBRARIES= "+" ".join(makefileItems["lib_LTLIBRARIES"])+'\n' - if makefileItems.has_key("salomepython_PYTHON"): - makefile=makefile+"salomepython_PYTHON= "+" ".join(makefileItems["salomepython_PYTHON"])+'\n' - if makefileItems.has_key("dist_salomescript_SCRIPTS"): - makefile=makefile+"dist_salomescript_SCRIPTS= "+" ".join(makefileItems["dist_salomescript_SCRIPTS"])+'\n' - if makefileItems.has_key("salomeres_DATA"): - makefile=makefile+"salomeres_DATA= "+" ".join(makefileItems["salomeres_DATA"])+'\n' - if makefileItems.has_key("salomeinclude_HEADERS"): - makefile=makefile+"salomeinclude_HEADERS= "+" ".join(makefileItems["salomeinclude_HEADERS"])+'\n' - if makefileItems.has_key("body"): - makefile=makefile+makefileItems["body"]+'\n' - return makefile - - def makeArgs(self, service): - """generate source service for arguments""" - params = [] - for name, typ in service.inport: - if typ=="file":continue #files are not passed through service interface - params.append("%s %s" % (corba_in_type(typ, self.module.name), name)) - for name, typ in service.outport: - if typ=="file":continue #files are not passed through service interface - params.append("%s %s" % (corba_out_type(typ, self.module.name), name)) - return ",".join(params) - - def makeCatalog(self): - """generate SALOME components catalog source""" - components = [] - for compo in self.module.components: - services = [] - for serv in compo.services: - params = [] - for name, typ in serv.inport: - params.append(cataInparam.substitute(name=name, type=typ)) - inparams = "\n".join(params) - params = [] - for name, typ in serv.outport: - params.append(cataOutparam.substitute(name=name, type=typ)) - if serv.ret != "void" : - params.append(cataOutparam.substitute(name="return", type=serv.ret)) - outparams = "\n".join(params) - streams = [] - for name, typ, dep in serv.instream: - streams.append(cataInStream.substitute(name=name, type=calciumTypes[typ], dep=dep)) - for name, typ, dep in serv.outstream: - streams.append(cataOutStream.substitute(name=name, type=calciumTypes[typ], dep=dep)) - for name, typ in serv.parallel_instream: - streams.append(cataInParallelStream.substitute(name=name, type=DatastreamParallelTypes[typ])) - for name, typ in serv.parallel_outstream: - streams.append(cataOutParallelStream.substitute(name=name, type=DatastreamParallelTypes[typ])) - datastreams = "\n".join(streams) - services.append(cataService.substitute(service=serv.name, author="EDF-RD", - inparams=inparams, outparams=outparams, datastreams=datastreams)) - impltype, implname = compo.getImpl() - components.append(cataCompo.substitute(component=compo.name, author="EDF-RD", impltype=impltype, implname=implname, - services='\n'.join(services))) - return catalog.substitute(components='\n'.join(components)) - - def makeidl(self): - """generate module IDL file source (CORBA interface)""" - from pacocompo import PACOComponent - interfaces = [] - idldefs="" - for compo in self.module.components: - if isinstance(compo, PACOComponent): - services = [] - for serv in compo.services: - params = [] - for name, typ in serv.inport: - if typ == "file":continue #files are not passed through IDL interface - params.append("in %s %s" % (idlTypes[typ], name)) - for name, typ in serv.outport: - if typ == "file":continue #files are not passed through IDL interface - params.append("out %s %s" % (idlTypes[typ], name)) - service = " void %s(" % serv.name - service = service+",".join(params)+");" - services.append(service) - - interfaces.append(parallel_interface.substitute(component=compo.name, services="\n".join(services))) - - else: - services = [] - for serv in compo.services: - params = [] - for name, typ in serv.inport: - if typ == "file":continue #files are not passed through IDL interface - if compo.impl in ("PY", "ASTER") and typ == "pyobj": - typ = "Engines::fileBlock" - else: - typ=idlTypes[typ] - params.append("in %s %s" % (typ, name)) - for name, typ in serv.outport: - if typ == "file":continue #files are not passed through IDL interface - if compo.impl in ("PY", "ASTER") and typ == "pyobj": - typ = "Engines::fileBlock" - else: - typ=idlTypes[typ] - params.append("out %s %s" % (typ, name)) - service = " %s %s(" % (idlTypes[serv.ret],serv.name) - service = service+",".join(params)+") raises (SALOME::SALOME_Exception);" - services.append(service) - - from hxxcompo import HXX2SALOMEComponent - from hxxparacompo import HXX2SALOMEParaComponent - if isinstance(compo,HXX2SALOMEComponent) or isinstance(compo,HXX2SALOMEParaComponent): - from hxx_tmpl import interfaceidlhxx - Inherited="" - if isinstance(compo,HXX2SALOMEParaComponent): - Inherited="SALOME_MED::ParaMEDMEMComponent" - idldefs="""#include "ParaMEDMEMComponent.idl"\n""" - else: - if compo.use_medmem==True: - Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver" - else: - Inherited="Engines::EngineComponent" - interfaces.append(interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services))) - else: - inheritedinterface="" - if compo.inheritedinterface: - inheritedinterface=compo.inheritedinterface+"," - interfaces.append(interface.substitute(component=compo.name, services="\n".join(services),inheritedinterface=inheritedinterface)) - - #build idl includes for SALOME modules - for mod in self.used_modules: - idldefs = idldefs + salome_modules[mod]["idldefs"] - - for compo in self.module.components: - if compo.interfacedefs: - idldefs = idldefs + compo.interfacedefs - - return idl.substitute(module=self.module.name, interfaces='\n'.join(interfaces),idldefs=idldefs) - - # For PaCO++ - def makexml(self): - from pacocompo import PACOComponent - interfaces = [] - for compo in self.module.components: - if isinstance(compo, PACOComponent): - services = [] - for serv in compo.services: - if serv.impl_type == "parallel": - service = xml_service.substitute(service_name=serv.name) - services.append(service) - interfaces.append(xml_interface.substitute(component=compo.name, xml_services="\n".join(services))) - return xml.substitute(module=self.module.name, interfaces='\n'.join(interfaces)) - - def makeFiles(self, dic, basedir): - """create files and directories defined in dictionary dic in basedir directory - dic key = file name to create - dic value = file content or dictionary defining the content of a sub directory - """ - for name, content in dic.items(): - filename = os.path.join(basedir, name) - if isinstance(content, str): - fil = open(filename, 'w') - fil.write(content) - fil.close() - else: - if not os.path.exists(filename): - os.makedirs(filename) - self.makeFiles(content, filename) - - def bootstrap(self): - """Execute the first build step (bootstrap autotools with autogen.sh script) : execution of libtool, autoconf, automake""" - ier = os.system("cd %s_SRC;sh autogen.sh" % self.module.name) - if ier != 0: - raise Invalid("bootstrap has ended in error") - - def configure(self): - """Execute the second build step (configure) with installation prefix as given by the prefix attribute of module""" - prefix = self.module.prefix - paco = self.context.get("paco") - mpi = self.context.get("mpi") - args = (self.module.name, self.kernel, self.aster) - cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s" % args - if self.gui: - cmd = cmd + " --with-gui=%s" % self.gui - if prefix: - prefix = os.path.abspath(prefix) - cmd = cmd + " --prefix=%s" % prefix - if paco: - cmd += " --with-paco=%s" % paco - if mpi: - cmd += " --with-mpi=%s" % mpi - - ier = os.system(cmd) - if ier != 0: - raise Invalid("configure has ended in error") - - def make(self): - """Execute the third build step (compile and link) : make""" - make_command = "make " - if self.makeflags: - make_command += self.makeflags - ier = os.system("cd %s_SRC;%s" % (self.module.name, make_command)) - if ier != 0: - raise Invalid("make has ended in error") - - def install(self): - """Execute the installation step : make install """ - makedirs(self.module.prefix) - ier = os.system("cd %s_SRC;make install" % self.module.name) - if ier != 0: - raise Invalid("install has ended in error") - - def make_appli(self, appliname, restrict=None, altmodules=None, resources=""): - """ - Create a SALOME application containing the module and preexisting SALOME modules. - - :param appliname: is a string that gives the name of the application (directory path where the application - will be installed). - :type appliname: str - :param restrict: If given (a list of module names), only those SALOME modules will be included in the - application. The default is to include all modules that are located in the same directory as the KERNEL module and have - the same suffix (for example, if KERNEL directory is KERNEL_V5 and GEOM directory is GEOM_V5, GEOM module is automatically - included, except if restrict is used). - :param altmodules: can be used to add SALOME modules that cannot be managed with the precedent rule. This parameter - is a dict with a module name as the key and the installation path as the value. - :param resources: can be used to define an alternative resources catalog (path of the file). - - For example, the following calls create a SALOME application with external modules and resources catalog in "appli" directory:: - - >>> g=Generator(m,context) - >>> g.generate() - >>> g.bootstrap() - >>> g.configure() - >>> g.make() - >>> g.install() - >>> g.make_appli("appli", restrict=["KERNEL"], altmodules={"GUI":GUI_ROOT_DIR, "YACS":YACS_ROOT_DIR}, - resources="myresources.xml") - - """ - makedirs(appliname) - - rootdir, kerdir = os.path.split(self.kernel) - - #collect modules besides KERNEL module with the same suffix if any - modules_dict = {} - if kerdir[:6] == "KERNEL": - suffix = kerdir[6:] - for mod in os.listdir(rootdir): - if mod[-len(suffix):] == suffix: - module = mod[:-len(suffix)] - path = os.path.join(rootdir, mod) - #try to find catalog files - lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*", "*Catalog.xml")) - if not lcata: - #catalogs have not been found : try the upper level - lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*Catalog.xml")) - if lcata: - #catalogs have been found : add the corresponding entries in the application - for cata in lcata: - catadir, catafile = os.path.split(cata) - name = catafile[:-11] - modules_dict[name] = ' ' % (name, path) - else: - modules_dict[module] = ' ' % (module, path) - - modules_dict["KERNEL"] = ' ' % self.kernel - - #keep only the modules which names are in restrict if given - modules = [] - if restrict: - for mod in restrict: - if modules_dict.has_key(mod): - modules.append(modules_dict[mod]) - else: - modules = modules_dict.values() - - #add the alternate modules if given - if altmodules: - for module, path in altmodules.items(): - modules.append(' ' % (module, path)) - - #add the generated module - modules.append(' ' % (self.module.name, os.path.abspath(self.module.prefix))) - - - #try to find a prerequisites file - prerequisites = self.context.get("prerequisites") - if not prerequisites: - #try to find one in rootdir - prerequisites = os.path.join(rootdir, "profile%s.sh" % suffix) - if not os.path.exists(prerequisites): - raise Invalid("Can not create an application : prerequisites file not defined or does not exist") - - #add resources catalog if it exists - resources_spec="" - if os.path.isfile(resources): - resources_spec='' % os.path.abspath(resources) - - #create config_appli.xml file - appli = application.substitute(prerequisites=prerequisites, - modules="\n".join(modules), - resources=resources_spec) - fil = open(os.path.join(appliname, "config_appli.xml"), 'w') - fil.write(appli) - fil.close() - - #execute appli_gen.py script - appligen = os.path.join(self.kernel, "bin", "salome", "appli_gen.py") - ier = os.system("cd %s;%s" % (appliname, appligen)) - if ier != 0: - raise Invalid("make_appli has ended in error") - - #add CatalogResources.xml if not created by appli_gen.py - if not os.path.exists(os.path.join(appliname, "CatalogResources.xml")): - #CatalogResources.xml does not exist create a minimal one - fil = open(os.path.join(appliname, 'CatalogResources.xml'), 'w') - command = """ - - - -""" - host = socket.gethostname().split('.')[0] - fil.write(command % host) - fil.close() - +# Copyright (C) 2009-2012 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +import os, shutil, glob, socket +import traceback +import warnings + +try: + from string import Template +except: + from compat import Template, set + +class Invalid(Exception): + pass + +debug=0 + +from mod_tmpl import resMakefile, makecommon, configure, paco_configure +from mod_tmpl import mainMakefile, autogen, application +from mod_tmpl import check_sphinx +from cata_tmpl import catalog, interface, idl, idlMakefile, parallel_interface +from cata_tmpl import xml, xml_interface, xml_service +from cata_tmpl import idlMakefilePaCO_BUILT_SOURCES, idlMakefilePaCO_nodist_salomeinclude_HEADERS +from cata_tmpl import idlMakefilePACO_salomepython_DATA, idlMakefilePACO_salomeidl_DATA +from cata_tmpl import idlMakefilePACO_INCLUDES +from cata_tmpl import cataOutStream, cataInStream, cataOutparam, cataInparam +from cata_tmpl import cataOutParallelStream, cataInParallelStream +from cata_tmpl import cataService, cataCompo +from aster_tmpl import check_aster +from salomemodules import salome_modules +from yacstypes import corbaTypes, corbaOutTypes, moduleTypes, idlTypes, corba_in_type, corba_out_type +from yacstypes import ValidTypes, PyValidTypes, calciumTypes, DatastreamParallelTypes +from yacstypes import ValidImpl, ValidImplTypes, ValidStreamTypes, ValidParallelStreamTypes, ValidDependencies +from gui_tmpl import pyguimakefile, pysalomeapp, cppguimakefile, cppsalomeapp +from doc_tmpl import docmakefile, docconf, docsalomeapp + +def makedirs(namedir): + """Create a new directory named namedir. If a directory already exists copy it to namedir.bak""" + if os.path.exists(namedir): + dirbak = namedir+".bak" + if os.path.exists(dirbak): + shutil.rmtree(dirbak) + os.rename(namedir, dirbak) + os.listdir(dirbak) #needed to update filesystem on special machines (cluster with NFS, for example) + os.makedirs(namedir) + +class Module(object): + """ + A :class:`Module` instance represents a SALOME module that contains components given as a list of + component instances (:class:`CPPComponent` or :class:`PYComponent` or :class:`F77Component` or :class:`ASTERComponent`) + with the parameter *components*. + + :param name: gives the name of the module. The SALOME source module + will be located in the directory. + :type name: str + :param components: gives the list of components of the module. + :param prefix: is the path of the installation directory. + :param layout: If given and has the value "monodir", all components + will be generated in a single directory. The default is to generate each component in its + own directory. + :param doc: can be used to add an online documentation to the module. It must be a list of file names (sources, images, ...) that will be + used to build a sphinx documentation (see http://sphinx.pocoo.org, for more information). If not given, the Makefile.am + and the conf.py (sphinx configuration) files are generated. In this case, the file name extension of source files must be .rst. + See small examples in Examples/pygui1 and Examples/cppgui1. + :param gui: can be used to add a GUI to the module. It must be a list of file names (sources, images, qt designer files, ...). + If not given, the Makefile.am and SalomeApp.xml are generated. All image files are put in the resources directory of the module. + The GUI can be implemented in C++ (file name extension '.cxx') or in Python (file name extension '.py'). + See small examples in Examples/pygui1 and Examples/cppgui1. + + For example, the following call defines a module named "mymodule" with 2 components c1 and c2 (they must have been + defined before) that will be installed in the "install" directory:: + + >>> m = module_generator.Module('mymodule', components=[c1,c2], + prefix="./install") + + """ + def __init__(self, name, components=None, prefix="",layout="multidir", doc=None, gui=None): + self.name = name + self.components = components or [] + self.prefix = prefix or "%s_INSTALL" % name + self.layout=layout + self.doc = doc + self.gui = gui + try: + self.validate() + except Invalid,e: + if debug: + traceback.print_exc() + print "Error in module %s: %s" % (name,e) + raise SystemExit + + def validate(self): + # Test Module name, canot have a "-" in the name + if self.name.find("-") != -1: + raise Invalid("Module name %s is not valid, remove character - in the module name" % self.name) + lcompo = set() + for compo in self.components: + if compo.name in lcompo: + raise Invalid("%s is already defined as a component of the module" % compo.name) + lcompo.add(compo.name) + compo.validate() + if self.gui and self.layout != "multidir": + raise Invalid("A module with GUI can not be generated if layout is not multidir") + +class Component(object): + def __init__(self, name, services=None, impl="PY", libs="", rlibs="", + includes="", kind="lib", sources=None, + inheritedclass="",compodefs="", + idls=None,interfacedefs="",inheritedinterface="",addedmethods=""): + self.name = name + self.impl = impl + self.kind = kind + self.services = services or [] + self.libs = libs + self.rlibs = rlibs + self.includes = includes + self.sources = sources or [] + self.inheritedclass=inheritedclass + self.compodefs=compodefs + self.idls=idls + self.interfacedefs=interfacedefs + self.inheritedinterface=inheritedinterface + self.addedmethods=addedmethods + + def validate(self): + if self.impl not in ValidImpl: + raise Invalid("%s is not a valid implementation. It should be one of %s" % (self.impl, ValidImpl)) + + lnames = set() + for serv in self.services: + serv.impl = self.impl + if serv.name in lnames: + raise Invalid("%s is already defined as a service of the module" % serv.name) + lnames.add(serv.name) + serv.validate() + + for src in self.sources: + if not os.path.exists(src): + raise Invalid("Source file %s does not exist" % src) + + def getImpl(self): + return "SO", "" + + def getMakefileItems(self,gen): + return {} + + def setPrerequisites(self, prerequisites_file): + self.prerequisites = prerequisites_file + +class Service(object): + """ + A :class:`Service` instance represents a component service with dataflow and datastream ports. + + :param name: gives the name of the service. + :type name: str + :param inport: gives the list of input dataflow ports. + :param outport: gives the list of output dataflow ports. An input or output dataflow port is defined + by a 2-tuple (port name, data type name). The list of supported basic data types is: "double", "long", "string", + "dblevec", "stringvec", "intvec", "file" and "pyobj" only for Python services. Depending on the implementation + language, it is also possible to use some types from SALOME modules (see :ref:`yacstypes`). + :param ret: gives the type of the return parameter + :param instream: gives the list of input datastream ports. + :param outstream: gives the list of output datastream ports. An input or output datastream port is defined + by a 3-tuple (port name, data type name, mode name). The list of possible data types is: "CALCIUM_double", "CALCIUM_integer", + "CALCIUM_real", "CALCIUM_string", "CALCIUM_complex", "CALCIUM_logical", "CALCIUM_long". The mode can be "I" (iterative mode) + or "T" (temporal mode). + :param defs: gives the source code to insert in the definition section of the component. It can be C++ includes + or Python imports + :type defs: str + :param body: gives the source code to insert in the service call. It can be any C++ + or Python code that fits well in the body of the service method. + :type body: str + + For example, the following call defines a minimal Python service with one input dataflow port (name "a", type double) + and one input datastream port:: + + >>> s1 = module_generator.Service('myservice', inport=[("a","double"),], + instream=[("aa","CALCIUM_double","I")], + body="print a") + + + """ + def __init__(self, name, inport=None, outport=None, ret="void", instream=None, outstream=None, + parallel_instream=None, parallel_outstream=None, defs="", body="", impl_type="sequential"): + self.name = name + self.inport = inport or [] + self.outport = outport or [] + self.ret = ret + self.instream = instream or [] + self.outstream = outstream or [] + self.parallel_instream = parallel_instream or [] + self.parallel_outstream = parallel_outstream or [] + self.defs = defs + self.body = body + self.impl = "" + self.impl_type = impl_type + + def validate(self): + lports = set() + for port in self.inport: + name, typ = self.validatePort(port) + if name in lports: + raise Invalid("%s is already defined as a service parameter" % name) + lports.add(name) + + for port in self.outport: + name, typ = self.validatePort(port) + if name in lports: + raise Invalid("%s is already defined as a service parameter" % name) + lports.add(name) + + lports = set() + for port in self.instream: + name, typ, dep = self.validateStream(port) + if name in lports: + raise Invalid("%s is already defined as a stream port" % name) + lports.add(name) + + for port in self.outstream: + name, typ, dep = self.validateStream(port) + if name in lports: + raise Invalid("%s is already defined as a stream port" % name) + lports.add(name) + + for port in self.parallel_instream: + name, typ = self.validateParallelStream(port) + if name in lports: + raise Invalid("%s is already defined as a stream port" % name) + lports.add(name) + + for port in self.parallel_outstream: + name, typ = self.validateParallelStream(port) + if name in lports: + raise Invalid("%s is already defined as a stream port" % name) + lports.add(name) + + self.validateImplType() + + def validatePort(self, port): + try: + name, typ = port + except: + raise Invalid("%s is not a valid definition of an data port (name,type)" % (port,)) + + if self.impl in ("PY", "ASTER"): + validtypes = PyValidTypes + else: + validtypes = ValidTypes + + if typ not in validtypes: + raise Invalid("%s is not a valid type. It should be one of %s" % (typ, validtypes)) + return name, typ + + def validateImplType(self): + if self.impl_type not in ValidImplTypes: + raise Invalid("%s is not a valid impl type. It should be one of %s" % (self.impl_type, ValidImplTypes)) + + def validateStream(self, port): + try: + name, typ, dep = port + except: + raise Invalid("%s is not a valid definition of a stream port (name,type,dependency)" % (port,)) + if typ not in ValidStreamTypes: + raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidStreamTypes)) + if dep not in ValidDependencies: + raise Invalid("%s is not a valid dependency. It should be one of %s" % (dep, ValidDependencies)) + return name, typ, dep + + def validateParallelStream(self, port): + try: + name, typ = port + except: + raise Invalid("%s is not a valid definition of a parallel stream port (name,type)" % (port,)) + if typ not in ValidParallelStreamTypes: + raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidParallelStreamTypes)) + return name, typ + +class Generator(object): + """ + A :class:`Generator` instance take a :class:`Module` instance as its first parameter and can be used to generate the + SALOME source module, builds it, installs it and includes it in a SALOME application. + + :param module: gives the :class:`Module` instance that will be used for the generation. + :param context: If given , its content is used to specify the prerequisites + environment file (key *"prerequisites"*) and the SALOME KERNEL installation directory (key *"kernel"*). + :type context: dict + + For example, the following call creates a generator for the module m:: + + >>> g = module_generator.Generator(m,context) + """ + def __init__(self, module, context=None): + self.module = module + self.context = context or {} + self.kernel = self.context["kernel"] + self.gui = self.context.get("gui") + self.makeflags = self.context.get("makeflags") + self.aster = "" + if self.module.gui and not self.gui: + raise Invalid("To generate a module with GUI, you need to set the 'gui' parameter in the context dictionnary") + for component in self.module.components: + component.setPrerequisites(self.context.get("prerequisites")) + + def generate(self): + """Generate a SALOME source module""" + module = self.module + namedir = module.name+"_SRC" + force = self.context.get("force") + update = self.context.get("update") + paco = self.context.get("paco") + if os.path.exists(namedir): + if force: + shutil.rmtree(namedir) + elif not update: + raise Invalid("The directory %s already exists" % namedir) + if update: + makedirs(namedir) + else: + os.makedirs(namedir) + + srcs = {} + makefile = "SUBDIRS=" + makefileItems={"header":""" +include $(top_srcdir)/adm_local/make_common_starter.am +AM_CFLAGS=$(SALOME_INCLUDES) -fexceptions +""", + "salomepython_PYTHON":[], + "dist_salomescript_SCRIPTS":[], + "salomeres_DATA":[], + "lib_LTLIBRARIES":[], + "salomeinclude_HEADERS":[], + "body":"", + } + + #get the list of SALOME modules used and put it in used_modules attribute + def get_dependent_modules(mod,modules): + modules[mod]=1 + if not salome_modules[mod].has_key("depends"):return + for m in salome_modules[mod]["depends"]: + if modules.has_key(m):continue + get_dependent_modules(m,modules) + + modules = {} + for compo in module.components: + for serv in compo.services: + for name, typ in serv.inport + serv.outport + [ ("return",serv.ret) ] : + mod = moduleTypes[typ] + if mod: + get_dependent_modules(mod,modules) + + self.used_modules = modules.keys() + + for compo in module.components: + #for components files + fdict=compo.makeCompo(self) + if self.module.layout=="multidir": + srcs[compo.name] = fdict + #for src/Makefile.am + makefile = makefile + " " + compo.name + else: + srcs.update(fdict) + #for src/Makefile.am + mdict=compo.getMakefileItems(self) + makefileItems["salomepython_PYTHON"]=makefileItems["salomepython_PYTHON"]+mdict.get("salomepython_PYTHON",[]) + makefileItems["dist_salomescript_SCRIPTS"]=makefileItems["dist_salomescript_SCRIPTS"]+mdict.get("dist_salomescript_SCRIPTS",[]) + makefileItems["salomeres_DATA"]=makefileItems["salomeres_DATA"]+mdict.get("salomeres_DATA",[]) + makefileItems["lib_LTLIBRARIES"]=makefileItems["lib_LTLIBRARIES"]+mdict.get("lib_LTLIBRARIES",[]) + makefileItems["salomeinclude_HEADERS"]=makefileItems["salomeinclude_HEADERS"]+mdict.get("salomeinclude_HEADERS",[]) + makefileItems["body"]=makefileItems["body"]+mdict.get("body","")+'\n' + + if module.gui: + GUIname=module.name+"GUI" + fdict=self.makeGui(namedir) + srcs[GUIname] = fdict + #for src/Makefile.am + makefile = makefile + " " + GUIname + + if self.module.layout == "multidir": + srcs["Makefile.am"] = makefile+'\n' + else: + srcs["Makefile.am"] = self.makeMakefile(makefileItems) + + docsubdir="" + if module.doc: + docsubdir="doc" + + #for catalog files + catalogfile = "%sCatalog.xml" % module.name + + need_boost=0 + if module.gui: + need_boost=1 + for compo in module.components: + if hasattr(compo,"calciumextendedinterface") and compo.calciumextendedinterface: + need_boost=1 + break + + #add makefile definitions to make_common_starter.am + other_includes="" + common_starter = makecommon.substitute(other_includes=other_includes) + for mod in self.used_modules: + common_starter = common_starter + salome_modules[mod]["makefiledefs"] + '\n' + + adm_local={"make_common_starter.am": common_starter, "check_aster.m4":check_aster} + if module.doc: + adm_local["check_sphinx.m4"]=check_sphinx + + self.makeFiles({"autogen.sh":autogen, + "Makefile.am":mainMakefile.substitute(docsubdir=docsubdir), + "README":"", "NEWS":"", "AUTHORS":"", "ChangeLog":"", + "src":srcs, + "resources":{"Makefile.am":resMakefile.substitute(module=module.name), catalogfile:self.makeCatalog()}, + "adm_local":adm_local, + }, namedir) + + #add checks for modules in configure.ac + configure_modules="" + for mod in self.used_modules: + configure_modules = configure_modules + salome_modules[mod]["configdefs"] + '\n' + + #for configure.ac + configure_makefiles = [] + if self.module.layout=="multidir": + for compo in module.components: + configure_makefiles.append(" src/"+compo.name+"/Makefile") + + if module.gui: + configure_makefiles.append(" src/%sGUI/Makefile" % module.name) + if module.doc: + configure_makefiles.append(" doc/Makefile") + + other_check="" + other_summary="" + other_require="" + + if need_boost: + other_check=other_check+"""CHECK_BOOST +""" + other_summary=other_summary+"""echo " Boost ................. : $boost_ok" +""" + + if module.gui: + other_check=other_check + """CHECK_SALOME_GUI +CHECK_QT +""" + other_summary=other_summary+'''echo " SALOME GUI ............. : $SalomeGUI_ok" +echo " Qt ..................... : $qt_ok" +''' + other_require=other_require + """ + if test "x$SalomeGUI_ok" = "xno"; then + AC_MSG_ERROR([SALOME GUI is required],1) + fi + if test "x$qt_ok" = "xno"; then + AC_MSG_ERROR([Qt library is required],1) + fi +""" + if module.doc: + other_check=other_check+"CHECK_SPHINX\n" + other_summary=other_summary+'''echo " Sphinx ................. : $sphinx_ok"\n''' + other_require=other_require + """ + if test "x$sphinx_ok" = "xno"; then + AC_MSG_ERROR([Sphinx documentation generator is required],1) + fi +""" + + files={} + #for idl files + idlfile = "%s.idl" % module.name + paco_config="" + PACO_BUILT_SOURCES="" + PACO_SALOMEINCLUDE_HEADERS="" + PACO_INCLUDES="" + PACO_salomepython_DATA="" + PACO_salomeidl_DATA="" + + if paco: + PACO_BUILT_SOURCES = idlMakefilePaCO_BUILT_SOURCES.substitute(module=module.name) + PACO_SALOMEINCLUDE_HEADERS = idlMakefilePaCO_nodist_salomeinclude_HEADERS.substitute(module=module.name) + PACO_salomepython_DATA = idlMakefilePACO_salomepython_DATA.substitute(module=module.name) + PACO_salomeidl_DATA = idlMakefilePACO_salomeidl_DATA.substitute(module=module.name) + PACO_INCLUDES = idlMakefilePACO_INCLUDES + paco_config=paco_configure + + files["configure.ac"]=configure.substitute(module=module.name.lower(), + makefiles='\n'.join(configure_makefiles), + paco_configure=paco_config, + modules=configure_modules, + other_check=other_check, + other_summary=other_summary, + other_require=other_require, + ) + + #if components have other idls + other_idls="" + other_sks="" + for compo in module.components: + if compo.idls: + for idl in compo.idls: + for fidl in glob.glob(idl): + other_idls=other_idls+os.path.basename(fidl) +" " + other_sks=other_sks+os.path.splitext(os.path.basename(fidl))[0]+"SK.cc " + + idlfiles={"Makefile.am": idlMakefile.substitute(module=module.name, + PACO_BUILT_SOURCES=PACO_BUILT_SOURCES, + PACO_SALOMEINCLUDE_HEADERS=PACO_SALOMEINCLUDE_HEADERS, + PACO_INCLUDES=PACO_INCLUDES, + PACO_salomepython_DATA=PACO_salomepython_DATA, + PACO_salomeidl_DATA=PACO_salomeidl_DATA, + other_idls=other_idls,other_sks=other_sks, + ), + idlfile : self.makeidl(), + } + if paco: + idlfiles["%s.xml" % module.name]=self.makexml() + + files["idl"]=idlfiles + + self.makeFiles(files,namedir) + + os.chmod(os.path.join(namedir, "autogen.sh"), 0777) + #copy source files if any in created tree + for compo in module.components: + for src in compo.sources: + if self.module.layout=="multidir": + shutil.copyfile(src, os.path.join(namedir, "src", compo.name, os.path.basename(src))) + else: + shutil.copyfile(src, os.path.join(namedir, "src", os.path.basename(src))) + + if compo.idls: + #copy provided idl files in idl directory + for idl in compo.idls: + for fidl in glob.glob(idl): + shutil.copyfile(fidl, os.path.join(namedir, "idl", os.path.basename(fidl))) + + checks= ("check_Kernel.m4", "check_omniorb.m4", "ac_linker_options.m4", "ac_cxx_option.m4", + "python.m4", "enable_pthreads.m4", "check_f77.m4", "acx_pthread.m4", "check_paco++.m4", + "check_mpi.m4", "check_lam.m4", "check_openmpi.m4", "check_mpich.m4") + if need_boost: + checks=checks+("check_boost.m4",) + for m4file in checks: + shutil.copyfile(os.path.join(self.kernel, "salome_adm", "unix", "config_files", m4file), + os.path.join(namedir, "adm_local", m4file)) + + if self.module.gui: + for m4file in ("check_GUI.m4", "check_qt.m4", "check_opengl.m4"): + shutil.copyfile(os.path.join(self.gui, "adm_local", "unix", "config_files", m4file), + os.path.join(namedir, "adm_local", m4file)) + + self.makeDoc(namedir) + return + + def makeDoc(self,namedir): + if not self.module.doc: + return + rep=os.path.join(namedir,"doc") + os.makedirs(rep) + for docs in self.module.doc: + for doc in glob.glob(docs): + name = os.path.basename(doc) + shutil.copyfile(doc, os.path.join(rep, name)) + + d={} + + others="" + if not self.module.gui: + #without gui but with doc: create a small SalomeApp.xml in doc directory + if not os.path.exists(os.path.join(namedir, "doc", "SalomeApp.xml")): + #create a minimal SalomeApp.xml + salomeapp=docsalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) + d["SalomeApp.xml"]=salomeapp + others="SalomeApp.xml" + + if not os.path.exists(os.path.join(namedir, "doc", "Makefile.am")): + #create a minimal makefile.am + d["Makefile.am"]=docmakefile.substitute(others=others) + + if not os.path.exists(os.path.join(namedir, "doc", "conf.py")): + #create a minimal conf.py + d["conf.py"]=docconf.substitute(module=self.module.name) + + self.makeFiles(d,os.path.join(namedir,"doc")) + + def makeGui(self,namedir): + if not self.module.gui: + return + ispython=False + iscpp=False + #Force creation of intermediate directories + os.makedirs(os.path.join(namedir, "src", self.module.name+"GUI")) + + for srcs in self.module.gui: + for src in glob.glob(srcs): + shutil.copyfile(src, os.path.join(namedir, "src", self.module.name+"GUI", os.path.basename(src))) + if src[-3:]==".py":ispython=True + if src[-4:]==".cxx":iscpp=True + if ispython and iscpp: + raise Invalid("Module GUI must be pure python or pure C++ but not mixed") + if ispython: + return self.makePyGUI(namedir) + if iscpp: + return self.makeCPPGUI(namedir) + raise Invalid("Module GUI must be in python or C++ but it is none of them") + + def makePyGUI(self,namedir): + d={} + if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "Makefile.am")): + #create a minimal makefile.am + sources=[] + other=[] + for srcs in self.module.gui: + for src in glob.glob(srcs): + if src[-3:]==".py": + sources.append(os.path.basename(src)) + else: + other.append(os.path.basename(src)) + makefile=pyguimakefile.substitute(sources=" ".join(sources),other_sources=" ".join(other)) + d["Makefile.am"]=makefile + + if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "SalomeApp.xml")): + #create a minimal SalomeApp.xml + salomeapp=pysalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) + d["SalomeApp.xml"]=salomeapp + + return d + + def makeCPPGUI(self,namedir): + d={} + if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "Makefile.am")): + #create a minimal makefile.am + sources=[] + other=[] + ui_files=[] + for srcs in self.module.gui: + for src in glob.glob(srcs): + if src[-4:]==".cxx": + sources.append(os.path.basename(src)) + elif src[-2:]==".h": + sources.append(os.path.basename(src)[:-2]+"_moc.cxx") + elif src[-3:]==".ui": + ui_files.append("ui_"+os.path.basename(src)[:-3]+".h") + elif src[-3:]==".ts": + other.append(os.path.basename(src)[:-3]+".qm") + elif src[-13:]=="SalomeApp.xml": + pass # This file is already included in the cppguimakefile template! + else: + other.append(os.path.basename(src)) + + makefile=cppguimakefile.substitute(sources=" ".join(sources),other_sources=" ".join(other), + module=self.module.name, uisources= " ".join(ui_files)) + d["Makefile.am"]=makefile + + if not os.path.exists(os.path.join(namedir, "src", self.module.name+"GUI", "SalomeApp.xml")): + #create a minimal SalomeApp.xml + salomeapp=cppsalomeapp.substitute(module=self.module.name,lmodule=self.module.name.lower()) + d["SalomeApp.xml"]=salomeapp + + return d + + def makeMakefile(self,makefileItems): + makefile="" + if makefileItems.has_key("header"): + makefile=makefile + makefileItems["header"]+'\n' + if makefileItems.has_key("lib_LTLIBRARIES"): + makefile=makefile+"lib_LTLIBRARIES= "+" ".join(makefileItems["lib_LTLIBRARIES"])+'\n' + if makefileItems.has_key("salomepython_PYTHON"): + makefile=makefile+"salomepython_PYTHON= "+" ".join(makefileItems["salomepython_PYTHON"])+'\n' + if makefileItems.has_key("dist_salomescript_SCRIPTS"): + makefile=makefile+"dist_salomescript_SCRIPTS= "+" ".join(makefileItems["dist_salomescript_SCRIPTS"])+'\n' + if makefileItems.has_key("salomeres_DATA"): + makefile=makefile+"salomeres_DATA= "+" ".join(makefileItems["salomeres_DATA"])+'\n' + if makefileItems.has_key("salomeinclude_HEADERS"): + makefile=makefile+"salomeinclude_HEADERS= "+" ".join(makefileItems["salomeinclude_HEADERS"])+'\n' + if makefileItems.has_key("body"): + makefile=makefile+makefileItems["body"]+'\n' + return makefile + + def makeArgs(self, service): + """generate source service for arguments""" + params = [] + for name, typ in service.inport: + if typ=="file":continue #files are not passed through service interface + params.append("%s %s" % (corba_in_type(typ, self.module.name), name)) + for name, typ in service.outport: + if typ=="file":continue #files are not passed through service interface + params.append("%s %s" % (corba_out_type(typ, self.module.name), name)) + return ",".join(params) + + def makeCatalog(self): + """generate SALOME components catalog source""" + components = [] + for compo in self.module.components: + services = [] + for serv in compo.services: + params = [] + for name, typ in serv.inport: + params.append(cataInparam.substitute(name=name, type=typ)) + inparams = "\n".join(params) + params = [] + for name, typ in serv.outport: + params.append(cataOutparam.substitute(name=name, type=typ)) + if serv.ret != "void" : + params.append(cataOutparam.substitute(name="return", type=serv.ret)) + outparams = "\n".join(params) + streams = [] + for name, typ, dep in serv.instream: + streams.append(cataInStream.substitute(name=name, type=calciumTypes[typ], dep=dep)) + for name, typ, dep in serv.outstream: + streams.append(cataOutStream.substitute(name=name, type=calciumTypes[typ], dep=dep)) + for name, typ in serv.parallel_instream: + streams.append(cataInParallelStream.substitute(name=name, type=DatastreamParallelTypes[typ])) + for name, typ in serv.parallel_outstream: + streams.append(cataOutParallelStream.substitute(name=name, type=DatastreamParallelTypes[typ])) + datastreams = "\n".join(streams) + services.append(cataService.substitute(service=serv.name, author="EDF-RD", + inparams=inparams, outparams=outparams, datastreams=datastreams)) + impltype, implname = compo.getImpl() + components.append(cataCompo.substitute(component=compo.name, author="EDF-RD", impltype=impltype, implname=implname, + services='\n'.join(services))) + return catalog.substitute(components='\n'.join(components)) + + def makeidl(self): + """generate module IDL file source (CORBA interface)""" + from pacocompo import PACOComponent + interfaces = [] + idldefs="" + for compo in self.module.components: + if isinstance(compo, PACOComponent): + services = [] + for serv in compo.services: + params = [] + for name, typ in serv.inport: + if typ == "file":continue #files are not passed through IDL interface + params.append("in %s %s" % (idlTypes[typ], name)) + for name, typ in serv.outport: + if typ == "file":continue #files are not passed through IDL interface + params.append("out %s %s" % (idlTypes[typ], name)) + service = " void %s(" % serv.name + service = service+",".join(params)+");" + services.append(service) + + interfaces.append(parallel_interface.substitute(component=compo.name, services="\n".join(services))) + + else: + services = [] + for serv in compo.services: + params = [] + for name, typ in serv.inport: + if typ == "file":continue #files are not passed through IDL interface + if compo.impl in ("PY", "ASTER") and typ == "pyobj": + typ = "Engines::fileBlock" + else: + typ=idlTypes[typ] + params.append("in %s %s" % (typ, name)) + for name, typ in serv.outport: + if typ == "file":continue #files are not passed through IDL interface + if compo.impl in ("PY", "ASTER") and typ == "pyobj": + typ = "Engines::fileBlock" + else: + typ=idlTypes[typ] + params.append("out %s %s" % (typ, name)) + service = " %s %s(" % (idlTypes[serv.ret],serv.name) + service = service+",".join(params)+") raises (SALOME::SALOME_Exception);" + services.append(service) + + from hxxcompo import HXX2SALOMEComponent + from hxxparacompo import HXX2SALOMEParaComponent + if isinstance(compo,HXX2SALOMEComponent) or isinstance(compo,HXX2SALOMEParaComponent): + from hxx_tmpl import interfaceidlhxx + Inherited="" + if isinstance(compo,HXX2SALOMEParaComponent): + Inherited="SALOME_MED::ParaMEDMEMComponent" + idldefs="""#include "ParaMEDMEMComponent.idl"\n""" + else: + if compo.use_medmem==True: + Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver" + else: + Inherited="Engines::EngineComponent" + interfaces.append(interfaceidlhxx.substitute(component=compo.name,inherited=Inherited, services="\n".join(services))) + else: + inheritedinterface="" + if compo.inheritedinterface: + inheritedinterface=compo.inheritedinterface+"," + interfaces.append(interface.substitute(component=compo.name, services="\n".join(services),inheritedinterface=inheritedinterface)) + + #build idl includes for SALOME modules + for mod in self.used_modules: + idldefs = idldefs + salome_modules[mod]["idldefs"] + + for compo in self.module.components: + if compo.interfacedefs: + idldefs = idldefs + compo.interfacedefs + + return idl.substitute(module=self.module.name, interfaces='\n'.join(interfaces),idldefs=idldefs) + + # For PaCO++ + def makexml(self): + from pacocompo import PACOComponent + interfaces = [] + for compo in self.module.components: + if isinstance(compo, PACOComponent): + services = [] + for serv in compo.services: + if serv.impl_type == "parallel": + service = xml_service.substitute(service_name=serv.name) + services.append(service) + interfaces.append(xml_interface.substitute(component=compo.name, xml_services="\n".join(services))) + return xml.substitute(module=self.module.name, interfaces='\n'.join(interfaces)) + + def makeFiles(self, dic, basedir): + """create files and directories defined in dictionary dic in basedir directory + dic key = file name to create + dic value = file content or dictionary defining the content of a sub directory + """ + for name, content in dic.items(): + filename = os.path.join(basedir, name) + if isinstance(content, str): + fil = open(filename, 'w') + fil.write(content) + fil.close() + else: + if not os.path.exists(filename): + os.makedirs(filename) + self.makeFiles(content, filename) + + def bootstrap(self): + """Execute the first build step (bootstrap autotools with autogen.sh script) : execution of libtool, autoconf, automake""" + ier = os.system("cd %s_SRC;sh autogen.sh" % self.module.name) + if ier != 0: + raise Invalid("bootstrap has ended in error") + + def configure(self): + """Execute the second build step (configure) with installation prefix as given by the prefix attribute of module""" + prefix = self.module.prefix + paco = self.context.get("paco") + mpi = self.context.get("mpi") + args = (self.module.name, self.kernel, self.aster) + cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s" % args + if self.gui: + cmd = cmd + " --with-gui=%s" % self.gui + if prefix: + prefix = os.path.abspath(prefix) + cmd = cmd + " --prefix=%s" % prefix + if paco: + cmd += " --with-paco=%s" % paco + if mpi: + cmd += " --with-mpi=%s" % mpi + + ier = os.system(cmd) + if ier != 0: + raise Invalid("configure has ended in error") + + def make(self): + """Execute the third build step (compile and link) : make""" + make_command = "make " + if self.makeflags: + make_command += self.makeflags + ier = os.system("cd %s_SRC;%s" % (self.module.name, make_command)) + if ier != 0: + raise Invalid("make has ended in error") + + def install(self): + """Execute the installation step : make install """ + makedirs(self.module.prefix) + ier = os.system("cd %s_SRC;make install" % self.module.name) + if ier != 0: + raise Invalid("install has ended in error") + + def make_appli(self, appliname, restrict=None, altmodules=None, resources=""): + """ + Create a SALOME application containing the module and preexisting SALOME modules. + + :param appliname: is a string that gives the name of the application (directory path where the application + will be installed). + :type appliname: str + :param restrict: If given (a list of module names), only those SALOME modules will be included in the + application. The default is to include all modules that are located in the same directory as the KERNEL module and have + the same suffix (for example, if KERNEL directory is KERNEL_V5 and GEOM directory is GEOM_V5, GEOM module is automatically + included, except if restrict is used). + :param altmodules: can be used to add SALOME modules that cannot be managed with the precedent rule. This parameter + is a dict with a module name as the key and the installation path as the value. + :param resources: can be used to define an alternative resources catalog (path of the file). + + For example, the following calls create a SALOME application with external modules and resources catalog in "appli" directory:: + + >>> g=Generator(m,context) + >>> g.generate() + >>> g.bootstrap() + >>> g.configure() + >>> g.make() + >>> g.install() + >>> g.make_appli("appli", restrict=["KERNEL"], altmodules={"GUI":GUI_ROOT_DIR, "YACS":YACS_ROOT_DIR}, + resources="myresources.xml") + + """ + makedirs(appliname) + + rootdir, kerdir = os.path.split(self.kernel) + + #collect modules besides KERNEL module with the same suffix if any + modules_dict = {} + if kerdir[:6] == "KERNEL": + suffix = kerdir[6:] + for mod in os.listdir(rootdir): + if mod[-len(suffix):] == suffix: + module = mod[:-len(suffix)] + path = os.path.join(rootdir, mod) + #try to find catalog files + lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*", "*Catalog.xml")) + if not lcata: + #catalogs have not been found : try the upper level + lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*Catalog.xml")) + if lcata: + #catalogs have been found : add the corresponding entries in the application + for cata in lcata: + catadir, catafile = os.path.split(cata) + name = catafile[:-11] + modules_dict[name] = ' ' % (name, path) + else: + modules_dict[module] = ' ' % (module, path) + + modules_dict["KERNEL"] = ' ' % self.kernel + + #keep only the modules which names are in restrict if given + modules = [] + if restrict: + for mod in restrict: + if modules_dict.has_key(mod): + modules.append(modules_dict[mod]) + else: + modules = modules_dict.values() + + #add the alternate modules if given + if altmodules: + for module, path in altmodules.items(): + modules.append(' ' % (module, path)) + + #add the generated module + modules.append(' ' % (self.module.name, os.path.abspath(self.module.prefix))) + + + #try to find a prerequisites file + prerequisites = self.context.get("prerequisites") + if not prerequisites: + #try to find one in rootdir + prerequisites = os.path.join(rootdir, "profile%s.sh" % suffix) + if not os.path.exists(prerequisites): + raise Invalid("Can not create an application : prerequisites file not defined or does not exist") + + #add resources catalog if it exists + resources_spec="" + if os.path.isfile(resources): + resources_spec='' % os.path.abspath(resources) + + #create config_appli.xml file + appli = application.substitute(prerequisites=prerequisites, + modules="\n".join(modules), + resources=resources_spec) + fil = open(os.path.join(appliname, "config_appli.xml"), 'w') + fil.write(appli) + fil.close() + + #execute appli_gen.py script + appligen = os.path.join(self.kernel, "bin", "salome", "appli_gen.py") + ier = os.system("cd %s;%s" % (appliname, appligen)) + if ier != 0: + raise Invalid("make_appli has ended in error") + + #add CatalogResources.xml if not created by appli_gen.py + if not os.path.exists(os.path.join(appliname, "CatalogResources.xml")): + #CatalogResources.xml does not exist create a minimal one + fil = open(os.path.join(appliname, 'CatalogResources.xml'), 'w') + command = """ + + + +""" + host = socket.gethostname().split('.')[0] + fil.write(command % host) + fil.close() + diff --git a/module_generator/hxxcompo.py b/module_generator/hxxcompo.py index 0b7b2f6..af445a3 100755 --- a/module_generator/hxxcompo.py +++ b/module_generator/hxxcompo.py @@ -1,495 +1,495 @@ -# Copyright (C) 2009-2012 EDF R&D -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# -""" - Module that generates SALOME c++ Component from a non SALOME c++ component - (its header and its shares library) -""" - -debug=1 -import os -import string -import fnmatch -from tempfile import mkstemp -from gener import Component, Invalid -from hxx_tmpl import cxxService, hxxCompo, cxxCompo, compoMakefile -from module_generator import Service -from yacstypes import corba_rtn_type,moduleTypes -from hxx_awk import parse01,parse1,parse2,parse3 -from hxx_awk import cpp2idl_mapping -# these tables contain the part of code which depends upon c++ types -from hxx_awk import cpp_impl_a,cpp_impl_b,cpp_impl_c -from hxx_awk import cpp2yacs_mapping -from tempfile import mkdtemp -from hxx_tmpl_gui import hxxgui_cxx, hxxgui_h, hxxgui_icon_ts -from hxx_tmpl_gui import hxxgui_message_en, hxxgui_message_fr -from hxx_tmpl_gui import hxxgui_config, hxxgui_xml_fr, hxxgui_xml_en -from gui_tmpl import cppsalomeapp - -# ------------------------------------------------------------------------------ - -class HXX2SALOMEComponent(Component): - def __init__(self, hxxfile , cpplib , cpp_path ): - # search a file within a directory tree - def search_file(pattern, root): - matches = [] - for path, dirs, files in os.walk(os.path.abspath(root)): - for filename in fnmatch.filter(files, pattern): - matches.append(os.path.join(path, filename)) - return matches - - hxxfileful = search_file(hxxfile,cpp_path) - cpplibful = search_file(cpplib,cpp_path) - format_error = 'Error in HXX2SALOMEComponent : file %s ot found in %s' - assert len(hxxfileful) > 0, format_error % (hxxfile, cpp_path) - assert len(cpplibful) > 0, format_error % (cpplib, cpp_path) - hxxfile = hxxfileful[0] - cpplib = cpplibful[0] - - # grab name of c++ component - cmd1="""awk '$1 == "class" && $0 !~ /;/ {print $2}' """ + hxxfile +\ - """|awk -F: '{printf "%s",$1}' """ - f=os.popen(cmd1) - class_name=f.readlines()[0] - name=class_name - print "classname=",class_name - f.close() - - # create temporary awk files for the parsing - (fd01,p01n)=mkstemp() - f01=os.fdopen(fd01,"w") - f01.write(parse01) - f01.close() - - (fd1,p1n)=mkstemp() - f1=os.fdopen(fd1,"w") - f1.write(parse1) - f1.close() - - (fd2,p2n)=mkstemp() - f2=os.fdopen(fd2,"w") - f2.write(parse2) - f2.close() - - (fd3,p3n)=mkstemp() - f3=os.fdopen(fd3,"w") - f3.write(parse3) - f3.close() - - # awk parsing of hxx files - - # result written in file parse_type_result - cmd2 = [ - "cat %s" % hxxfile, - "awk -f %s" % p01n, - "sed 's/virtual //g'", - "sed 's/MEDMEM_EXPORT//g'", - "sed 's/throw.*;/;/g'", - "awk -f %s" % p1n, - "awk -f %s" % p2n, - "awk -v class_name=%s -f %s" % (class_name, p3n) ] - cmd2 = ' | '.join(cmd2) - - #os.system(cmd2) - import subprocess, sys - subprocess.call(cmd2, shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT) - os.remove(p01n) - os.remove(p1n) - os.remove(p2n) - os.remove(p3n) - - # Retrieve the information which was generated in - # the file parse_type_result. - # The structure of the file is : - # - # Function return_type function_name - # [arg1_type arg1_name] - # [arg2_type arg2_name] - # ... - # The service names are stored in list_of_services - # The information relative to a service (called service_name) is stored in - # the dictionnary service_definition[service_name] - list_of_services=[] - service_definition={} - result_parsing=open("parse_type_result","r") - for line in result_parsing.readlines(): - line=line[0:-1] # get rid of trailing \n - words = string.split(line,';') - - if len(words) >=3 and words[0] == "Function": # detect a new service - function_name=words[2] - # store the name of new service - list_of_services.append(function_name) - # create a dict to store informations relative to this service - service_definition[function_name]={} - service_definition[function_name]["ret"]=words[1] # return type - service_definition[function_name]["inports"]=[] - service_definition[function_name]["outports"]=[] - service_definition[function_name]["ports"]=[] - service_definition[function_name]["impl"]=[] - - # an argument type and argument name of the current service - if len(words) == 2: - current_service=list_of_services[-1] - current_service_dict=service_definition[current_service] - typename=words[0] - argname=words[1] - # store in c++ order the arg names - current_service_dict["ports"].append( (argname,typename) ) - - # separate in from out parameters - inout=cpp2idl_mapping[typename][0:2] - assert inout=="in" or inout=="ou",'Error in table cpp2idl_mapping' - if inout == "in": - current_service_dict["inports"].append((argname, typename) ) - else: - current_service_dict["outports"].append((argname, typename) ) - # - # For each service : - # - generate implementation of c++ servant - # - store it in service_definition[serv]["impl"] - for serv in list_of_services: - if debug: - print "service : ",serv - print " inports -> ",service_definition[serv]["inports"] - print " outports -> ",service_definition[serv]["outports"] - print " return -> ",service_definition[serv]["ret"] - - - # Part 1 : Argument pre-processing - s_argument_processing="//\tArguments processing\n" - for (argname,argtype) in service_definition[serv]["inports"] + \ - service_definition[serv]["outports"]: - format=cpp_impl_a[argtype] - s_argument_processing += format % {"arg" : argname } - - # if there was no args - if s_argument_processing=="//\tArguments processing\n": - s_argument_processing="" - - - # Part 2 : Call to the underlying c++ function - s_call_cpp_function="//\tCall cpp component\n\t" - rtn_type=service_definition[serv]["ret"] - - # if return type is void, the call syntax is different - if rtn_type == "void" : - s_call_cpp_function += "cppCompo_->%s(" % serv - else: - s_call_cpp_function +=\ - "%s _rtn_cpp = cppCompo_->%s(" % (rtn_type ,serv ) - - for (argname,argtype) in service_definition[serv]["ports"]: - # special treatment for some arguments - post="" - pre="" - - if string.find(cpp_impl_a[argtype],"auto_ptr" ) != -1 : - # for auto_ptr argument, retrieve the raw pointer behind - post=".get()" - if argtype == "const MEDMEM::MESH&" or \ - argtype == "const MEDMEM::SUPPORT&" : - # we cannot create MESHClient on the stack - # (private constructor!), - # so we create it on the heap and dereference it - pre="*" - - post+="," # separator between arguments - s_call_cpp_function += " %s_%s%s" % ( pre,argname,post) - if s_call_cpp_function[-1]==',': - # get rid of trailing comma - s_call_cpp_function=s_call_cpp_function[0:-1] - - s_call_cpp_function=s_call_cpp_function+');\n' - - # Part 3.a : Out Argument Post-processing - s_argument_postprocessing="//\tPost-processing & return\n" - for (argname,argtype) in service_definition[serv]["outports"]: - format=cpp_impl_c[argtype] - # the treatment of %(module) is postponed in makecxx() - # because we don't know here the module name - s_argument_postprocessing += \ - format % {"arg" : argname, "module" : "%(module)s" } - - # Part 3.b : In Argument Post-processing - for (argname,argtype) in service_definition[serv]["inports"]: - # not all in types require a treatment - if cpp_impl_c.has_key(argtype): - format=cpp_impl_c[argtype] - # id : treatment of %(module) is postponed in makecxx - s_argument_postprocessing += \ - format % {"arg" : argname, "module" : "%(module)s" } - - # Part 3.c : return processing - s_rtn_processing=cpp_impl_b[rtn_type] - - format_end_serv = "\tendService(\"%(class_name)s_i::%(serv_name)s\");" - format_end_serv += "\n\tEND_OF(\"%(class_name)s_i::%(serv_name)s\");\n" - s_rtn_processing += format_end_serv %\ - { "serv_name" : serv, "class_name" : class_name } - - if rtn_type != "void": - s_rtn_processing += "\treturn _rtn_ior;" - - service_definition[serv]["impl"] = s_argument_processing + \ - s_call_cpp_function + \ - s_argument_postprocessing + \ - s_rtn_processing - if debug: - print "implementation :\n",service_definition[serv]["impl"] - - # - # Create a list of Service objects (called services), - # and give it to Component constructor - # - services=[] - self.use_medmem=False - self.use_medcoupling=False - for serv in list_of_services: - # for inports and outports, Service class expects a list of tuples, - # each tuple containing the name and the yacs type of the port - # thus we need to convert c++ types to yacs types - # (we use for that the cpp2yacs_mapping table) - inports=[] - for op in service_definition[serv]["inports"]: - inports.append([op[0], cpp2yacs_mapping[op[1]] ] ) - - outports = [] - for op in service_definition[serv]["outports"]: - outports.append([op[0], cpp2yacs_mapping[op[1]] ] ) - - Return="void" - if service_definition[serv]["ret"] != "void": - Return=cpp2yacs_mapping[service_definition[serv]["ret"]] - - # find out if component uses medmem types and/or medcoupling types - for (argname,argtype) in inports + outports + [("return",Return)]: - if moduleTypes[argtype]=="MED": - if argtype.count("CorbaInterface")>0: - self.use_medcoupling=True - else: - self.use_medmem=True - break - - code=service_definition[serv]["impl"] - if debug: - print "service : ",serv - print " inports -> ",service_definition[serv]["inports"] - print " converted inports -> ",inports - print " outports -> ",service_definition[serv]["outports"] - print " converted outports -> ",outports - print " Return -> ",service_definition[serv]["ret"] - print " converted Return -> ",Return - - services.append(Service(serv, - inport=inports, - outport=outports, - ret=Return, - defs="", - body=code, - ) ) - - Includes="-I${"+name+"CPP_ROOT_DIR}/include" - Libs="-L${"+name+"CPP_ROOT_DIR}/lib -l"+name+"CXX" - Compodefs="" - Inheritedclass="" - self.inheritedconstructor="" - if self.use_medmem: - Compodefs=""" -#include CORBA_CLIENT_HEADER(MED) -#include CORBA_CLIENT_HEADER(MED_Gen) -#include "FIELDClient.hxx" -#include "MESHClient.hxx" -#include "MEDMEM_Support_i.hxx" -#include "MEDMEM_Mesh_i.hxx" -#include "MEDMEM_FieldTemplate_i.hxx" -#include "Med_Gen_Driver_i.hxx" -""" - Inheritedclass="Med_Gen_Driver_i, public SALOMEMultiComm" - self.inheritedconstructor="Med_Gen_Driver_i(orb)," - - if self.use_medcoupling: - Compodefs+=""" -#include CORBA_CLIENT_HEADER(MEDCouplingCorbaServant) -#include CORBA_CLIENT_HEADER(MED_Gen) -#include "MEDCouplingFieldDoubleServant.hxx" -#include "MEDCouplingUMeshServant.hxx" -#include "DataArrayDoubleServant.hxx" -#include "MEDCouplingFieldDouble.hxx" -#include "MEDCouplingUMesh.hxx" -#include "MEDCouplingUMeshClient.hxx" -#include "MEDCouplingFieldDouble.hxx" -#include "MEDCouplingFieldDoubleClient.hxx" -#include "MEDCouplingMemArray.hxx" -#include "DataArrayDoubleClient.hxx" -""" - - Component.__init__(self, name, services, impl="CPP", libs=Libs, - rlibs="", includes=Includes, kind="lib", - sources=None,inheritedclass=Inheritedclass, - compodefs=Compodefs) - -# ------------------------------------------------------------------------------ - def makeCompo(self, gen): - """generate files for C++ component - return a dict where key is the file name and - value is the content of the file - """ - cxxfile = "%s_i.cxx" % self.name - hxxfile = "%s_i.hxx" % self.name - return {"Makefile.am":gen.makeMakefile(self.getMakefileItems(gen)), - cxxfile:self.makecxx(gen), - hxxfile:self.makehxx(gen) - } - -# ------------------------------------------------------------------------------ - def getMakefileItems(self,gen): - makefileItems={"header":""" -include $(top_srcdir)/adm_local/make_common_starter.am - -"""} - makefileItems["lib_LTLIBRARIES"]=["lib"+self.name+"Engine.la"] - makefileItems["salomeinclude_HEADERS"]=["%s_i.hxx" % self.name] - makefileItems["body"]=compoMakefile.substitute(module=gen.module.name, - component=self.name, - libs=self.libs, - includes=self.includes) - return makefileItems - -# ------------------------------------------------------------------------------ - def makehxx(self, gen): - """return a string that is the content of .hxx file - """ - services = [] - for serv in self.services: - service = " %s %s(" % (corba_rtn_type(serv.ret,gen.module.name), - serv.name) - service = service+gen.makeArgs(serv)+") throw (SALOME::SALOME_Exception);" - services.append(service) - servicesdef = "\n".join(services) - - inheritedclass=self.inheritedclass - if self.inheritedclass: - inheritedclass= " public virtual " + self.inheritedclass + "," - - return hxxCompo.substitute(component=self.name, - module=gen.module.name, - servicesdef=servicesdef, - inheritedclass=inheritedclass, - compodefs=self.compodefs) - -# ------------------------------------------------------------------------------ - def makecxx(self, gen, exe=0): - """return a string that is the content of .cxx file - """ - services = [] - inits = [] - defs = [] - for serv in self.services: - defs.append(serv.defs) - print "CNC bug : ",serv.body - service = cxxService.substitute( - component=self.name, - service=serv.name, - ret=corba_rtn_type(serv.ret,gen.module.name), - parameters=gen.makeArgs(serv), - body=serv.body % {"module":gen.module.name+"_ORB"} ) - services.append(service) - return cxxCompo.substitute(component=self.name, - inheritedconstructor=self.inheritedconstructor, - servicesdef="\n".join(defs), - servicesimpl="\n".join(services)) - -# ------------------------------------------------------------------------------ - def getGUIfilesTemplate(self): - """generate in a temporary directory files for a generic GUI, - and return a list with file names. - it is the responsability of the user to get rid - of the temporary directory when finished - """ - gui_cxx=hxxgui_cxx.substitute(component_name=self.name) - gui_h=hxxgui_h.substitute(component_name=self.name) - gui_icon_ts=hxxgui_icon_ts.substitute(component_name=self.name) - gui_message_en=hxxgui_message_en.substitute(component_name=self.name) - gui_message_fr=hxxgui_message_fr.substitute(component_name=self.name) - gui_config=hxxgui_config.substitute(component_name=self.name) - gui_xml_fr=hxxgui_xml_fr.substitute(component_name=self.name) - gui_xml_en=hxxgui_xml_en.substitute(component_name=self.name) - gui_salomeapp_gen=cppsalomeapp.substitute(module=self.name,lmodule=self.name.lower()) - # for a salome component generated by hxx2salome from a c++ component, the documentation points at the c++ component documentation - salome_doc_path=os.path.join("%"+self.name+"_ROOT_DIR%","share","doc","salome","gui",self.name.lower(),"index.html") - cpp_doc_path=os.path.join("%"+self.name+"CPP_ROOT_DIR%","share","doc",self.name,"index.html") - gui_salomeapp=gui_salomeapp_gen.replace(salome_doc_path,cpp_doc_path) - temp_dir=mkdtemp() - gui_cxx_file_name=os.path.join(temp_dir,self.name+"GUI.cxx") - gui_h_file_name=os.path.join(temp_dir,self.name+"GUI.h") - gui_icon_ts_file_name=os.path.join(temp_dir,self.name+"_icons.ts") - gui_message_en_file_name=os.path.join(temp_dir,self.name+"_msg_en.ts") - gui_message_fr_file_name=os.path.join(temp_dir,self.name+"_msg_fr.ts") - gui_config_file_name=os.path.join(temp_dir,"config") - gui_xml_fr_file_name=os.path.join(temp_dir,self.name+"_en.xml") - gui_xml_en_file_name=os.path.join(temp_dir,self.name+"_fr.xml") - gui_salomeapp_file_name=os.path.join(temp_dir,"SalomeApp.xml") - list_of_gui_names=[] - - gui_cxx_file=open(gui_cxx_file_name,"w") - gui_cxx_file.write(gui_cxx) - gui_cxx_file.close() - list_of_gui_names.append(gui_cxx_file_name) - - gui_h_file=open(gui_h_file_name,"w") - gui_h_file.write(gui_h) - gui_h_file.close() - list_of_gui_names.append(gui_h_file_name) - - gui_icon_ts_file=open(gui_icon_ts_file_name,"w") - gui_icon_ts_file.write(gui_icon_ts) - gui_icon_ts_file.close() - list_of_gui_names.append(gui_icon_ts_file_name) - - gui_message_en_file=open(gui_message_en_file_name,"w") - gui_message_en_file.write(gui_message_en) - gui_message_en_file.close() - list_of_gui_names.append(gui_message_en_file_name) - - gui_message_fr_file=open(gui_message_fr_file_name,"w") - gui_message_fr_file.write(gui_message_fr) - gui_message_fr_file.close() - list_of_gui_names.append(gui_message_fr_file_name) - - gui_config_file=open(gui_config_file_name,"w") - gui_config_file.write(gui_config) - gui_config_file.close() - list_of_gui_names.append(gui_config_file_name) - - gui_xml_fr_file=open(gui_xml_fr_file_name,"w") - gui_xml_fr_file.write(gui_xml_fr) - gui_xml_fr_file.close() - list_of_gui_names.append(gui_xml_fr_file_name) - - gui_xml_en_file=open(gui_xml_en_file_name,"w") - gui_xml_en_file.write(gui_xml_en) - gui_xml_en_file.close() - list_of_gui_names.append(gui_xml_en_file_name) - - gui_salomeapp_file=open(gui_salomeapp_file_name,"w") - gui_salomeapp_file.write(gui_salomeapp) - gui_salomeapp_file.close() - list_of_gui_names.append(gui_salomeapp_file_name) - - - return list_of_gui_names +# Copyright (C) 2009-2012 EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# +""" + Module that generates SALOME c++ Component from a non SALOME c++ component + (its header and its shares library) +""" + +debug=1 +import os +import string +import fnmatch +from tempfile import mkstemp +from gener import Component, Invalid +from hxx_tmpl import cxxService, hxxCompo, cxxCompo, compoMakefile +from module_generator import Service +from yacstypes import corba_rtn_type,moduleTypes +from hxx_awk import parse01,parse1,parse2,parse3 +from hxx_awk import cpp2idl_mapping +# these tables contain the part of code which depends upon c++ types +from hxx_awk import cpp_impl_a,cpp_impl_b,cpp_impl_c +from hxx_awk import cpp2yacs_mapping +from tempfile import mkdtemp +from hxx_tmpl_gui import hxxgui_cxx, hxxgui_h, hxxgui_icon_ts +from hxx_tmpl_gui import hxxgui_message_en, hxxgui_message_fr +from hxx_tmpl_gui import hxxgui_config, hxxgui_xml_fr, hxxgui_xml_en +from gui_tmpl import cppsalomeapp + +# ------------------------------------------------------------------------------ + +class HXX2SALOMEComponent(Component): + def __init__(self, hxxfile , cpplib , cpp_path ): + # search a file within a directory tree + def search_file(pattern, root): + matches = [] + for path, dirs, files in os.walk(os.path.abspath(root)): + for filename in fnmatch.filter(files, pattern): + matches.append(os.path.join(path, filename)) + return matches + + hxxfileful = search_file(hxxfile,cpp_path) + cpplibful = search_file(cpplib,cpp_path) + format_error = 'Error in HXX2SALOMEComponent : file %s ot found in %s' + assert len(hxxfileful) > 0, format_error % (hxxfile, cpp_path) + assert len(cpplibful) > 0, format_error % (cpplib, cpp_path) + hxxfile = hxxfileful[0] + cpplib = cpplibful[0] + + # grab name of c++ component + cmd1="""awk '$1 == "class" && $0 !~ /;/ {print $2}' """ + hxxfile +\ + """|awk -F: '{printf "%s",$1}' """ + f=os.popen(cmd1) + class_name=f.readlines()[0] + name=class_name + print "classname=",class_name + f.close() + + # create temporary awk files for the parsing + (fd01,p01n)=mkstemp() + f01=os.fdopen(fd01,"w") + f01.write(parse01) + f01.close() + + (fd1,p1n)=mkstemp() + f1=os.fdopen(fd1,"w") + f1.write(parse1) + f1.close() + + (fd2,p2n)=mkstemp() + f2=os.fdopen(fd2,"w") + f2.write(parse2) + f2.close() + + (fd3,p3n)=mkstemp() + f3=os.fdopen(fd3,"w") + f3.write(parse3) + f3.close() + + # awk parsing of hxx files - + # result written in file parse_type_result + cmd2 = [ + "cat %s" % hxxfile, + "awk -f %s" % p01n, + "sed 's/virtual //g'", + "sed 's/MEDMEM_EXPORT//g'", + "sed 's/throw.*;/;/g'", + "awk -f %s" % p1n, + "awk -f %s" % p2n, + "awk -v class_name=%s -f %s" % (class_name, p3n) ] + cmd2 = ' | '.join(cmd2) + + #os.system(cmd2) + import subprocess, sys + subprocess.call(cmd2, shell=True, stdout=sys.stdout, stderr=subprocess.STDOUT) + os.remove(p01n) + os.remove(p1n) + os.remove(p2n) + os.remove(p3n) + + # Retrieve the information which was generated in + # the file parse_type_result. + # The structure of the file is : + # + # Function return_type function_name + # [arg1_type arg1_name] + # [arg2_type arg2_name] + # ... + # The service names are stored in list_of_services + # The information relative to a service (called service_name) is stored in + # the dictionnary service_definition[service_name] + list_of_services=[] + service_definition={} + result_parsing=open("parse_type_result","r") + for line in result_parsing.readlines(): + line=line[0:-1] # get rid of trailing \n + words = string.split(line,';') + + if len(words) >=3 and words[0] == "Function": # detect a new service + function_name=words[2] + # store the name of new service + list_of_services.append(function_name) + # create a dict to store informations relative to this service + service_definition[function_name]={} + service_definition[function_name]["ret"]=words[1] # return type + service_definition[function_name]["inports"]=[] + service_definition[function_name]["outports"]=[] + service_definition[function_name]["ports"]=[] + service_definition[function_name]["impl"]=[] + + # an argument type and argument name of the current service + if len(words) == 2: + current_service=list_of_services[-1] + current_service_dict=service_definition[current_service] + typename=words[0] + argname=words[1] + # store in c++ order the arg names + current_service_dict["ports"].append( (argname,typename) ) + + # separate in from out parameters + inout=cpp2idl_mapping[typename][0:2] + assert inout=="in" or inout=="ou",'Error in table cpp2idl_mapping' + if inout == "in": + current_service_dict["inports"].append((argname, typename) ) + else: + current_service_dict["outports"].append((argname, typename) ) + # + # For each service : + # - generate implementation of c++ servant + # - store it in service_definition[serv]["impl"] + for serv in list_of_services: + if debug: + print "service : ",serv + print " inports -> ",service_definition[serv]["inports"] + print " outports -> ",service_definition[serv]["outports"] + print " return -> ",service_definition[serv]["ret"] + + + # Part 1 : Argument pre-processing + s_argument_processing="//\tArguments processing\n" + for (argname,argtype) in service_definition[serv]["inports"] + \ + service_definition[serv]["outports"]: + format=cpp_impl_a[argtype] + s_argument_processing += format % {"arg" : argname } + + # if there was no args + if s_argument_processing=="//\tArguments processing\n": + s_argument_processing="" + + + # Part 2 : Call to the underlying c++ function + s_call_cpp_function="//\tCall cpp component\n\t" + rtn_type=service_definition[serv]["ret"] + + # if return type is void, the call syntax is different + if rtn_type == "void" : + s_call_cpp_function += "cppCompo_->%s(" % serv + else: + s_call_cpp_function +=\ + "%s _rtn_cpp = cppCompo_->%s(" % (rtn_type ,serv ) + + for (argname,argtype) in service_definition[serv]["ports"]: + # special treatment for some arguments + post="" + pre="" + + if string.find(cpp_impl_a[argtype],"auto_ptr" ) != -1 : + # for auto_ptr argument, retrieve the raw pointer behind + post=".get()" + if argtype == "const MEDMEM::MESH&" or \ + argtype == "const MEDMEM::SUPPORT&" : + # we cannot create MESHClient on the stack + # (private constructor!), + # so we create it on the heap and dereference it + pre="*" + + post+="," # separator between arguments + s_call_cpp_function += " %s_%s%s" % ( pre,argname,post) + if s_call_cpp_function[-1]==',': + # get rid of trailing comma + s_call_cpp_function=s_call_cpp_function[0:-1] + + s_call_cpp_function=s_call_cpp_function+');\n' + + # Part 3.a : Out Argument Post-processing + s_argument_postprocessing="//\tPost-processing & return\n" + for (argname,argtype) in service_definition[serv]["outports"]: + format=cpp_impl_c[argtype] + # the treatment of %(module) is postponed in makecxx() + # because we don't know here the module name + s_argument_postprocessing += \ + format % {"arg" : argname, "module" : "%(module)s" } + + # Part 3.b : In Argument Post-processing + for (argname,argtype) in service_definition[serv]["inports"]: + # not all in types require a treatment + if cpp_impl_c.has_key(argtype): + format=cpp_impl_c[argtype] + # id : treatment of %(module) is postponed in makecxx + s_argument_postprocessing += \ + format % {"arg" : argname, "module" : "%(module)s" } + + # Part 3.c : return processing + s_rtn_processing=cpp_impl_b[rtn_type] + + format_end_serv = "\tendService(\"%(class_name)s_i::%(serv_name)s\");" + format_end_serv += "\n\tEND_OF(\"%(class_name)s_i::%(serv_name)s\");\n" + s_rtn_processing += format_end_serv %\ + { "serv_name" : serv, "class_name" : class_name } + + if rtn_type != "void": + s_rtn_processing += "\treturn _rtn_ior;" + + service_definition[serv]["impl"] = s_argument_processing + \ + s_call_cpp_function + \ + s_argument_postprocessing + \ + s_rtn_processing + if debug: + print "implementation :\n",service_definition[serv]["impl"] + + # + # Create a list of Service objects (called services), + # and give it to Component constructor + # + services=[] + self.use_medmem=False + self.use_medcoupling=False + for serv in list_of_services: + # for inports and outports, Service class expects a list of tuples, + # each tuple containing the name and the yacs type of the port + # thus we need to convert c++ types to yacs types + # (we use for that the cpp2yacs_mapping table) + inports=[] + for op in service_definition[serv]["inports"]: + inports.append([op[0], cpp2yacs_mapping[op[1]] ] ) + + outports = [] + for op in service_definition[serv]["outports"]: + outports.append([op[0], cpp2yacs_mapping[op[1]] ] ) + + Return="void" + if service_definition[serv]["ret"] != "void": + Return=cpp2yacs_mapping[service_definition[serv]["ret"]] + + # find out if component uses medmem types and/or medcoupling types + for (argname,argtype) in inports + outports + [("return",Return)]: + if moduleTypes[argtype]=="MED": + if argtype.count("CorbaInterface")>0: + self.use_medcoupling=True + else: + self.use_medmem=True + break + + code=service_definition[serv]["impl"] + if debug: + print "service : ",serv + print " inports -> ",service_definition[serv]["inports"] + print " converted inports -> ",inports + print " outports -> ",service_definition[serv]["outports"] + print " converted outports -> ",outports + print " Return -> ",service_definition[serv]["ret"] + print " converted Return -> ",Return + + services.append(Service(serv, + inport=inports, + outport=outports, + ret=Return, + defs="", + body=code, + ) ) + + Includes="-I${"+name+"CPP_ROOT_DIR}/include" + Libs="-L${"+name+"CPP_ROOT_DIR}/lib -l"+name+"CXX" + Compodefs="" + Inheritedclass="" + self.inheritedconstructor="" + if self.use_medmem: + Compodefs=""" +#include CORBA_CLIENT_HEADER(MED) +#include CORBA_CLIENT_HEADER(MED_Gen) +#include "FIELDClient.hxx" +#include "MESHClient.hxx" +#include "MEDMEM_Support_i.hxx" +#include "MEDMEM_Mesh_i.hxx" +#include "MEDMEM_FieldTemplate_i.hxx" +#include "Med_Gen_Driver_i.hxx" +""" + Inheritedclass="Med_Gen_Driver_i, public SALOMEMultiComm" + self.inheritedconstructor="Med_Gen_Driver_i(orb)," + + if self.use_medcoupling: + Compodefs+=""" +#include CORBA_CLIENT_HEADER(MEDCouplingCorbaServant) +#include CORBA_CLIENT_HEADER(MED_Gen) +#include "MEDCouplingFieldDoubleServant.hxx" +#include "MEDCouplingUMeshServant.hxx" +#include "DataArrayDoubleServant.hxx" +#include "MEDCouplingFieldDouble.hxx" +#include "MEDCouplingUMesh.hxx" +#include "MEDCouplingUMeshClient.hxx" +#include "MEDCouplingFieldDouble.hxx" +#include "MEDCouplingFieldDoubleClient.hxx" +#include "MEDCouplingMemArray.hxx" +#include "DataArrayDoubleClient.hxx" +""" + + Component.__init__(self, name, services, impl="CPP", libs=Libs, + rlibs="", includes=Includes, kind="lib", + sources=None,inheritedclass=Inheritedclass, + compodefs=Compodefs) + +# ------------------------------------------------------------------------------ + def makeCompo(self, gen): + """generate files for C++ component + return a dict where key is the file name and + value is the content of the file + """ + cxxfile = "%s_i.cxx" % self.name + hxxfile = "%s_i.hxx" % self.name + return {"Makefile.am":gen.makeMakefile(self.getMakefileItems(gen)), + cxxfile:self.makecxx(gen), + hxxfile:self.makehxx(gen) + } + +# ------------------------------------------------------------------------------ + def getMakefileItems(self,gen): + makefileItems={"header":""" +include $(top_srcdir)/adm_local/make_common_starter.am + +"""} + makefileItems["lib_LTLIBRARIES"]=["lib"+self.name+"Engine.la"] + makefileItems["salomeinclude_HEADERS"]=["%s_i.hxx" % self.name] + makefileItems["body"]=compoMakefile.substitute(module=gen.module.name, + component=self.name, + libs=self.libs, + includes=self.includes) + return makefileItems + +# ------------------------------------------------------------------------------ + def makehxx(self, gen): + """return a string that is the content of .hxx file + """ + services = [] + for serv in self.services: + service = " %s %s(" % (corba_rtn_type(serv.ret,gen.module.name), + serv.name) + service = service+gen.makeArgs(serv)+") throw (SALOME::SALOME_Exception);" + services.append(service) + servicesdef = "\n".join(services) + + inheritedclass=self.inheritedclass + if self.inheritedclass: + inheritedclass= " public virtual " + self.inheritedclass + "," + + return hxxCompo.substitute(component=self.name, + module=gen.module.name, + servicesdef=servicesdef, + inheritedclass=inheritedclass, + compodefs=self.compodefs) + +# ------------------------------------------------------------------------------ + def makecxx(self, gen, exe=0): + """return a string that is the content of .cxx file + """ + services = [] + inits = [] + defs = [] + for serv in self.services: + defs.append(serv.defs) + print "CNC bug : ",serv.body + service = cxxService.substitute( + component=self.name, + service=serv.name, + ret=corba_rtn_type(serv.ret,gen.module.name), + parameters=gen.makeArgs(serv), + body=serv.body % {"module":gen.module.name+"_ORB"} ) + services.append(service) + return cxxCompo.substitute(component=self.name, + inheritedconstructor=self.inheritedconstructor, + servicesdef="\n".join(defs), + servicesimpl="\n".join(services)) + +# ------------------------------------------------------------------------------ + def getGUIfilesTemplate(self): + """generate in a temporary directory files for a generic GUI, + and return a list with file names. + it is the responsability of the user to get rid + of the temporary directory when finished + """ + gui_cxx=hxxgui_cxx.substitute(component_name=self.name) + gui_h=hxxgui_h.substitute(component_name=self.name) + gui_icon_ts=hxxgui_icon_ts.substitute(component_name=self.name) + gui_message_en=hxxgui_message_en.substitute(component_name=self.name) + gui_message_fr=hxxgui_message_fr.substitute(component_name=self.name) + gui_config=hxxgui_config.substitute(component_name=self.name) + gui_xml_fr=hxxgui_xml_fr.substitute(component_name=self.name) + gui_xml_en=hxxgui_xml_en.substitute(component_name=self.name) + gui_salomeapp_gen=cppsalomeapp.substitute(module=self.name,lmodule=self.name.lower()) + # for a salome component generated by hxx2salome from a c++ component, the documentation points at the c++ component documentation + salome_doc_path=os.path.join("%"+self.name+"_ROOT_DIR%","share","doc","salome","gui",self.name.lower(),"index.html") + cpp_doc_path=os.path.join("%"+self.name+"CPP_ROOT_DIR%","share","doc",self.name,"index.html") + gui_salomeapp=gui_salomeapp_gen.replace(salome_doc_path,cpp_doc_path) + temp_dir=mkdtemp() + gui_cxx_file_name=os.path.join(temp_dir,self.name+"GUI.cxx") + gui_h_file_name=os.path.join(temp_dir,self.name+"GUI.h") + gui_icon_ts_file_name=os.path.join(temp_dir,self.name+"_icons.ts") + gui_message_en_file_name=os.path.join(temp_dir,self.name+"_msg_en.ts") + gui_message_fr_file_name=os.path.join(temp_dir,self.name+"_msg_fr.ts") + gui_config_file_name=os.path.join(temp_dir,"config") + gui_xml_fr_file_name=os.path.join(temp_dir,self.name+"_en.xml") + gui_xml_en_file_name=os.path.join(temp_dir,self.name+"_fr.xml") + gui_salomeapp_file_name=os.path.join(temp_dir,"SalomeApp.xml") + list_of_gui_names=[] + + gui_cxx_file=open(gui_cxx_file_name,"w") + gui_cxx_file.write(gui_cxx) + gui_cxx_file.close() + list_of_gui_names.append(gui_cxx_file_name) + + gui_h_file=open(gui_h_file_name,"w") + gui_h_file.write(gui_h) + gui_h_file.close() + list_of_gui_names.append(gui_h_file_name) + + gui_icon_ts_file=open(gui_icon_ts_file_name,"w") + gui_icon_ts_file.write(gui_icon_ts) + gui_icon_ts_file.close() + list_of_gui_names.append(gui_icon_ts_file_name) + + gui_message_en_file=open(gui_message_en_file_name,"w") + gui_message_en_file.write(gui_message_en) + gui_message_en_file.close() + list_of_gui_names.append(gui_message_en_file_name) + + gui_message_fr_file=open(gui_message_fr_file_name,"w") + gui_message_fr_file.write(gui_message_fr) + gui_message_fr_file.close() + list_of_gui_names.append(gui_message_fr_file_name) + + gui_config_file=open(gui_config_file_name,"w") + gui_config_file.write(gui_config) + gui_config_file.close() + list_of_gui_names.append(gui_config_file_name) + + gui_xml_fr_file=open(gui_xml_fr_file_name,"w") + gui_xml_fr_file.write(gui_xml_fr) + gui_xml_fr_file.close() + list_of_gui_names.append(gui_xml_fr_file_name) + + gui_xml_en_file=open(gui_xml_en_file_name,"w") + gui_xml_en_file.write(gui_xml_en) + gui_xml_en_file.close() + list_of_gui_names.append(gui_xml_en_file_name) + + gui_salomeapp_file=open(gui_salomeapp_file_name,"w") + gui_salomeapp_file.write(gui_salomeapp) + gui_salomeapp_file.close() + list_of_gui_names.append(gui_salomeapp_file_name) + + + return list_of_gui_names