cd $script_dir
-list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 hxx1"
+list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 mpi1 parahxx1 hxx1"
for dir in $list_dirs ; do
cd $dir
echo Building $dir ...
script_dir=`dirname $0`
cd $script_dir
-list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 hxx1"
+list_dirs="calcium1 calcium2 cpp1 cpp2 cppgui1 fort1 fort2 pydoc1 pygui1 pyth1 pyth2 types1 mpi1 parahxx1 hxx1"
for dir in $list_dirs ; do
cd $dir
--- /dev/null
+# Copyright (C) 2009-2015 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, or (at your option) any later version.
+#
+# 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
+#
+
+clean:
+ rm -rf *.o *.so appli install *.bak traceExec_* mymodule_* *.err *.log
+ cd mpilib; make clean
--- /dev/null
+A example of a MPI component
+=========================================
+
+To build this example, modify the ../exec.sh file to take into account your configuration.
+Run build.sh to build and test the component.
+
+You should get a SALOME module in source form (mymodule_SRC), its installation (install) and
+a SALOME application (appli) composed of modules KERNEL, GUI, YACS and the new module cppcompos.
+
+To run a coupling:
+
+ 1. start SALOME in background : ./appli/salome -t
+ 2. run the example schema in a SALOME session : ./appli/salome shell -- driver coupling.xml
+ 3. examine output files in /tmp
+ 4. shutdown SALOME : ./appli/salome killall
--- /dev/null
+(cd mpilib; make)
+../exec.sh python components.py
+
+# test
+appli/salome shell ../test_compo.py
+
--- /dev/null
+# -*- coding: utf-8 -*-
+import os
+from module_generator import Generator,Module,Service
+from module_generator import MPIComponent
+from module_generator import Library
+
+SALOME_ROOT=os.getenv("SALOME_DIR")
+prerequis_file=os.path.join(SALOME_ROOT, "salome_prerequisites.sh")
+
+kernel_root_dir=os.getenv("KERNEL_ROOT_DIR")
+gui_root_dir=os.getenv("GUI_ROOT_DIR")
+yacs_root_dir=os.getenv("YACS_ROOT_DIR")
+
+context={'update':1,
+ "makeflags":"-j2",
+ "prerequisites":prerequis_file,
+ "kernel":kernel_root_dir
+ }
+
+cwd=os.getcwd()
+
+# PUT HERE DEFINITIONS OF THE COMPONENTS AND THE SERVICES
+body_a="""
+Mylibmpi myinstance;
+res_val = myinstance.mympi_funct(in_val);
+"""
+
+defs_service="""
+"""
+
+service_s = Service("mpifunc",
+ inport=[("in_val", "long")],
+ outport=[("res_val", "long")],
+ body=body_a,
+ defs=defs_service
+ )
+
+mpilib_root_path = os.path.join(cwd, "mpilib")
+mpilib_include_path = os.path.join(mpilib_root_path, "include")
+mpilib_lib_path = os.path.join(mpilib_root_path, "lib")
+
+compodefs = """
+#include "mylibmpi.h"
+"""
+
+compo=MPIComponent("mycompoMpi",
+ services=[service_s],
+ compodefs=compodefs,
+ libs=[Library(name="mylibmpi", path=mpilib_lib_path)],
+ rlibs=mpilib_lib_path,
+ includes=mpilib_include_path,
+ )
+
+g=Generator(Module("mymodule",components=[compo],prefix="./install"),context)
+g.generate()
+g.configure()
+g.make()
+g.install()
+g.make_appli("appli",
+ restrict=["KERNEL","GUI","YACS","JOBMANAGER"])
+
+
--- /dev/null
+<?xml version='1.0' encoding='iso-8859-1' ?>
+<proc name="newSchema_1">
+ <property name="DefaultStudyID" value="1"/>
+ <type name="string" kind="string"/>
+ <struct name="Engines/dataref">
+ <member name="ref" type="string"/>
+ </struct>
+ <type name="bool" kind="bool"/>
+ <sequence name="boolvec" content="bool"/>
+ <type name="double" kind="double"/>
+ <sequence name="dblevec" content="double"/>
+ <objref name="file" id="file"/>
+ <type name="int" kind="int"/>
+ <sequence name="intvec" content="int"/>
+ <struct name="stringpair">
+ <member name="name" type="string"/>
+ <member name="value" type="string"/>
+ </struct>
+ <sequence name="propvec" content="stringpair"/>
+ <objref name="pyobj" id="python:obj:1.0"/>
+ <sequence name="seqboolvec" content="boolvec"/>
+ <sequence name="seqdblevec" content="dblevec"/>
+ <sequence name="seqintvec" content="intvec"/>
+ <sequence name="seqpyobj" content="pyobj"/>
+ <sequence name="stringvec" content="string"/>
+ <sequence name="seqstringvec" content="stringvec"/>
+ <container name="DefaultContainer">
+ <property name="container_kind" value="Salome"/>
+ <property name="attached_on_cloning" value="0"/>
+ <property name="container_name" value="FactoryServer"/>
+ <property name="name" value="localhost"/>
+ </container>
+ <container name="container0">
+ <property name="container_kind" value="Salome"/>
+ <property name="attached_on_cloning" value="0"/>
+ <property name="isMPI" value="true"/>
+ <property name="nb_parallel_procs" value="3"/>
+ </container>
+ <service name="mpifunc1">
+ <component>mycompoMpi</component>
+ <load container="container0"/>
+ <method>mpifunc</method>
+ <inport name="in_val" type="int"/>
+ <outport name="res_val" type="int"/>
+ </service>
+ <parameter>
+ <tonode>mpifunc1</tonode><toport>in_val</toport>
+ <value><int>1</int></value>
+ </parameter>
+ <presentation name="mpifunc1" x="4" y="42" width="158" height="63" expanded="1" expx="4" expy="42" expWidth="158" expHeight="63" shownState="0"/>
+ <presentation name="__ROOT__" x="0" y="0" width="166" height="109" expanded="1" expx="0" expy="0" expWidth="166" expHeight="109" shownState="0"/>
+</proc>
--- /dev/null
+
+all : myexe
+
+myexe : lib/libmylibmpi.so src/myexempi.cxx include/mylibmpi.h
+ mpic++ -o myexe -Iinclude src/myexempi.cxx -Llib -lmylibmpi
+
+lib/libmylibmpi.so : src/mylibmpi.cxx include/mylibmpi.h
+ mkdir -p lib; mpic++ -shared -fPIC -o lib/libmylibmpi.so -Iinclude src/mylibmpi.cxx
+
+clean :
+ rm -f myexe lib/libmylibmpi.so *~
--- /dev/null
+#ifndef _mylibmpi_h_
+#define _mylibmpi_h_
+
+#define MASTER 0
+
+class Mylibmpi
+{
+ public:
+ int mympi_funct(int v);
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "mylibmpi.h"
+#include <iostream>
+#include <mpi.h>
+
+int main(int argc, char* argv[])
+{
+ int namelen, numprocs, myid ;
+ int result;
+ Mylibmpi myinstance;
+
+ /** initialisation de mpi **/
+ MPI_Init(&argc,&argv);
+ /** combien y-a-t-il de processeurs ? **/
+ MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
+ /** numero du processus courant **/
+ MPI_Comm_rank(MPI_COMM_WORLD,&myid);
+
+ result = myinstance.mympi_funct(3);
+ if(MASTER == myid)
+ std::cout << "Resultat:" << result << std::endl;
+
+ /** fin du pg **/
+ MPI_Finalize();
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+#include "mylibmpi.h"
+#include "mpi.h"
+
+int Mylibmpi::mympi_funct(int v)
+{
+ int namelen, numprocs, myid ;
+ char processor_name[MPI_MAX_PROCESSOR_NAME] ;
+ int local_result;
+ int result, err_code;
+
+ /** combien y-a-t-il de processeurs ? **/
+ MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
+ /** numero du processus courant **/
+ MPI_Comm_rank(MPI_COMM_WORLD,&myid);
+ /** num du processeur courant **/
+ MPI_Get_processor_name(processor_name,&namelen);
+
+ local_result = myid + v;
+ err_code = MPI_Reduce(&local_result, &result, 1, MPI_INT, MPI_SUM,
+ MASTER, MPI_COMM_WORLD);
+ if(MPI_SUCCESS != err_code)
+ printf("%d: failure on mpc_reduce\n", myid);
+
+ return result;
+// if(MASTER == myid)
+//printf("id %d: result=%d\n", myid, result);
+
+}
\ No newline at end of file
--- /dev/null
+# Copyright (C) 2009-2015 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, or (at your option) any later version.
+#
+# 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
+#
+
+clean:
+ rm -rf *.o *.so appli install *.bak traceExec_* hxxcompos_* *.err *.log par*
--- /dev/null
+../exec.sh python components.py
+
+# test
+LD_LIBRARY_PATH=`pwd`/../mpi1/mpilib/lib/ appli/salome shell ../test_compo.py
+
--- /dev/null
+# Copyright (C) 2009-2015 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, or (at your option) any later version.
+#
+# 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
+from module_generator import Generator,Module,Service
+from module_generator import CPPComponent,PYComponent,HXX2SALOMEParaComponent
+class Invalid(Exception):
+ pass
+
+kernel_root_dir=os.environ["KERNEL_ROOT_DIR"]
+gui_root_dir=os.environ["GUI_ROOT_DIR"]
+yacs_root_dir=os.environ["YACS_ROOT_DIR"]
+med_root_dir=os.environ["MED_ROOT_DIR"]
+SALOME_ROOT=os.getenv("SALOME_DIR")
+prereq_file=os.path.join(SALOME_ROOT, "salome_prerequisites.sh")
+
+if not os.path.exists(prereq_file):
+ prereq_file=os.path.join(kernel_root_dir,"..","..","env_products.sh")
+if not os.path.exists(prereq_file):
+ raise Invalid("prerequisite file env_products.sh not found. please replace it manually in component.py")
+
+context={'update':1,
+ "makeflags":"",
+ "prerequisites":prereq_file,
+ "kernel":kernel_root_dir,
+ "gui":gui_root_dir,
+ "med":med_root_dir,
+ "yacs":yacs_root_dir,
+ }
+
+cwd=os.getcwd()
+cpppath=os.path.join(cwd,"..","mpi1","mpilib")
+
+# PUT HERE DEFINITIONS OF THE COMPONENTS AND THE SERVICES
+
+c1=HXX2SALOMEParaComponent("mylibmpi.h","libmylibmpi.so" , cpppath )
+
+g=Generator(Module("hxxcompos",components=[c1],prefix="./install"),context)
+g.generate()
+g.configure()
+g.make()
+g.install()
+g.make_appli("appli",
+ restrict=["KERNEL","GUI","YACS","MED"],
+ )
--- /dev/null
+<?xml version='1.0' encoding='iso-8859-1' ?>
+<proc name="newSchema_1">
+ <property name="DefaultStudyID" value="1"/>
+ <type name="string" kind="string"/>
+ <struct name="Engines/dataref">
+ <member name="ref" type="string"/>
+ </struct>
+ <type name="bool" kind="bool"/>
+ <sequence name="boolvec" content="bool"/>
+ <type name="double" kind="double"/>
+ <sequence name="dblevec" content="double"/>
+ <objref name="file" id="file"/>
+ <type name="int" kind="int"/>
+ <sequence name="intvec" content="int"/>
+ <struct name="stringpair">
+ <member name="name" type="string"/>
+ <member name="value" type="string"/>
+ </struct>
+ <sequence name="propvec" content="stringpair"/>
+ <objref name="pyobj" id="python:obj:1.0"/>
+ <sequence name="seqboolvec" content="boolvec"/>
+ <sequence name="seqdblevec" content="dblevec"/>
+ <sequence name="seqintvec" content="intvec"/>
+ <sequence name="seqpyobj" content="pyobj"/>
+ <sequence name="stringvec" content="string"/>
+ <sequence name="seqstringvec" content="stringvec"/>
+ <container name="DefaultContainer">
+ <property name="container_kind" value="Salome"/>
+ <property name="attached_on_cloning" value="0"/>
+ <property name="container_name" value="FactoryServer"/>
+ <property name="name" value="localhost"/>
+ </container>
+ <container name="container0">
+ <property name="container_kind" value="Salome"/>
+ <property name="attached_on_cloning" value="0"/>
+ <property name="isMPI" value="true"/>
+ <property name="nb_parallel_procs" value="3"/>
+ </container>
+ <service name="mympi_funct1">
+ <component>Mylibmpi</component>
+ <load container="container0"/>
+ <method>mympi_funct</method>
+ <inport name="v" type="int"/>
+ <outport name="return" type="int"/>
+ </service>
+ <parameter>
+ <tonode>mympi_funct1</tonode><toport>v</toport>
+ <value><int>1</int></value>
+ </parameter>
+ <presentation name="mympi_funct1" x="57" y="33" width="158" height="63" expanded="1" expx="57" expy="33" expWidth="158" expHeight="63" shownState="0"/>
+ <presentation name="__ROOT__" x="0" y="0" width="219" height="100" expanded="1" expx="0" expy="0" expWidth="219" expHeight="100" shownState="0"/>
+</proc>
from yacstypes import add_type
from salomemodules import add_module
from gener import Library
+from mpicompo import MPIComponent
#ifndef _${module}_IDL_
#define _${module}_IDL_
-#include "DSC_Engines.idl"
#include "SALOME_Exception.idl"
-#include "SALOME_PACOExtension.idl"
#include "SALOME_Component.idl"
#include "SALOME_Comm.idl"
-#include "SALOME_Parametric.idl"
${idldefs}
$${KERNEL_SalomeIDLKernel}
$${KERNEL_OpUtil}
$${KERNEL_SalomeContainer}
- $${KERNEL_SalomeDSCContainer}
- $${KERNEL_SalomeDSCSuperv}
- $${KERNEL_SalomeDatastream}
- $${KERNEL_SalomeDSCSupervBasic}
- $${KERNEL_CalciumC}
SalomeIDL${module}
${libs}
)
return a dict where key is the file name and value is the file content
"""
(cmake_text, cmake_vars) = self.additionalLibraries()
+ # DSC_libs are needed for datastream ports only
+ DSC_libs = """${KERNEL_SalomeDSCContainer}
+ ${KERNEL_SalomeDSCSuperv}
+ ${KERNEL_SalomeDatastream}
+ ${KERNEL_SalomeDSCSupervBasic}
+ ${KERNEL_CalciumC}
+ """
+ cmake_vars = DSC_libs + cmake_vars
cxxfile = "%s.cxx" % self.name
hxxfile = "%s.hxx" % self.name
if self.kind == "exe":
debug=0
from mod_tmpl import *
-from cata_tmpl import catalog, interface, idl, parallel_interface
+from cata_tmpl import catalog, interface, idl
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
cmake_vars = cmake_vars + "${" + lib.cmakeVarName() + "}\n "
var_template = Template("$${${name}_SalomeIDL${name}}")
- for mod in self.depend_modules:
+ for mod in self.getDependentModules():
if salome_modules[mod]["linklibs"]:
cmake_vars = cmake_vars + salome_modules[mod]["linklibs"]
else:
def setPrerequisites(self, prerequisites_file):
self.prerequisites = prerequisites_file
+ def getIdlInterfaces(self):
+ services = self.getIdlServices()
+ inheritedinterface=""
+ if self.inheritedinterface:
+ inheritedinterface=self.inheritedinterface+","
+ return interface.substitute(component=self.name,
+ services="\n".join(services),
+ inheritedinterface=inheritedinterface)
+
+ def getIdlServices(self):
+ services = []
+ for serv in self.services:
+ params = []
+ for name, typ in serv.inport:
+ if typ == "file":continue #files are not passed through IDL interface
+ if self.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 self.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)
+ return services
+
+ def getIdlDefs(self):
+ idldefs = """
+#include "DSC_Engines.idl"
+#include "SALOME_Parametric.idl"
+"""
+ if self.interfacedefs:
+ idldefs = idldefs + self.interfacedefs
+ return idldefs
+
+ def getDependentModules(self):
+ """get the list of SALOME modules used by the component
+ """
+ def get_dependent_modules(mod,modules):
+ modules.add(mod)
+ if salome_modules[mod].has_key("depends"):
+ for m in salome_modules[mod]["depends"]:
+ if m not in modules:
+ get_dependent_modules(m,modules)
+
+ depend_modules = set()
+ for serv in self.services:
+ for name, typ in serv.inport + serv.outport + [ ("return",serv.ret) ] :
+ mod = moduleTypes[typ]
+ if mod:
+ get_dependent_modules(mod,depend_modules)
+ return depend_modules
+
class Service(object):
"""
A :class:`Service` instance represents a component service with dataflow and datastream ports.
srcs = {}
#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 = {}
+ modules = set()
for compo in module.components:
- compo.depend_modules = set()
- 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)
- compo.depend_modules.add(mod)
-
- self.used_modules = modules.keys()
+ modules |= compo.getDependentModules()
+
+ self.used_modules = modules
for compo in module.components:
#for components files
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))
+ interfaces.append(compo.getIdlInterfaces())
#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)
+ idldefs = idldefs + compo.getIdlDefs()
+
+ filteredDefs = []
+ for defLine in idldefs.split('\n'):
+ if defLine not in filteredDefs:
+ filteredDefs.append(defLine)
+
+ return idl.substitute(module=self.module.name,
+ interfaces='\n'.join(interfaces),
+ idldefs='\n'.join(filteredDefs) )
# For PaCO++
def makexml(self):
$${OMNIORB_INCLUDE_DIR}
$${PROJECT_BINARY_DIR}
$${PROJECT_BINARY_DIR}/idl
+ $${MEDCOUPLING_INCLUDE_DIRS}
${includes}
)
$${KERNEL_SalomeIDLKernel}
$${KERNEL_OpUtil}
$${KERNEL_SalomeContainer}
- $${KERNEL_SalomeDSCContainer}
- $${KERNEL_SalomeDSCSuperv}
- $${KERNEL_SalomeDatastream}
- $${KERNEL_SalomeDSCSupervBasic}
- $${KERNEL_CalciumC}
$${KERNEL_SalomeMPIContainer}
$${MED_paramedmemcompo}
+ $${MED_paramedcouplingcorba}
SalomeIDL${module}
${libs}
)
gui_salomeapp_file.close()
list_of_gui_names.append(gui_salomeapp_file_name)
return list_of_gui_names
+
+ def getIdlInterfaces(self):
+ services = self.getIdlServices()
+ from hxx_tmpl import interfaceidlhxx
+ Inherited=""
+ if self.use_medmem==True:
+ Inherited="Engines::EngineComponent,SALOME::MultiCommClass,SALOME_MED::MED_Gen_Driver"
+ else:
+ Inherited="Engines::EngineComponent"
+ return interfaceidlhxx.substitute(component=self.name,inherited=Inherited, services="\n".join(services))
+
servicesimpl="\n".join(services),
thread_impl=self.thread_impl % {"module":gen.module.name} )
+ def getIdlInterfaces(self):
+ services = self.getIdlServices()
+ from hxx_tmpl import interfaceidlhxx
+ Inherited=""
+ Inherited="SALOME_MED::ParaMEDMEMComponent"
+ return interfaceidlhxx.substitute(component=self.name,inherited=Inherited, services="\n".join(services))
+
+ def getIdlDefs(self):
+ idldefs="""#include "ParaMEDMEMComponent.idl"\n"""
+ if self.interfacedefs:
+ idldefs = idldefs + self.interfacedefs
+ return idldefs
+
+ def getDependentModules(self):
+ """ This component depends on "MED" because it inherits from ParaMEDMEMComponent
+ """
+ depend_modules = Component.getDependentModules(self)
+ depend_modules.add("MED")
+ return depend_modules
--- /dev/null
+# Copyright (C) 2009-2015 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, or (at your option) any later version.
+#
+# 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
+#
+
+try:
+ from string import Template
+except:
+ from compat import Template,set
+
+# cxx file of a MPI component.
+# template parameters:
+# component : component name
+# servicesdef : extra "#include"
+# servicesimpl : services implementations
+cxxCompo="""
+#include "${component}.hxx"
+#include <string>
+#include <unistd.h>
+#include <signal.h>
+#include <SALOME_NamingService.hxx>
+#include <Utils_SALOME_Exception.hxx>
+#include "Utils_CorbaException.hxx"
+#include <pthread.h>
+#include <execinfo.h>
+
+typedef struct
+{
+ bool exception;
+ std::string msg;
+} exception_st;
+
+//DEFS
+${servicesdef}
+//ENDDEF
+
+
+using namespace std;
+
+//! Constructor for component "${component}" instance
+/*!
+ *
+ */
+${component}_i::${component}_i(CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableServer::ObjectId * contId,
+ const char *instanceName,
+ const char *interfaceName,
+ bool regist)
+ : Engines_Component_i(orb, poa, contId, instanceName, interfaceName,
+ false, regist)
+{
+ _thisObj = this ;
+ _id = _poa->activate_object(_thisObj);
+}
+
+${component}_i::${component}_i(CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ Engines::Container_ptr container,
+ const char *instanceName,
+ const char *interfaceName,
+ bool regist)
+ : Engines_Component_i(orb, poa, container, instanceName, interfaceName,
+ false, regist)
+{
+ _thisObj = this ;
+ _id = _poa->activate_object(_thisObj);
+}
+
+//! Destructor for component "${component}" instance
+${component}_i::~${component}_i()
+{
+}
+
+${servicesimpl}
+
+extern "C"
+{
+ PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableServer::ObjectId * contId,
+ const char *instanceName,
+ const char *interfaceName)
+ {
+ MESSAGE("PortableServer::ObjectId * ${component}Engine_factory()");
+ int is_mpi_container;
+ bool regist;
+ int numproc;
+
+ MPI_Initialized(&is_mpi_container);
+ if (!is_mpi_container)
+ {
+ int argc = 0;
+ char ** argv = NULL;
+ MPI_Init(&argc, &argv);
+ }
+
+ MPI_Comm_rank( MPI_COMM_WORLD, &numproc );
+ regist = ( numproc == 0 );
+ ${component}_i * myEngine = new ${component}_i(orb, poa, contId, instanceName, interfaceName, regist);
+ return myEngine->getId() ;
+ }
+}
+"""
+cxxCompo=Template(cxxCompo)
+
+# Header file of a MPI component
+# template parameters:
+# component : component name
+# module : module name
+# compodefs : additional "#include" and other specific declarations
+# servicesdef : declaration of component services
+hxxCompo="""
+#ifndef _${component}_HXX_
+#define _${component}_HXX_
+
+#include <SALOME_Component.hh>
+#include "Superv_Component_i.hxx"
+#include "${module}.hh"
+#include "MPIObject_i.hxx"
+
+//COMPODEFS
+${compodefs}
+//ENDDEF
+
+class ${component}_i: public virtual POA_${module}_ORB::${component},
+ ${inheritedclass}
+ public virtual MPIObject_i,
+ public virtual Engines_Component_i
+{
+ public:
+ ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
+ PortableServer::ObjectId * contId,
+ const char *instanceName, const char *interfaceName,
+ bool regist = true);
+ ${component}_i(CORBA::ORB_ptr orb, PortableServer::POA_ptr poa,
+ Engines::Container_ptr container,
+ const char *instanceName, const char *interfaceName,
+ bool regist = true);
+ virtual ~${component}_i();
+${servicesdef}
+};
+
+extern "C"
+{
+ PortableServer::ObjectId * ${component}Engine_factory( CORBA::ORB_ptr orb,
+ PortableServer::POA_ptr poa,
+ PortableServer::ObjectId * contId,
+ const char *instanceName,
+ const char *interfaceName);
+}
+#endif
+
+"""
+hxxCompo=Template(hxxCompo)
+
+# Declaration of the thread function to run a MPI service.
+# template parameters:
+# service : name of the service.
+# input_vals : declarations of input ports of the service.
+hxxThreadService="""
+void * th_${service}(void * s);
+typedef struct {
+ int ip; // mpi process id
+ Engines::IORTab* tior;
+ ${input_vals}
+} thread_${service}_struct;
+
+"""
+hxxThreadService=Template(hxxThreadService)
+
+# Body of a service.
+# template parameters:
+# module : module name
+# component : component name
+# service : service name
+# out_vals : declaration of output ports ("type1 name1;\ntype2 name2;")
+# service_call :
+# in_vals : copy of input ports to thread structure
+# parameters : list of parameters ("type1 name1, type2 name2")
+# body : user body
+cxxService="""
+void * th_${service}(void * s)
+{
+ std::ostringstream msg;
+ exception_st *est = new exception_st;
+ est->exception = false;
+
+ thread_${service}_struct *st = (thread_${service}_struct *)s;
+
+ try
+ {
+ ${out_vals}
+ ${module}_ORB::${component}_var compo = ${module}_ORB::${component}::_narrow((*(st->tior))[st->ip]);
+ compo->${service_call};
+ }
+ catch(const SALOME::SALOME_Exception &ex)
+ {
+ est->exception = true;
+ est->msg = ex.details.text;
+ }
+ catch(const CORBA::Exception &ex)
+ {
+ est->exception = true;
+ msg << "CORBA::Exception: " << ex;
+ est->msg = msg.str();
+ }
+
+ delete st;
+ return ((void*)est);
+}
+
+void ${component}_i::${service}(${parameters})
+{
+ beginService("${component}_i::${service}");
+ void *ret_th;
+ pthread_t *th;
+ exception_st *est;
+
+ try
+ {
+ // Run the service in every MPI process
+ if(_numproc == 0)
+ {
+ th = new pthread_t[_nbproc];
+ for(int ip=1;ip<_nbproc;ip++)
+ {
+ thread_${service}_struct *st = new thread_${service}_struct;
+ st->ip = ip;
+ st->tior = _tior;
+ ${in_vals}
+ pthread_create(&(th[ip]),NULL,th_${service},(void*)st);
+ }
+ }
+
+//BODY
+${body}
+//ENDBODY
+ if(_numproc == 0)
+ {
+ for(int ip=1;ip<_nbproc;ip++)
+ {
+ pthread_join(th[ip],&ret_th);
+ est = (exception_st*)ret_th;
+ if(est->exception)
+ {
+ std::ostringstream msg;
+ msg << "[" << ip << "] " << est->msg;
+ delete est;
+ delete[] th;
+ THROW_SALOME_CORBA_EXCEPTION(msg.str().c_str(),SALOME::INTERNAL_ERROR);
+ }
+ delete est;
+ }
+ delete[] th;
+ }
+ }
+ catch ( const SALOME_Exception & ex)
+ {
+ THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
+ }
+ catch ( const SALOME::SALOME_Exception & ex)
+ {
+ throw;
+ }
+ catch ( const std::exception& ex)
+ {
+ THROW_SALOME_CORBA_EXCEPTION(CORBA::string_dup(ex.what()), SALOME::INTERNAL_ERROR);
+ }
+ catch (...)
+ {
+ THROW_SALOME_CORBA_EXCEPTION("unknown exception", SALOME::INTERNAL_ERROR);
+ }
+ endService("${component}_i::${service}");
+}
+
+"""
+cxxService=Template(cxxService)
+
+interface="""
+ interface ${component}:${inheritedinterface} Engines::MPIObject, Engines::EngineComponent
+ {
+${services}
+ };
+"""
+interface=Template(interface)
\ No newline at end of file
--- /dev/null
+# Copyright (C) 2009-2015 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, or (at your option) any later version.
+#
+# 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 defines CPPComponent for SALOME components implemented in C++
+"""
+
+import os
+from gener import Component, Invalid
+from cpp_tmpl import initService, cxxService, hxxCompo, cxxCompo
+from cpp_tmpl import exeCPP, cmake_src_compo_cpp
+from yacstypes import corba_rtn_type, corba_in_type
+import mpi_tmpl
+from cppcompo import CPPComponent
+
+try:
+ from string import Template
+except:
+ from compat import Template,set
+
+class MPIComponent(CPPComponent):
+ """
+ A :class:`MPIComponent` instance represents a C++ SALOME component with services given as a list of :class:`Service`
+ instances with the parameter *services*.
+
+ :param name: gives the name of the component.
+ :type name: str
+ :param services: the list of services (:class:`Service`) of the component.
+ :param kind: For this type of component, "lib" is the unique valid option. The component is built as a dynamic library.
+ :param libs: list of the additional libraries. see *Library* class.
+ If you want to add "libmylib.so", installed in "/path/to/lib" you should use:
+ libs=[Library(name="mylib", path="/path/to/lib")]
+ For more advanced features, see the documentation of cmake / FIND_LIBRARY
+ :param rlibs: space-separated list specifying the rpath to use in installed targets
+ :param includes: additional include directories, separated by spaces.
+ :param sources: gives all the external source files to add in the compilation step (list of paths).
+ :param exe_path: is only used when kind is "exe" and gives the path to the standalone component.
+ :param compodefs: can be used to add extra definition code in the component for example when using a base class
+ to define the component class by deriving it (see *inheritedclass* parameter)
+ :param inheritedclass: can be used to define a base class for the component. The base class can be defined in external
+ source or with the *compodefs* parameter. The value of the *inheritedclass* parameter is the name of the base class.
+ :param idls: can be used to add extra idl CORBA interfaces to the component. This parameter must gives a list of idl file
+ names that are added into the generated module (idl directory) and compiled with the generated idl of the module.
+ :param interfacedefs: can be used to add idl definitions (or includes of idl files) into the generated idl of the module.
+ :param inheritedinterface: can be used to make the component inherit an extra idl interface that has been included through
+ the *idls* and *interfacedefs* parameters. See the cppgui1 example for how to use these last parameters.
+ :param addedmethods: is a C++ specific parameter that can be used to redefine a component method (DumpPython for example). This
+ parameter is a string that must contain the definition and implementation code of the method. See the cppgui1 example
+ for how to use it.
+
+ For example, the following call defines a standalone component named "mycompo" with one service s1 (it must have been defined before)::
+
+ >>> c1 = module_generator.CPPComponent('mycompo', services=[s1,], kind="exe",
+ exe_path="./launch.sh")
+ """
+ def __init__(self, name, services=None, libs=[], rlibs="", includes="", kind="lib",
+ exe_path=None, sources=None, inheritedclass="", compodefs="",
+ idls=None,interfacedefs="",inheritedinterface="",addedmethods=""):
+ self.exe_path = exe_path
+ Component.__init__(self, name, services, impl="CPP", libs=libs, rlibs=rlibs,
+ includes=includes, kind=kind, sources=sources,
+ inheritedclass=inheritedclass, compodefs=compodefs, idls=idls,
+ interfacedefs=interfacedefs, inheritedinterface=inheritedinterface,
+ addedmethods=addedmethods)
+
+ def validate(self):
+ """ validate component definition parameters"""
+ Component.validate(self)
+ kinds = ("lib")
+ if self.kind not in kinds:
+ raise Invalid("kind must be one of %s for component %s" % (kinds,self.name))
+
+ def libraryName(self):
+ """ Name of the target library
+ """
+ ret=""
+ if self.kind == "lib":
+ ret = self.name + "Engine"
+ else:
+ raise Invalid("Invalid kind of component: %s. Supported kinds are 'lib' and 'exe'" % self.name)
+ return ret
+
+ def makeCompo(self, gen):
+ """generate files for C++ component
+
+ return a dict where key is the file name and value is the file content
+ """
+ (cmake_text, cmake_vars) = self.additionalLibraries()
+ cmake_vars = "${KERNEL_SalomeMPIContainer}\n " + cmake_vars
+ cxxfile = "%s.cxx" % self.name
+ hxxfile = "%s.hxx" % self.name
+ ret = { cxxfile:self.makecxx(gen),
+ hxxfile:self.makehxx(gen)
+ }
+ sources = " ".join(map(os.path.basename,self.sources))
+ cmakelist_content = cmake_src_compo_cpp.substitute(
+ module = gen.module.name,
+ component = self.name,
+ componentlib = self.libraryName(),
+ includes = self.includes,
+ sources = sources,
+ libs = cmake_vars,
+ find_libs = cmake_text,
+ target_properties = self.targetProperties())
+
+ ret["CMakeLists.txt"] = cmakelist_content
+
+ return ret
+
+ def makeThServiceDeclaration(self, service, module_name):
+ inputVals = []
+ for port in service.inport:
+ name, typ = service.validatePort(port)
+ inputVals.append("%s %s;" % (corba_in_type(typ, module_name), name ))
+ return mpi_tmpl.hxxThreadService.substitute(service=service.name,
+ input_vals="\n".join(inputVals))
+
+ def makehxx(self, gen):
+ """return a string that is the content of .hxx file
+ """
+ services = []
+ compodefs=self.compodefs
+ for serv in self.services:
+ service = " %s %s(" % (corba_rtn_type(serv.ret,gen.module.name),serv.name)
+ service = service+gen.makeArgs(serv)+");"
+ services.append(service)
+ compodefs = compodefs + self.makeThServiceDeclaration(serv,gen.module.name)
+
+ if self.addedmethods:
+ services.append(self.addedmethods)
+ servicesdef = "\n".join(services)
+
+ inheritedclass=self.inheritedclass
+ if self.inheritedclass:
+ inheritedclass= " public virtual " + self.inheritedclass + ","
+
+ return mpi_tmpl.hxxCompo.substitute(component=self.name, module=gen.module.name,
+ servicesdef=servicesdef, inheritedclass=inheritedclass,
+ compodefs=compodefs)
+
+ def makecxx(self, gen):
+ """return a string that is the content of .cxx file
+ """
+ services = []
+ inits = []
+ defs = []
+ for serv in self.services:
+ defs.append(serv.defs)
+ in_vals = []
+ out_vals = []
+ call_params = []
+ for name, typ in serv.inport:
+ in_vals.append("st->%s = %s;" % (name, name ))
+ call_params.append("st->%s" % name)
+
+ for name, typ in serv.outport:
+ out_vals.append("%s %s;" % (corba_in_type(typ, gen.module.name), name ))
+ call_params.append(name)
+
+ service_call = "%s(%s)" % (serv.name, ",".join(call_params))
+
+ service = mpi_tmpl.cxxService.substitute(module=gen.module.name,
+ component=self.name, service=serv.name,
+ out_vals="\n".join(out_vals),
+ service_call=service_call,
+ in_vals="\n".join(in_vals),
+ parameters=gen.makeArgs(serv),
+ body=serv.body)
+ services.append(service)
+
+ return mpi_tmpl.cxxCompo.substitute(component=self.name,
+ servicesdef="\n".join(defs),
+ servicesimpl="\n".join(services))
+
+ def getIdlInterfaces(self):
+ services = self.getIdlServices()
+ inheritedinterface=""
+ if self.inheritedinterface:
+ inheritedinterface=self.inheritedinterface+","
+ return mpi_tmpl.interface.substitute(component=self.name,
+ services="\n".join(services),
+ inheritedinterface=inheritedinterface)
+
+ def getIdlDefs(self):
+ idldefs = """
+#include "SALOME_MPIObject.idl"
+"""
+ if self.interfacedefs:
+ idldefs = idldefs + self.interfacedefs
+ return idldefs
+
+ def additionalLibraries(self):
+ cmake_text, cmake_vars = Component.additionalLibraries(self)
+ if "MED" in self.getDependentModules():
+ cmake_vars = cmake_vars + """
+ ${MED_paramedmemcompo}
+ ${MED_paramedcouplingcorba}
+"""
+ return cmake_text, cmake_vars
+
from paco_tmpl import hxxparallel_instream, hxxparallel_outstream, hxxinit_ok
from paco_tmpl import hxxparallel_instream_init, hxxparallel_outstream_init, cxxService_connect
from paco_tmpl import cxx_cons_service, cxx_cons_parallel_outstream, cxx_cons_parallel_instream
+from cata_tmpl import parallel_interface
class PACOComponent(Component):
return cxxfile
+ def getIdlServices(self):
+ services = []
+ for serv in self.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)
+ return services
+
+ def getIdlInterfaces(self):
+ services = self.getIdlServices()
+ return parallel_interface.substitute(component=self.name, services="\n".join(services))
+
+ def getIdlDefs(self):
+ idldefs = """
+#include "SALOME_PACOExtension.idl"
+"""
+ if self.interfacedefs:
+ idldefs = idldefs + self.interfacedefs
+ return idldefs
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-major_version=7
-minor_version=8
+major_version=8
+minor_version=0
patch_version=0
-complete_version="%d.%d.%d" % (major_version, minor_version, patch_version)
\ No newline at end of file
+complete_version="%d.%d.%d" % (major_version, minor_version, patch_version)