From 95e2195f941fb3b9921a3bf6c92e6109710a8e70 Mon Sep 17 00:00:00 2001 From: crouzet Date: Mon, 15 Jul 2019 17:09:59 +0200 Subject: [PATCH] sat prepare and sat install with pip, triggered by pip properties --- commands/compile.py | 130 ++++++++++++++++++++++++++++++++++++++------ commands/source.py | 16 ++++++ src/__init__.py | 21 +++++++ src/product.py | 23 ++++++++ 4 files changed, 173 insertions(+), 17 deletions(-) diff --git a/commands/compile.py b/commands/compile.py index 4c469bc..fb1fee0 100644 --- a/commands/compile.py +++ b/commands/compile.py @@ -18,6 +18,7 @@ import os import re +import subprocess import src import src.debug as DBG @@ -328,23 +329,36 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end): # build_sources : cmake -> cmake, make, make install # build_sources : script -> script executions res = 0 - if (src.product.product_is_autotools(p_info) or - src.product.product_is_cmake(p_info)): - res, len_end_line, error_step = compile_product_cmake_autotools(sat, - p_name_info, - config, - options, - logger, - header, - len_end) - if src.product.product_has_script(p_info): - res, len_end_line, error_step = compile_product_script(sat, - p_name_info, - config, - options, - logger, - header, - len_end) + + + # check if pip should be used : the application and product have pip property + if (src.appli_test_property(config,"pip", "yes") and + src.product.product_test_property(p_info,"pip", "yes")): + res, len_end_line, error_step = compile_product_pip(sat, + p_name_info, + config, + options, + logger, + header, + len_end) + else: + if (src.product.product_is_autotools(p_info) or + src.product.product_is_cmake(p_info)): + res, len_end_line, error_step = compile_product_cmake_autotools(sat, + p_name_info, + config, + options, + logger, + header, + len_end) + if src.product.product_has_script(p_info): + res, len_end_line, error_step = compile_product_script(sat, + p_name_info, + config, + options, + logger, + header, + len_end) # Check that the install directory exists if res==0 and not(os.path.exists(p_info.install_dir)): @@ -376,6 +390,88 @@ def compile_product(sat, p_name_info, config, options, logger, header, len_end): return res, len_end_line, error_step + +def compile_product_pip(sat, + p_name_info, + config, + options, + logger, + header, + len_end): + '''Execute the proper build procedure for pip products + :param p_name_info tuple: (str, Config) => (product_name, product_info) + :param config Config: The global configuration + :param logger Logger: The logger instance to use for the display + and logging + :param header Str: the header to display when logging + :param len_end Int: the lenght of the the end of line (used in display) + :return: 1 if it fails, else 0. + :rtype: int + ''' + p_name, p_info = p_name_info + + # Execute "sat configure", "sat make" and "sat install" + res = 0 + error_step = "" + pip_install_in_python=False + if src.appli_test_property(config,"pip_install_dir", "python"): + # pip will install product in python directory" + pip_install_cmd="pip3 install --disable-pip-version-check --no-index --find-links=%s --build %s %s==%s" %\ + (config.LOCAL.archive_dir, p_info.build_dir, p_name, p_info.version) + pip_install_in_python=True + + else: + # pip will install product in product install_dir + pip_install_dir=os.path.join(p_info.install_dir, "lib", "python${PYTHON_VERSION:0:3}", "site-packages") + pip_install_cmd="pip3 install --disable-pip-version-check --no-index --find-links=%s --build %s --target %s %s==%s" %\ + (config.LOCAL.archive_dir, p_info.build_dir, pip_install_dir, p_name, p_info.version) + log_step(logger, header, "PIP") + logger.write("\n"+pip_install_cmd+"\n", 4) + len_end_line = len_end + 3 + error_step = "" + build_environ = src.environment.SalomeEnviron(config, + src.environment.Environ(dict(os.environ)), + True) + environ_info = src.product.get_product_dependencies(config, + p_info) + build_environ.silent = (config.USER.output_verbose_level < 5) + build_environ.set_full_environ(logger, environ_info) + + if pip_install_in_python and (options.clean_install or options.clean_all): + # for products installed by pip inside python install dir + # finish the clean by uninstalling the product from python install dir + pip_clean_cmd="pip3 uninstall -y %s==%s" % (p_name, p_info.version) + res_pipclean = (subprocess.call(pip_clean_cmd, + shell=True, + cwd=config.LOCAL.workdir, + env=build_environ.environ.environ, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) == 0) + if not res_pipclean: + logger.write("\n",1) + logger.warning("pip3 uninstall failed!") + + res_pip = (subprocess.call(pip_install_cmd, + shell=True, + cwd=config.LOCAL.workdir, + env=build_environ.environ.environ, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) == 0) + if res_pip: + res=0 + if pip_install_in_python: + # when product is installed in python, create install_dir + # (to put inside product info and mark the installation success) + os.mkdir(p_info.install_dir) + else: + #log_res_step(logger, res) + res=1 + error_step = "PIP" + + return res, len_end_line, error_step + + + def compile_product_cmake_autotools(sat, p_name_info, config, diff --git a/commands/source.py b/commands/source.py index 823e1da..54bd9f0 100644 --- a/commands/source.py +++ b/commands/source.py @@ -19,6 +19,7 @@ import os import shutil import re +import subprocess import src import prepare @@ -153,6 +154,21 @@ def get_source_from_archive(config, product_info, source_dir, logger): :return: True if it succeed, else False :rtype: boolean ''' + + # check if pip should be used : pip mode id activated if the application and product have pip property + if (src.appli_test_property(config,"pip", "yes") and + src.product.product_test_property(product_info,"pip", "yes")): + # download whl in local archive dir + pip_download_cmd="pip download --disable-pip-version-check --destination-directory %s --no-deps %s==%s " %\ + (config.LOCAL.archive_dir, product_info.name, product_info.version) + logger.write(pip_download_cmd, 3, False) + res_pip = (subprocess.call(pip_download_cmd, + shell=True, + cwd=config.LOCAL.workdir, + stdout=logger.logTxtFile, + stderr=subprocess.STDOUT) == 0) + return res_pip + # check archive exists if not os.path.exists(product_info.archive_info.archive_name): # The archive is not found on local file system (ARCHIVEPATH) diff --git a/src/__init__.py b/src/__init__.py index 310c669..ad0997b 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -91,6 +91,27 @@ def check_config_has_profile( config, details = None ): details.append(message) raise SatException( message ) +def appli_test_property(config,property_name, property_value): + """Generic function to test if an application has a property set to a value + :param config class 'common.pyconf.Config': The config. + :param property_name : The name of the property to check + :param property_value : The value of the property to test + :return: True if the application has the property set to property_value + :rtype: boolean + """ + # first check if application has property_value + if not ("APPLICATION" in config and + "properties" in config.APPLICATION and + property_name in config.APPLICATION.properties): + return False + + # then check to the property is set to property_value + eval_expression = 'config.APPLICATION.properties.%s == "%s"' %\ + (property_name,property_value) + result = eval(eval_expression) + return result + + def config_has_application( config ): return 'APPLICATION' in config diff --git a/src/product.py b/src/product.py index 44d20e9..ce07ef7 100644 --- a/src/product.py +++ b/src/product.py @@ -1069,6 +1069,29 @@ def product_is_compile_time(product_info): "compile_time" in product_info.properties and product_info.properties.compile_time == "yes") + +def product_test_property(product_info, property_name, property_value): + """Generic function to test if a product has a property set to a value + + :param product_info Config: The configuration specific to + the product + :param property_name : The name of the property to check + :param property_value : The value of the property to test + :return: True if the product has the property and the property is set to property_value + :rtype: boolean + """ + # first check if product has the property + if not ("properties" in product_info and + property_name in product_info.properties): + return False + + # then check to the property is set to property_value + eval_expression = 'product_info.properties.%s == "%s"' % (property_name,property_value) + result = eval(eval_expression) + return result + + + def get_product_components(product_info): """Get the component list to generate with the product -- 2.39.2