1 import os, shutil, glob, socket
4 from string import Template
6 from compat import Template, set
8 class Invalid(Exception):
11 from mod_tmpl import resMakefile, makecommon, configure
12 from mod_tmpl import mainMakefile, autogen, application
13 from cata_tmpl import catalog, interface, idl, idlMakefile
14 from cata_tmpl import cataOutStream, cataInStream, cataOutparam, cataInparam
15 from cata_tmpl import cataService, cataCompo
16 from aster_tmpl import check_aster
18 corbaTypes = {"double":"CORBA::Double", "long":"CORBA::Long",
19 "string":"const char*", "dblevec":"const %s::dblevec&",
20 "stringvec":"const %s::stringvec&", "intvec":"const %s::intvec&"}
21 corbaOutTypes = {"double":"CORBA::Double&", "long":"CORBA::Long&",
22 "string":"CORBA::String_out", "dblevec":"%s::dblevec_out",
23 "stringvec":"%s::stringvec_out", "intvec":"%s::intvec_out"}
25 def corba_in_type(typ, module):
26 if typ in ("dblevec", "intvec", "stringvec"):
27 return corbaTypes[typ] % module
29 return corbaTypes[typ]
31 def corba_out_type(typ, module):
32 if typ in ("dblevec", "intvec", "stringvec"):
33 return corbaOutTypes[typ] % module
35 return corbaOutTypes[typ]
37 calciumTypes = {"CALCIUM_double":"CALCIUM_double",
38 "CALCIUM_integer":"CALCIUM_integer",
39 "CALCIUM_real":"CALCIUM_real",
40 "CALCIUM_string":"CALCIUM_string",
41 "CALCIUM_complex":"CALCIUM_complex",
42 "CALCIUM_logical":"CALCIUM_logical",
45 ValidImpl = ("CPP", "PY", "F77", "ASTER")
46 ValidTypes = corbaTypes.keys()
47 ValidStreamTypes = calciumTypes.keys()
48 ValidDependencies = ("I", "T")
49 PyValidTypes = ValidTypes+["pyobj"]
51 def makedirs(namedir):
52 if os.path.exists(namedir):
53 dirbak = namedir+".bak"
54 if os.path.exists(dirbak):
56 os.rename(namedir, dirbak)
57 os.listdir(dirbak) #sert seulement a mettre a jour le systeme de fichier sur certaines machines
61 def __init__(self, name, components=None, prefix=""):
63 self.components = components or []
64 self.prefix = prefix or "%s_INSTALL" % name
69 for compo in self.components:
70 if compo.name in lcompo:
71 raise Invalid("%s is already defined as a component of the module" % compo.name)
72 lcompo.add(compo.name)
74 class Component(object):
75 def __init__(self, name, services=None, impl="PY", libs="", rlibs="",
76 includes="", kind="lib"):
80 self.services = services or []
83 self.includes = includes
87 if self.impl not in ValidImpl:
88 raise Invalid("%s is not a valid implementation. It should be one of %s" % (self.impl, ValidImpl))
91 for serv in self.services:
93 if serv.name in lnames:
94 raise Invalid("%s is already defined as a service of the module" % serv.name)
101 class Service(object):
102 def __init__(self, name, inport=None, outport=None, instream=None,
103 outstream=None, body="", defs=""):
105 self.inport = inport or []
106 self.outport = outport or []
107 self.instream = instream or []
108 self.outstream = outstream or []
115 for port in self.inport:
116 name, typ = self.validatePort(port)
118 raise Invalid("%s is already defined as a service parameter" % name)
121 for port in self.outport:
122 name, typ = self.validatePort(port)
124 raise Invalid("%s is already defined as a service parameter" % name)
128 for port in self.instream:
129 name, typ, dep = self.validateStream(port)
131 raise Invalid("%s is already defined as a stream port" % name)
134 for port in self.outstream:
135 name, typ, dep = self.validateStream(port)
137 raise Invalid("%s is already defined as a stream port" % name)
140 def validatePort(self, port):
144 raise Invalid("%s is not a valid definition of an data port (name,type)" % (port,))
146 if self.impl in ("PY", "ASTER"):
147 validtypes = PyValidTypes
149 validtypes = ValidTypes
151 if typ not in validtypes:
152 raise Invalid("%s is not a valid type. It should be one of %s" % (typ, validtypes))
155 def validateStream(self, port):
157 name, typ, dep = port
159 raise Invalid("%s is not a valid definition of a stream port (name,type,dependency)" % (port,))
160 if typ not in ValidStreamTypes:
161 raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidStreamTypes))
162 if dep not in ValidDependencies:
163 raise Invalid("%s is not a valid dependency. It should be one of %s" % (dep, ValidDependencies))
164 return name, typ, dep
166 class Generator(object):
167 def __init__(self, module, context=None):
169 self.context = context or {}
170 self.kernel = self.context["kernel"]
175 namedir = module.name+"_SRC"
176 force = self.context.get("force")
177 update = self.context.get("update")
178 if os.path.exists(namedir):
180 shutil.rmtree(namedir)
182 raise Invalid("The directory %s already exists" % namedir)
189 makefile = "SUBDIRS="
191 for compo in module.components:
192 makefile = makefile+" "+compo.name
193 srcs[compo.name] = compo.makeCompo(self)
194 makefiles.append(" src/"+compo.name+"/Makefile")
196 srcs["Makefile.am"] = makefile+'\n'
197 idlfile = "%s.idl" % module.name
198 catalogfile = "%sCatalog.xml" % module.name
200 self.makeFiles({"autogen.sh":autogen,
201 "Makefile.am":mainMakefile,
202 "README":"", "NEWS":"", "AUTHORS":"", "ChangeLog":"",
203 "configure.ac":configure.substitute(module=module.name.lower(), makefiles='\n'.join(makefiles)),
204 "idl":{"Makefile.am":idlMakefile.substitute(module=module.name), idlfile:self.makeidl()},
206 "resources":{"Makefile.am":resMakefile.substitute(module=module.name), catalogfile:self.makeCatalog()},
207 "adm_local":{"make_common_starter.am":makecommon, "check_aster.m4":check_aster},
209 os.chmod(os.path.join(namedir, "autogen.sh"), 0777)
211 for m4file in ("check_Kernel.m4", "check_omniorb.m4",
212 "ac_linker_options.m4", "ac_cxx_option.m4",
213 "python.m4", "enable_pthreads.m4", "check_f77.m4",
214 "acx_pthread.m4", "check_boost.m4"):
215 shutil.copyfile(os.path.join(self.kernel, "salome_adm", "unix", "config_files", m4file),
216 os.path.join(namedir, "adm_local", m4file))
220 def makeArgs(self, service):
222 for name, typ in service.inport:
223 params.append("%s %s" % (corba_in_type(typ, self.module.name), name))
224 for name, typ in service.outport:
225 params.append("%s %s" % (corba_out_type(typ, self.module.name), name))
226 return ",".join(params)
228 def makeCatalog(self):
230 for compo in self.module.components:
232 for serv in compo.services:
234 for name, typ in serv.inport:
235 params.append(cataInparam.substitute(name=name, type=typ))
236 inparams = "\n".join(params)
238 for name, typ in serv.outport:
239 params.append(cataOutparam.substitute(name=name, type=typ))
240 outparams = "\n".join(params)
242 for name, typ, dep in serv.instream:
243 streams.append(cataInStream.substitute(name=name, type=calciumTypes[typ], dep=dep))
244 for name, typ, dep in serv.outstream:
245 streams.append(cataOutStream.substitute(name=name, type=calciumTypes[typ], dep=dep))
246 datastreams = "\n".join(streams)
247 services.append(cataService.substitute(service=serv.name, author="EDF-RD",
248 inparams=inparams, outparams=outparams, datastreams=datastreams))
249 impltype, implname = compo.getImpl()
250 components.append(cataCompo.substitute(component=compo.name, author="EDF-RD", impltype=impltype, implname=implname,
251 services='\n'.join(services)))
252 return catalog.substitute(components='\n'.join(components))
256 for compo in self.module.components:
258 for serv in compo.services:
260 for name, typ in serv.inport:
261 if compo.impl in ("PY", "ASTER") and typ == "pyobj":
262 typ = "Engines::fileBlock"
263 params.append("in %s %s" % (typ, name))
264 for name, typ in serv.outport:
265 if compo.impl in ("PY", "ASTER") and typ == "pyobj":
266 typ = "Engines::fileBlock"
267 params.append("out %s %s" % (typ, name))
268 service = " void %s(" % serv.name
269 service = service+",".join(params)+") raises (SALOME::SALOME_Exception);"
270 services.append(service)
271 interfaces.append(interface.substitute(component=compo.name, services="\n".join(services)))
272 return idl.substitute(module=self.module.name, interfaces='\n'.join(interfaces))
274 def makeFiles(self, dic, basedir):
275 for name, content in dic.items():
276 filename = os.path.join(basedir, name)
277 if isinstance(content, str):
278 fil = open(filename, 'w')
282 if not os.path.exists(filename):
283 os.makedirs(filename)
284 self.makeFiles(content, filename)
287 ier = os.system("cd %s_SRC;sh autogen.sh" % self.module.name)
289 raise Invalid("bootstrap has ended in error")
292 prefix = self.module.prefix
294 prefix = os.path.abspath(prefix)
295 cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s --prefix=%s"
296 ier = os.system(cmd % (self.module.name, self.kernel, self.aster, prefix))
298 cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s"
299 ier = os.system(cmd % (self.module.name, self.kernel, self.aster))
301 raise Invalid("configure has ended in error")
304 ier = os.system("cd %s_SRC;make" % self.module.name)
306 raise Invalid("make has ended in error")
309 ier = os.system("cd %s_SRC;make install" % self.module.name)
311 raise Invalid("install has ended in error")
313 def make_appli(self, appliname, restrict=None, altmodules=None):
316 rootdir, kerdir = os.path.split(self.kernel)
318 #collect modules besides KERNEL module with the same suffix if any
320 if kerdir[:6] == "KERNEL":
322 for mod in os.listdir(rootdir):
323 if mod[-len(suffix):] == suffix:
324 module = mod[:-len(suffix)]
325 path = os.path.join(rootdir, mod)
326 #try to find catalog files
327 lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*", "*Catalog.xml"))
329 #catalogs have not been found : try the upper level
330 lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*Catalog.xml"))
332 #catalogs have been found : add the corresponding entries in the application
334 catadir, catafile = os.path.split(cata)
335 name = catafile[:-11]
336 modules_dict[name] = ' <module name="%s" path="%s"/>' % (name, path)
338 modules_dict[module] = ' <module name="%s" path="%s"/>' % (module, path)
340 modules_dict["KERNEL"] = ' <module name="KERNEL" path="%s"/>' % self.kernel
342 #keep only the modules which names are in restrict if given
346 if modules_dict.has_key(mod):
347 modules.append(modules_dict[mod])
349 modules = modules_dict.values()
351 #add the alternate modules if given
353 for module, path in altmodules.items():
354 modules.append(' <module name="%s" path="%s"/>' % (module, path))
356 #add the generated module
357 modules.append(' <module name="%s" path="%s"/>' % (self.module.name, os.path.abspath(self.module.prefix)))
359 #try to find a prerequisites file
360 prerequisites = self.context.get("prerequisites")
361 if not prerequisites:
362 #try to find one in rootdir
363 prerequisites = os.path.join(rootdir, "profile%s.sh" % suffix)
364 if not os.path.exists(prerequisites):
365 raise Invalid("Can not create an application : prerequisites file not defined or does not exist")
367 #create config_appli.xml file
368 appli = application.substitute(prerequisites=prerequisites, modules="\n".join(modules))
369 fil = open(os.path.join(appliname, "config_appli.xml"), 'w')
373 #execute appli_gen.py script
374 appligen = os.path.join(self.kernel, "bin", "salome", "appli_gen.py")
375 ier = os.system("cd %s;%s" % (appliname, appligen))
377 raise Invalid("make_appli has ended in error")
379 #add CatalogResources.xml if not created by appli_gen.py
380 if not os.path.exists(os.path.join(appliname, "CatalogResources.xml")):
381 #CatalogResources.xml does not exist create a minimal one
382 fil = open(os.path.join(appliname, 'CatalogResources.xml'), 'w')
383 command = """<!DOCTYPE ResourcesCatalog>
385 <machine hostname="%s" protocol="ssh" mode="interactive" />
388 host = socket.gethostname().split('.')[0]
389 fil.write(command % host)