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