Salome HOME
spns #34338: post build script is not embedded in archive
[tools/sat.git] / src / compilation.py
index f774861a03a7a4a694c7e89735a5def85804b207..751fe73b911891c94f4de45f3fa9d46768d169be 100644 (file)
@@ -19,6 +19,8 @@
 import os
 import subprocess
 import sys
+import shutil
+import glob
 
 import src
 
@@ -30,225 +32,94 @@ C_COMPILE_ENV_LIST = ["CC",
                       "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):
+    def __init__(self,
+                 config,
+                 logger,
+                 product_name,
+                 product_info,
+                 options = src.options.OptResult(),
+                 check_src=True):
         self.config = config
         self.logger = logger
         self.options = options
+        self.product_name = product_name
         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.install_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()
+        self.debug_mode = False
+        if "debug" in self.product_info and self.product_info.debug == "yes":
+            self.debug_mode = True
+        self.verbose_mode = False
+        if "verbose" in self.product_info and self.product_info.verbose == "yes":
+            self.verbose_mode = True
 
     ##
-    # Shortcut method to log in both log files.
+    # Shortcut method to log in log file.
     def log(self, text, level, showInfo=True):
         self.logger.write(text, level, showInfo)
         self.logger.logTxtFile.write(src.printcolors.cleancolor(text))
+        self.logger.flush()
 
     ##
     # 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')
+    def prepare(self, add_env_launch=False):
 
         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)
+        environ_info = src.product.get_product_dependencies(self.config,
+                                                            self.product_name,
+                                                            self.product_info)
+        #environ_info.append(self.product_info.name)
 
         # 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 = src.environment.SalomeEnviron(self.config,
+                                      src.environment.Environ(dict(os.environ)),
+                                      True)
+        self.build_environ.silent = (self.config.USER.output_verbose_level < 5)
         self.build_environ.set_full_environ(self.logger, environ_info)
-
+        
+        if add_env_launch:
         # 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)
+            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
+        return 0
 
     ##
     # 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'
+        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())
+            cmake_option += " %s " % " ".join(
+                                        self.product_info.cmake_options.split())
 
         # add debug option
         if self.debug_mode:
@@ -256,13 +127,21 @@ class Builder:
         else :
             cmake_option += " -DCMAKE_BUILD_TYPE=Release"
 
-        # In case CMAKE_GENERATOR is defined in environment, use it in spite of automatically detect it
+        # add verbose option if specified in application for this product.
+        if self.verbose_mode:
+            cmake_option += " -DCMAKE_VERBOSE_MAKEFILE=ON"
+
+        # 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)
+            cmake_option += " -DCMAKE_GENERATOR=\"%s\"" \
+                                       % self.config.APPLICATION.cmake_generator
+        command = ("cmake %s -DCMAKE_INSTALL_PREFIX=%s %s" %
+                            (cmake_option, self.install_dir, self.source_dir))
 
         self.log_command(command)
+        # for key in sorted(self.build_environ.environ.environ.keys()):
+            # print key, "  ", self.build_environ.environ.environ[key]
         res = subprocess.call(command,
                               shell=True,
                               cwd=str(self.build_dir),
@@ -270,52 +149,44 @@ class Builder:
                               stdout=self.logger.logTxtFile,
                               stderr=subprocess.STDOUT)
 
-        self.results.cmake = (res == 0)
-        self.log_result(res)
-        return self.results.cmake
+        self.put_txt_log_in_appli_log_dir("cmake")
+        if res == 0:
+            return res
+        else:
+            return 1
 
     ##
     # 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
+        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)
+        command = str('%s/build_configure') % (self.source_dir)
+        command = command + " " + options
+        self.log_command(command)
 
-        self.log_result(res)
-        return self.results.buildconfigure
+        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.put_txt_log_in_appli_log_dir("build_configure")
+        if res == 0:
+            return res
+        else:
+            return 1
 
     ##
     # 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 = "%s/configure --prefix=%s" % (self.source_dir,
+                                                str(self.install_dir))
 
         command = command + " " + options
         self.log_command(command)
@@ -326,10 +197,12 @@ class Builder:
                               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
+        
+        self.put_txt_log_in_appli_log_dir("configure")
+        if res == 0:
+            return res
+        else:
+            return 1
 
     def hack_libtool(self):
         if not os.path.exists(str(self.build_dir + 'libtool')):
@@ -360,40 +233,15 @@ CC=\\"hack_libtool\\"%g" libtool'''
                         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)
+    def make(self, nb_proc, make_opt=""):
 
         # make
         command = 'make'
