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)
75 class Component(object):
76 def __init__(self, name, services=None, impl="PY", libs="", rlibs="",
77 includes="", kind="lib", sources=None):
81 self.services = services or []
84 self.includes = includes
85 self.sources = sources or []
88 if self.impl not in ValidImpl:
89 raise Invalid("%s is not a valid implementation. It should be one of %s" % (self.impl, ValidImpl))
92 for serv in self.services:
94 if serv.name in lnames:
95 raise Invalid("%s is already defined as a service of the module" % serv.name)
99 for src in self.sources:
100 if not os.path.exists(src):
101 raise Invalid("Source file %s does not exist" % src)
106 class Service(object):
107 def __init__(self, name, inport=None, outport=None, instream=None,
108 outstream=None, body="", defs=""):
110 self.inport = inport or []
111 self.outport = outport or []
112 self.instream = instream or []
113 self.outstream = outstream or []
120 for port in self.inport:
121 name, typ = self.validatePort(port)
123 raise Invalid("%s is already defined as a service parameter" % name)
126 for port in self.outport:
127 name, typ = self.validatePort(port)
129 raise Invalid("%s is already defined as a service parameter" % name)
133 for port in self.instream:
134 name, typ, dep = self.validateStream(port)
136 raise Invalid("%s is already defined as a stream port" % name)
139 for port in self.outstream:
140 name, typ, dep = self.validateStream(port)
142 raise Invalid("%s is already defined as a stream port" % name)
145 def validatePort(self, port):
149 raise Invalid("%s is not a valid definition of an data port (name,type)" % (port,))
151 if self.impl in ("PY", "ASTER"):
152 validtypes = PyValidTypes
154 validtypes = ValidTypes
156 if typ not in validtypes:
157 raise Invalid("%s is not a valid type. It should be one of %s" % (typ, validtypes))
160 def validateStream(self, port):
162 name, typ, dep = port
164 raise Invalid("%s is not a valid definition of a stream port (name,type,dependency)" % (port,))
165 if typ not in ValidStreamTypes:
166 raise Invalid("%s is not a valid type. It should be one of %s" % (typ, ValidStreamTypes))
167 if dep not in ValidDependencies:
168 raise Invalid("%s is not a valid dependency. It should be one of %s" % (dep, ValidDependencies))
169 return name, typ, dep
171 class Generator(object):
172 def __init__(self, module, context=None):
174 self.context = context or {}
175 self.kernel = self.context["kernel"]
180 namedir = module.name+"_SRC"
181 force = self.context.get("force")
182 update = self.context.get("update")
183 if os.path.exists(namedir):
185 shutil.rmtree(namedir)
187 raise Invalid("The directory %s already exists" % namedir)
194 makefile = "SUBDIRS="
196 for compo in module.components:
197 makefile = makefile+" "+compo.name
198 srcs[compo.name] = compo.makeCompo(self)
199 makefiles.append(" src/"+compo.name+"/Makefile")
201 srcs["Makefile.am"] = makefile+'\n'
202 idlfile = "%s.idl" % module.name
203 catalogfile = "%sCatalog.xml" % module.name
205 self.makeFiles({"autogen.sh":autogen,
206 "Makefile.am":mainMakefile,
207 "README":"", "NEWS":"", "AUTHORS":"", "ChangeLog":"",
208 "configure.ac":configure.substitute(module=module.name.lower(), makefiles='\n'.join(makefiles)),
209 "idl":{"Makefile.am":idlMakefile.substitute(module=module.name), idlfile:self.makeidl()},
211 "resources":{"Makefile.am":resMakefile.substitute(module=module.name), catalogfile:self.makeCatalog()},
212 "adm_local":{"make_common_starter.am":makecommon, "check_aster.m4":check_aster},
214 os.chmod(os.path.join(namedir, "autogen.sh"), 0777)
215 #copy source files if any in creates tree
216 for compo in module.components:
217 for src in compo.sources:
218 shutil.copyfile(src, os.path.join(namedir, "src", compo.name, src))
220 for m4file in ("check_Kernel.m4", "check_omniorb.m4",
221 "ac_linker_options.m4", "ac_cxx_option.m4",
222 "python.m4", "enable_pthreads.m4", "check_f77.m4",
223 "acx_pthread.m4", "check_boost.m4"):
224 shutil.copyfile(os.path.join(self.kernel, "salome_adm", "unix", "config_files", m4file),
225 os.path.join(namedir, "adm_local", m4file))
229 def makeArgs(self, service):
231 for name, typ in service.inport:
232 params.append("%s %s" % (corba_in_type(typ, self.module.name), name))
233 for name, typ in service.outport:
234 params.append("%s %s" % (corba_out_type(typ, self.module.name), name))
235 return ",".join(params)
237 def makeCatalog(self):
239 for compo in self.module.components:
241 for serv in compo.services:
243 for name, typ in serv.inport:
244 params.append(cataInparam.substitute(name=name, type=typ))
245 inparams = "\n".join(params)
247 for name, typ in serv.outport:
248 params.append(cataOutparam.substitute(name=name, type=typ))
249 outparams = "\n".join(params)
251 for name, typ, dep in serv.instream:
252 streams.append(cataInStream.substitute(name=name, type=calciumTypes[typ], dep=dep))
253 for name, typ, dep in serv.outstream:
254 streams.append(cataOutStream.substitute(name=name, type=calciumTypes[typ], dep=dep))
255 datastreams = "\n".join(streams)
256 services.append(cataService.substitute(service=serv.name, author="EDF-RD",
257 inparams=inparams, outparams=outparams, datastreams=datastreams))
258 impltype, implname = compo.getImpl()
259 components.append(cataCompo.substitute(component=compo.name, author="EDF-RD", impltype=impltype, implname=implname,
260 services='\n'.join(services)))
261 return catalog.substitute(components='\n'.join(components))
265 for compo in self.module.components:
267 for serv in compo.services:
269 for name, typ in serv.inport:
270 if compo.impl in ("PY", "ASTER") and typ == "pyobj":
271 typ = "Engines::fileBlock"
272 params.append("in %s %s" % (typ, name))
273 for name, typ in serv.outport:
274 if compo.impl in ("PY", "ASTER") and typ == "pyobj":
275 typ = "Engines::fileBlock"
276 params.append("out %s %s" % (typ, name))
277 service = " void %s(" % serv.name
278 service = service+",".join(params)+") raises (SALOME::SALOME_Exception);"
279 services.append(service)
280 interfaces.append(interface.substitute(component=compo.name, services="\n".join(services)))
281 return idl.substitute(module=self.module.name, interfaces='\n'.join(interfaces))
283 def makeFiles(self, dic, basedir):
284 for name, content in dic.items():
285 filename = os.path.join(basedir, name)
286 if isinstance(content, str):
287 fil = open(filename, 'w')
291 if not os.path.exists(filename):
292 os.makedirs(filename)
293 self.makeFiles(content, filename)
296 ier = os.system("cd %s_SRC;sh autogen.sh" % self.module.name)
298 raise Invalid("bootstrap has ended in error")
301 prefix = self.module.prefix
303 prefix = os.path.abspath(prefix)
304 cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s --prefix=%s"
305 ier = os.system(cmd % (self.module.name, self.kernel, self.aster, prefix))
307 cmd = "cd %s_SRC;./configure --with-kernel=%s --with-aster=%s"
308 ier = os.system(cmd % (self.module.name, self.kernel, self.aster))
310 raise Invalid("configure has ended in error")
313 ier = os.system("cd %s_SRC;make" % self.module.name)
315 raise Invalid("make has ended in error")
318 ier = os.system("cd %s_SRC;make install" % self.module.name)
320 raise Invalid("install has ended in error")
322 def make_appli(self, appliname, restrict=None, altmodules=None):
325 rootdir, kerdir = os.path.split(self.kernel)
327 #collect modules besides KERNEL module with the same suffix if any
329 if kerdir[:6] == "KERNEL":
331 for mod in os.listdir(rootdir):
332 if mod[-len(suffix):] == suffix:
333 module = mod[:-len(suffix)]
334 path = os.path.join(rootdir, mod)
335 #try to find catalog files
336 lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*", "*Catalog.xml"))
338 #catalogs have not been found : try the upper level
339 lcata = glob.glob(os.path.join(path, "share", "salome", "resources", "*Catalog.xml"))
341 #catalogs have been found : add the corresponding entries in the application
343 catadir, catafile = os.path.split(cata)
344 name = catafile[:-11]
345 modules_dict[name] = ' <module name="%s" path="%s"/>' % (name, path)
347 modules_dict[module] = ' <module name="%s" path="%s"/>' % (module, path)
349 modules_dict["KERNEL"] = ' <module name="KERNEL" path="%s"/>' % self.kernel
351 #keep only the modules which names are in restrict if given
355 if modules_dict.has_key(mod):
356 modules.append(modules_dict[mod])
358 modules = modules_dict.values()
360 #add the alternate modules if given
362 for module, path in altmodules.items():
363 modules.append(' <module name="%s" path="%s"/>' % (module, path))
365 #add the generated module
366 modules.append(' <module name="%s" path="%s"/>' % (self.module.name, os.path.abspath(self.module.prefix)))
368 #try to find a prerequisites file
369 prerequisites = self.context.get("prerequisites")
370 if not prerequisites:
371 #try to find one in rootdir
372 prerequisites = os.path.join(rootdir, "profile%s.sh" % suffix)
373 if not os.path.exists(prerequisites):
374 raise Invalid("Can not create an application : prerequisites file not defined or does not exist")
376 #create config_appli.xml file
377 appli = application.substitute(prerequisites=prerequisites, modules="\n".join(modules))
378 fil = open(os.path.join(appliname, "config_appli.xml"), 'w')
382 #execute appli_gen.py script
383 appligen = os.path.join(self.kernel, "bin", "salome", "appli_gen.py")
384 ier = os.system("cd %s;%s" % (appliname, appligen))
386 raise Invalid("make_appli has ended in error")
388 #add CatalogResources.xml if not created by appli_gen.py
389 if not os.path.exists(os.path.join(appliname, "CatalogResources.xml")):
390 #CatalogResources.xml does not exist create a minimal one
391 fil = open(os.path.join(appliname, 'CatalogResources.xml'), 'w')
392 command = """<!DOCTYPE ResourcesCatalog>
394 <machine hostname="%s" protocol="ssh" mode="interactive" />
397 host = socket.gethostname().split('.')[0]
398 fil.write(command % host)