Salome HOME
Add Builder class
authorSerge Rehbinder <serge.rehbinder@cea.fr>
Mon, 25 Apr 2016 13:34:29 +0000 (15:34 +0200)
committerSerge Rehbinder <serge.rehbinder@cea.fr>
Mon, 25 Apr 2016 13:34:29 +0000 (15:34 +0200)
commands/environ.py
data/products/PRODUCT_ARCHIVE.pyconf
data/products/PRODUCT_GIT.pyconf
src/__init__.py
src/compilation.py [new file with mode: 0644]
src/environment.py
src/fileEnviron.py
src/product.py

index 981e69c5d8eeafe0ed9bc47de1500bbcecebe7b6..6ea7395fd667f630fb2f4de0326f1b7a3c34e784 100644 (file)
@@ -17,8 +17,6 @@
 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
 import os
-import sys
-import subprocess
 
 import src
 
@@ -36,465 +34,6 @@ parser.add_option('t', 'target', 'string', 'out_dir',
 C_SHELLS = { "bash": "sh", "batch": "bat" }
 C_ALL_SHELL = [ "bash", "batch" ]
 
-class SalomeEnviron:
-    """Class to manage the environment of SALOME.
-    """
-
-    def __init__(self, cfg, environ, forBuild=False):
-        self.environ = environ
-        self.cfg = cfg
-        self.forBuild = forBuild
-        self.silent = False
-
-    def __repr__(self):
-        """easy non exhaustive quick resume for debug print"""
-        res={}
-        res["environ"]=str(self.environ)
-        res["forBuild"]=self.forBuild
-        return self.__class__.__name__ + str(res)[0:-1] + " ...etc...}"
-
-    def append(self, key, value, sep=os.pathsep):
-        return self.environ.append(key, value, sep)
-
-    def prepend(self, key, value, sep=os.pathsep):
-        return self.environ.prepend(key, value, sep)
-
-    def is_defined(self, key):
-        return self.environ.is_defined(key)
-
-    def get(self, key):
-        return self.environ.get(key)
-
-    def set(self, key, value):
-        # check if value needs to be evaluated
-        if value is not None and value.startswith("`") and value.endswith("`"):
-            res = subprocess.Popen("echo %s" % value, shell=True, stdout=subprocess.PIPE).communicate()
-            value = res[0].strip()
-
-        return self.environ.set(key, value)
-
-    def dump(self, out):
-        """Write the environment to out"""
-        for k in self.environ.environ.keys():
-            try:
-                value = self.get(k)
-            except:
-                value = "?"
-            out.write("%s=%s\n" % (k, value))
-
-    def add_line(self, nb_line):
-        if 'add_line' in dir(self.environ):
-            self.environ.add_line(nb_line)
-
-    def add_comment(self, comment):
-        if 'add_comment' in dir(self.environ):
-            self.environ.add_comment(comment)
-
-    def add_warning(self, warning):
-        if 'add_warning' in dir(self.environ):
-            self.environ.add_warning(warning)
-
-    def finish(self, required):
-        if 'finish' in dir(self.environ):
-            self.environ.add_line(1)
-            self.environ.add_comment("clean all the path")
-            self.environ.finish(required)
-
-    def list_version_4_prereq(self, prerequisite, logger):
-        alist = []
-        for path in self.cfg.TOOLS.environ.prereq_install_dir:
-            if not os.path.exists(path):
-                continue
-            prereqlist = os.listdir(path)
-            for prereq in prereqlist:
-                if prereq.split("-")[0] == prerequisite:
-                    #logger.error(str(prereq) + "\n")
-                    alist.append(str(prereq))
-
-        if len(alist) > 0:
-            logger.write(_("Available prerequisites are:") + "\n\t%s\n" % '\n\t'.join(alist), 2)
-
-    def set_python_libdirs(self):
-        if src.architecture.is_windows():
-            # sysconfig.get_python_lib() does not return appropriate path on Windows
-            # clearly decide here once for windows
-            ver = self.get('PYTHON_VERSION')
-            self.set('PYTHON_LIBDIR0', os.path.join('lib', 'python' + ver, 'site-packages'))
-            self.set('PYTHON_LIBDIR1', os.path.join('lib64', 'python' + ver, 'site-packages'))
-
-        else:
-            """obsolete: too hazardous for WHEN we have to interpret that throught new python script salomeContext
-            #less "' is clearer and safer for Popen etc...
-            cmd = 'python -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(plat_specific=%s, standard_lib=False, prefix=str()))"'
-            #False==0 ; True==1
-            self.environ.command_value('PYTHON_LIBDIR0', cmd % "False")
-            self.environ.command_value('PYTHON_LIBDIR1', cmd % "True")
-            """
-            #cleary decide here once for linux
-            ver = self.get('PYTHON_VERSION')
-            self.set('PYTHON_LIBDIR0', os.path.join('lib', 'python' + ver, 'site-packages'))
-            self.set('PYTHON_LIBDIR1', os.path.join('lib64', 'python' + ver, 'site-packages'))
-          
-        self.python_lib0 = self.get('PYTHON_LIBDIR0')
-        self.python_lib1 = self.get('PYTHON_LIBDIR1')
-
-    ##
-    # Get the products name to add in SALOME_MODULES environment variable
-    # It is the name of the product, except in the case where the is a component name.
-    # And it has to be in SALOME_MODULES variable only if has_gui = "yes"
-    def getNames(self, lProducts):
-        lProdHasGui = [p for p in lProducts if 'has_gui' in src.product.get_product_config(self.cfg, p) and src.product.get_product_config(self.cfg, p).has_gui=='yes']
-        lProdName = []
-        for ProdName in lProdHasGui:
-            pi = src.product.get_product_config(self.cfg, ProdName)
-            if 'component_name' in pi:
-                lProdName.append(pi.component_name)
-            else:
-                lProdName.append(ProdName)
-        return lProdName
-
-    ##
-    # Sets the environment defined in the PRODUCT file.
-    def set_application_env(self, logger):
-        if 'environ' in self.cfg.APPLICATION:
-            self.add_comment("APPLICATION environment")
-            for p in self.cfg.APPLICATION.environ:
-                self.set(p, self.cfg.APPLICATION.environ[p])
-            self.add_line(1)
-
-        if 'environ_script' in self.cfg.APPLICATION:
-            for pscript in self.cfg.APPLICATION.environ_script:
-                self.add_comment("script %s" % pscript)
-                sname = pscript.replace(" ", "_")
-                self.run_env_script("APPLICATION_%s" % sname, self.cfg.APPLICATION.environ_script[pscript], logger)
-                self.add_line(1)
-        
-        if 'profile' in self.cfg.APPLICATION:
-            profile_product = self.cfg.APPLICATION.profile.product
-            product_info_profile = src.product.get_product_config(self.cfg, profile_product)
-            profile_share_salome = os.path.join( product_info_profile.install_dir, "share", "salome" )
-            self.set( "SUITRoot", profile_share_salome )
-            self.set( "SalomeAppConfig", os.path.join( profile_share_salome, "resources", profile_product.lower() ) )
-        
-        # The list of products to launch
-        lProductsName = self.getNames(self.cfg.APPLICATION.products.keys())
-        
-        self.set( "SALOME_MODULES",    ','.join(lProductsName))
-
-    ##
-    # Set xxx_ROOT_DIR and xxx_SRC_DIR.
-    def set_salome_minimal_product_env(self, product_info, logger, single_dir, cfgdic=None):
-        # set root dir
-        root_dir = product_info.name + "_ROOT_DIR"
-        indic = cfgdic is not None and root_dir in cfgdic
-        if not self.is_defined(root_dir) and not indic:
-            if single_dir:
-                self.set(root_dir, os.path.join(self.get('INSTALL_ROOT'), 'SALOME'))
-            elif 'install_dir' in product_info and product_info.install_dir:
-                self.set(root_dir, product_info.install_dir)
-            elif not self.silent:
-                logger.write("  " + _("No install_dir for product %s\n") % product_info.name, 5)
-
-        # set source dir, unless the product is fixed (no source dir)
-        if not src.product.product_is_fixed(product_info):
-            src_dir = product_info.name + "_SRC_DIR"
-            indic = cfgdic is not None and src_dir in cfgdic
-            if not self.is_defined(src_dir) and not indic:
-                self.set(src_dir, product_info.source_dir)
-
-    def set_salome_generic_product_env(self, product):
-        pi = src.product.get_product_config(self.cfg, product)
-        env_root_dir = self.get(pi.name + "_ROOT_DIR")
-        l_binpath_libpath = []
-
-        # create additional ROOT_DIR for CPP components
-        if 'component_name' in pi:
-            compo_name = pi.component_name
-            if compo_name + "CPP" == product:
-                compo_root_dir = compo_name + "_ROOT_DIR"
-                envcompo_root_dir = os.path.join( self.cfg.TOOLS.common.install_root, compo_name )
-                self.set(compo_root_dir ,  envcompo_root_dir)
-                bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome')
-                lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome')
-                l_binpath_libpath.append( (bin_path, lib_path) )
-
-        appliname = 'salome'
-        if src.get_cfg_param(pi, 'product_type', 'SALOME').upper() not in [ "SALOME", "SMESH_PLUGIN", "SAMPLE" ]:
-            appliname = ''
-
-        bin_path = os.path.join(env_root_dir, 'bin', appliname)
-        lib_path = os.path.join(env_root_dir, 'lib', appliname)
-        l_binpath_libpath.append( (bin_path, lib_path) )
-
-        for bin_path, lib_path in l_binpath_libpath:
-            if not self.forBuild:
-                self.prepend('PATH', bin_path)
-                if src.architecture.is_windows():
-                    self.prepend('PATH', lib_path)
-                else :
-                    self.prepend('LD_LIBRARY_PATH', lib_path)
-
-            l = [ bin_path, lib_path,
-                  os.path.join(env_root_dir, self.python_lib0, appliname),
-                  os.path.join(env_root_dir, self.python_lib1, appliname)
-                ]
-            self.prepend('PYTHONPATH', l)
-
-    ##
-    # Loads environment define in the configuration.
-    def load_cfg_environment(self, cfg_env):
-        for env_def in cfg_env:
-            val = cfg_env[env_def]
-            if isinstance(val, src.pyconf.Mapping):
-                continue
-
-            if isinstance(val, src.pyconf.Sequence):
-                # transform into list of strings
-                val = map(lambda l: l, val)
-
-            if env_def.startswith("_"):
-                # separator exception for PV_PLUGIN_PATH
-                if env_def[1:] == 'PV_PLUGIN_PATH':
-                    self.prepend(env_def[1:], val, ';')
-                else:
-                    self.prepend(env_def[1:], val)
-            elif env_def.endswith("_"):
-                # separator exception for PV_PLUGIN_PATH
-                if env_def[:-1] == 'PV_PLUGIN_PATH':
-                    self.prepend(env_def[:-1], val, ';')
-                else:
-                    self.prepend(env_def[:-1], val)
-            else:
-                self.set(env_def, val)
-
-    ##
-    # Sets the environment of a product.
-    def set_a_product(self, product, logger, single_dir):
-               
-        if not self.silent:
-            logger.write(_("Setting environment for %s\n") % product, 4)
-
-        self.add_line(1)
-        self.add_comment('setting environ for ' + product)
-        
-        pi = src.product.get_product_config(self.cfg, product)
-
-        # Do not define environment if the product is native or fixed
-        if src.product.product_is_native(pi):
-            return
-
-        if "environ" in pi:
-            # set environment using definition of the product
-            self.set_salome_minimal_product_env(pi, logger, single_dir, pi.environ)
-            self.set_salome_generic_product_env(product)
-            self.load_cfg_environment(pi.environ)
-            if self.forBuild and "build" in pi.environ:
-                self.load_cfg_environment(pi.environ.build)
-            if not self.forBuild and "launch" in pi.environ:
-                self.load_cfg_environment(pi.environ.launch)
-        else:
-            # no environment defined in config
-            self.set_salome_minimal_product_env(pi, logger, single_dir)
-            if 'install_dir' in pi :
-                self.set_salome_generic_product_env(product)
-
-        # if product_info defines a env_scripts load it
-        if 'env_script' in pi:
-            self.run_env_script(product, pi.env_script, logger)
-            
-
-    ##
-    # Runs an environment script.
-    def run_env_script(self, product, env_script, logger=None):
-        if not os.path.exists(env_script):
-            raise src.SatException(_("Environment script not found: %s") % env_script)
-
-        if not self.silent and logger is not None:
-            logger.write("  ** load %s\n" % env_script, 4)
-
-        try:
-            import imp
-            pyproduct = imp.load_source(product + "_env_script", env_script)
-            pyproduct.load_env(self)
-        except:
-            __, exceptionValue, exceptionTraceback = sys.exc_info()
-            print(exceptionValue)
-            import traceback
-            traceback.print_tb(exceptionTraceback)
-            traceback.print_exc()
-
-    ##
-    # Sets the environment for all the products.
-    def set_products(self, logger, src_root=None, single_dir=False):
-        self.add_line(1)
-        self.add_comment('setting environ for all products')
-
-        self.set_python_libdirs()
-
-        if src_root is None:
-            src_root = self.cfg.APPLICATION.workdir
-        self.set('SRC_ROOT', src_root)
-
-        appli_name = "APPLI"
-        if "APPLI" in self.cfg and "application_name" in self.cfg.APPLI:
-            appli_name = self.cfg.APPLI.application_name
-        self.set("SALOME_APPLI_ROOT", os.path.join(self.cfg.APPLICATION.workdir, appli_name))
-
-        if not single_dir:
-            single_dir = src.get_cfg_param(self.cfg.APPLICATION, "compil_in_single_dir", "no") == 'yes'
-
-        for product in src.get_cfg_param(self.cfg.APPLICATION, "imported_products", []):
-            self.set_a_product(product, logger, single_dir=single_dir)
-            self.finish(False)
-
-        for product in self.cfg.APPLICATION.products.keys():
-            self.set_a_product(product, logger, single_dir=single_dir)
-            self.finish(False)
-
-   
-    ##
-    # Sets the full environment for prerequisites and products specified in env_info dictionary.
-    def set_full_environ(self, logger, env_info):
-        # set product environ
-        self.set_application_env(logger)
-
-        # set products
-        self.set('INSTALL_ROOT', self.cfg.TOOLS.common.install_root)
-        self.set('SRC_ROOT', self.cfg.TOOLS.common.source_root)
-        self.set_python_libdirs()
-
-        single_dir = src.get_cfg_param(self.cfg.PRODUCT, "compil_in_single_dir", "no") == 'yes'
-        for product in env_info['products']:
-            self.set_a_product(product, logger, single_dir=single_dir)
-
-##
-# Class to dump the environment to a file.
-class FileEnvWriter:
-    def __init__(self, config, logger, out_dir, src_root, single_dir, env_info=None):
-        self.config = config
-        self.logger = logger
-        self.out_dir = out_dir
-        self.src_root= src_root
-        self.single_dir = single_dir
-        self.silent = True
-        self.env_info = env_info
-
-    def write_env_file(self, filename, forBuild, shell):
-        """Create an environment file."""
-        if not self.silent:
-            self.logger.write(_("Create environment file %s\n") % src.printcolors.printcLabel(filename), 3)
-
-        # create then env object
-        env_file = open(os.path.join(self.out_dir, filename), "w")
-        tmp = src.fileEnviron.get_file_environ(env_file, shell, {}, self.config )
-        env = SalomeEnviron(self.config, tmp, forBuild)
-        env.silent = self.silent
-
-        if self.env_info is not None:
-            env.set_full_environ(self.logger, self.env_info)
-        else:
-            # set env from PRODUCT
-            env.set_application_env(self.logger)
-            # set the products
-            env.set_products(self.logger,
-                            src_root=self.src_root, single_dir=self.single_dir)
-
-        # add cleanup and close
-        env.finish(True)
-        env_file.close()
-
-        return env_file.name
-
-    def write_product_file(self, filename, shell):
-        """Create a product file."""
-        if not self.silent:
-            self.logger.write(_("Create product file %s\n") % src.printcolors.printcLabel(filename), 3)
-
-        prod_file = open(os.path.join(self.out_dir, filename), "w")
-        if shell == "bash":
-            content = _bash_content % self.out_dir
-        elif shell == "batch":
-            content = _batch_content % self.out_dir
-        else:
-            raise src.SatException(_("Unknown shell: %s") % shell)
-
-        prod_file.write(content)
-        prod_file.close()
-       
-        return prod_file.name
-   
-    def write_cfgForPy_file(self, aFile, additional_env = {}):
-        """append to current opened aFile a cfgForPy environment (python syntax)."""
-        if not self.silent:
-            self.logger.write(_("Create configuration file %s\n") % src.printcolors.printcLabel(aFile.name), 3)
-
-        # create then env object
-        tmp = src.fileEnviron.get_file_environ(aFile, "cfgForPy", {}, self.config)
-        forBuild = True
-        forLaunch = False
-        env = SalomeEnviron(self.config, tmp, forLaunch)
-        env.silent = self.silent
-
-        if self.env_info is not None:
-            env.set_full_environ(self.logger, self.env_info)
-        else:
-            # set env from PRODUCT
-            env.set_application_env(self.logger)
-            # set the prerequisites
-            env.set_prerequisites(self.logger)
-            # set the products
-            env.set_products(self.logger,
-                            src_root=self.src_root, single_dir=self.single_dir)
-
-        if len(additional_env) != 0:
-            for variable in additional_env:
-                env.set(variable, additional_env[variable])
-
-        # add cleanup and close
-        env.finish(True)
-
-
-# create bash product file
-_bash_content = """PRODUCT_DIR=%s
-if [[ "${ENV_FOR_LAUNCH}x" == "x" ]]
-then
-    export ENV_FOR_LAUNCH=1
-fi
-
-if [[ "${ENV_FOR_LAUNCH}" == "1" ]]
-then
-    source $PRODUCT_DIR/env_launch.sh
-else
-    source $PRODUCT_DIR/env_build.sh
-fi
-"""
-
-# create batch product file
-_batch_content = """set PRODUCT_DIR=%s
-IF NOT DEFINED ENV_FOR_LAUNCH set ENV_FOR_LAUNCH=1
-
-if "%%ENV_FOR_LAUNCH%%"=="1" (
-    %%PRODUCT_DIR%%\\env_launch.bat
-) else (
-    %%PRODUCT_DIR%%\\env_build.bat
-)
-"""
-
-##
-# Definition of a Shell.
-class Shell:
-    def __init__(self, name, extension):
-        self.name = name
-        self.extension = extension
-
-##
-# Loads the environment (used to run the tests).
-def load_environment(config, build, logger):
-    environ = SalomeEnviron(config, src.environment.Environ(os.environ), build)
-    environ.set_application_env(logger)
-    environ.set_prerequisites(logger)
-    environ.set_products(logger)
-    environ.finish(True)
 
 ##
 # Writes all the environment files
@@ -522,9 +61,9 @@ def write_all_source_files(config, logger, out_dir=None, src_root=None,
         if shell not in C_SHELLS:
             logger.write(_("Unknown shell: %s\n") % shell, 2)
         else:
-            shells_list.append(Shell(shell, C_SHELLS[shell]))
+            shells_list.append(src.environment.Shell(shell, C_SHELLS[shell]))
     
-    writer = FileEnvWriter(config, logger, out_dir, src_root, single_dir, env_info)
+    writer = src.environment.FileEnvWriter(config, logger, out_dir, src_root, single_dir, env_info)
     writer.silent = silent
     files = []
     for_build = True
index bbda9f17977dd0fb0643bf35dcf60f808fd289f2..cb3ff804e3ce536e6573e29111e06fc629f98bda 100644 (file)
@@ -33,17 +33,21 @@ PRODUCT_ARCHIVE_4_4_2 :
     }
     environ :
     {
-        "_LD_LIBRARY_PATH" : "${SOFT_ROOT_DIR}" + $VARS.sep + "lib"
-        "_PYTHONPATH" : ["${SOFT_ROOT_DIR}" + $VARS.sep + "lib"
-            "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR0}"
-            "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR1}"]
+               build: 
+               {   
+                   "_LD_LIBRARY_PATH" : "COUCOU"
+                   "_PYTHONPATH" : ["${SOFT_ROOT_DIR}" + $VARS.sep + "lib"
+                       "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR0}"
+                       "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR1}"]
+               }
     }
+    env_script : "/home/sr755891/SAT-ETENDU/00-DEV/RESOURCES/env_scripts/pytz.py"
        present_files :
        {
           source : ['my_test_file.txt', 'my_test_file.txt~']
           install : ['', '', '']
        }
-    depend : []
+    depend : ['PRODUCT_NATIVE', 'PRODUCT_CVS']
     opt_depend : []
     type : "sample"
     source_dir : $APPLICATION.workdir + $VARS.sep + 'SOURCES' + $VARS.sep + $name
index 34dbdc2609569669c414bbab9d6371c51a60819d..761379115c128d0847fddc3a4c58eaee898d51d4 100644 (file)
@@ -15,7 +15,7 @@ PRODUCT_GIT :
             "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR0}"
             "${SOFT_ROOT_DIR}" + $VARS.sep + "${PYTHON_LIBDIR1}"]
     }