-        if self.options.makeflags:
-            command = command + " " + self.options.makeflags
-        command = command + " -j" + str(nbproc)
-
+        command = command + " -j" + str(nb_proc)
+        command = command + " " + make_opt
         self.log_command(command)
         res = subprocess.call(command,
                               shell=True,
@@ -401,30 +249,26 @@ CC=\\"hack_libtool\\"%g" libtool'''
                               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
+        self.put_txt_log_in_appli_log_dir("make")
+        if res == 0:
+            return res
+        else:
+            return 1
     
     ##
     # Runs msbuild to build the module.
-    def wmake(self):
-        nbproc = self.get_nb_proc()
+    def wmake(self,nb_proc, opt_nb_proc = None):
 
-        hh = 'MSBUILD /m:%s' % str(nbproc)
+        hh = 'MSBUILD /m:%s' % str(nb_proc)
         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)
+        command = command + " /maxcpucount:" + str(nb_proc)
         if self.debug_mode:
-            command = command + " /p:Configuration=Debug"
+            command = command + " /p:Configuration=Debug  /p:Platform=x64 "
         else:
-            command = command + " /p:Configuration=Release"
+            command = command + " /p:Configuration=Release /p:Platform=x64 "
         command = command + " ALL_BUILD.vcxproj"
 
         self.log_command(command)
@@ -434,24 +278,24 @@ CC=\\"hack_libtool\\"%g" libtool'''
                               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
+        
+        self.put_txt_log_in_appli_log_dir("make")
+        if res == 0:
+            return res
+        else:
+            return 1
 
     ##
     # Runs 'make install'.
     def install(self):
-        self.log_step('INSTALL')
-        if self.config.VARS.dist_name=="Win":
+        if src.architecture.is_windows():
             command = 'msbuild INSTALL.vcxproj'
             if self.debug_mode:
-                command = command + " /p:Configuration=Debug"
+                command = command + " /p:Configuration=Debug  /p:Platform=x64 "
             else:
-                command = command + " /p:Configuration=Release"
+                command = command + " /p:Configuration=Release  /p:Platform=x64 "
         else :
             command = 'make install'
-
         self.log_command(command)
 
         res = subprocess.call(command,
@@ -460,58 +304,74 @@ CC=\\"hack_libtool\\"%g" libtool'''
                               env=self.build_environ.environ.environ,
                               stdout=self.logger.logTxtFile,
                               stderr=subprocess.STDOUT)
+        
+        res_check=self.check_install()
+        if res_check > 0 :
+            self.log_command("Error in sat check install - some files are not installed!")
+        self.put_txt_log_in_appli_log_dir("makeinstall")
 
-        self.results.install = (res == 0)
-        self.log_result(res)
-        return self.results.install
+        res+=res_check
+        if res == 0:
+            return res
+        else:
+            return 1
+
+    # this function checks wether a list of file patterns (specified by check_install keyword) 
+    # exixts after the make install. The objective is to ensure the installation is complete.
+    # patterns are given relatively to the install dir of the product
+    def check_install(self):
+        res=0
+        if "check_install" in self.product_info:
+            self.log_command("Check installation of files")
+            for pattern in self.product_info.check_install:
+                # pattern is given relatively to the install dir
+                complete_pattern=os.path.join(self.product_info.install_dir, pattern) 
+                self.log_command("    -> check %s" % complete_pattern)
+                # expansion of pattern : takes into account environment variables and unix shell rules
+                list_of_path=glob.glob(os.path.expandvars(complete_pattern))
+                if not list_of_path:
+                    # we expect to find at least one entry, if not we consider the test failed
+                    res+=1
+                    self.logger.write("Error, sat check install failed for file pattern %s\n" % complete_pattern, 1)
+                    self.log_command("Error, sat check install failed for file pattern %s" % complete_pattern)
+        return res
 
     ##
     # Runs 'make_check'.
-    def check(self):
-        self.log_step('CHECK')
+    def check(self, command=""):
         if src.architecture.is_windows():
-            command = 'msbuild RUN_TESTS.vcxproj'
+            cmd = 'msbuild RUN_TESTS.vcxproj /p:Configuration=Release  /p:Platform=x64 '
         else :
-            if self.use_autotools :
-                command = 'make check'
-            else :
-                command = 'make test'
-            
-        self.log_command(command)
+            if self.product_info.build_source=="autotools" :
+                cmd = 'make check'
+            else:
+                cmd = 'make test'
+        
+        if command:
+            cmd = command
+        
+        self.log_command(cmd)
+        self.log_command("For more detailed logs, see test logs in %s" % self.build_dir)
 
