1 # Copyright (C) 2009-2015 EDF R&D
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Lesser General Public License for more details.
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 Module that defines CPPComponent for SALOME components implemented in C++
25 from gener import Component, Invalid
26 from cpp_tmpl import initService, cxxService, hxxCompo, cxxCompo
27 from cpp_tmpl import exeCPP, cmake_src_compo_cpp
28 from yacstypes import corba_rtn_type, corba_in_type
30 from cppcompo import CPPComponent
33 from string import Template
35 from compat import Template,set
37 class MPIComponent(CPPComponent):
39 A :class:`MPIComponent` instance represents a C++ SALOME component with services given as a list of :class:`Service`
40 instances with the parameter *services*.
42 :param name: gives the name of the component.
44 :param services: the list of services (:class:`Service`) of the component.
45 :param kind: If it is given and has the value "exe", the component will be built as a standalone
46 component (executable or shell script). The default is to build the component as a dynamic library.
47 :param libs: list of the additional libraries. see *Library* class.
48 If you want to add "libmylib.so", installed in "/path/to/lib" you should use:
49 libs=[Library(name="mylib", path="/path/to/lib")]
50 For more advanced features, see the documentation of cmake / FIND_LIBRARY
51 :param rlibs: space-separated list specifying the rpath to use in installed targets
52 :param includes: additional include directories, separated by spaces.
53 :param sources: gives all the external source files to add in the compilation step (list of paths).
54 :param exe_path: is only used when kind is "exe" and gives the path to the standalone component.
55 :param compodefs: can be used to add extra definition code in the component for example when using a base class
56 to define the component class by deriving it (see *inheritedclass* parameter)
57 :param inheritedclass: can be used to define a base class for the component. The base class can be defined in external
58 source or with the *compodefs* parameter. The value of the *inheritedclass* parameter is the name of the base class.
59 :param idls: can be used to add extra idl CORBA interfaces to the component. This parameter must gives a list of idl file
60 names that are added into the generated module (idl directory) and compiled with the generated idl of the module.
61 :param interfacedefs: can be used to add idl definitions (or includes of idl files) into the generated idl of the module.
62 :param inheritedinterface: can be used to make the component inherit an extra idl interface that has been included through
63 the *idls* and *interfacedefs* parameters. See the cppgui1 example for how to use these last parameters.
64 :param addedmethods: is a C++ specific parameter that can be used to redefine a component method (DumpPython for example). This
65 parameter is a string that must contain the definition and implementation code of the method. See the cppgui1 example
68 For example, the following call defines a standalone component named "mycompo" with one service s1 (it must have been defined before)::
70 >>> c1 = module_generator.CPPComponent('mycompo', services=[s1,], kind="exe",
71 exe_path="./launch.sh")
73 def __init__(self, name, services=None, libs=[], rlibs="", includes="", kind="lib",
74 exe_path=None, sources=None, inheritedclass="", compodefs="",
75 idls=None,interfacedefs="",inheritedinterface="",addedmethods=""):
76 self.exe_path = exe_path
77 Component.__init__(self, name, services, impl="CPP", libs=libs, rlibs=rlibs,
78 includes=includes, kind=kind, sources=sources,
79 inheritedclass=inheritedclass, compodefs=compodefs, idls=idls,
80 interfacedefs=interfacedefs, inheritedinterface=inheritedinterface,
81 addedmethods=addedmethods)
84 """ validate component definition parameters"""
85 Component.validate(self)
87 if self.kind not in kinds:
88 raise Invalid("kind must be one of %s for component %s" % (kinds,self.name))
90 def libraryName(self):
91 """ Name of the target library
94 if self.kind == "lib":
95 ret = self.name + "Engine"
97 raise Invalid("Invalid kind of component: %s. Supported kinds are 'lib' and 'exe'" % self.name)
100 def makeCompo(self, gen):
101 """generate files for C++ component
103 return a dict where key is the file name and value is the file content
105 (cmake_text, cmake_vars) = self.additionalLibraries()
106 cmake_vars = "${KERNEL_SalomeMPIContainer}\n " + cmake_vars
107 cxxfile = "%s.cxx" % self.name
108 hxxfile = "%s.hxx" % self.name
109 if self.kind == "exe":
113 ret = { cxxfile:self.makecxx(gen, exe_opt),
114 hxxfile:self.makehxx(gen)
116 sources = " ".join(map(os.path.basename,self.sources))
117 cmakelist_content = cmake_src_compo_cpp.substitute(
118 module = gen.module.name,
119 component = self.name,
120 componentlib = self.libraryName(),
121 includes = self.includes,
124 find_libs = cmake_text,
125 target_properties = self.targetProperties())
127 ret["CMakeLists.txt"] = cmakelist_content
131 def makeThServiceDeclaration(self, service, module_name):
133 for port in service.inport:
134 name, typ = service.validatePort(port)
135 inputVals.append("%s %s;" % (corba_in_type(typ, module_name), name ))
136 return mpi_tmpl.hxxThreadService.substitute(service=service.name,
137 input_vals="\n".join(inputVals))
139 def makehxx(self, gen):
140 """return a string that is the content of .hxx file
143 compodefs=self.compodefs
144 for serv in self.services:
145 service = " %s %s(" % (corba_rtn_type(serv.ret,gen.module.name),serv.name)
146 service = service+gen.makeArgs(serv)+");"
147 services.append(service)
148 compodefs = compodefs + self.makeThServiceDeclaration(serv,gen.module.name)
150 if self.addedmethods:
151 services.append(self.addedmethods)
152 servicesdef = "\n".join(services)
154 inheritedclass=self.inheritedclass
155 if self.inheritedclass:
156 inheritedclass= " public virtual " + self.inheritedclass + ","
158 return mpi_tmpl.hxxCompo.substitute(component=self.name, module=gen.module.name,
159 servicesdef=servicesdef, inheritedclass=inheritedclass,
162 def makecxx(self, gen, exe=0):
163 """return a string that is the content of .cxx file
168 for serv in self.services:
169 defs.append(serv.defs)
173 for name, typ in serv.inport:
174 in_vals.append("st->%s = %s;" % (name, name ))
175 call_params.append("st->%s" % name)
177 for name, typ in serv.outport:
178 out_vals.append("%s %s;" % (corba_in_type(typ, gen.module.name), name ))
179 call_params.append(name)
181 service_call = "%s(%s)" % (serv.name, ",".join(call_params))
183 service = mpi_tmpl.cxxService.substitute(module=gen.module.name,
184 component=self.name, service=serv.name,
185 out_vals="\n".join(out_vals),
186 service_call=service_call,
187 in_vals="\n".join(in_vals),
188 parameters=gen.makeArgs(serv),
190 services.append(service)
192 return mpi_tmpl.cxxCompo.substitute(component=self.name,
193 servicesdef="\n".join(defs),
194 servicesimpl="\n".join(services))
196 def getIdlInterfaces(self):
197 services = self.getIdlServices()
198 inheritedinterface=""
199 if self.inheritedinterface:
200 inheritedinterface=self.inheritedinterface+","
201 return mpi_tmpl.interface.substitute(component=self.name,
202 services="\n".join(services),
203 inheritedinterface=inheritedinterface)
205 def getIdlDefs(self):
207 #include "SALOME_MPIObject.idl"
209 if self.interfacedefs:
210 idldefs = idldefs + self.interfacedefs