]> SALOME platform Git repositories - tools/sat.git/blob - src/environment.py
Salome HOME
d76466b0887f1ad7ba9d6aea4622230b62dda12b
[tools/sat.git] / src / environment.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2013  CEA/DEN
4 #
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.
9 #
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.
14 #
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
18
19 import os
20 import subprocess
21 import string
22 import sys
23 import copy
24
25 import src
26 import src.debug as DBG
27 import pprint as PP
28
29
30 class Environ:
31     """\
32     Class to manage the environment context
33     """
34     def __init__(self, environ=None):
35         """Initialization. If the environ argument is passed, the environment
36            will be add to it, else it is the external environment.
37            
38         :param environ dict:  
39         """
40         if environ is not None:
41             self.environ = environ
42         else:
43             self.environ = os.environ
44
45     def __repr__(self):
46         """easy non exhaustive quick resume for debug print"""
47         return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(self.environ))
48
49     def _expandvars(self, value):
50         """\
51         replace some $VARIABLE into its actual value in the environment
52         
53         :param value str: the string to be replaced
54         :return: the replaced variable
55         :rtype: str
56         """
57         if src.architecture.is_windows():
58             delim = "%"
59         else:
60             delim = "$"
61         if delim in value:
62             # The string.Template class is a string class 
63             # for supporting $-substitutions
64             zt = string.Template(value)
65             zt.delimiter = delim
66             try:
67                 value = zt.substitute(self.environ)
68             except KeyError as exc:
69                 pass
70                 #raise src.SatException(_("Missing definition "
71                 #                         "in environment: %s") % str(exc))
72         return value
73
74     def append_value(self, key, value, sep=os.pathsep):
75         """\
76         append value to key using sep,
77         if value contains ":" or ";" then raise error
78
79         :param key str: the environment variable to append
80         :param value str: the value to append to key
81         :param sep str: the separator string
82         """
83         # check that value so no contain the system separator
84         separator=os.pathsep
85         if separator in value:
86             raise Exception("Environ append key '%s' value '%s' contains forbidden character '%s'" % (key, value, separator))
87
88         # check if the key is already in the environment
89         if key in self.environ:
90             value_list = self.environ[key].split(sep)
91             # Check if the value is already in the key value or not
92             if not value in value_list:
93                 value_list.append(value)
94             else:
95                 value_list.append(value_list.pop(value_list.index(value)))
96             self.set(key, sep.join(value_list))
97         else:
98             self.set(key, value)
99
100     def append(self, key, value, sep=os.pathsep):
101         """\
102         Same as append_value but the value argument can be a list
103         
104         :param key str: the environment variable to append
105         :param value str or list: the value(s) to append to key
106         :param sep str: the separator string
107         """
108         if isinstance(value, list):
109             for v in value:
110                 self.append_value(key, v, sep)
111         else:
112             self.append_value(key, value, sep)
113
114     def prepend_value(self, key, value, sep=os.pathsep):
115         """\
116         prepend value to key using sep,
117         if value contains ":" or ";" then raise error
118         
119         :param key str: the environment variable to prepend
120         :param value str: the value to prepend to key
121         :param sep str: the separator string
122         """
123         # check that value so no contain the system separator
124         separator=os.pathsep
125         if separator in value:
126             raise Exception("Environ append key '%s' value '%s' contains forbidden character '%s'" % (key, value, separator))
127
128         # check if the key is already in the environment
129         if key in self.environ:
130             value_list = self.environ[key].split(sep)
131             if not value in value_list:
132                 value_list.insert(0, value)
133             else:
134                 value_list.insert(0, value_list.pop(value_list.index(value)))
135             self.set(key, sep.join(value_list))
136         else:
137             self.set(key, value)
138
139     def prepend(self, key, value, sep=os.pathsep):
140         """\
141         Same as prepend_value but the value argument can be a list
142         
143         :param key str: the environment variable to prepend
144         :param value str or list: the value(s) to prepend to key
145         :param sep str: the separator string
146         """
147         if isinstance(value, list):
148             for v in reversed(value): # prepend list, first item at last to stay first
149                 self.prepend_value(key, v, sep)
150         else:
151             self.prepend_value(key, value, sep)
152
153     def is_defined(self, key):
154         """\
155         Check if the key exists in the environment
156         
157         :param key str: the environment variable to check
158         """
159         return key in self.environ.keys()
160
161     def set(self, key, value):
162         """\
163         Set the environment variable "key" to value "value"
164         
165         :param key str: the environment variable to set
166         :param value str: the value
167         """
168         self.environ[key] = self._expandvars(value)
169
170     def get(self, key):
171         """\
172         Get the value of the environment variable "key"
173         
174         :param key str: the environment variable
175         """
176         if key in self.environ:
177             return self.environ[key]
178         else:
179             return ""
180
181     def get_value(self, key):
182         """\
183         Get the value of the environment variable "key"
184         This method is added for API compatibility with FileEnviron class
185         
186         :param key str: the environment variable
187         """
188         return self.get(key)
189
190
191
192 class SalomeEnviron:
193     """\
194     Class to manage the environment of SALOME.
195     """
196     def __init__(self,
197                  cfg,
198                  environ,
199                  forBuild=False,
200                  for_package=None,
201                  enable_simple_env_script = True):
202         """\
203         Initialization.
204
205         :param cfg Config: the global config
206         :param environ Environ: the Environ instance where 
207                                 to store the environment variables
208         :param forBuild bool: If true, it is a launch environment, 
209                               else a build one
210         :param for_package str: If not None, produce a relative environment 
211                                 designed for a package. 
212         """
213         self.environ = environ
214         self.cfg = cfg
215         self.forBuild = forBuild
216         self.for_package = for_package
217         self.enable_simple_env_script = enable_simple_env_script
218         self.silent = False
219         self.has_python = False
220         self.__set_sorted_products_list()
221
222     def __repr__(self):
223         """easy almost exhaustive quick resume for debug print"""
224         res = {
225           "environ" : self.environ,
226           "forBuild" : self.forBuild,
227           "for_package" : self.for_package,
228         }
229         return "%s(\n%s\n)" % (self.__class__.__name__, PP.pformat(res))
230
231     def __set_sorted_products_list(self):
232         from compile import get_dependencies_graph, depth_first_topo_graph
233         all_products_infos = src.product.get_products_infos(
234                                  self.cfg.APPLICATION.products,
235                                  self.cfg)
236         
237         all_products_graph=get_dependencies_graph(all_products_infos)
238         visited_nodes=[]
239         sorted_nodes=[]
240         for n in all_products_graph:
241             if n not in visited_nodes:
242                 visited_nodes,sorted_nodes=depth_first_topo_graph(
243                                                all_products_graph, 
244                                                n, 
245                                                visited_nodes,
246                                                sorted_nodes)
247         self.sorted_product_list=sorted_nodes
248
249         # store the list of compile time products
250         # they should be added in build env
251         compile_time_products=[]
252         for (pname,pinfo) in all_products_infos:
253            if src.product.product_is_compile_time(pinfo):
254                compile_time_products.append(pname)
255         self.compile_time_products=compile_time_products
256
257
258     def append(self, key, value, sep=os.pathsep):
259         """\
260         append value to key using sep
261         
262         :param key str: the environment variable to append
263         :param value str: the value to append to key
264         :param sep str: the separator string
265         """
266         return self.environ.append(key, value, sep)
267
268     def prepend(self, key, value, sep=os.pathsep):
269         """\
270         prepend value to key using sep
271         
272         :param key str: the environment variable to prepend
273         :param value str: the value to prepend to key
274         :param sep str: the separator string
275         """
276         return self.environ.prepend(key, value, sep)
277
278     def is_defined(self, key):
279         """\
280         Check if the key exists in the environment
281         
282         :param key str: the environment variable to check
283         """
284         return self.environ.is_defined(key)
285
286     def get(self, key):
287         """\
288         Get the value of the environment variable "key"
289         
290         :param key str: the environment variable
291         """
292         return self.environ.get(key)
293
294     def get_value(self, key):
295         """\
296         Get the real value of the environment variable "key"
297         This method is added for API compatibility with FileEnviron class
298         
299         :param key str: the environment variable
300         """
301         if key in self.environ:
302             return self.environ[key]
303         else:
304             return ""
305
306     def set(self, key, value):
307         """\
308         Set the environment variable "key" to value "value"
309         
310         :param key str: the environment variable to set
311         :param value str: the value
312         """
313         # check if value needs to be evaluated
314         if value is not None and value.startswith("`") and value.endswith("`"):
315             res = subprocess.Popen("echo %s" % value,
316                                    shell=True,
317                                    stdout=subprocess.PIPE).communicate()
318             value = res[0].strip()
319
320         return self.environ.set(key, value)
321
322     def dump(self, out):
323         """\
324         Write the environment to out
325         
326         :param out file: the stream where to write the environment
327         """
328         for k in self.environ.environ.keys():
329             try:
330                 value = self.get(k)
331             except:
332                 value = "?"
333             out.write("%s=%s\n" % (k, value))
334
335     def add_line(self, nb_line):
336         """\
337         Add empty lines to the out stream (in case of file generation)
338         
339         :param nb_line int: the number of empty lines to add
340         """
341         if 'add_line' in dir(self.environ):
342             self.environ.add_line(nb_line)
343
344     def add_comment(self, comment):
345         """\
346         Add a commentary to the out stream (in case of file generation)
347         
348         :param comment str: the commentary to add
349         """
350         if 'add_comment' in dir(self.environ):
351             self.environ.add_comment(comment)
352
353     def add_warning(self, warning):
354         """\
355         Add a warning to the out stream (in case of file generation)
356         
357         :param warning str: the warning to add
358         """
359         if 'add_warning' in dir(self.environ):
360             self.environ.add_warning(warning)
361
362     def finish(self):
363         """\
364         Add a final instruction in the out file (in case of file generation)
365         
366         :param required bool: Do nothing if required is False
367         """
368         if 'finish' in dir(self.environ):
369             self.environ.add_line(1)
370             # what for ?
371             # self.environ.add_comment("clean all the path")
372             self.environ.finish()
373
374     def set_python_libdirs(self):
375         """Set some generic variables for python library paths"""
376         ver = self.get('PYTHON_VERSION')
377         self.set('PYTHON_LIBDIR', os.path.join('lib',
378                                                 'python' + ver,
379                                                 'site-packages'))
380         self.python_lib = self.get('PYTHON_LIBDIR')
381         self.has_python = True
382
383     def set_application_env(self, logger):
384         """\
385         Sets the environment defined in the APPLICATION file.
386         
387         :param logger Logger: The logger instance to display messages
388         """
389         
390         if self.for_package:
391            if src.architecture.is_windows():
392               self.set("PRODUCT_ROOT_DIR", "%out_dir_Path%")
393            else:
394               self.set("PRODUCT_ROOT_DIR", "out_dir_Path")
395
396         else:
397            self.cfg.APPLICATION.environ.PRODUCT_ROOT_DIR = src.pyconf.Reference(self.cfg, src.pyconf.DOLLAR, "workdir")
398
399         # these sensitive variables are reset to avoid bad environment interactions
400         self.add_line(1)
401         self.add_comment("reset these sensitive variables to avoid bad environment interactions")
402         self.add_comment("comment these to lines if you wish a different behaviour")
403         if not src.architecture.is_windows():
404            self.set("LD_LIBRARY_PATH", "")
405         self.set("PYTHONPATH", "")
406         self.add_line(1)
407
408         # Set the variables defined in the "environ" section
409         if 'environ' in self.cfg.APPLICATION:
410             # we write PRODUCT environment it in order to conform to 
411             # parseConfigFile.py
412             self.add_comment("PRODUCT environment") 
413             self.load_cfg_environment(self.cfg.APPLICATION.environ)
414             if self.forBuild and "build" in self.cfg.APPLICATION.environ:
415                 self.load_cfg_environment(self.cfg.APPLICATION.environ.build)
416             if not self.forBuild and "launch" in self.cfg.APPLICATION.environ:
417                 self.load_cfg_environment(self.cfg.APPLICATION.environ.launch)
418             self.add_line(1)
419
420
421     def set_salome_minimal_product_env(self, product_info, logger):
422         """\
423         Sets the minimal environment for a SALOME product.
424         xxx_ROOT_DIR and xxx_SRC_DIR
425         
426         :param product_info Config: The product description
427         :param logger Logger: The logger instance to display messages        
428         """
429         # set root dir
430         DBG.write("set_salome_minimal_product_env", product_info)
431         root_dir = product_info.name + "_ROOT_DIR"
432         if 'install_dir' in product_info and product_info.install_dir:
433             self.set(root_dir, product_info.install_dir)
434         elif not self.silent:
435             logger.write("  " + _("No install_dir for product %s\n") %
436                           product_info.name, 5)
437     
438         source_in_package = src.get_property_in_product_cfg(product_info,
439                                                            "sources_in_package")
440         if not self.for_package or source_in_package == "yes":
441             # set source dir, unless no source dir
442             if not src.product.product_is_fixed(product_info):
443                 src_dir = product_info.name + "_SRC_DIR"
444                 if not self.for_package:
445                     self.set(src_dir, product_info.source_dir)
446                 else:
447                     self.set(src_dir, os.path.join("out_dir_Path",
448                              "SOURCES",
449                              os.path.basename(product_info.source_dir)))
450
451     def expand_salome_modules(self, pi):
452         if 'component_name' in pi:
453             compo_name = pi.component_name
454         else:
455             compo_name = pi.name
456         self.append('SALOME_MODULES', compo_name, ',')
457         
458         
459     def set_salome_generic_product_env(self, pi):
460         """\
461         Sets the generic environment for a SALOME product.
462         
463         :param pi Config: The product description
464         """
465         # Construct XXX_ROOT_DIR
466         env_root_dir = self.get(pi.name + "_ROOT_DIR")
467         l_binpath_libpath = []
468         # create additional ROOT_DIR for CPP components
469         if 'component_name' in pi:
470             compo_name = pi.component_name
471             if compo_name + "CPP" == pi.name:
472                 compo_root_dir = compo_name + "_ROOT_DIR"
473                 envcompo_root_dir = os.path.join(
474                             self.cfg.TOOLS.common.install_root, compo_name )
475                 self.set(compo_root_dir ,  envcompo_root_dir)
476                 bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome')
477                 lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome')
478                 l_binpath_libpath.append( (bin_path, lib_path) )
479
480
481         if src.get_property_in_product_cfg(pi, "fhs"):
482             lib_path = os.path.join(env_root_dir, 'lib')
483             bin_path = os.path.join(env_root_dir, 'bin')
484             if self.has_python:
485             # if the application doesn't include python, we don't need these two lines
486                 pylib_path = os.path.join(env_root_dir, self.python_lib)
487         else:
488             lib_path = os.path.join(env_root_dir, 'lib', 'salome')
489             bin_path = os.path.join(env_root_dir, 'bin', 'salome')
490             if self.has_python:
491             # if the application doesn't include python, we don't need these two lines
492                 pylib_path = os.path.join(env_root_dir, self.python_lib, 'salome')
493
494         # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and 
495         # PYTHONPATH
496         l_binpath_libpath.append( (bin_path, lib_path) )
497
498         for bin_path, lib_path in l_binpath_libpath:
499             if not self.forBuild:
500                 self.prepend('PATH', bin_path)
501                 if src.architecture.is_windows():
502                     self.prepend('PATH', lib_path)
503                 else :
504                     self.prepend('LD_LIBRARY_PATH', lib_path)
505
506             l = [ bin_path, lib_path ]
507             if not src.product.product_is_wheel(pi):
508                 if self.has_python:
509                     l.append(pylib_path)
510                 self.prepend('PYTHONPATH', l)
511
512     def set_cpp_env(self, product_info):
513         """\
514         Sets the generic environment for a SALOME cpp product.
515         
516         :param product_info Config: The product description
517         """
518         # Construct XXX_ROOT_DIR
519         env_root_dir = self.get(product_info.name + "_ROOT_DIR")
520         l_binpath_libpath = []
521
522         # Construct the paths to prepend to PATH and LD_LIBRARY_PATH and 
523         # PYTHONPATH
524         bin_path = os.path.join(env_root_dir, 'bin')
525         lib_path = os.path.join(env_root_dir, 'lib')
526         l_binpath_libpath.append( (bin_path, lib_path) )
527
528         for bin_path, lib_path in l_binpath_libpath:
529             if not self.forBuild:
530                 self.prepend('PATH', bin_path)
531                 if src.architecture.is_windows():
532                     self.prepend('PATH', lib_path)
533                 else :
534                     self.prepend('LD_LIBRARY_PATH', lib_path)
535
536             l = [ bin_path, lib_path ]
537             if self.has_python:
538                 l.append(os.path.join(env_root_dir, self.python_lib))
539             self.prepend('PYTHONPATH', l)
540
541     def load_cfg_environment(self, cfg_env):
542         """\
543         Loads environment defined in cfg_env 
544         
545         :param cfg_env Config: A config containing an environment    
546         """
547         # Loop on cfg_env values
548         for env_def in cfg_env:
549             val = cfg_env[env_def]
550             
551             # if it is env_script, do not do anything (reserved keyword)
552             if env_def == "env_script":
553                 continue
554             
555             # if it is a dict, do not do anything
556             if isinstance(val, src.pyconf.Mapping):
557                 continue
558
559             # if it is a list, loop on its values
560             if isinstance(val, src.pyconf.Sequence):
561                 # transform into list of strings
562                 l_val = []
563                 for item in val:
564                     l_val.append(item)
565                 val = l_val
566
567             # "_" means that the value must be prepended
568             if env_def.startswith("_"):
569                 # separator exception for PV_PLUGIN_PATH
570                 if env_def[1:] == 'PV_PLUGIN_PATH':
571                     self.prepend(env_def[1:], val, ';')
572                 else:
573                     self.prepend(env_def[1:], val)
574             elif env_def.endswith("_"):
575                 # separator exception for PV_PLUGIN_PATH
576                 if env_def[:-1] == 'PV_PLUGIN_PATH':
577                     self.append(env_def[:-1], val, ';')
578                 else:
579                     self.append(env_def[:-1], val)
580             else:
581                 self.set(env_def, val)
582
583     def set_a_product(self, product, logger):
584         """\
585         Sets the environment of a product. 
586         
587         :param product str: The product name
588         :param logger Logger: The logger instance to display messages
589         """
590
591         # Get the informations corresponding to the product
592         pi = src.product.get_product_config(self.cfg, product)
593         # skip compile time products at run time 
594         if not self.forBuild:
595             if src.product.product_is_compile_time(pi):
596                 return
597
598         # skip pip products when pip is activated and installation is done in python 
599         #if (src.appli_test_property(self.cfg,"pip", "yes") and 
600         #    src.product.product_test_property(pi,"pip", "yes") and
601         #    src.appli_test_property(self.cfg,"pip_install_dir", "python") ):
602         #        return
603
604         # skip mesa products (if any) at run time, 
605         # unless use_mesa property was activated
606         if not self.forBuild:
607             if not ("APPLICATION" in self.cfg  and
608                     "properties" in self.cfg.APPLICATION  and
609                     "use_mesa" in self.cfg.APPLICATION.properties  and
610                     self.cfg.APPLICATION.properties.use_mesa == "yes") :
611                 if ("properties" in pi and
612                     "is_mesa" in pi.properties  and
613                     pi.properties.is_mesa == "yes") :
614                     logger.write(_("Skip mesa product %s\n") % pi.name, 4)
615                     return
616                
617         
618         if self.for_package:
619             prod_base_name=os.path.basename(pi.install_dir)
620             if prod_base_name.startswith("config"):
621                 # case of a products installed in base. We remove "config-i"
622                 prod_base_name=os.path.basename(os.path.dirname(pi.install_dir))
623             pi.install_dir = os.path.join(
624                                  "out_dir_Path",
625                                  self.for_package,
626                                  prod_base_name)
627
628         if not self.silent:
629             logger.write(_("Setting environment for %s\n") % product, 4)
630
631         self.add_line(1)
632         self.add_comment('setting environ for ' + product)
633             
634         # Do not define environment if the product is native
635         if src.product.product_is_native(pi):
636             if src.product.product_has_env_script(pi):
637                 self.run_env_script(pi, native=True)
638             return
639                
640         # Set an additional environment for SALOME products
641         if src.product.product_is_salome(pi):
642             # set environment using definition of the product
643             self.set_salome_minimal_product_env(pi, logger)
644             self.set_salome_generic_product_env(pi)
645            
646         
647         # Expand SALOME_MODULES variable for products which have a salome gui
648         if src.product.product_has_salome_gui(pi):
649             self.expand_salome_modules(pi)
650
651         # use variable LICENCE_FILE to communicate the licence file name to the environment script
652         licence_file_name = src.product.product_has_licence(pi, self.cfg.PATHS.LICENCEPATH)
653         if licence_file_name:
654             logger.write("licence file found for product %s : %s\n" % (pi.name, licence_file_name), 5) 
655             self.set("LICENCE_FILE", licence_file_name)
656
657         if src.product.product_is_cpp(pi):
658             # set a specific environment for cpp modules
659             self.set_salome_minimal_product_env(pi, logger)
660             self.set_cpp_env(pi)
661             
662             if src.product.product_is_generated(pi):
663                 if "component_name" in pi:
664                     # hack the source and install directories in order to point  
665                     # on the generated product source install directories
666                     install_dir_save = pi.install_dir
667                     source_dir_save = pi.source_dir
668                     name_save = pi.name
669                     pi.install_dir = os.path.join(self.cfg.APPLICATION.workdir,
670                                                   self.cfg.INTERNAL.config.install_dir,
671                                                   pi.component_name)
672                     if self.for_package:
673                         pi.install_dir = os.path.join("out_dir_Path",
674                                                       self.for_package,
675                                                       pi.component_name)
676                     pi.source_dir = os.path.join(self.cfg.APPLICATION.workdir,
677                                                   "GENERATED",
678                                                   pi.component_name)
679                     pi.name = pi.component_name
680                     self.set_salome_minimal_product_env(pi, logger)
681                     self.set_salome_generic_product_env(pi)
682                     
683                     # Put original values
684                     pi.install_dir = install_dir_save
685                     pi.source_dir = source_dir_save
686                     pi.name = name_save
687         
688         # Put the environment define in the configuration of the product
689         if "environ" in pi:
690             self.load_cfg_environment(pi.environ)
691             if self.forBuild and "build" in pi.environ:
692                 self.load_cfg_environment(pi.environ.build)
693             if not self.forBuild and "launch" in pi.environ:
694                 self.load_cfg_environment(pi.environ.launch)
695             # if product_info defines a env_scripts, load it
696             if 'env_script' in pi.environ:
697                 self.run_env_script(pi, logger)
698
699         
700             
701
702     def run_env_script(self, product_info, logger=None, native=False):
703         """\
704         Runs an environment script. 
705         
706         :param product_info Config: The product description
707         :param logger Logger: The logger instance to display messages
708         :param native Boolean: if True load set_native_env instead of set_env
709         """
710         env_script = product_info.environ.env_script
711         # Check that the script exists
712         if not os.path.exists(env_script):
713             raise src.SatException(_("Environment script not found: %s") % 
714                                    env_script)
715
716         if not self.silent and logger is not None:
717             logger.write("  ** load %s\n" % env_script, 4)
718
719         # import the script and run the set_env function
720         try:
721             import imp
722             pyproduct = imp.load_source(product_info.name + "_env_script",
723                                         env_script)
724             if not native:
725                 if self.forBuild and "set_env_build" in dir(pyproduct):
726                     pyproduct.set_env_build(self,
727                                             product_info.install_dir,
728                                             product_info.version)
729                 elif (not self.forBuild) and "set_env_launch" in dir(pyproduct):
730                     pyproduct.set_env_launch(self,
731                                             product_info.install_dir,
732                                             product_info.version)
733                 else:
734                     # at least this one is mandatory,
735                     # if set_env_build and set_env_build are not defined
736                     pyproduct.set_env(self,
737                                       product_info.install_dir,
738                                       product_info.version)
739             else:
740                 # not mandatory, if set_nativ_env not defined, we do nothing
741                 if "set_nativ_env" in dir(pyproduct):
742                     pyproduct.set_nativ_env(self)
743         except:
744             __, exceptionValue, exceptionTraceback = sys.exc_info()
745             print(exceptionValue)
746             import traceback
747             traceback.print_tb(exceptionTraceback)
748             traceback.print_exc()
749
750     def set_products(self, logger, src_root=None):
751         """\
752         Sets the environment for all the products. 
753         
754         :param logger Logger: The logger instance to display messages
755         :param src_root src: the application working directory
756         """
757         self.add_line(1)
758         self.add_comment('setting environ for all products')
759
760         # Make sure that the python lib dirs are set after python
761         if "Python" in self.sorted_product_list:
762             self.set_a_product("Python", logger)
763             self.set_python_libdirs()
764
765         # for a build environment, add compile time products (like cmake)
766         if self.forBuild :
767             for product in self.compile_time_products:
768                 self.set_a_product(product, logger)
769
770         # The loop on the products
771         for product in self.sorted_product_list:
772             if product == "Python":
773                 continue
774             self.set_a_product(product, logger)
775  
776     def set_full_environ(self, logger, env_info):
777         """\
778         Sets the full environment for products 
779         specified in env_info dictionary. 
780         
781         :param logger Logger: The logger instance to display messages
782         :param env_info list: the list of products
783         """
784         DBG.write("set_full_environ for", env_info)
785         # DBG.write("set_full_environ config", self.cfg.APPLICATION.environ, True)
786         # set product environ
787         self.set_application_env(logger)
788
789         # use the sorted list of all products to sort the list of products 
790         # we have to set
791         sorted_product_list=[]
792         for n in self.sorted_product_list:
793             if n in env_info:
794                 sorted_product_list.append(n)
795
796         if "Python" in sorted_product_list:
797             self.set_a_product("Python", logger)
798             self.set_python_libdirs()
799
800         # for a build environment, add compile time products (like cmake)
801         if self.forBuild :
802             for product in self.compile_time_products:
803                 self.set_a_product(product, logger)
804
805         # set products
806         for product in sorted_product_list:
807             if product == "Python":
808                 continue
809             self.set_a_product(product, logger)
810
811 class FileEnvWriter:
812     """\
813     Class to dump the environment to a file.
814     """
815     def __init__(self, config, logger, out_dir, src_root, env_info=None):
816         """\
817         Initialization.
818
819         :param cfg Config: the global config
820         :param logger Logger: The logger instance to display messages
821         :param out_dir str: The directory path where t put the output files
822         :param src_root str: The application working directory
823         :param env_info str: The list of products to add in the files.
824         """
825         self.config = config
826         self.logger = logger
827         self.out_dir = out_dir
828         self.src_root= src_root
829         self.silent = True
830         self.env_info = env_info
831
832     def write_tcl_files(self,
833                         forBuild, 
834                         shell, 
835                         for_package = None,
836                         no_path_init=False,
837                         additional_env = {}):
838         """\
839         Create tcl environment files for environment module.
840         
841         :param forBuild bool: if true, the build environment
842         :param shell str: the type of file wanted (.sh, .bat)
843         :param for_package bool: if true do specific stuff for required for packages
844         :param no_path_init bool: if true generate a environ file that do not reinitialise paths
845         :param additional_env dict: contains sat_ prefixed variables to help the génération, 
846                                     and also variables to add in the environment.
847         :return: The path to the generated file
848         :rtype: str
849         """
850
851         # get the products informations
852         all_products=self.config.APPLICATION.products
853         products_infos = src.product.get_products_infos(all_products, self.config) 
854
855         # set a global environment (we need it to resolve variable references
856         # between dependent products
857         global_environ = src.environment.SalomeEnviron(self.config,
858                                   src.environment.Environ(additional_env),
859                                   False)
860         global_environ.set_products(self.logger)
861         
862         # The loop on the products
863         for product in all_products:
864             # create one file per product
865             pi = src.product.get_product_config(self.config, product)
866             if "base" not in pi:  # we write tcl files only for products in base
867                 continue
868
869             # get the global environment, and complete it with sat_ prefixed 
870             # prefixed variables which are used to transfer info to 
871             # TclFileEnviron class  
872             product_env = copy.deepcopy(global_environ.environ)
873             product_env.environ["sat_product_name"] = pi.name
874             product_env.environ["sat_product_version"] = pi.version
875             product_env.environ["sat_product_base_path"] = src.get_base_path(self.config)
876             product_env.environ["sat_product_base_name"] = pi.base
877    
878             # store infos in sat_product_load_depend to set dependencies in tcl file
879             sat_product_load_depend=""
880             for p_name,p_info in products_infos:
881                 if p_name in pi.depend:
882                     sat_product_load_depend+="module load %s/%s/%s;" % (pi.base, 
883                                                                         p_info.name, 
884                                                                         p_info.version)
885             if len(sat_product_load_depend)>0:
886                 # if there are dependencies, store the module to load (get rid of trailing ;)
887                 product_env.environ["sat_product_load_depend"]=sat_product_load_depend[0:-1]
888
889
890             env_file_name = os.path.join(product_env.environ["sat_product_base_path"], 
891                                          "modulefiles", 
892                                          product_env.environ["sat_product_base_name"],
893                                          product_env.environ["sat_product_name"], 
894                                          product_env.environ["sat_product_version"])
895             prod_dir_name=os.path.dirname(env_file_name)
896             if not os.path.isdir(prod_dir_name):
897                 os.makedirs(prod_dir_name)
898
899             env_file = open(env_file_name, "w")
900             file_environ = src.fileEnviron.get_file_environ(env_file,
901                                            "tcl", product_env)
902             env = SalomeEnviron(self.config, 
903                                 file_environ, 
904                                 False, 
905                                 for_package=for_package)
906             if "Python" in pi.depend:
907                 # short cut, env.python_lib is required by set_a_product for salome modules
908                 env.has_python="True"
909                 env.python_lib=global_environ.get("PYTHON_LIBDIR")
910             env.set_a_product(product, self.logger)
911             env_file.close()
912             if not self.silent:
913                 self.logger.write(_("    Create tcl module environment file %s\n") % 
914                                   src.printcolors.printcLabel(env_file_name), 3)
915
916
917     def write_env_file(self,
918                        filename,
919                        forBuild, 
920                        shell, 
921                        for_package = None,
922                        no_path_init=False,
923                        additional_env = {}):
924         """\
925         Create an environment file.
926         
927         :param filename str: the file path
928         :param forBuild bool: if true, the build environment
929         :param shell str: the type of file wanted (.sh, .bat)
930         :param for_package bool: if true do specific stuff for required for packages
931         :param no_path_init bool: if true generate a environ file that do not reinitialise paths
932         :param additional_env dict: contains sat_ prefixed variables to help the génération, 
933                                     and also variables to add in the environment.
934         :return: The path to the generated file
935         :rtype: str
936         """
937         if not self.silent:
938             self.logger.write(_("Create environment file %s\n") % 
939                               src.printcolors.printcLabel(filename), 3)
940         # create then env object
941         env_file = open(os.path.join(self.out_dir, filename), "w")
942
943         # we duplicate additional_env, and transmit it to fileEnviron, which will use its sat_ prefixed variables.
944         # the other variables of additional_env are added to the environement file at the end of this function.
945         salome_env = copy.deepcopy(additional_env)
946         file_environ = src.fileEnviron.get_file_environ(env_file,
947                                                shell,
948                                                src.environment.Environ(salome_env))
949         if no_path_init:
950             # specify we don't want to reinitialise paths
951             # path will keep the inherited value, which will be appended with new values.
952             file_environ.set_no_init_path()
953
954         env = SalomeEnviron(self.config, 
955                             file_environ, 
956                             forBuild, 
957                             for_package=for_package)
958
959         env.silent = self.silent
960
961         # Set the environment
962         if self.env_info is not None:
963             env.set_full_environ(self.logger, self.env_info)
964         else:
965             # set env from the APPLICATION
966             env.set_application_env(self.logger)
967             # set the products
968             env.set_products(self.logger,
969                             src_root=self.src_root)
970         # Add the additional environment if it is not empty
971         if len(additional_env) != 0:
972             env.add_line(1)
973             env.add_comment("[APPLI variables]")
974             for variable in additional_env:
975                 if not variable.startswith("sat_"):
976                     # by convention variables starting with sat_ are used to transfer information, 
977                     # not to be written in env
978                     env.set(variable, additional_env[variable])
979
980         # finalise the writing and close the file
981         env.finish()
982         env_file.close()
983
984         return env_file.name
985    
986
987 class Shell:
988     """\
989     Definition of a Shell.
990     """
991     def __init__(self, name, extension):
992         """\
993         Initialization.
994
995         :param name str: the shell name
996         :param extension str: the shell extension
997         """
998         self.name = name
999         self.extension = extension
1000
1001 def load_environment(config, build, logger):
1002     """\
1003     Loads the environment (used to run the tests, for example).
1004     
1005     :param config Config: the global config
1006     :param build bool: build environement if True
1007     :param logger Logger: The logger instance to display messages
1008     """
1009     environ = SalomeEnviron(config, Environ(os.environ), build)
1010     environ.set_application_env(logger)
1011     environ.set_products(logger)