-        self.results.check_tried = True
-        res = subprocess.call(command,
+        res = subprocess.call(cmd,
                               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)
+        self.put_txt_log_in_appli_log_dir("makecheck")
+        if res == 0:
+            return res
         else:
-            self.log(_('No clean: not specified in the config\n'), 5)
-
-    def get_result(self):
-        return self.results
+            return 1
       
     ##
     # Performs a default build for this module.
-    def do_default_build(self, build_conf_options="", configure_options="", show_warning=True):
+    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
@@ -544,114 +404,142 @@ CC=\\"hack_libtool\\"%g" libtool'''
 
         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.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()
+    def do_python_script_build(self, script, nb_proc):
         # script found
-        self.logger.write(_("Compile %(module)s using script %(script)s\n") % \
-            { 'module': self.module, 'script': src.printcolors.printcLabel(script) }, 4)
+        self.logger.write(_("Compile %(product)s using script %(script)s\n") % \
+            { 'product': self.product_info.name,
+             'script': src.printcolors.printcLabel(script) }, 4)
         try:
             import imp
-            pymodule = imp.load_source(self.module + "_compile_script", script)
+            product = self.product_info.name
+            pymodule = imp.load_source(product + "_compile_script", script)
+            self.nb_proc = nb_proc
             retcode = pymodule.compil(self.config, self, self.logger)
         except:
             __, exceptionValue, exceptionTraceback = sys.exc_info()
-            print(exceptionValue)
+            self.logger.write(str(exceptionValue), 1)
             import traceback
             traceback.print_tb(exceptionTraceback)
             traceback.print_exc()
+            retcode = 1
+        finally:
+            self.put_txt_log_in_appli_log_dir("script")
 
         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)
+    def complete_environment(self, make_options):
+        assert self.build_environ is not None
+        # pass additional variables to environment 
+        # (may be used by the build script)
+        self.build_environ.set("APPLICATION_NAME", self.config.APPLICATION.name)
+        self.build_environ.set("SOURCE_DIR", str(self.source_dir))
+        self.build_environ.set("INSTALL_DIR", str(self.install_dir))
+        self.build_environ.set("PRODUCT_INSTALL", str(self.install_dir))
+        self.build_environ.set("BUILD_DIR", str(self.build_dir))
+        self.build_environ.set("PRODUCT_BUILD", str(self.build_dir))
+        self.build_environ.set("MAKE_OPTIONS", make_options)
+        self.build_environ.set("DIST_NAME", self.config.VARS.dist_name)
+        self.build_environ.set("DIST_VERSION", self.config.VARS.dist_version)
+        self.build_environ.set("DIST", self.config.VARS.dist)
+        self.build_environ.set("VERSION", self.product_info.version)
+        # if product is in hpc mode, set SAT_HPC to 1 
+        # in order for the compilation script to take it into account
+        if src.product.product_is_hpc(self.product_info):
+            self.build_environ.set("SAT_HPC", "1")
+        if self.debug_mode:
+            self.build_environ.set("SAT_DEBUG", "1")
+        if self.verbose_mode:
+            self.build_environ.set("SAT_VERBOSE", "1")
 
-            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')
+    def do_batch_script_build(self, script, nb_proc):
 
-            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)
+        if src.architecture.is_windows():
+            make_options = "/maxcpucount:%s" % nb_proc
+        else :
+            make_options = "-j%s" % nb_proc
 
-        return retcode
+        self.log_command("  " + _("Run build script %s\n") % script)
+        self.complete_environment(make_options)
+        
+        res = subprocess.call(script, 
+                              shell=True,
+                              stdout=self.logger.logTxtFile,
+                              stderr=subprocess.STDOUT,
+                              cwd=str(self.build_dir),
+                              env=self.build_environ.environ.environ)
+
+        res_check=self.check_install()
+        if res_check > 0 :
+            self.log_command("Error in sat check install - some files are not installed!")
+
+        self.put_txt_log_in_appli_log_dir("script")
+        res += res_check
+        if res == 0:
+            return res
+        else:
+            return 1
+    
+    def do_script_build(self, script, number_of_proc=0):
+        # define make options (may not be used by the script)
+        if number_of_proc==0:
+            nb_proc = src.get_cfg_param(self.product_info,"nb_proc", 0)
+            if nb_proc == 0: 
+                nb_proc = self.config.VARS.nb_proc
+        else:
+            nb_proc = min(number_of_proc, self.config.VARS.nb_proc)
+            
+        extension = script.split('.')[-1]
+        if extension in ["bat","sh"]:
+            return self.do_batch_script_build(script, nb_proc)
+        if extension == "py":
+            return self.do_python_script_build(script, nb_proc)
+        
+        msg = _("The script %s must have .sh, .bat or .py extension." % script)
+        raise src.SatException(msg)
+    
+    def put_txt_log_in_appli_log_dir(self, file_name):
+        '''Put the txt log (that contain the system logs, like make command
+           output) in the directory <APPLICATION DIR>/LOGS/<product_name>/
+    
+        :param file_name Str: the name of the file to write
+        '''
+        if self.logger.logTxtFile == sys.__stdout__:
+            return
+        dir_where_to_put = os.path.join(self.config.APPLICATION.workdir,
+                                        "LOGS",
+                                        self.product_info.name)
+        file_path = os.path.join(dir_where_to_put, file_name)
+        src.ensure_path_exists(dir_where_to_put)
+        # write the logTxtFile copy it to the destination, and then recreate 
+        # it as it was
+        self.logger.logTxtFile.close()
+        shutil.move(self.logger.txtFilePath, file_path)
+        self.logger.logTxtFile = open(str(self.logger.txtFilePath), 'w')
+        self.logger.logTxtFile.write(open(file_path, "r").read())
+