-    depend : []
+    depend : [PRODUCT_ARCHIVE, PRODUCT_NATIVE]
     opt_depend : []
     type : "sample"
     source_dir : $APPLICATION.workdir + $VARS.sep + 'SOURCES' + $VARS.sep + $name
index 04a0928a6ef47721820afb78db3f4ffb5ae0c753..0b61594e5495604eaeb2cee02aa075dfa2faeccf 100644 (file)
@@ -31,6 +31,7 @@ from . import logger
 from . import product
 from . import environment
 from . import fileEnviron
+from . import compilation
 
 OK_STATUS = "OK"
 KO_STATUS = "KO"
diff --git a/src/compilation.py b/src/compilation.py
new file mode 100644 (file)
index 0000000..f774861
--- /dev/null
@@ -0,0 +1,657 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+#  Copyright (C) 2010-2013  CEA/DEN
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+
+import os
+import subprocess
+import sys
+
+import src
+
+C_COMPILE_ENV_LIST = ["CC",
+                      "CXX",
+                      "F77",
+                      "CFLAGS",
+                      "CXXFLAGS",
+                      "LIBS",
+                      "LDFLAGS"]
+
+class CompilationResult:
+    def __init__(self):
+        self.prepare = False
+        self.buildconfigure = False
+        self.configure = False
+        self.cmake = False
+        self.make = False
+        self.install = False
+        self.check = False
+        self.check_tried = False
+        self.ignored = False
+        self.reason = ""
+
+    def isOK(self):
+        if self.ignored:
+            return False
+
+        return self.prepare \
+            and self.buildconfigure \
+            and self.configure \
+            and self.cmake \
+            and self.make \
+            and self.install \
+            and self.check
+
+    def setAllFail(self):
+        self.prepare = False
+        self.buildconfigure = False
+        self.configure = False
+        self.cmake = False
+        self.make = False
+        self.install = False
+        self.check = False
+
+    def setIgnored(self, reason=None):
+        self.ignored = True
+        if reason:
+            self.reason = reason
+        else:
+            self.reason = _("ignored")
+
+    def getErrorText(self):
+        if self.ignored or len(self.reason):
+            return self.reason
+
+        if not self.prepare: return "PREPARE BUILD"
+        if not self.buildconfigure: return "BUILD CONFIGURE"
+        if not self.configure: return "CONFIGURE"
+        if not self.cmake: return "CMAKE"
+        if not self.make: return "MAKE"
+        if not self.install: return "INSTALL"
+        if not self.check: return "CHECK"
+        
+        return ""
+
+class Builder:
+    """Class to handle all construction steps, like cmake, configure, make, ...
+    """
+    def __init__(self, config, logger, options, product_info, debug_mode=False, check_src=True):
+        self.config = config
+        self.logger = logger
+        self.options = options
+        self.product_info = product_info
+        self.build_dir = src.Path(self.product_info.build_dir)
+        self.source_dir = src.Path(self.product_info.source_dir)
+        self.source_dir = src.Path(self.product_info.install_dir)
+        self.header = ""
+        self.debug_mode = debug_mode
+
+        if not self.source_dir.exists() and check_src:
+            raise src.SatException(_("No sources found for product %(product)s in %(source_dir)s" % \
+                { "product": self.product, "source_dir": self.source_dir } ))
+
+        # check that required modules exist
+        for dep in self.product_info.depend:
+            assert dep in self.config.TOOLS.src.product_info, "UNDEFINED product: %s" % dep
+            dep_info = self.config.TOOLS.src.product_info[dep]
+            if 'install_dir' in dep_info and not os.path.exists(dep_info.install_dir):
+                raise src.SatException(_("Module %s is required") % dep)
+
+        self.results = CompilationResult()
+
+    ##
+    # Shortcut method to log in both log files.
+    def log(self, text, level, showInfo=True):
+        self.logger.write(text, level, showInfo)
+        self.logger.logTxtFile.write(src.printcolors.cleancolor(text))
+
+    ##
+    # Shortcut method to log a command.
+    def log_command(self, command):
+        self.log("> %s\n" % command, 5)
+
+    def log_result(self, res):
+        if res == 0:
+            self.logger.write("%s\n" % src.printcolors.printc(src.OK_STATUS), 5)
+        else:
+            self.logger.write("%s, code = %s\n" % (src.printcolors.printc(src.KO_STATUS), res), 5)
+
+    ##
+    # Logs a compilation step (configure, make ...)
+    def log_step(self, step):
+        if self.config.USER.output_level == 3:
+            self.logger.write("\r%s%s" % (self.header, " " * 20), 3)
+            self.logger.write("\r%s%s" % (self.header, step), 3)
+        self.log("==== %s \n" % src.printcolors.printcInfo(step), 4)
+        self.logger.flush()
+
+    ##
+    # Prepares the environment for windows.
+    # Build two environment: one for building and one for testing (launch).
+    def wprepare(self):
+        self.log_step('PREPARE BUILD')
+
+        if not self.build_dir.exists():
+            # create build dir
+            self.build_dir.make()
+        elif self.options.clean_all:
+            self.log('  %s\n' % src.printcolors.printcWarning("CLEAN ALL"), 4)
+            # clean build dir if clean_all option given
+            self.log('  clean previous build = %s\n' % str(self.build_dir), 4)
+            self.build_dir.rm()
+            self.build_dir.make()
+
+        if self.options.clean_all or self.options.clean_install:
+            if os.path.exists(str(self.install_dir)) and not self.single_dir:
+                self.log('  clean previous install = %s\n' % str(self.install_dir), 4)
+                self.install_dir.rm()
+
+        self.log('  build_dir   = %s\n' % str(self.build_dir), 4)
+        self.log('  install_dir = %s\n' % str(self.install_dir), 4)
+        self.log('\n', 4)
+        
+        environ_info = {}
+        
+        # add products in depend and opt_depend list recursively
+        environ_info['products'] = src.product.get_product_dependencies(self.config, self.product_info)
+
+        # create build environment
+        self.build_environ = src.environment.SalomeEnviron(self.config, src.environment.Environ(dict(os.environ)), True)
+        self.build_environ.silent = (self.config.USER.output_level < 5)
+        self.build_environ.set_full_environ(self.logger, environ_info)
+
+        # create runtime environment
+        self.launch_environ = src.environment.SalomeEnviron(self.config, src.environment.Environ(dict(os.environ)), False)
+        self.launch_environ.silent = True # no need to show here
+        self.launch_environ.set_full_environ(self.logger, environ_info)
+
+        for ee in C_COMPILE_ENV_LIST:
+            vv = self.build_environ.get(ee)
+            if len(vv) > 0:
+                self.log("  %s = %s\n" % (ee, vv), 4, False)
+
+        self.results.prepare = True
+        self.log_result(0)
+        return self.results.prepare
+
+    ##
+    # Prepares the environment.
+    # Build two environment: one for building and one for testing (launch).
+    def prepare(self):
+        self.log_step('PREPARE BUILD')
+
+        if not self.build_dir.exists():
+            # create build dir
+            self.build_dir.make()
+        elif self.options.clean_all:
+            self.log('  %s\n' % src.printcolors.printcWarning("CLEAN ALL"), 4)
+            # clean build dir if clean_all option given
+            self.log('  clean previous build = %s\n' % str(self.build_dir), 4)
+            self.build_dir.rm()
+            self.build_dir.make()
+
+        if self.options.clean_all or self.options.clean_install:
+            if os.path.exists(str(self.install_dir)) and not self.single_dir:
+                self.log('  clean previous install = %s\n' % str(self.install_dir), 4)
+                self.install_dir.rm()
+
+        self.log('  build_dir   = %s\n' % str(self.build_dir), 4)
+        self.log('  install_dir = %s\n' % str(self.install_dir), 4)
+        self.log('\n', 4)
+
+        # set the environment
+        environ_info = {}
+
+        # add products in depend and opt_depend list recursively
+        environ_info['products'] = src.product.get_product_dependencies(self.config, self.product_info)
+
+        # create build environment
+        self.build_environ = src.environment.SalomeEnviron(self.config, src.environment.Environ(dict(os.environ)), True)
+        self.build_environ.silent = (self.config.USER.output_level < 5)
+        self.build_environ.set_full_environ(self.logger, environ_info)
+
+        # create runtime environment
+        self.launch_environ = src.environment.SalomeEnviron(self.config, src.environment.Environ(dict(os.environ)), False)
+        self.launch_environ.silent = True # no need to show here
+        self.launch_environ.set_full_environ(self.logger, environ_info)
+
+        for ee in C_COMPILE_ENV_LIST:
+            vv = self.build_environ.get(ee)
+            if len(vv) > 0:
+                self.log("  %s = %s\n" % (ee, vv), 4, False)
+
+        self.results.prepare = True
+        self.log_result(0)
+        return self.results.prepare
+
+    ##
+    # Runs cmake with the given options.
+    def cmake(self, options=""):
+        self.log_step('CMAKE')
+
+        # cmake so no (build)configure
+        self.results.configure = True
+
+        cmake_option = options
+        cmake_option +=' -DCMAKE_VERBOSE_MAKEFILE=ON -DSALOME_CMAKE_DEBUG=ON'
+        if 'cmake_options' in self.product_info:
+            cmake_option += " %s " % " ".join(self.product_info.cmake_options.split())
+
+        # add debug option
+        if self.debug_mode:
+            cmake_option += " -DCMAKE_BUILD_TYPE=Debug"
+        else :
+            cmake_option += " -DCMAKE_BUILD_TYPE=Release"
+
+        # In case CMAKE_GENERATOR is defined in environment, use it in spite of automatically detect it
+        if 'cmake_generator' in self.config.APPLICATION:
+            cmake_option += ' -DCMAKE_GENERATOR=%s' % self.config.PRODUCT.cmake_generator
+        
+        command = "cmake %s -DCMAKE_INSTALL_PREFIX=%s %s" %(cmake_option, self.install_dir, self.source_dir)
+
+        self.log_command(command)
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.results.cmake = (res == 0)
+        self.log_result(res)
+        return self.results.cmake
+
+    ##
+    # Runs build_configure with the given options.
+    def build_configure(self, options=""):
+        skip = src.get_cfg_param(self.product_info, "build_configure", False)
+        if skip:
+            self.results.buildconfigure = True
+            res = 0
+        else:
+            self.log_step('BUILD CONFIGURE')
+
+            self.results.buildconfigure = False
+
+            if 'buildconfigure_options' in self.product_info:
+                options += " %s " % self.product_info.buildconfigure_options
+
+            command = str('./build_configure')
+            command = command + " " + options
+            self.log_command(command)
+
+            res = subprocess.call(command,
+                                  shell=True,
+                                  cwd=str(self.source_dir),
+                                  env=self.build_environ.environ.environ,
+                                  stdout=self.logger.logTxtFile,
+                                  stderr=subprocess.STDOUT)
+            self.results.buildconfigure = (res == 0)
+
+        self.log_result(res)
+        return self.results.buildconfigure
+
+    ##
+    # Runs configure with the given options.
+    def configure(self, options=""):
+        self.log_step('CONFIGURE')
+
+        # configure so no cmake
+        self.results.cmake = True
+
+        if 'configure_options' in self.product_info:
+            options += " %s " % self.product_info.configure_options
+
+        command = "%s/configure --prefix=%s" % (self.source_dir, str(self.install_dir))
+
+        command = command + " " + options
+        self.log_command(command)
+
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.log_result(res)
+        self.results.configure = (res == 0)
+        return self.results.configure
+
+    def hack_libtool(self):
+        if not os.path.exists(str(self.build_dir + 'libtool')):
+            return
+
+        lf = open(os.path.join(str(self.build_dir), "libtool"), 'r')
+        for line in lf.readlines():
+            if 'hack_libtool' in line:
+                return
+
+        # fix libtool by replacing CC="<compil>" with hack_libtool function
+        hack_command='''sed -i "s%^CC=\\"\(.*\)\\"%hack_libtool() { \\n\\
+if test \\"\$(echo \$@ | grep -E '\\\\\\-L/usr/lib(/../lib)?(64)? ')\\" == \\\"\\\" \\n\\
+  then\\n\\
+    cmd=\\"\\1 \$@\\"\\n\\
+  else\\n\\
+    cmd=\\"\\1 \\"\`echo \$@ | sed -r -e 's|(.*)-L/usr/lib(/../lib)?(64)? (.*)|\\\\\\1\\\\\\4 -L/usr/lib\\\\\\3|g'\`\\n\\
+  fi\\n\\
+  \$cmd\\n\\
+}\\n\\
+CC=\\"hack_libtool\\"%g" libtool'''
+
+        self.log_command(hack_command)
+        subprocess.call(hack_command,
+                        shell=True,
+                        cwd=str(self.build_dir),
+                        env=self.build_environ.environ.environ,
+                        stdout=self.logger.logTxtFile,
+                        stderr=subprocess.STDOUT)
+
+    def get_nb_proc(self):
+        nbproc = -1
+        if "nb_proc" in self.product_info:
+            # nb proc is specified in module definition
+            nbproc = self.product_info.nb_proc
+            if self.options.nb_proc and self.options.nb_proc < self.product_info.nb_proc:
+                # use command line value only if it is lower than module definition
+                nbproc = self.options.nb_proc
+        else:
+            # nb proc is not specified in module definition
+            if self.options.nb_proc:
+                nbproc = self.options.nb_proc
+            else:
+                nbproc = self.config.VARS.nb_proc
+        
+        assert nbproc > 0
+        return nbproc
+
+    ##
+    # Runs make to build the module.
+    def make(self):
+        nbproc = self.get_nb_proc()
+
+        hh = 'MAKE -j%s' % str(nbproc)
+        if self.debug_mode:
+            hh += " " + src.printcolors.printcWarning("DEBUG")
+        self.log_step(hh)
+
+        # make
+        command = 'make'
+        if self.options.makeflags:
+            command = command + " " + self.options.makeflags
+        command = command + " -j" + str(nbproc)
+
+        self.log_command(command)
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.results.make = (res == 0)
+        self.log_result(res)
+        return self.results.make
+    
+    ##
+    # Runs msbuild to build the module.
+    def wmake(self):
+        nbproc = self.get_nb_proc()
+
+        hh = 'MSBUILD /m:%s' % str(nbproc)
+        if self.debug_mode:
+            hh += " " + src.printcolors.printcWarning("DEBUG")
+        self.log_step(hh)
+
+        # make
+        command = 'msbuild'
+        if self.options.makeflags:
+            command = command + " " + self.options.makeflags
+        command = command + " /maxcpucount:" + str(nbproc)
+        if self.debug_mode:
+            command = command + " /p:Configuration=Debug"
+        else:
+            command = command + " /p:Configuration=Release"
+        command = command + " ALL_BUILD.vcxproj"
+
+        self.log_command(command)
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.results.make = (res == 0)
+        self.log_result(res)
+        return self.results.make
+
+    ##
+    # Runs 'make install'.
+    def install(self):
+        self.log_step('INSTALL')
+        if self.config.VARS.dist_name=="Win":
+            command = 'msbuild INSTALL.vcxproj'
+            if self.debug_mode:
+                command = command + " /p:Configuration=Debug"
+            else:
+                command = command + " /p:Configuration=Release"
+        else :
+            command = 'make install'
+
+        self.log_command(command)
+
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.results.install = (res == 0)
+        self.log_result(res)
+        return self.results.install
+
+    ##
+    # Runs 'make_check'.
+    def check(self):
+        self.log_step('CHECK')
+        if src.architecture.is_windows():
+            command = 'msbuild RUN_TESTS.vcxproj'
+        else :
+            if self.use_autotools :
+                command = 'make check'
+            else :
+                command = 'make test'
+            
+        self.log_command(command)
+
+        self.results.check_tried = True
+        res = subprocess.call(command,
+                              shell=True,
+                              cwd=str(self.build_dir),
+                              env=self.launch_environ.environ.environ,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT)
+
+        self.results.check = (res == 0)
+        self.log_result(res)
+        return self.results.check
+
+    ##
+    # Cleans the build.
+    def clean(self):
+        self.log_step('CLEAN')
+
+        if src.get_cfg_param(self.config.PRODUCT, 'clean_build_dir', 'no') == "yes":
+            if self.results.buildconfigure and self.results.configure \
+                and self.results.make and self.results.install and self.results.check:
+                self.log(_('Clean BUILD directory\n'), 4)
+                self.build_dir.rm()
+            else:
+                self.log(_('No clean: some error during compilation\n'), 5)
+        else:
+            self.log(_('No clean: not specified in the config\n'), 5)
+
+    def get_result(self):
+        return self.results
+      
+    ##
+    # Performs a default build for this module.
+    def do_default_build(self, build_conf_options="", configure_options="", show_warning=True):
+        use_autotools = False
+        if 'use_autotools' in self.product_info:
+            uc = self.product_info.use_autotools
+            if uc in ['always', 'yes']: 
+                use_autotools = True
+            elif uc == 'option': 
+                use_autotools = self.options.autotools
+
+
+        self.use_autotools = use_autotools
+
+        use_ctest = False
+        if 'use_ctest' in self.product_info:
+            uc = self.product_info.use_ctest
+            if uc in ['always', 'yes']: 
+                use_ctest = True
+            elif uc == 'option': 
+                use_ctest = self.options.ctest
+
+        self.use_ctest = use_ctest
+
+        if show_warning:
+            cmd = ""
+            if use_autotools: cmd = "(autotools)"
+            if use_ctest: cmd = "(ctest)"
+            
+            self.log("\n", 4, False)
+            self.log("%(module)s: Run default compilation method %(cmd)s\n" % \
+                { "module": self.module, "cmd": cmd }, 4)
+
+        if use_autotools:
+            if not self.prepare(): return self.get_result()
+            if not self.build_configure(build_conf_options): return self.get_result()
+            if not self.configure(configure_options): return self.get_result()
+            if not self.make(): return self.get_result()
+            if not self.install(): return self.get_result()
+            self.results.check = True
+            if not self.clean(): return self.get_result()
+           
+        else: # CMake
+            if self.config.VARS.dist_name=='Win':
+                if not self.wprepare(): return self.get_result()
+                self.results.buildconfigure = True
+                if not self.cmake(): return self.get_result()
+                self.results.ctest = True
+                if not self.wmake(): return self.get_result()
+                if not self.install(): return self.get_result()
+                self.results.check = True
+                if not self.clean(): return self.get_result()
+            else :
+                if not self.prepare(): return self.get_result()
+                self.results.buildconfigure = True
+                if not self.cmake(): return self.get_result()
+                self.results.ctest = True
+                if not self.make(): return self.get_result()
+                if not self.install(): return self.get_result()
+                self.results.check = True
+                if not self.clean(): return self.get_result()
+
+        return self.get_result()
+
+    ##
+    # Performs a build with a script.
+    def do_script_build(self, script):
+        retcode = CompilationResult()
+        retcode.setAllFail()
+        # script found
+        self.logger.write(_("Compile %(module)s using script %(script)s\n") % \
+            { 'module': self.module, 'script': src.printcolors.printcLabel(script) }, 4)
+        try:
+            import imp
+            pymodule = imp.load_source(self.module + "_compile_script", script)
+            retcode = pymodule.compil(self.config, self, self.logger)
+        except:
+            __, exceptionValue, exceptionTraceback = sys.exc_info()
+            print(exceptionValue)
+            import traceback
+            traceback.print_tb(exceptionTraceback)
+            traceback.print_exc()
+
+        return retcode
+
+    ##
+    # Builds the module.
+    # If a script is specified used it, else use 'default' method.
+    def run_compile(self, no_compile=False):
+        retcode = CompilationResult()
+        retcode.setAllFail()
+
+        if no_compile:
+            if os.path.exists(str(self.install_dir)):
+                retcode.setIgnored(_("already installed"))
+            else:
+                retcode.setIgnored(src.printcolors.printcError(_("NOT INSTALLED")))
+
+            self.log_file.close()
+            os.remove(os.path.realpath(self.log_file.name))
+            return retcode
+
+        # check if the module is already installed
+        if not self.single_dir and os.path.exists(str(self.install_dir)) \
+            and not self.options.clean_all and not self.options.clean_install:
+
+            retcode.setIgnored(_("already installed"))
+            self.log_file.close()
+            os.remove(os.path.realpath(self.log_file.name))
+            return retcode
+
+        if 'compile_method' in self.product_info:
+            if self.product_info.compile_method == "copy":
+                self.prepare()
+                retcode.prepare = self.results.prepare
+                retcode.buildconfigure = True
+                retcode.configure = True
+                retcode.make = True
+                retcode.cmake = True
+                retcode.ctest = True
+                
+                if not self.source_dir.smartcopy(self.install_dir):
+                    raise src.SatException(_("Error when copying %s sources to install dir") % self.module)
+                retcode.install = True
+                retcode.check = True
+
+            elif self.product_info.compile_method == "default":
+                retcode = self.do_default_build(show_warning=False)
+                
+
+            elif os.path.isfile(self.product_info.compile_method):
+                retcode = self.do_script_build(self.product_info.compile_method)
+
+            else:
+                raise src.SatException(_("Unknown compile_method: %s") % self.product_info.compile_method)
+
+        else:
+            script = os.path.join(self.config.VARS.dataDir, 'compil_scripts', 'modules', self.module + '.py')
+
+            if not os.path.exists(script):
+                # no script use default method
+                retcode = self.do_default_build(show_warning=False)
+            else:
+                retcode = self.do_script_build(script)
+
+        return retcode
index 95f7b3c6cad3c0c32117193053736481103feece..935f957c903b1e8876baaebb94686657dbcfee66 100644 (file)
 import os
 import subprocess
 import string
+import sys
 
 import src
 
+# create bash product file
+_bash_content = """PRODUCT_DIR=%s
+if [[ "${ENV_FOR_LAUNCH}x" == "x" ]]
+then
+    export ENV_FOR_LAUNCH=1
+fi
+
+if [[ "${ENV_FOR_LAUNCH}" == "1" ]]
+then
+    source $PRODUCT_DIR/env_launch.sh
+else
+    source $PRODUCT_DIR/env_build.sh
+fi
+"""
+
+# create batch product file
+_batch_content = """set PRODUCT_DIR=%s
+IF NOT DEFINED ENV_FOR_LAUNCH set ENV_FOR_LAUNCH=1
+
+if "%%ENV_FOR_LAUNCH%%"=="1" (
+    %%PRODUCT_DIR%%\\env_launch.bat
+) else (
+    %%PRODUCT_DIR%%\\env_build.bat
+)
+"""
+
 class Environ:
     '''Class to manage the environment context
     '''
@@ -160,3 +187,434 @@ class Environ:
                                  stdout=subprocess.PIPE,
                                  env=self.environ).communicate()[0]
         self.environ[key] = value
+
+
+class SalomeEnviron:
+    """Class to manage the environment of SALOME.
+    """
+
+    def __init__(self, cfg, environ, forBuild=False):
+        self.environ = environ
+        self.cfg = cfg
+        self.forBuild = forBuild
+        self.silent = False
+
+    def __repr__(self):
+        """easy non exhaustive quick resume for debug print"""
+        res={}
+        res["environ"]=str(self.environ)
+        res["forBuild"]=self.forBuild
+        return self.__class__.__name__ + str(res)[0:-1] + " ...etc...}"
+
+    def append(self, key, value, sep=os.pathsep):
+        return self.environ.append(key, value, sep)
+
+    def prepend(self, key, value, sep=os.pathsep):
+        return self.environ.prepend(key, value, sep)
+
+    def is_defined(self, key):
+        return self.environ.is_defined(key)
+
+    def get(self, key):
+        return self.environ.get(key)
+
+    def set(self, key, value):
+        # check if value needs to be evaluated
+        if value is not None and value.startswith("`") and value.endswith("`"):
+            res = subprocess.Popen("echo %s" % value, shell=True, stdout=subprocess.PIPE).communicate()
+            value = res[0].strip()
+
+        return self.environ.set(key, value)
+
+    def dump(self, out):
+        """Write the environment to out"""
+        for k in self.environ.environ.keys():
+            try:
+                value = self.get(k)
+            except:
+                value = "?"
+            out.write("%s=%s\n" % (k, value))
+
+    def add_line(self, nb_line):
+        if 'add_line' in dir(self.environ):
+            self.environ.add_line(nb_line)
+
+    def add_comment(self, comment):
+        if 'add_comment' in dir(self.environ):
+            self.environ.add_comment(comment)
+
+    def add_warning(self, warning):
+        if 'add_warning' in dir(self.environ):
+            self.environ.add_warning(warning)
+
+    def finish(self, required):
+        if 'finish' in dir(self.environ):
+            self.environ.add_line(1)
+            self.environ.add_comment("clean all the path")
+            self.environ.finish(required)
+
+    def list_version_4_prereq(self, prerequisite, logger):
+        alist = []
+        for path in self.cfg.TOOLS.environ.prereq_install_dir:
+            if not os.path.exists(path):
+                continue
+            prereqlist = os.listdir(path)
+            for prereq in prereqlist:
+                if prereq.split("-")[0] == prerequisite:
+                    #logger.error(str(prereq) + "\n")
+                    alist.append(str(prereq))
+
+        if len(alist) > 0:
+            logger.write(_("Available prerequisites are:") + "\n\t%s\n" % '\n\t'.join(alist), 2)
+
+    def set_python_libdirs(self):
+        if src.architecture.is_windows():
+            # sysconfig.get_python_lib() does not return appropriate path on Windows
+            # clearly decide here once for windows
+            ver = self.get('PYTHON_VERSION')
+            self.set('PYTHON_LIBDIR0', os.path.join('lib', 'python' + ver, 'site-packages'))
+            self.set('PYTHON_LIBDIR1', os.path.join('lib64', 'python' + ver, 'site-packages'))
+
+        else:
+            ver = self.get('PYTHON_VERSION')
+            self.set('PYTHON_LIBDIR0', os.path.join('lib', 'python' + ver, 'site-packages'))
+            self.set('PYTHON_LIBDIR1', os.path.join('lib64', 'python' + ver, 'site-packages'))
+          
+        self.python_lib0 = self.get('PYTHON_LIBDIR0')
+        self.python_lib1 = self.get('PYTHON_LIBDIR1')
+
+    ##
+    # Get the products name to add in SALOME_MODULES environment variable
+    # It is the name of the product, except in the case where the is a component name.
+    # And it has to be in SALOME_MODULES variable only if has_gui = "yes"
+    def getNames(self, lProducts):
+        lProdHasGui = [p for p in lProducts if 'has_gui' in src.product.get_product_config(self.cfg, p) and src.product.get_product_config(self.cfg, p).has_gui=='yes']
+        lProdName = []
+        for ProdName in lProdHasGui:
+            pi = src.product.get_product_config(self.cfg, ProdName)
+            if 'component_name' in pi:
+                lProdName.append(pi.component_name)
+            else:
+                lProdName.append(ProdName)
+        return lProdName
+
+    ##
+    # Sets the environment defined in the PRODUCT file.
+    def set_application_env(self, logger):
+        if 'environ' in self.cfg.APPLICATION:
+            self.add_comment("APPLICATION environment")
+            for p in self.cfg.APPLICATION.environ:
+                self.set(p, self.cfg.APPLICATION.environ[p])
+            self.add_line(1)
+
+        if 'environ_script' in self.cfg.APPLICATION:
+            for pscript in self.cfg.APPLICATION.environ_script:
+                self.add_comment("script %s" % pscript)
+                sname = pscript.replace(" ", "_")
+                self.run_env_script("APPLICATION_%s" % sname, self.cfg.APPLICATION.environ_script[pscript], logger)
+                self.add_line(1)
+        
+        if 'profile' in self.cfg.APPLICATION:
+            profile_product = self.cfg.APPLICATION.profile.product
+            product_info_profile = src.product.get_product_config(self.cfg, profile_product)
+            profile_share_salome = os.path.join( product_info_profile.install_dir, "share", "salome" )
+            self.set( "SUITRoot", profile_share_salome )
+            self.set( "SalomeAppConfig", os.path.join( profile_share_salome, "resources", profile_product.lower() ) )
+        
+        # The list of products to launch
+        lProductsName = self.getNames(self.cfg.APPLICATION.products.keys())
+        
+        self.set( "SALOME_MODULES",    ','.join(lProductsName))
+
+    ##
+    # Set xxx_ROOT_DIR and xxx_SRC_DIR.
+    def set_salome_minimal_product_env(self, product_info, logger, single_dir, cfgdic=None):
+        # set root dir
+        root_dir = product_info.name + "_ROOT_DIR"
+        indic = cfgdic is not None and root_dir in cfgdic
+        if not self.is_defined(root_dir) and not indic:
+            if single_dir:
+                self.set(root_dir, os.path.join(self.get('INSTALL_ROOT'), 'SALOME'))
+            elif 'install_dir' in product_info and product_info.install_dir:
+                self.set(root_dir, product_info.install_dir)
+            elif not self.silent:
+                logger.write("  " + _("No install_dir for product %s\n") % product_info.name, 5)
+
+        # set source dir, unless the product is fixed (no source dir)
+        if not src.product.product_is_fixed(product_info):
+            src_dir = product_info.name + "_SRC_DIR"
+            indic = cfgdic is not None and src_dir in cfgdic
+            if not self.is_defined(src_dir) and not indic:
+                self.set(src_dir, product_info.source_dir)
+
+    def set_salome_generic_product_env(self, product):
+        pi = src.product.get_product_config(self.cfg, product)
+        env_root_dir = self.get(pi.name + "_ROOT_DIR")
+        l_binpath_libpath = []
+
+        # create additional ROOT_DIR for CPP components
+        if 'component_name' in pi:
+            compo_name = pi.component_name
+            if compo_name + "CPP" == product:
+                compo_root_dir = compo_name + "_ROOT_DIR"
+                envcompo_root_dir = os.path.join( self.cfg.TOOLS.common.install_root, compo_name )
+                self.set(compo_root_dir ,  envcompo_root_dir)
+                bin_path = os.path.join(envcompo_root_dir, 'bin', 'salome')
+                lib_path = os.path.join(envcompo_root_dir, 'lib', 'salome')
+                l_binpath_libpath.append( (bin_path, lib_path) )
+
+        appliname = 'salome'
+        if src.get_cfg_param(pi, 'product_type', 'SALOME').upper() not in [ "SALOME", "SMESH_PLUGIN", "SAMPLE" ]:
+            appliname = ''
+
+        bin_path = os.path.join(env_root_dir, 'bin', appliname)
+        lib_path = os.path.join(env_root_dir, 'lib', appliname)
+        l_binpath_libpath.append( (bin_path, lib_path) )
+
+        for bin_path, lib_path in l_binpath_libpath:
+            if not self.forBuild:
+                self.prepend('PATH', bin_path)
+                if src.architecture.is_windows():
+                    self.prepend('PATH', lib_path)
+                else :
+                    self.prepend('LD_LIBRARY_PATH', lib_path)
+
+            l = [ bin_path, lib_path,
+                  os.path.join(env_root_dir, self.python_lib0, appliname),
+                  os.path.join(env_root_dir, self.python_lib1, appliname)
+                ]
+            self.prepend('PYTHONPATH', l)
+
+    ##
+    # Loads environment define in the configuration.
+    def load_cfg_environment(self, cfg_env):
+        for env_def in cfg_env:
+            val = cfg_env[env_def]
+            if isinstance(val, src.pyconf.Mapping):
+                continue
+
+            if isinstance(val, src.pyconf.Sequence):
+                # transform into list of strings
+                l_val = []
+                for item in val:
+                    l_val.append(item)
+                val = l_val
+
+            if env_def.startswith("_"):
+                # separator exception for PV_PLUGIN_PATH
+                if env_def[1:] == 'PV_PLUGIN_PATH':
+                    self.prepend(env_def[1:], val, ';')
+                else:
+                    self.prepend(env_def[1:], val)
+            elif env_def.endswith("_"):
+                # separator exception for PV_PLUGIN_PATH
+                if env_def[:-1] == 'PV_PLUGIN_PATH':
+                    self.prepend(env_def[:-1], val, ';')
+                else:
+                    self.prepend(env_def[:-1], val)
+            else:
+                self.set(env_def, val)
+
+    ##
+    # Sets the environment of a product.
+    def set_a_product(self, product, logger, single_dir):
+               
+        if not self.silent:
+            logger.write(_("Setting environment for %s\n") % product, 4)
+
+        self.add_line(1)
+        self.add_comment('setting environ for ' + product)
+        
+        pi = src.product.get_product_config(self.cfg, product)
+
+        # Do not define environment if the product is native or fixed
+        if src.product.product_is_native(pi):
+            return
+
+        if "environ" in pi:
+            # set environment using definition of the product
+            self.set_salome_minimal_product_env(pi, logger, single_dir, pi.environ)
+            self.set_salome_generic_product_env(product)
+            self.load_cfg_environment(pi.environ)
+            if self.forBuild and "build" in pi.environ:
+                self.load_cfg_environment(pi.environ.build)
+            if not self.forBuild and "launch" in pi.environ:
+                self.load_cfg_environment(pi.environ.launch)
+        else:
+            # no environment defined in config
+            self.set_salome_minimal_product_env(pi, logger, single_dir)
+            if 'install_dir' in pi :
+                self.set_salome_generic_product_env(product)
+
+        # if product_info defines a env_scripts load it
+        if 'env_script' in pi:
+            self.run_env_script(pi, logger)
+            
+
+    ##
+    # Runs an environment script.
+    def run_env_script(self, product_info, logger=None):
+        env_script = product_info.env_script
+        if not os.path.exists(product_info.env_script):
+            raise src.SatException(_("Environment script not found: %s") % env_script)
+
+        if not self.silent and logger is not None:
+            logger.write("  ** load %s\n" % product_info.env_script, 4)
+
+        try:
+            import imp
+            pyproduct = imp.load_source(product_info.name + "_env_script", env_script)
+            pyproduct.set_env(self, product_info.install_dir, product_info.version)
+        except:
+            __, exceptionValue, exceptionTraceback = sys.exc_info()
+            print(exceptionValue)
+            import traceback
+            traceback.print_tb(exceptionTraceback)
+            traceback.print_exc()
+
+    ##
+    # Sets the environment for all the products.
+    def set_products(self, logger, src_root=None, single_dir=False):
+        self.add_line(1)
+        self.add_comment('setting environ for all products')
+
+        self.set_python_libdirs()
+
+        if src_root is None:
+            src_root = self.cfg.APPLICATION.workdir
+        self.set('SRC_ROOT', src_root)
+
+        appli_name = "APPLI"
+        if "APPLI" in self.cfg and "application_name" in self.cfg.APPLI:
+            appli_name = self.cfg.APPLI.application_name
+        self.set("SALOME_APPLI_ROOT", os.path.join(self.cfg.APPLICATION.workdir, appli_name))
+
+        if not single_dir:
+            single_dir = src.get_cfg_param(self.cfg.APPLICATION, "compil_in_single_dir", "no") == 'yes'
+
+        for product in src.get_cfg_param(self.cfg.APPLICATION, "imported_products", []):
+            self.set_a_product(product, logger, single_dir=single_dir)
+            self.finish(False)
+
+        for product in self.cfg.APPLICATION.products.keys():
+            self.set_a_product(product, logger, single_dir=single_dir)
+            self.finish(False)
+
+   
+    ##
+    # Sets the full environment for prerequisites and products specified in env_info dictionary.
+    def set_full_environ(self, logger, env_info):
+        # set product environ
+        self.set_application_env(logger)
+
+        # set products
+        install_root = os.path.join(self.cfg.APPLICATION.workdir, "INSTALL")
+        source_root = os.path.join(self.cfg.APPLICATION.workdir, "SOURCES")
+        self.set('INSTALL_ROOT', install_root)
+        self.set('SRC_ROOT', source_root)
+        self.set_python_libdirs()
+
+        single_dir = src.get_cfg_param(self.cfg.APPLICATION, "compil_in_single_dir", "no") == 'yes'
+        for product in env_info['products']:
+            self.set_a_product(product, logger, single_dir=single_dir)
+
+##
+# Class to dump the environment to a file.
+class FileEnvWriter:
+    def __init__(self, config, logger, out_dir, src_root, single_dir, env_info=None):
+        self.config = config
+        self.logger = logger
+        self.out_dir = out_dir
+        self.src_root= src_root
+        self.single_dir = single_dir
+        self.silent = True
+        self.env_info = env_info
+
+    def write_env_file(self, filename, forBuild, shell):
+        """Create an environment file."""
+        if not self.silent:
+            self.logger.write(_("Create environment file %s\n") % src.printcolors.printcLabel(filename), 3)
+
+        # create then env object
+        env_file = open(os.path.join(self.out_dir, filename), "w")
+        tmp = src.fileEnviron.get_file_environ(env_file, shell, {}, self.config )
+        env = SalomeEnviron(self.config, tmp, forBuild)
+        env.silent = self.silent
+
+        if self.env_info is not None:
+            env.set_full_environ(self.logger, self.env_info)
+        else:
+            # set env from PRODUCT
+            env.set_application_env(self.logger)
+            # set the products
+            env.set_products(self.logger,
+                            src_root=self.src_root, single_dir=self.single_dir)
+
+        # add cleanup and close
+        env.finish(True)
+        env_file.close()
+
+        return env_file.name
+
+    def write_product_file(self, filename, shell):
+        """Create a product file."""
+        if not self.silent:
+            self.logger.write(_("Create product file %s\n") % src.printcolors.printcLabel(filename), 3)
+
+        prod_file = open(os.path.join(self.out_dir, filename), "w")
+        if shell == "bash":
+            content = _bash_content % self.out_dir
+        elif shell == "batch":
+            content = _batch_content % self.out_dir
+        else:
+            raise src.SatException(_("Unknown shell: %s") % shell)
+
+        prod_file.write(content)
+        prod_file.close()
+       
+        return prod_file.name
+   
+    def write_cfgForPy_file(self, aFile, additional_env = {}):
+        """append to current opened aFile a cfgForPy environment (python syntax)."""
+        if not self.silent:
+            self.logger.write(_("Create configuration file %s\n") % src.printcolors.printcLabel(aFile.name), 3)
+
+        # create then env object
+        tmp = src.fileEnviron.get_file_environ(aFile, "cfgForPy", {}, self.config)
+        forBuild = True
+        forLaunch = False
+        env = SalomeEnviron(self.config, tmp, forLaunch)
+        env.silent = self.silent
+
+        if self.env_info is not None:
+            env.set_full_environ(self.logger, self.env_info)
+        else:
+            # set env from PRODUCT
+            env.set_application_env(self.logger)
+            # set the prerequisites
+            env.set_prerequisites(self.logger)
+            # set the products
+            env.set_products(self.logger,
+                            src_root=self.src_root, single_dir=self.single_dir)
+
+        if len(additional_env) != 0:
+            for variable in additional_env:
+                env.set(variable, additional_env[variable])
+
+        # add cleanup and close
+        env.finish(True)
+
+##
+# Definition of a Shell.
+class Shell:
+    def __init__(self, name, extension):
+        self.name = name
+        self.extension = extension
+
+##
+# Loads the environment (used to run the tests).
+def load_environment(config, build, logger):
+    environ = SalomeEnviron(config, Environ(os.environ), build)
+    environ.set_application_env(logger)
+    environ.set_products(logger)
+    environ.finish(True)
\ No newline at end of file
index 389fc3b29d47a3026cc6ba7244fc7b4a0894f363..e23d2a3c5bb9713d2496c3c2297d51a2704ab88a 100644 (file)
@@ -140,7 +140,8 @@ class FileEnviron:
             self.prepend_value(key, value, sep)
 
     def is_defined(self, key):
-        return self.environ.has_key(key)
+        return (key in self.environ)
+
 
     def set(self, key, value):
         raise NotImplementedError("set is not implement for this shell!")
index de0e1d3a4f59c7276337bca4fae7a9ca2d68b49c..8ef412536b13390d863dbfe7d528da1b1b57011c 100644 (file)
@@ -117,10 +117,11 @@ def get_product_config(config, product_name):
         prod_info.name = product_name
         prod_info.get_source = "native"
     
-    # Set the debug and dev keys
+    # Set the debug, dev and version keys
     if prod_info is not None:
         prod_info.debug = debug
         prod_info.dev = dev
+        prod_info.version = version
      
     # Set the install_dir key
     if "install_dir" not in prod_info:
@@ -158,6 +159,28 @@ def get_products_infos(lproducts, config):
             raise src.SatException(msg)
     return products_infos
 
+def get_product_dependencies(config, product_info):
+    '''Get recursively the list of products that are 
+       in the product_info dependencies
+    
+    :param config Config: The global configuration
+    :param product_info Config: The configuration specific to 
+                               the product
+    :return: the list of products in dependence
+    :rtype: list
+    '''
+    if "depend" not in product_info or product_info.depend == []:
+        return []
+    res = []
+    for prod in product_info.depend:
+        if prod not in res:
+            res.append(prod)
+        prod_info = get_product_config(config, prod)
+        dep_prod = get_product_dependencies(config, prod_info)
+        for prod_in_dep in dep_prod:
+            if prod_in_dep not in res:
+                res.append(prod_in_dep)
+    return res
 
 def product_is_sample(product_info):
     '''Know if a product has the sample type