3 # Copyright (C) 2010-2013 CEA/DEN
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 parser = src.options.Options()
28 parser.add_option('p', 'products', 'list2', 'products',
29 _("the list of products to generate"))
30 parser.add_option('', 'yacsgen', 'string', 'yacsgen',
31 _("path to YACSGEN's module_generator package"))
33 def generate_component_list(config, product_info, context, logger):
36 for compo in src.product.get_product_components(product_info):
37 header = " %s %s " % (src.printcolors.printcLabel(compo),
38 "." * (20 - len(compo)))
39 res = generate_component(config,
45 if config.USER.output_verbose_level == 3:
46 logger.write("\r%s%s\r%s" % (header, " " * 20, header), 3)
47 logger.write(src.printcolors.printc(res), 3, False)
48 logger.write("\n", 3, False)
51 def generate_component(config, compo, product_info, context, header, logger):
52 hxxfile = compo + ".hxx"
53 cpplib = "lib" + compo + "CXX.so"
54 cpp_path = product_info.install_dir
56 logger.write("%s\n" % header, 4, False)
57 src.printcolors.print_value(logger, "hxxfile", hxxfile, 4)
58 src.printcolors.print_value(logger, "cpplib", cpplib, 4)
59 src.printcolors.print_value(logger, "cpp_path", cpp_path, 4)
61 # create a product_info at runtime
62 pp = src.pyconf.Mapping(config)
65 generate_dir = os.path.join(config.APPLICATION.workdir, "GENERATED")
66 install_dir = os.path.join(config.APPLICATION.workdir, "INSTALL")
67 build_dir = os.path.join(config.APPLICATION.workdir, "BUILD")
68 pp.source_dir = os.path.join(generate_dir, compo + "_SRC")
69 pp.install_dir = os.path.join(install_dir, compo)
70 pp.build_dir = os.path.join(build_dir, compo)
71 pp.depend = product_info.depend
72 pp.depend.append(product_info.name, "") # add cpp module
73 pp.opt_depend = product_info.opt_depend
75 config.PRODUCTS[compo].default = pp
77 builder = src.compilation.Builder(config, logger, pp, check_src=False)
78 builder.header = header
80 # generate the component
81 # create GENERETE dir if necessary
82 if not os.path.exists(generate_dir):
83 os.mkdir(generate_dir)
85 # delete previous generated directory if it already exists
86 if os.path.exists(pp.source_dir):
87 logger.write(" delete %s\n" % pp.source_dir, 4)
88 shutil.rmtree(pp.source_dir)
90 # generate generates in the current directory => change for generate dir
92 os.chdir(generate_dir)
94 # inline class to override bootstrap method
95 import module_generator
96 class sat_generator(module_generator.Generator):
97 # old bootstrap for automake (used if salome version <= 7.4)
98 def bootstrap(self, source_dir, log_file):
99 # replace call to default bootstrap() by using subprocess call (cleaner)
100 command = "sh autogen.sh"
101 ier = subprocess.call(command, shell=True, cwd=source_dir,
102 stdout=log_file, stderr=subprocess.STDOUT)
104 raise src.SatException("bootstrap has ended in error")
107 # determine salome version
108 VersionSalome = src.get_salome_version(config)
109 if VersionSalome >= 750 :
111 builder.log_step('USE CMAKE')
114 builder.log_step('USE AUTOTOOLS')
117 builder.log_step('GENERATE')
119 prevstdout = sys.stdout
120 prevstderr = sys.stderr
123 sys.stdout = logger.logTxtFile
124 sys.stderr = logger.logTxtFile
126 if src.product.product_is_mpi(product_info):
127 salome_compo = module_generator.HXX2SALOMEParaComponent(hxxfile,
131 salome_compo = module_generator.HXX2SALOMEComponent(hxxfile,
135 if product_info.has_gui == "yes":
136 # get files to build a template GUI
137 gui_files = salome_compo.getGUIfilesTemplate()
141 mg = module_generator.Module(compo, components=[salome_compo],
142 prefix=generate_dir, gui=gui_files)
143 g = sat_generator(mg, context)
147 result = "BUID_CONFIGURE"
148 builder.log_step('BUID_CONFIGURE (no bootstrap)')
149 g.bootstrap(pp.source_dir, logger.logTxtFile)
151 result = src.OK_STATUS
153 sys.stdout = prevstdout
154 sys.stderr = prevstderr
156 # go back to previous directory
159 # do the compilation using the builder object
160 if not builder.prepare(): return "Error in prepare"
162 if not builder.configure(): return "Error in configure"
164 if not builder.cmake(): return "Error in cmake"
166 if not builder.make(): return "Error in make"
167 if not builder.install(): return "Error in make install"
169 # copy specified logo in generated component install directory
170 # rem : logo is not copied in source dir because this would require
171 # to modify the generated makefile
172 if "logo" in product_info:
173 destlogo = os.path.join(pp.install_dir, "share", "salome",
174 "resources", compo.lower(), compo + ".png")
175 src.Path(product_info.logo).copyfile(destlogo)
179 def build_context(config, logger):
181 products_list = [ 'KERNEL', 'GUI' ]
182 environ_info['products'] = config.APPLICATION.products
183 ctxenv = src.environment.SalomeEnviron(config,
184 src.environment.Environ(dict(
188 ctxenv.set_full_environ(logger, environ_info)
191 for p in products_list:
192 prod_env = p + "_ROOT_DIR"
193 val = os.getenv(prod_env)
194 if os.getenv(prod_env) is None:
195 if p not in config.APPLICATION.products:
196 warn = _("product %(product)s is not defined. Include it in the"
197 " application or define $%(env)s.") % \
198 { "product": p, "env": prod_env}
199 logger.write(src.printcolors.printcWarning(warn), 1)
200 logger.write("\n", 3, False)
202 val = ctxenv.environ.environ[prod_env]
205 # the dictionary requires all keys
206 # but the generation requires only values for KERNEL and GUI
210 "kernel": dicdir["KERNEL"],
211 "gui": dicdir["GUI"],
220 def check_module_generator(directory=None):
221 """Check if module_generator is available.
223 :param directory str: The directory of YACSGEN.
224 :return: The YACSGEN path if the module_generator is available, else None
228 if directory is not None and directory not in sys.path:
229 sys.path.insert(0, dir)
234 #import module_generator
235 info = imp.find_module("module_generator")
244 def check_yacsgen(config, directory, logger):
245 """Check if YACSGEN is available.
247 :param config Config: The global configuration.
248 :param directory str: The directory given by option --yacsgen
249 :param logger Logger: The logger instance
250 :return: The path to yacsgen directory
253 # first check for YACSGEN (command option, then product, then environment)
256 if directory is not None:
257 yacsgen_dir = directory
258 yacs_src = _("Using YACSGEN form command line")
259 elif 'YACSGEN' in config.APPLICATION.products:
260 yacsgen_info = src.product.get_product_config(config, 'YACSGEN')
261 yacsgen_dir = yacsgen_info.install_dir
262 yacs_src = _("Using YACSGEN form application")
263 elif os.environ.has_key("YACSGEN_ROOT_DIR"):
264 yacsgen_dir = os.getenv("YACSGEN_ROOT_DIR")
265 yacs_src = _("Using YACSGEN form environment")
267 if yacsgen_dir is None:
268 return (False, _("The generate command requires YACSGEN."))
270 logger.write(" %s\n" % yacs_src, 2, True)
271 logger.write(" %s\n" % yacsgen_dir, 5, True)
273 if not os.path.exists(yacsgen_dir):
274 message = _("YACSGEN directory not found: '%s'") % yacsgen_dir
275 return (False, _(message))
277 # load module_generator
278 c = check_module_generator(yacsgen_dir)
282 pv = os.getenv("PYTHON_VERSION")
284 python_info = src.product.get_product_config(config, "Python")
285 pv = '.'.join(python_info.version.split('.')[:2])
286 assert pv is not None, "$PYTHON_VERSION not defined"
287 yacsgen_dir = os.path.join(yacsgen_dir, "lib", "python%s" % pv,
289 c = check_module_generator(yacsgen_dir)
294 _("The python module mosule_generator was not found in YACSGEN"))
298 '''method that is called when salomeTools is called with --help option.
300 :return: The text to display for the generate command description.
303 return _("The generate command generates SALOME modules from 'pure cpp' "
304 "products.\nWARNING this command NEEDS YACSGEN to run!")
307 def run(args, runner, logger):
308 '''method that is called when salomeTools is called with generate parameter.
311 # Check that the command has been called with an application
312 src.check_config_has_application(runner.cfg)
314 logger.write(_('Generation of SALOME modules for application %s\n') % \
315 src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
317 (options, args) = parser.parse_args(args)
319 status = src.KO_STATUS
321 # verify that YACSGEN is available
322 yacsgen_dir = check_yacsgen(runner.cfg, options.yacsgen, logger)
324 if isinstance(yacsgen_dir, tuple):
326 __, error = yacsgen_dir
327 msg = _("Error: %s" % error)
328 logger.write(src.printcolors.printcError(msg), 1)
329 logger.write("\n", 1)
332 # Make the generator module visible by python
333 sys.path.insert(0, yacsgen_dir)
335 src.printcolors.print_value(logger, _("YACSGEN dir"), yacsgen_dir, 3)
336 logger.write("\n", 2)
337 products = runner.cfg.APPLICATION.products
339 products = options.products
344 context = build_context(runner.cfg, logger)
345 for product in products:
346 header = _("Generating %s") % src.printcolors.printcLabel(product)
347 header += " %s " % ("." * (20 - len(product)))
348 logger.write(header, 3)
351 if product not in runner.cfg.PRODUCTS:
352 logger.write(_("Unknown product\n"), 3, False)
355 pi = src.product.get_product_config(runner.cfg, product)
356 if not src.product.product_is_generated(pi):
357 logger.write(_("not a generated product\n"), 3, False)
362 result = generate_component_list(runner.cfg,
366 except Exception as exc:
369 if result != src.OK_STATUS:
370 result = _("ERROR: %s") % result
371 details.append([product, result])
373 if len(details) == 0:
374 status = src.OK_STATUS
375 else: #if config.USER.output_level != 3:
376 logger.write("\n", 2, False)
377 logger.write(_("The following modules were not generated correctly:\n"), 2)
379 logger.write(" %s: %s\n" % (d[0], d[1]), 2, False)
380 logger.write("\n", 2, False)
382 if status == src.OK_STATUS: