3 # Copyright (C) 2010-2012 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
23 # Define all possible option for the compile command : sat compile <options>
24 parser = src.options.Options()
25 parser.add_option('p', 'products', 'list2', 'products',
26 _('products to configure. This option can be'
27 ' passed several time to configure several products.'))
28 parser.add_option('', 'with_fathers', 'boolean', 'fathers',
29 _("build all necessary modules to the given module (KERNEL is build before"
30 " building GUI)."), False)
31 parser.add_option('', 'with_children', 'boolean', 'children',
32 _("build all modules using the given module (all SMESH plugins are build "
33 "after SMESH)."), False)
34 parser.add_option('', 'clean_all', 'boolean', 'clean_all',
35 _("clean BUILD dir and INSTALL dir before building module."), False)
36 parser.add_option('', 'clean_install', 'boolean', 'clean_install',
37 _("clean INSTALL dir before building module."), False)
38 parser.add_option('', 'make_flags', 'string', 'makeflags',
39 _("add extra options to the 'make' command."))
40 parser.add_option('', 'show', 'boolean', 'no_compile',
41 _("DO NOT COMPILE just show if modules are installed or not."), False)
42 parser.add_option('', 'stop_first_fail', 'boolean', 'stop_first_fail', _("Stop"
43 "s the command at first module compilation fail."), False)
45 def get_products_list(options, cfg, logger):
46 '''method that gives the product list with their informations from
47 configuration regarding the passed options.
49 :param options Options: The Options instance that stores the commands
51 :param cfg Config: The global configuration
52 :param logger Logger: The logger instance to use for the display and
54 :return: The list of (product name, product_informations).
57 # Get the products to be prepared, regarding the options
58 if options.products is None:
59 # No options, get all products sources
60 products = cfg.APPLICATION.products
62 # if option --products, check that all products of the command line
63 # are present in the application.
64 products = options.products
66 if p not in cfg.APPLICATION.products:
67 raise src.SatException(_("Product %(product)s "
68 "not defined in application %(application)s") %
69 { 'product': p, 'application': cfg.VARS.application} )
71 # Construct the list of tuple containing
72 # the products name and their definition
73 products_infos = src.product.get_products_infos(products, cfg)
75 products_infos = [pi for pi in products_infos if not(
76 src.product.product_is_native(pi[1]) or
77 src.product.product_is_fixed(pi[1]))]
81 def get_recursive_fathers(config, p_name_p_info, without_native_fixed=False):
82 """ Get the recursive list of the dependencies of the product defined by
85 :param config Config: The global configuration
86 :param prod_info Config: The specific config of the product
87 :param without_native_fixed boolean: If true, do not include the fixed
88 or native products in the result
89 :return: The list of product_informations.
92 p_name, p_info = p_name_p_info
93 # Initialization of the resulting list
95 # Minimal case : no dependencies
96 if "depend" not in p_info or p_info.depend == []:
98 # Add the dependencies and call the function to get the dependencies of the
100 for father_name in p_info.depend:
101 l_fathers_name = [pn_pi[0] for pn_pi in l_fathers]
102 if father_name not in l_fathers_name:
103 if father_name not in config.APPLICATION.products:
104 msg = _("The product %(father_name)s that is in %(product_nam"
105 "e)s dependencies is not present in application "
106 "%(appli_name)s" % {"father_name" : father_name,
107 "product_name" : p_name.name,
108 "appli_name" : config.VARS.application})
109 raise src.SatException(msg)
110 prod_info_father = src.product.get_product_config(config,
112 pname_pinfo_father = (prod_info_father.name, prod_info_father)
113 # Do not append the father if the it is native or fixed and
114 # the corresponding parameter is called
115 if without_native_fixed:
116 if not(src.product.product_is_native(prod_info_father) or
117 src.product.product_is_fixed(prod_info_father)):
118 l_fathers.append(pname_pinfo_father)
120 l_fathers.append(pname_pinfo_father)
121 # Get the dependencies of the dependency
122 l_grand_fathers = get_recursive_fathers(config,
124 without_native_fixed = without_native_fixed)
125 l_fathers += l_grand_fathers
128 def sort_products(config, p_infos):
129 """ Sort the p_infos regarding the dependencies between the products
131 :param config Config: The global configuration
132 :param p_infos list: List of (str, Config) => (product_name, product_info)
134 l_prod_sorted = deepcopy_list(p_infos)
136 l_fathers = get_recursive_fathers(config, prod, without_native_fixed=True)
137 l_fathers = [father for father in l_fathers if father in p_infos]
140 for p_sorted in l_prod_sorted:
141 if p_sorted in l_fathers:
142 l_fathers.remove(p_sorted)
144 l_prod_sorted.remove(prod)
145 l_prod_sorted.insert(l_prod_sorted.index(p_sorted)+1, prod)
150 def deepcopy_list(input_list):
152 for elem in input_list:
156 def log_step(logger, header, step):
157 logger.write("\r%s%s" % (header, " " * 20), 3)
158 logger.write("\r%s%s" % (header, step), 3)
159 logger.write("\n==== %s \n" % src.printcolors.printcInfo(step), 4)
162 def log_res_step(logger, res):
164 logger.write("%s \n" % src.printcolors.printcSuccess("OK"), 4)
167 logger.write("%s \n" % src.printcolors.printcError("KO"), 4)
170 def compile_all_products(sat, config, products_infos, logger):
171 '''Execute the proper configuration commands
172 in each product build directory.
174 :param config Config: The global configuration
175 :param products_info list: List of
176 (str, Config) => (product_name, product_info)
177 :param logger Logger: The logger instance to use for the display and logging
178 :return: the number of failing commands.
182 for p_name_info in products_infos:
183 res_prod = compile_product(sat, p_name_info, config, logger)
188 def compile_product(sat, p_name_info, config, logger):
189 '''Execute the proper configuration command(s)
190 in the product build directory.
192 :param p_name_info tuple: (str, Config) => (product_name, product_info)
193 :param config Config: The global configuration
194 :param logger Logger: The logger instance to use for the display
196 :return: 1 if it fails, else 0.
200 p_name, __ = p_name_info
203 logger.write("\n", 4, False)
204 logger.write("################ ", 4)
205 header = _("Compilation of %s") % src.printcolors.printcLabel(p_name)
206 header += " %s " % ("." * (20 - len(p_name)))
207 logger.write(header, 3)
208 logger.write("\n", 4, False)
211 # Execute "sat configure", "sat make" and "sat install"
215 log_step(logger, header, "CONFIGURE")
216 res_c = sat.configure(config.VARS.application + " --products " + p_name, verbose = 0)
217 log_res_step(logger, res_c)
220 log_step(logger, header, "MAKE")
221 res_c = sat.make(config.VARS.application + " --products " + p_name, verbose = 0)
222 log_res_step(logger, res_c)
225 log_step(logger, header, "MAKE INSTALL")
226 res_c = sat.makeinstall(config.VARS.application + " --products " + p_name, verbose = 0)
227 log_res_step(logger, res_c)
232 logger.write("\r%s%s" % (header, " " * len_end_line), 3)
233 logger.write("\r" + header + src.printcolors.printcError("KO"))
234 logger.write("==== %(KO)s in compile of %(name)s \n" %
235 { "name" : p_name , "KO" : src.printcolors.printcInfo("ERROR")}, 4)
238 logger.write("\r%s%s" % (header, " " * len_end_line), 3)
239 logger.write("\r" + header + src.printcolors.printcSuccess("OK"))
240 logger.write("==== %s \n" % src.printcolors.printcInfo("OK"), 4)
241 logger.write("==== Make of %(name)s %(OK)s \n" %
242 { "name" : p_name , "OK" : src.printcolors.printcInfo("OK")}, 4)
244 logger.write("\n", 3, False)
249 '''method that is called when salomeTools is called with --help option.
251 :return: The text to display for the compile command description.
254 return _("The compile command construct the products of the application")
256 def run(args, runner, logger):
257 '''method that is called when salomeTools is called with compile parameter.
261 (options, args) = parser.parse_args(args)
263 # check that the command has been called with an application
264 src.check_config_has_application( runner.cfg )
266 # Get the list of products to treat
267 products_infos = get_products_list(options, runner.cfg, logger)
269 # Sort the list regarding the dependencies of the products
270 products_infos = sort_products(runner.cfg, products_infos)
272 # Print some informations
273 logger.write(_('Executing the compile command in the build '
274 'directories of the application %s\n') %
275 src.printcolors.printcLabel(runner.cfg.VARS.application), 1)
278 (_("SOURCE directory"),
279 os.path.join(runner.cfg.APPLICATION.workdir, 'SOURCES')),
280 (_("BUILD directory"),
281 os.path.join(runner.cfg.APPLICATION.workdir, 'BUILD'))
283 src.print_info(logger, info)
285 # Call the function that will loop over all the products and execute
286 # the right command(s)
287 res = compile_all_products(runner, runner.cfg, products_infos, logger)
289 # Print the final state
290 nb_products = len(products_infos)
296 logger.write(_("\nCompilation: %(status)s (%(valid_result)d/%(nb_products)d)\n") % \
297 { 'status': src.printcolors.printc(final_status),
298 'valid_result': nb_products - res,
299 'nb_products': nb_products }, 1)