Salome HOME
Minor fix
[tools/install.git] / runInstall
index 64efac428ccac2fee29e71f4c4206984ca4fed78..b7f7f210945bab4d94f077e9603471fd158294ca 100755 (executable)
@@ -6,36 +6,38 @@ Installation Wizard launching script.
 This script is the part of the SALOME installation procedure.
 Author    : Vadim SANDLER, Open CASCADE SAS (vadim.sandler@opencascade.com)
 Created   : Thu Dec 18 12:01:00 2002
-Copyright : 2002-2007 CEA
+Copyright : 2002-2013 CEA
 
 """
 
-__version__ = "1.0.1"
+__version__ = "1.1.5"
+
+# --- imports --- #
+import sys
+try:
+    import xml.sax, xml.dom.minidom
+    import os, re
+    import types
+    import random
+    import warnings
+except Exception, an_exc:
+    sys.exit("Error: %s! Please check the installed Python package." % str(an_exc))
+    pass
 
 # --- avoid "deprecation" warnings --- #
-import warnings
 warnings.filterwarnings("ignore", "", DeprecationWarning)
 
-# --- imports --- #
-import xmllib
-import sys, os, re
-import types
-import random
-
 # --- global variables --- #
 opt_parser = None
 root_path  = None
 
-# --- XML tags definition --- #
-__TAG__SOURCES__    = "install sources"
-__TAG__BINARIES__   = "install binaries"
-__TAG__NATIVE__     = "use native"
-__TAG__PREINSTALL__ = "not install"
-__TAG__BUILDSRC__   = "build sources"
+# --- actions definition --- #
+__BINARIES__   = "install_binary"
+__BUILDSRC__   = "install_source_and_build"
+__PREINSTALL__ = "try_preinstalled"
 
-# --- product context definition --- #
-__CTX__SALOME__SRC__  = "salome sources"
-__CTX__SALOME__BIN__  = "salome binaries"
+# --- product type definition --- #
+__CTX__COMPONENT__    = "component"
 __CTX__PREREQUISITE__ = "prerequisite"
 
 #------------------------------------------------------------------#
@@ -159,7 +161,7 @@ class ArgOption:
             msg  = "invalid type: %s : should be 'bool' or None" % self.type
             raise OptError(msg, self)
         # default
-        if self.default:
+        if self.default is not None:
             try:
                 if self.type == "string": self.default = str(self.default)
                 if self.type == "int":    self.default = int(self.default)
@@ -223,7 +225,7 @@ class ArgParser:
         if not args: args = sys.argv[1:]
         values = Values()
         for o in self.options:
-            if o.default:
+            if o.default is not None:
                 setattr(values, o.dest, o.default)
             elif not hasattr(values,o.dest):
                 setattr(values, o.dest, None)
@@ -361,43 +363,36 @@ class ArgParser:
 #------------------------------------------------------------------#
 
 #===================================================================
-# class Config : general configuration options : version, OS, etc...
+# class Config : general configuration options : version, target and
+#                temporary directories, etc...
 #===================================================================
 class Config :
     """
     General configuration file options:
     - Install Wizard window caption
     - SALOME platform version
-    - Copyright and libcense info
-    - Target Linux OS version
+    - Copyright and license info
+    - Default target and temporary directories
+    - List of optional libraries for Salome
     """
     def __init__(self,
                  theVersion   = None,
                  theCaption   = None,
                  theCopyright = None,
                  theLicense   = None,
-                 theOS        = None):
+                 thePlatforms = None,
+                 theTargetdir = None,
+                 theTmpdir    = None,
+                 theOptLibs   = None):
         self.version   = strip(theVersion)
         self.caption   = strip(theCaption)
         self.copyright = strip(theCopyright)
         self.license   = strip(theLicense)
-        self.os        = strip(theOS)
-
-#===================================================================
-# class Path : default target, temporary directories options
-#===================================================================
-class Path :
-    """
-    Path options:
-    - default target directory
-    - default temporary directory
-    """
-    def __init__(self,
-                 theTargetdir = None,
-                 theTmpdir    = None):
+        self.platforms = strip(thePlatforms)
         self.targetdir = strip(theTargetdir)
         self.tmpdir    = strip(theTmpdir)
-        
+        self.optlibs   = strip(theOptLibs)
+
 #==============================================================
 # class Product : pre-requisite product options
 #==============================================================
@@ -405,7 +400,7 @@ class Product :
     """
     Product options:
     - name, version
-    - supported installation modes and the default one
+    - target Linux OS version
     - dependencies
     - required disk space
     - installation script
@@ -413,110 +408,154 @@ class Product :
     """
     def __init__(self,
                  theName,
+                 theType               = None,
+                 theOS                 = None,
                  theVersion            = None,
-                 theInstall            = None,
-                 theSupportred         = None,
                  theDependencies       = None,
+                 theWoGuiInstallation  = None,
                  theInstalldiskspace   = None,
-                 theTemporarydiskspace = None,
                  theScript             = None,
-                 thePickUpEnvironment  = None,
-                 theContext            = None):
+                 thePickUpEnvironment  = None):
         self.name               = strip(theName)
+        self.type               = strip(theType)
+        self.os                 = strip(theOS)
         self.version            = strip(theVersion)
-        self.install            = strip(theInstall)
-        self.supported          = strip(theSupportred)
         self.dependencies       = strip(theDependencies)
+        self.woguiinst          = strip(theWoGuiInstallation)
         self.installdiskspace   = strip(theInstalldiskspace)
-        self.temporarydiskspace = strip(theTemporarydiskspace)
         self.script             = strip(theScript)
         self.pickupEnv          = strip(thePickUpEnvironment)
-        self.context            = strip(theContext)
-        self.whattodo           = self.install
+        self.whattodo           = __BINARIES__
         
-    def hasContext(self, ctx):
-        try:
-            return ctx in [ strip(s) for s in self.context.split(",") ]
-        except:
-            pass
-        return False
-
     def setMode(self, mode):
-        if mode not in [__TAG__SOURCES__, __TAG__BINARIES__, __TAG__NATIVE__, __TAG__PREINSTALL__]:
+        if mode not in [__BINARIES__, __BUILDSRC__, __PREINSTALL__]:
             return
-        try:
-            supported = [ strip(s) for s in self.supported.split(",") ]
-            if mode in supported or mode == __TAG__PREINSTALL__:
-                self.install = mode
-                self.whattodo = self.install
-            salbin = self.hasContext(__CTX__SALOME__BIN__)
-            salsrc = self.hasContext(__CTX__SALOME__SRC__)
-            if mode == __TAG__SOURCES__:
-                if salbin and not salsrc:
-                    self.install = __TAG__PREINSTALL__
-                    self.whattodo = self.install
-                elif salsrc:
-                    self.whattodo = __TAG__BUILDSRC__
-        except:
-            pass
+        self.whattodo = mode
         return
         
 #===================================================================
 # class ConfigParser : XML files parser implementation
 #===================================================================
-class ConfigParser(xmllib.XMLParser):
+class ConfigParser:
     """
     XML configuration files parser
     """
-    def __init__(self, is_force_src=False):
-        xmllib.XMLParser.__init__(self)
+    def __init__(self, is_force_src=False, pltname=None):
+        self.docElem = None
         self.products = []
-        self.currentdata = []
-        self.path = None
+        self.full_prods_list = []
         self.config = None
         self.is_force_src = is_force_src
+        self.pltname = pltname
+        pass
         
-    def handle_data(self, data):
-        self.currentdata.append(data)
+    def parse_config(self):
+        # Parse 'config' part of the XML file
+        configElem = self.docElem.getElementsByTagName('config')[0]
         
-    def start_product(self, attrs):
-        if not attrs.get('name', '').strip():         return
-        if check_bool(attrs.get('disable', 'false')): return
-        aProduct = Product(attrs.get('name'),
-                           attrs.get('version',            None),
-                           attrs.get('install',            None),
-                           attrs.get('supported',          None),
-                           attrs.get('dependancies',       None),
-                           attrs.get('installdiskspace',   None),
-                           attrs.get('temporarydiskspace', None),
-                           attrs.get('script',             None),
-                           attrs.get('pickupenv',          None),
-                           attrs.get('context',            None))
-        if self.is_force_src:
-            aProduct.setMode(__TAG__SOURCES__)
-        self.products.append(aProduct)
-        pass
-
-    def end_product(self):
-        pass
-
-    def start_config(self, attrs):
-        self.config = Config(attrs.get('version',   None),
-                             attrs.get('caption',   None),
-                             attrs.get('copyright', None),
-                             attrs.get('license',   None),
-                             attrs.get('os',        None))
+        self.config = Config(configElem.getAttribute('version').strip(),
+                             configElem.getAttribute('caption').strip(),
+                             configElem.getAttribute('copyright').strip(),
+                             configElem.getAttribute('license').strip(),
+                             configElem.getAttribute('platforms').strip(),
+                             configElem.getAttribute('targetdir').strip(),
+                             configElem.getAttribute('tempdir').strip(),
+                             configElem.getAttribute('optionallibs').strip())
+        if not self.pltname and self.config.platforms:
+            self.pltname = self.config.platforms.split(",")[0].strip()
         pass
     
-    def end_config(self):
+    def parse_dependencies(self):
+        # Parse 'dependencies' part of the XML file
+        depsMap = {}
+        depsElem = self.docElem.getElementsByTagName('dependencies')[0]
+        for prodElem in depsElem.getElementsByTagName('product'):
+            prodName = prodElem.getAttribute('name').strip()
+            if not prodName: continue
+            depsList = []
+            for depElem in prodElem.getElementsByTagName('dep'):
+                depsList.append(depElem.firstChild.data)
+                pass
+            depsMap[prodName] = depsList
+            pass
+        return depsMap
+    
+    def parse_product(self):
+        # Parse 'products' part of the XML file
+        depsMap = self.parse_dependencies()
+        prodsElem = self.docElem.getElementsByTagName('products')[0]
+        sal_prods_list = []; req_prods_list = []
+        modules_list = []; prereqs_list = []
+        for prodElem in prodsElem.getElementsByTagName('product'):
+            prodName = prodElem.getAttribute('name').strip()
+            if not prodName: continue
+            instElems = prodElem.getElementsByTagName('installation')
+            instElem = None
+            for node in instElems:
+                if not self.pltname or self.pltname == node.getAttribute('os').strip():
+                    instElem = node
+                    break
+                pass
+            if not instElem: continue
+            if check_bool(str(instElem.getAttribute('disable').strip())): continue
+            depsList = []
+            if prodName in depsMap: depsList = depsMap[prodName]
+            aProduct = Product(prodName,
+                               prodElem.getAttribute('type').strip(),
+                               instElem.getAttribute('os').strip(),
+                               instElem.getAttribute('version').strip(),
+                               depsList,
+                               instElem.getAttribute('woguimode').strip(),
+                               instElem.getAttribute('installdiskspace').strip(),
+                               instElem.getAttribute('script').strip(),
+                               instElem.getAttribute('pickupenv').strip())
+            if self.is_force_src:
+                aProduct.setMode(__BUILDSRC__)
+                pass
+            if prodElem.getAttribute('type').strip() == "component":
+                sal_prods_list.append(aProduct)
+                # fill an ordered modules list -----------
+                modules_list.append(prodName)
+                modules_list.append(prodName + "_src")
+                pass
+            else: #prerequisite
+                req_prods_list.append(aProduct)
+                # fill an ordered prerequisites list -----------
+                prereqs_list.append(prodName)
+                #AKL: prerequisite sources and temp files are removed, by default.
+                #     So, there is no need to make sources environment
+                #if aProduct.whattodo == __BUILDSRC__: prereqs_list.append(prodName + "_src")
+                pass
+            pass
+        self.products.extend( req_prods_list )
+        self.products.extend( sal_prods_list )
+        if len(self.products) != 0:
+            gcc_product = Product("gcc",
+                                  __CTX__PREREQUISITE__,
+                                  self.products[0].os,
+                                  "",
+                                  [],
+                                  None,
+                                  "0,0,0",
+                                  "gcc-common.sh",
+                                  "")
+            gcc_product.setMode(__PREINSTALL__)
+            self.products.insert(0, gcc_product)
+            prereqs_list.insert(0, gcc_product.name)
+            pass
+        self.full_prods_list.extend( prereqs_list )
+        self.full_prods_list.extend( modules_list )
         pass
 
-    def start_path (self, attrs):
-        self.path = Path(attrs.get('targetdir', None),
-                         attrs.get('tempdir',   None))
-        pass
-        
-    def end_path(self):
+    def parse(self, xml_file):
+        filehandle = open(xml_file)
+        sax_parser = xml.sax.make_parser()
+        doc = xml.dom.minidom.parse(filehandle, sax_parser)
+        filehandle.close()
+
+        self.docElem = doc.documentElement
+        self.parse_config()
+        self.parse_product()
         pass
 
     def getProduct(self, prod):
@@ -525,6 +564,7 @@ class ConfigParser(xmllib.XMLParser):
                 return product
         return None
 
+
 #------------------------------------------------------------------#
 #                                                                  #
 #                         SERVICE FUNCTIONS                        #
@@ -646,15 +686,22 @@ def parse_parameters():
     help_str += "If this parameter is missing, then the program tries to define the "
     help_str += "Linux platform and use the corresponding xml file. For example, "
     help_str += "for Red Hat 8.0 config_RedHat_8.0.xml file is used in this case. "
-    help_str += "If program fails to define target Linux platform or the corresponding "
-    help_str += "xml file is not provided with the Installation Wizard, then default "
-    help_str += "config.xml file is used."
     opt_parser.add_option("-f",
                           "--file",
                           action="store",
                           dest="xmlfile",
                           metavar="FILE",
                           help=help_str)
+    help_str  = "The platform specification.\n"
+    help_str += "This option can be used in conjunction with --file option in order"
+    help_str += "to specify Linux platform name when XML file contains installation"
+    help_str += "options for several platforms."
+    opt_parser.add_option("-p",
+                          "--platform",
+                          action="store",
+                          dest="platform",
+                          metavar="PLT",
+                          help=help_str)
     help_str  = "The target directory the products to be installed to.\n"
     help_str += "When used this parameter overrides the default target directory "
     help_str += "defined in the configuration xml file."
@@ -673,8 +720,8 @@ def parse_parameters():
                           dest="tmp_dir",
                           metavar="DIR",
                           help=help_str)
-    help_str  = "Force all products to be installed from sources\n"
-    help_str += "including SALOME modules."
+    help_str  = "Force all products to be installed from sources \n"
+    help_str += "including SALOME modules.\n"
     help_str += "If this option is used all the default installation modes are ignored."
     opt_parser.add_option("-a",
                           "--all-from-sources",
@@ -682,6 +729,14 @@ def parse_parameters():
                           dest="force_sources",
                           default=False,
                           help=help_str)
+    help_str  = "Install all SALOME binaries packages to one directory.\n"
+    help_str += "This option is ignored when --all-from-sources (-a) option is used."
+    opt_parser.add_option("-s",
+                          "--single-directory",
+                          action="store_true",
+                          dest="single_dir",
+                          default=False,
+                          help=help_str)
     help_str  = "Prints version information and quits."
     opt_parser.add_option("-v",
                           "--version",
@@ -695,7 +750,7 @@ def parse_parameters():
     (options, args) = opt_parser.parse_args()
     if options.help:
         # print help info and quit
-        print "\nSALOME Installation Wizard\n"
+        print "\nSALOME Installation Wizard (running on %s)\n" % get_os_name()
         opt_parser.print_help()
         print ""
         sys.exit(0)
@@ -706,7 +761,7 @@ def parse_parameters():
         os.system(cmd)
         print ""
         sys.exit(0)
-    return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui, options.force_sources]
+    return [options.xmlfile, options.target_dir, options.tmp_dir, options.gui, options.force_sources, options.single_dir, options.platform]
 
 #=================================================================
 # strip : removes spaces at the beginning and at the end of the 
@@ -726,19 +781,26 @@ def strip(param):
 #=================================================================
 def get_dependencies(prods):
     """
-    Gets full list of pre-requisite products.
+    Gets a list of installed and required products.
     """
-    list = []
+    prods_list = []
     for product in prods:
-        deps = product.dependencies.split(",")
-        for dep in deps:
-            if dep and not dep in list:
-                list.append( dep )
-                
-        if product and not product in list:
-            list.append( product.name )
+        for dep in product.dependencies:
+            if dep and dep not in prods_list:
+                prods_list.append( dep )
+                dep_name = dep
+                if product.whattodo == __BUILDSRC__:
+                    dep_name = dep + "_src"
+                if dep_name not in parser.full_prods_list:
+                    msg = "Prerequisite '%s' is required for '%s' product,\n"%(dep, product.name)
+                    msg += "but the first one is absent in the list of products to be installed!\n"
+                    msg += "Please check your XML file."
+                    warning(msg)
+
+        if product.name and product.name not in prods_list:
+            prods_list.append( product.name )
             
-    return " ".join( list )
+    return " ".join( prods_list )
 
 #==============================================================
 # create_dir : creates a directory with (optional) permissions,
@@ -828,35 +890,28 @@ def check_disk_space(products, scripts_dir, target_dir, tmp_dir, is_force_src=Fa
     install_space = 0
     temporary_space = 0
     for product in products:
-        if product.install in [__TAG__NATIVE__, __TAG__PREINSTALL__]:
-            continue
         prod_space = 0
         try:
             spaces = product.installdiskspace.split(',')
             prod_space = int( spaces[0] )
-            if len( spaces ) > 1 and product.install == __TAG__SOURCES__ and not is_force_src:
-                prod_space = int( spaces[1] )
+            if product.whattodo == __BINARIES__:
+                prod_space = int( spaces[0] )
+                if product.type == __CTX__COMPONENT__:
+                    prod_space += int( spaces[1] )
+            else:
+                if product.type == __CTX__PREREQUISITE__:
+                    prod_space = int( spaces[0] )
+                else:
+                    prod_space = int( spaces[2] )
         except:
             pass
         install_space = install_space + prod_space
-        if product.install == __TAG__SOURCES__:
-            tmp_space = 0
-            try:
-                tmp_space = int( product.temporarydiskspace )
-            except:
-                pass
-            temporary_space = max( temporary_space, tmp_space )
         pass
 
     res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", target_dir, install_space))
     if res:
         msg = "There is no enough space to install the products. Stopped..."
         error_exit(msg, False)
-    
-    res = os.system("%s/%s %s %d"%(scripts_dir, "checkSize.sh", tmp_dir, temporary_space))
-    if res:
-        msg = "There is no enough space for temporary directory. Stopped..."
-        error_exit(msg, False)
     pass
  
 #===============================================================
@@ -879,7 +934,7 @@ def has_binaries(products):
     Returns True if some product is installed in 'binaries' mode.
     """
     for product in products:
-        if product.install == __TAG__BINARIES__:
+        if product.whattodo == __BINARIES__:
             return True
     return False
 
@@ -892,7 +947,7 @@ def has_sources(products):
     Returns True if some product is installed in 'sources' mode.
     """
     for product in products:
-        if product.install == __TAG__SOURCES__:
+        if product.whattodo == __BUILDSRC__:
             return True
     return False
 
@@ -911,79 +966,211 @@ def get_tmp_dir(dir):
         if not os.path.exists( tmp_dir ):
             return tmp_dir
     return "%s/%s%d"%(dir, dir_prefix, random.randint(range_bottom,range_top))
-    
+
+#==============================================================
+# get_os_release : gets OS release; the OS name, version and
+#                  architecture
+#                  For example:
+#                  RedHat, 8.0; Mandriva, 2006.0, 64
+#===============================================================
+def get_os_release():
+    filename = "/etc/issue"
+    # ---
+    plt_name = "unknown"
+    plt_ver  = ""
+    plt_arch = ""   
+    if os.path.exists(filename):
+        # ---
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+        # ---
+        regvar  = re.compile("(.*)\s+[^\s]*[R|r]elease[^\s]*\s+([\d.]*)")
+        regvar1 = re.compile("(.*)\s+[^\s]*[L|l][I|i][N|n][U|u][X|x][^\s]*(.*)\s+([\d.]*)\s+")
+        regvar2 = re.compile("([A-Za-z]+)\s+([0-9.]+)\s+.*")
+        for l in lines:
+            res = re.search(regvar, l)
+            if not res:
+                res = re.search(regvar1, l)
+            if not res:
+                res = re.search(regvar2, l)
+            if res:
+                plt_name = " ".join(" ".join(res.groups()[:len(res.groups())-1]).split())
+                # workaround for Mandrake and other platforms
+                plt_name = plt_name.replace("Linux", "").replace("linux", "").replace("LINUX", "").strip()
+                # workaround for SuSe
+                plt_name = plt_name.replace("Welcome to", "").strip()
+                # ---
+                plt_name = " ".join(plt_name.split())
+                plt_ver  = res.group(len(res.groups()))
+                if re.search(r'x86_64', l):
+                    plt_arch = "64bit"
+                    pass
+                # workaround for Red Hat Enterprise
+                if not plt_arch:
+                    try:
+                        import platform
+                        if platform.machine() == "x86_64":
+                            plt_arch = "64bit"
+                            pass
+                        pass
+                    except:
+                        pass
+                    pass
+                break
+            pass
+        pass
+
+    return plt_name, plt_ver, plt_arch
+
+#==============================================================
+# get_os_name : gets qualified OS name
+#               For example:
+#               Mandriva 2010.0 64bit
+#===============================================================
+def get_os_name():
+    plt_name, plt_ver, plt_arch = get_os_release()
+    data = []
+    for i in plt_name, plt_ver, plt_arch:
+        if i: data.append(i)
+    return " ".join(data)
+
+#==============================================================
+# check_xml_file : checks XML file existence and readability
+#===============================================================
+def check_xml_file(xml_file):
+    """
+    Checks XML file existence and readability.
+    """
+    if not os.path.isfile(xml_file):
+        msg = "Configuration file %s is not found!"%xml_file
+        error_exit(msg, False)
+
+    if not os.access(xml_file, os.R_OK):
+        msg = "There is no read access for %s file!"%xml_file
+        error_exit(msg, False)
+    pass
+
+#==============================================================
+# get_supported_plts : gets map of supported Linux platforms and
+#                      corresponding configuration files
+#===============================================================
+def get_supported_platforms(xml_file=None):
+    """
+    Gets map of supported Linux platforms and
+    corresponding configuration files.
+    """
+    platforms_map = {}
+    if xml_file:
+        xml_file_list = [xml_file]
+        pass
+    else:
+        xml_file_list = filter(lambda i: i.endswith(".xml"), os.listdir(get_program_path()))
+        while 'config.xml' in xml_file_list: xml_file_list.remove('config.xml')
+        if os.path.exists(os.path.join(get_program_path(), 'config.xml')):
+            xml_file_list.append('config.xml')
+        xml_file_list = [os.path.abspath(i) for i in xml_file_list]
+        pass
+    for an_xml_file in xml_file_list: # XML files parsing
+        check_xml_file(an_xml_file)
+        parser = ConfigParser()
+        parser.parse(an_xml_file)
+        if parser.config.platforms is not None:
+            for plt in parser.config.platforms.split(","):
+                if not plt or plt in platforms_map.keys(): continue
+                platforms_map[strip(plt)] = an_xml_file
+                pass
+            pass
+        pass
+    return platforms_map
+
+#==============================================================
+# Print menu with list of supported platform
+# and return user choice
+#===============================================================
+def select_platform(all_platforms):
+    platforms = all_platforms.keys()
+    platforms.sort()
+    pltname = None
+    while not pltname:
+        print "Please, select any platform from the list below."
+        print "--------------------------"
+        for idx in range(len(platforms)):
+            print " %2d. %s" % (idx+1, " ".join(platforms[idx].split("_")))
+        print "  0. Exit"
+        print "--------------------------"
+        print "Type your choice (%d-%d) and press <Enter>:" % (0, len(platforms)),
+        try:
+            idx = raw_input()
+        except:
+            sys.exit(1)
+        try:
+            idx = int(idx)
+        except:
+            warning("Invalid input!")
+            pass
+        if idx == 0: sys.exit(0)
+        if idx > 0 and idx <= len(platforms):
+            pltname = platforms[idx-1]
+        else:
+            warning("Invalid input!")
+        pass
+    return pltname, all_platforms[pltname]
+
+#==============================================================
+# Check existence of required libraries in system and
+# warn user if some ones are absent
+#===============================================================
+def check_not_found_libs(filepath, optlibs):
+    a_file = open(filepath, 'r')
+    nf_mand_libs = list()
+    nf_opt_libs = list()
+    pref_opt_libs = optlibs.split(",")
+    for line in a_file:
+        line = line.strip()
+        if not line:
+            continue
+        line = line.split(" ")[0]
+        if line in nf_mand_libs or line in nf_opt_libs:
+            continue
+        is_optional = False;
+        for opt_lib in pref_opt_libs:
+            if line.lower().startswith(opt_lib.lower().strip()):
+                is_optional = True
+                break
+        if is_optional:
+            nf_opt_libs.append(line)
+        else:
+            nf_mand_libs.append(line)
+        pass
+
+    msg = "=== WARNING: Some libraries are absent! ===\n"
+    if nf_mand_libs:
+        msg += "One or several MANDATORY libraries listed below are not found. SALOME may not work properly.\n\t"
+        msg += "\n\t".join(nf_mand_libs)
+        msg += "\n"
+    if nf_opt_libs:
+        msg += "One or several OPTIONAL libraries listed below are not found. This does not affect on the correct work of SALOME platform.\n\t"
+        msg += "\n\t".join(nf_opt_libs)
+    if nf_mand_libs or nf_opt_libs:
+        print msg
+    a_file.close()
+    pass
+
 #------------------------------------------------------------------#
 #                                                                  #
 #                    EXECUTION STARTS HERE                         #
 #                                                                  #
 #------------------------------------------------------------------#
-    
+
 if __name__ == "__main__":
+    # get program dir
+    cur_dir = get_program_path()
     # parse command line
-    [xml_file, target_dir, tmp_dir, is_gui, is_force_src] = parse_parameters()
+    [xml_file, target_dir, tmp_dir, is_gui, is_force_src, is_single_dir, pltname] = parse_parameters()
     if xml_file:   xml_file   = os.path.abspath(xml_file)
     if target_dir: target_dir = os.path.abspath(target_dir)
     if tmp_dir:    tmp_dir    = os.path.abspath(tmp_dir)
-    # get program dir
-    cur_dir = get_program_path()
-
-    # define xml file to be used
-    if (xml_file is None):
-        plt_name = ""
-        plt_ver  = ""
-        plt_bit  = ""
-        xml_file_name = "config.xml"
-        if os.path.exists("/etc/fedora-release"):
-            # - Fedora Core 4
-            plt_name = "Fedora"
-            data = open("/etc/fedora-release").readline()
-            res = re.search(r'Fedora.*release\s+([\d.]*)', data)
-           if res:
-                plt_ver = res.group(1)
-        elif os.path.exists("/etc/redhat-release"):
-            # - Red Hat Linux 8.0
-            # - Red Hat Linux 9
-            # - Mandrake Linux 10.1
-            # - Scientific Linux 3.0.5
-           # - Mandriva 2006.0 32bit/64bit
-            data = open("/etc/redhat-release").readline()
-           res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
-           if res:
-                plt_name = "".join(res.group(1).split())
-                plt_ver  = res.group(2)
-               if re.search(r'x86_64', data):
-                    plt_bit  = "_64"
-        elif os.path.exists("/etc/debian_version"):
-            # - Debian 3.1
-            plt_name = "Debian"
-            plt_ver = open("/etc/debian_version").readline().strip()
-        elif os.path.exists("/etc/mandriva-release"):
-            # - Mandriva 2006 (an additional check if above check fails)
-            data = open("/etc/mandriva-release").readline()
-           res = re.search(r'(.*)[L|l]inux.*release\s+([\d.]*)', data)
-           if res:
-                plt_name = "".join(res.group(1).split())
-                plt_ver  = res.group(2)
-               if re.search(r'x86_64', data):
-                    plt_bit  = "_64"
-                pass
-        _xml_file_name = "config_%s_%s%s.xml"%(plt_name, plt_ver, plt_bit)
-        if plt_name and plt_ver and os.path.exists("%s/%s"%(cur_dir, _xml_file_name)):
-            xml_file_name = _xml_file_name
-        else:
-            msg  = "Not supported Linux platform!\n"
-            msg += "Trying to use default configuration file!"
-            warning(msg)
-
-        xml_file = "%s/%s"%(cur_dir, xml_file_name)
-
-    if not xml_file or not os.path.exists(xml_file):
-        msg = "Configuration file %s is not found!"%xml_file
-        error_exit(msg)
-
-    if not os.access(xml_file, os.R_OK):
-        msg = "There is no read access for %s file!"%xml_file
-        error_exit(msg)
 
     #---- GUI ----------------
 
@@ -994,44 +1181,88 @@ if __name__ == "__main__":
         if not env.has_key("LD_LIBRARY_PATH") :
             env["LD_LIBRARY_PATH"] = ""
 
-        env["LD_LIBRARY_PATH"] =  ".:" + env["LD_LIBRARY_PATH"]
+        env["LD_LIBRARY_PATH"] =  "./bin/lib:" + ".:" + env["LD_LIBRARY_PATH"]
         env["PATH"] = ".:" + env["PATH"]
 
-        cmd = "./bin/SALOME_InstallWizard --file %s"%xml_file
+        cmd = "./bin/SALOME_InstallWizard"
+        if xml_file is not None:
+            cmd += " --file %s"%xml_file
+        if pltname is not None:
+            cmd += " --platform %s"%pltname
         if target_dir is not None:
             cmd += " --target %s"%target_dir
         if tmp_dir is not None:
             cmd += " --tmp %s"%tmp_dir
         if is_force_src:
             cmd += " --all-from-sources"
+        if is_single_dir:
+            cmd += " --single-directory"
         cmd += "&"
         sys.exit(os.system(cmd))
 
     #-----  TUI ---------------------
+    #
+    # define xml file to be used
+    #
+    # get current Linux platform
+    plt_name, plt_ver, plt_arch = get_os_release()
+    data = []
+    for i in plt_name, plt_ver, plt_arch:
+        if i: data.append(i)
+    full_plt_name = " ".join(data)
+    # get all supported platforms
+    all_platforms = get_supported_platforms(xml_file)
+    if all_platforms:
+        if pltname:
+            # platform name is specified in the command line
+            if pltname in all_platforms:
+                # if specified platform is supported, choose the corresponding XML file for use
+                xml_file = all_platforms[pltname]
+            else:
+                # if specified platform is NOT supported, print warning message
+                # and prompt user to choose another platform
+                msg = "Specified platform is not supported: %s" % (pltname)
+                warning(msg)
+                pltname, xml_file = select_platform(all_platforms)
+                pass
+            pass
+        elif full_plt_name in all_platforms:
+            # if current platform is supported, choose the corresponding XML file for use
+            pltname  = full_plt_name
+            xml_file = all_platforms[pltname]
+        else:
+            if xml_file and len(all_platforms) == 1:
+                # XML file is specified and contains only one platform definition
+                xml_file = all_platforms.values()[0]
+                pltname  = all_platforms.keys()[0]
+            else:
+                # current Linux platform is not supported, print warning message
+                # and prompt user to choose platform from the list
+                warning("Not supported Linux platform: %s."%" ".join(data))
+                pltname, xml_file = select_platform(all_platforms)
+            pass
+        pass
+    else:
+        # current Linux platform is not supported, exit
+        if pltname:
+            msg = "Not supported Linux platform: %s."%pltname
+        else:
+            msg = "Not supported Linux platform: %s."%" ".join(data)
+        error_exit(msg, False)
+        pass
 
     # parse XML file -----------
     message("Parsing XML configuration file: %s"%xml_file)
-    filehandle = open(xml_file)
-    data = filehandle.read()
-    filehandle.close()
-    parser = ConfigParser(is_force_src)
-    parser.feed(data)
-    parser.close()
-
-    # actions map
-    what_to_do = { __TAG__SOURCES__    : "install_source",
-                   __TAG__BINARIES__   : "install_binary",
-                   __TAG__NATIVE__     : "try_native",
-                   __TAG__PREINSTALL__ : "try_preinstalled",
-                   __TAG__BUILDSRC__   : "install_source_and_build"}
+    parser = ConfigParser(is_force_src, pltname)
+    parser.parse(xml_file)
+
     # source directory map
     bin_dir = ""
-    if parser.config.os:
-        bin_dir += "/%s"%parser.config.os
-    subdir = { __TAG__SOURCES__    : "SOURCES",
-               __TAG__BINARIES__   : "BINARIES" + bin_dir,
-               __TAG__NATIVE__     : "",
-               __TAG__PREINSTALL__ : ""}
+    if parser.config.platforms:
+        bin_dir += "/%s"%"_".join( parser.pltname.split() )
+    subdir = { __BINARIES__   : "BINARIES" + bin_dir,
+               __BUILDSRC__   : "SOURCES",
+               __PREINSTALL__ : ""}
 
     # check scripts directory -----------
     scripts_dir = "%s/%s"%(cur_dir, "config_files")
@@ -1046,14 +1277,14 @@ if __name__ == "__main__":
         check_dir(source_dir)
 
     if has_src:
-        check_dir("%s/%s"%(source_dir,subdir[__TAG__SOURCES__]))
+        check_dir("%s/%s"%(source_dir,subdir[__BUILDSRC__]))
 
     if has_bin:
-        check_dir("%s/%s"%(source_dir,subdir[__TAG__BINARIES__]))
+        check_dir("%s/%s"%(source_dir,subdir[__BINARIES__]))
 
     # check/create target dir -----------
     if target_dir is None:
-        target_dir = parser.path.targetdir
+        target_dir = parser.config.targetdir
     target_dir = substituteVars(target_dir)
 
     message("Creating target directory: " + target_dir)
@@ -1067,7 +1298,7 @@ if __name__ == "__main__":
 
     # check/create temporary dir -----------
     if tmp_dir is None:
-        tmp_dir = parser.path.tmpdir
+        tmp_dir = parser.config.tmpdir
     if not tmp_dir:
         tmp_dir = "/tmp"
     tmp_dir = substituteVars(tmp_dir)
@@ -1091,37 +1322,82 @@ if __name__ == "__main__":
 
     # get dependencies list -----------
     list_of_dep = get_dependencies(parser.products)
+    products_string = " ".join(parser.full_prods_list)
+
+    # don't remove sources and tmp files, by default -----------
+    rm_src_tmp = "FALSE"
 
     # starting -----------
     message("Starting ...")
     
     # install products -----------
     for product in parser.products:
+        # remove only prerequisites temporary files
+        if product.type == __CTX__PREREQUISITE__ or \
+           (product.type == __CTX__COMPONENT__ and product.whattodo == __BUILDSRC__):
+            rm_src_tmp = "TRUE"
         message("... processing %s ..."%product.name)
-        cmd = '%s/%s %s %s %s/%s %s "%s" %s'%(scripts_dir,
-                                              product.script,
-                                              what_to_do[product.whattodo],
-                                              tmp_dir,
-                                              source_dir,
-                                              subdir[product.install],
-                                              target_dir,
-                                              list_of_dep,
-                                              product.name)
+        cmd = '%s/%s %s %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % (
+            scripts_dir, product.script,
+            product.whattodo,
+            tmp_dir,
+            source_dir, subdir[product.whattodo],
+            target_dir,
+            products_string,
+            product.name,
+            products_string,
+            source_dir, subdir[__BUILDSRC__],
+            rm_src_tmp,
+            source_dir, subdir[__BINARIES__]
+            )
+        # install all modules with GUI
+        if product.woguiinst is not None and product.woguiinst != "":
+           cmd += ' TRUE'
+        # use single directory or not
+        if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir:
+            cmd += ' TRUE'
         res = os.system(cmd)
+        rm_src_tmp = "FALSE"
+        pass
 
     # pickup environment -----------
     message("Creating environment files")
     for product in parser.products :
         if check_bool(product.pickupEnv):
-            cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s'%(scripts_dir,
-                                                          product.script,
-                                                          tmp_dir,
-                                                          source_dir,
-                                                          subdir[product.install],
-                                                          target_dir,
-                                                          list_of_dep,
-                                                          product.name)
+            cmd = '%s/%s pickup_env %s %s/%s %s "%s" %s "%s" %s/%s %s %s/%s' % (
+                scripts_dir, product.script,
+                tmp_dir,
+                source_dir, subdir[product.whattodo],
+                target_dir,
+                products_string,
+                product.name,
+                products_string,
+                source_dir, subdir[__BUILDSRC__],
+                rm_src_tmp,
+                source_dir, subdir[__BINARIES__]
+                )
+            # install all modules with GUI
+            if product.woguiinst is not None and product.woguiinst != "":
+               cmd += ' TRUE'
+            # use single directory or not
+            if product.whattodo == __BINARIES__ and product.type == __CTX__COMPONENT__ and is_single_dir:
+                cmd += ' TRUE'
             res = os.system(cmd)
+            pass
+        pass
+
+    if not is_force_src:
+        if is_single_dir:
+            # modify *.la files, if --single-directory option was pointed -----------
+            message("Modifying of *.la files of SALOME modules...")
+            cmd = '%s/modifyLaFiles.sh modify_la_files %s' % (scripts_dir, target_dir)
+            res = os.system(cmd)
+        else:
+            # check that all required libraries are in system
+            message("Check existence of Fortran and other required libraries...")
+            cmd = '%s/checkFortran.sh find_libraries %s > %s/not_found_libs.txt' % (scripts_dir, target_dir, tmp_dir)
+            if os.system(cmd):
+                check_not_found_libs("%s/not_found_libs.txt" % (tmp_dir), parser.config.optlibs)
 
     # clean temporary directory -----------
     message("Cleaning temporary directory")