# @ build_bios.py # Builds BIOS using configuration files and dynamically # imported functions from board directory # # Copyright (c) 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # """ This module builds BIOS using configuration files and dynamically imported functions from board directory """ import os import re import sys import signal import shutil import argparse import traceback import subprocess from importlib import import_module try: # python 2.7 import ConfigParser as configparser except ImportError: # python 3 import configparser def pre_build(build_config, build_type="DEBUG", silent=False, toolchain=None): """Sets the environment variables that shall be used for the build :param build_config: The build configuration as defined in the JOSN configuration files :type build_config: Dictionary :param build_type: The build target, DEBUG, RELEASE, RELEASE_PDB, TEST_RELEASE :type build_type: String :param silent: Enables build in silent mode :type silent: Boolean :param toolchain: Specifies the tool chain tag to use for the build :type toolchain: String :returns: The updated environment variables :rtype: Dictionary """ # get current environment variables config = os.environ.copy() # patch the build config build_config = patch_config(build_config) # update the current config with the build config config.update(build_config) # make the config and build python 2.7 compartible config = py_27_fix(config) # Set WORKSPACE environment. config["WORKSPACE"] = os.path.abspath(os.path.join("..", "..", "..", "")) print("Set WORKSPACE as: {}".format(config["WORKSPACE"])) # Check whether Git has been installed and been added to system path. try: subprocess.Popen(["git", "--help"], stdout=subprocess.PIPE) except OSError: print("The 'git' command is not recognized.") print("Please make sure that Git is installed\ and has been added to system path.") sys.exit(1) # Create the Conf directory under WORKSPACE if not os.path.isdir(os.path.join(config["WORKSPACE"], "Conf")): try: # create directory os.makedirs(os.path.join(config["WORKSPACE"], "Conf")) # copy files to it config_template_path = os.path.join(config["WORKSPACE"], config["BASE_TOOLS_PATH"], "Conf") config_path = os.path.join(config["WORKSPACE"], "Conf") shutil.copyfile(config_template_path + os.sep + "target.template", config_path + os.sep + "target.txt") shutil.copyfile(config_template_path + os.sep + "tools_def.template", config_path + os.sep + "tools_def.txt") shutil.copyfile(config_template_path + os.sep + "build_rule.template", config_path + os.sep + "build_rule.txt") except OSError: print("Error while creating Conf") sys.exit(1) # Set other environments. # Basic Rule: # Platform override Silicon override Core # Source override Binary config["WORKSPACE_PLATFORM"] = os.path.join(config["WORKSPACE"], config["WORKSPACE_PLATFORM"]) config["WORKSPACE_SILICON"] = os.path.join(config["WORKSPACE"], config["WORKSPACE_SILICON"]) config["WORKSPACE_PLATFORM_BIN"] = \ os.path.join(config["WORKSPACE"], config["WORKSPACE_PLATFORM_BIN"]) config["WORKSPACE_SILICON_BIN"] = \ os.path.join(config["WORKSPACE"], config["WORKSPACE_SILICON_BIN"]) config["WORKSPACE_FSP_BIN"] = os.path.join(config["WORKSPACE"], config["WORKSPACE_FSP_BIN"]) # add to package path config["PACKAGES_PATH"] = config["WORKSPACE_PLATFORM"] config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_SILICON"] config["PACKAGES_PATH"] += os.pathsep + config["WORKSPACE_SILICON_BIN"] config["PACKAGES_PATH"] += os.pathsep + \ os.path.join(config["WORKSPACE"], "FSP") config["PACKAGES_PATH"] += os.pathsep + \ os.path.join(config["WORKSPACE"], "edk2") config["PACKAGES_PATH"] += os.pathsep + os.path.join(config["WORKSPACE"]) config["EDK_TOOLS_PATH"] = os.path.join(config["WORKSPACE"], config["EDK_TOOLS_PATH"]) config["BASE_TOOLS_PATH"] = config["EDK_TOOLS_PATH"] config["EDK_TOOLS_BIN"] = os.path.join(config["WORKSPACE"], config["EDK_TOOLS_BIN"]) config["PLATFORM_FSP_BIN_PACKAGE"] = \ os.path.join(config['WORKSPACE_FSP_BIN'], config['FSP_BIN_PKG']) config['PROJECT_DSC'] = os.path.join(config["WORKSPACE_PLATFORM"], config['PROJECT_DSC']) config['BOARD_PKG_PCD_DSC'] = os.path.join(config["WORKSPACE_PLATFORM"], config['BOARD_PKG_PCD_DSC']) config["CONF_PATH"] = os.path.join(config["WORKSPACE"], "Conf") # get the python path if os.environ.get("PYTHON_HOME") is None: config["PYTHON_HOME"] = None if os.environ.get("PYTHONPATH") is not None: config["PYTHON_HOME"] = os.environ.get("PYTHONPATH") else: print("PYTHONPATH environment variable is not found") sys.exit(1) # if python is installed, disable the binary base tools. # python is installed if this code is running :) if config.get("PYTHON_HOME") is not None: if config.get("EDK_TOOLS_BIN") is not None: del config["EDK_TOOLS_BIN"] # Run edk setup and update config if os.name == 'nt': edk2_setup_cmd = [os.path.join(config["EFI_SOURCE"], "edksetup"), "Rebuild"] if config.get("EDK_SETUP_OPTION") and \ config["EDK_SETUP_OPTION"] != " ": edk2_setup_cmd.append(config["EDK_SETUP_OPTION"]) _, _, result, return_code = execute_script(edk2_setup_cmd, config, collect_env=True, shell=True) if return_code == 0 and result is not None and isinstance(result, dict): config.update(result) # nmake BaseTools source # and enable BaseTools source build shell = True command = ["nmake", "-f", os.path.join(config["BASE_TOOLS_PATH"], "Makefile")] if os.name == "posix": # linux shell = False command = ["make", "-C", os.path.join(config["BASE_TOOLS_PATH"])] _, _, result, return_code = execute_script(command, config, shell=shell) if return_code != 0: build_failed(config) config["SILENT_MODE"] = 'TRUE' if silent else 'FALSE' print("==============================================") if os.path.isfile(os.path.join(config['WORKSPACE'], "Prep.log")): os.remove(os.path.join(config['WORKSPACE'], "Prep.log")) config["PROJECT"] = os.path.join(config["PLATFORM_BOARD_PACKAGE"], config["BOARD"]) # Setup Build # @todo: Need better TOOL_CHAIN_TAG detection if toolchain is not None: config["TOOL_CHAIN_TAG"] = toolchain elif config.get("TOOL_CHAIN_TAG") is None: if os.name == 'nt': config["TOOL_CHAIN_TAG"] = "VS2015" else: config["TOOL_CHAIN_TAG"] = "GCC5" # echo Show CL revision config["PrepRELEASE"] = build_type if build_type == "DEBUG": config["TARGET"] = 'DEBUG' config["TARGET_SHORT"] = 'D' else: config["TARGET"] = 'RELEASE' config["TARGET_SHORT"] = 'R' # set BUILD_DIR_PATH path config["BUILD_DIR_PATH"] = os.path.join(config["WORKSPACE"], 'Build', config["PROJECT"], "{}_{}".format( config["TARGET"], config["TOOL_CHAIN_TAG"])) # set BUILD_DIR path config["BUILD_DIR"] = os.path.join('Build', config["PROJECT"], "{}_{}".format( config["TARGET"], config["TOOL_CHAIN_TAG"])) config["BUILD_X64"] = os.path.join(config["BUILD_DIR_PATH"], 'X64') config["BUILD_IA32"] = os.path.join(config["BUILD_DIR_PATH"], 'IA32') if not os.path.isdir(config["BUILD_DIR_PATH"]): try: os.makedirs(config["BUILD_DIR_PATH"]) except OSError: print("Error while creating Build folder") sys.exit(1) # Set FSP_WRAPPER_BUILD if config['FSP_WRAPPER_BUILD'] == "TRUE": # Create dummy Fsp_Rebased_S_padded.fd to build the BiosInfo.inf # if it is wrapper build, due to the SECTION inclusion open(os.path.join(config["WORKSPACE_FSP_BIN"], config["FSP_BIN_PKG"], "Fsp_Rebased_S_padded.fd"), 'w').close() if not os.path.isdir(config["BUILD_X64"]): try: os.mkdir(config["BUILD_X64"]) except OSError: print("Error while creating {}".format(config["BUILD_X64"])) sys.exit(1) # update config file with changes update_target_file(config) # Additional pre build scripts for this platform result = pre_build_ex(config) if result is not None and isinstance(result, dict): config.update(result) # print user settings print("BIOS_SIZE_OPTION = {}".format(config["BIOS_SIZE_OPTION"])) print("EFI_SOURCE = {}".format(config["EFI_SOURCE"])) print("TARGET = {}".format(config["TARGET"])) print("TARGET_ARCH = {}".format("IA32 X64")) print("TOOL_CHAIN_TAG = {}".format(config["TOOL_CHAIN_TAG"])) print("WORKSPACE = {}".format(config["WORKSPACE"])) print("WORKSPACE_CORE = {}".format(config["WORKSPACE_CORE"])) print("EXT_BUILD_FLAGS = {}".format(config["EXT_BUILD_FLAGS"])) return config def build(config): """Builds the BIOS image :param config: The environment variables to be used in the build process :type config: Dictionary :returns: nothing """ if config["FSP_WRAPPER_BUILD"] == "TRUE": pattern = "Fsp_Rebased.*\\.fd$" file_dir = os.path.join(config['WORKSPACE_FSP_BIN'], config['FSP_BIN_PKG']) for item in os.listdir(file_dir): if re.search(pattern, item): os.remove(os.path.join(file_dir, item)) command = [os.path.join(config['PYTHON_HOME'], "python"), os.path.join(config['WORKSPACE_PLATFORM'], config['PLATFORM_PACKAGE'], 'Tools', 'Fsp', 'RebaseAndPatchFspBinBaseAddress.py'), os.path.join(config['WORKSPACE_PLATFORM'], config['FLASH_MAP_FDF']), os.path.join(config['WORKSPACE_FSP_BIN'], config['FSP_BIN_PKG']), "Fsp.fd", os.path.join(config['WORKSPACE_PLATFORM'], config['PROJECT'], config['BOARD_PKG_PCD_DSC']), "0x0"] _, _, _, return_code = execute_script(command, config, shell=False) if return_code != 0: print("ERROR:RebaseAndPatchFspBinBaseAddress failed") sys.exit(return_code) # create Fsp_Rebased.fd which is Fsp_Rebased_S.fd + # Fsp_Rebased_M + Fsp_Rebased_T with open(os.path.join(file_dir, "Fsp_Rebased_S.fd"), 'rb') as fsp_s, \ open(os.path.join(file_dir, "Fsp_Rebased_M.fd"), 'rb') as fsp_m, \ open(os.path.join(file_dir, "Fsp_Rebased_T.fd"), 'rb') as fsp_t: fsp_rebased = fsp_s.read() + fsp_m.read() + fsp_t.read() with open(os.path.join(file_dir, "Fsp_Rebased.fd"), 'wb') as new_fsp: new_fsp.write(fsp_rebased) if not os.path.isfile(os.path.join(file_dir, "Fsp_Rebased.fd")): print("!!! ERROR:failed to create fsp!!!") sys.exit(1) # Output the build variables the user has selected. print("==========================================") print(" User Selected build options:") print(" SILENT_MODE = ", config.get("SILENT_MODE")) print(" REBUILD_MODE = ", config.get("REBUILD_MODE")) print(" BUILD_ROM_ONLY = ", config.get("BUILD_ROM_ONLY")) print("==========================================") command = ["build", "-n", config["NUMBER_OF_PROCESSORS"]] if config["REBUILD_MODE"] and config["REBUILD_MODE"] != "": command.append(config["REBUILD_MODE"]) if config["EXT_BUILD_FLAGS"] and config["EXT_BUILD_FLAGS"] != "": command.append(config["EXT_BUILD_FLAGS"]) if config.get("SILENT_MODE", "FALSE") == "TRUE": command.append("--silent") command.append("--quiet") else: command.append("--log=" + config.get("BUILD_LOG", "Build.log")) command.append("--report-file=" + config.get("BUILD_REPORT", "BuildReport.log")) if config.get("VERBOSE", "FALSE") == "TRUE": command.append("--verbose") if config.get("MAX_SOCKET") is not None: command.append("-D") command.append("MAX_SOCKET=" + config["MAX_SOCKET"]) _, _, _, exit_code = execute_script(command, config) if exit_code != 0: build_failed(config) # Additional build scripts for this platform result = build_ex(config) if result is not None and isinstance(result, dict): config.update(result) return config def post_build(config): """Post build process of BIOS image :param config: The environment variables to be used in the build process :type config: Dictionary :returns: nothing """ print("Running post_build to complete the build process.") # Additional build scripts for this platform result = post_build_ex(config) if result is not None and isinstance(result, dict): config.update(result) # cleanup pattern = "Fsp_Rebased.*\\.fd$" file_dir = os.path.join(config['WORKSPACE_FSP_BIN'], config['FSP_BIN_PKG']) for item in os.listdir(file_dir): if re.search(pattern, item): os.remove(os.path.join(file_dir, item)) if config.get("DYNAMIC_BUILD_INIT_FILES") is not None: for item in config["DYNAMIC_BUILD_INIT_FILES"].split(","): try: os.remove(item) # remove __init__.py os.remove(item + "c") # remove __init__.pyc as well except OSError: pass def build_failed(config): """Displays results when build fails :param config: The environment variables used in the build process :type config: Dictionary :returns: nothing """ print(" The EDKII BIOS Build has failed!") # clean up if config.get("DYNAMIC_BUILD_INIT_FILES") is not None: for item in config["DYNAMIC_BUILD_INIT_FILES"].split(","): if os.path.isfile(item): try: os.remove(item) # remove __init__.py os.remove(item + "c") # remove __init__.pyc as well except OSError: pass sys.exit(1) def import_platform_lib(path, function): """Imports custom functions for the platforms being built :param path: the location of the custom build script to be executed :type path: String :param path: the function to be executed :type path: String :returns: nothing """ if path.endswith(".py"): path = path[:-3] path = path.replace(os.sep, ".") module = import_module(path) lib = getattr(module, function) return lib def pre_build_ex(config): """ An extension of the pre_build process as defined platform specific pre_build setup script :param config: The environment variables used in the pre build process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ if config.get("ADDITIONAL_SCRIPTS"): try: platform_function =\ import_platform_lib(config["ADDITIONAL_SCRIPTS"], "pre_build_ex") functions = {"execute_script": execute_script} return platform_function(config, functions) except ImportError as error: print(config["ADDITIONAL_SCRIPTS"], str(error)) build_failed(config) return None def build_ex(config): """ An extension of the build process as defined platform specific build setup script :param config: The environment variables used in the build process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ if config.get("ADDITIONAL_SCRIPTS"): try: platform_function =\ import_platform_lib(config["ADDITIONAL_SCRIPTS"], "build_ex") functions = {"execute_script": execute_script} return platform_function(config, functions) except ImportError as error: print("error", config["ADDITIONAL_SCRIPTS"], str(error)) build_failed(config) return None def post_build_ex(config): """ An extension of the post build process as defined platform specific build setup script :param config: The environment variables used in the post build process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ if config.get("ADDITIONAL_SCRIPTS"): try: platform_function =\ import_platform_lib(config["ADDITIONAL_SCRIPTS"], "post_build_ex") functions = {"execute_script": execute_script} return platform_function(config, functions) except ImportError as error: print(config["ADDITIONAL_SCRIPTS"], str(error)) build_failed(config) return None def clean_ex(config): """ An extension of the platform cleanning :param config: The environment variables used in the clean process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ if config.get("ADDITIONAL_SCRIPTS"): try: platform_function =\ import_platform_lib(config["ADDITIONAL_SCRIPTS"], "clean_ex") functions = {"execute_script": execute_script} return platform_function(config, functions) except ImportError as error: print(config["ADDITIONAL_SCRIPTS"], str(error)) build_failed(config) return None def get_environment_variables(std_out_str, marker): """Gets the environment variables from a process :param std_out_str: The std_out pipe :type std_out_str: String :param marker: A begining and end mark of environment variables printed to std_out :type marker: String :returns: The environment variables read from the process' std_out pipe :rtype: Tuple """ start_env_update = False environment_vars = {} out_put = "" for line in std_out_str.split("\n"): if start_env_update and len(line.split("=")) == 2: key, value = line.split("=") environment_vars[key] = value else: out_put += "\n" + line.replace(marker, "") if marker in line: if start_env_update: start_env_update = False else: start_env_update = True return (out_put, environment_vars) def execute_script(command, env_variables, collect_env=False, enable_std_pipe=False, shell=True): """launches a process that executes a script/shell command passed to it :param command: The command/script with its commandline arguments to be executed :type command: List:String :param env_variables: Environment variables passed to the process :type env_variables: String :param collect_env: Enables the collection of evironment variables when process execution is done :type collect_env: Boolean :param enable_std_pipe: Enables process out to be piped to :type enable_std_pipe: String :returns: a tuple of std_out, stderr , environment variables, return code :rtype: Tuple: (std_out, stderr , enVar, return_code) """ print("Calling " + " ".join(command)) env_marker = '-----env-----' env = {} kwarg = {"env": env_variables, "universal_newlines": True, "shell": shell, "cwd": env_variables["WORKSPACE"]} if enable_std_pipe or collect_env: kwarg["stdout"] = subprocess.PIPE kwarg["stderr"] = subprocess.PIPE # collect environment variables if collect_env: # get the binary that prints environment variables based on os if os.name == 'nt': get_var_command = "set" else: get_var_command = "env" # modify the command to print the environment variables if isinstance(command, list): command += ["&&", "echo", env_marker, "&&", get_var_command, "&&", "echo", env_marker] else: command += " " + " ".join(["&&", "echo", env_marker, "&&", get_var_command, "&&", "echo", env_marker]) # execute the command execute = subprocess.Popen(command, **kwarg) std_out, stderr = execute.communicate() code = execute.returncode # wait for process to be done execute.wait() # if collect enviroment variables if collect_env: # get the new environment variables std_out, env = get_environment_variables(std_out, env_marker) return (std_out, stderr, env, code) def patch_config(config): """ An extension of the platform cleanning :param config: The environment variables used in the build process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ new_config = {} for key in config: new_config[str(key)] = str(config[key].replace("/", os.sep)) return new_config def py_27_fix(config): """ Prepares build for python 2.7 => build :param config: The environment variables used in the build process :type config: Dictionary :returns: config dictionary :rtype: Dictionary """ if not sys.version_info > (3, 0): path_list = [] # create __init__.py in directories in this path if config.get("ADDITIONAL_SCRIPTS"): # get the directory path_to_directory =\ os.path.dirname(config.get("ADDITIONAL_SCRIPTS")) path = "" for directories in path_to_directory.split(os.sep): path += directories + os.sep init_file = path + os.sep + "__init__.py" if not os.path.isfile(init_file): open(init_file, 'w').close() path_list.append(init_file) config["DYNAMIC_BUILD_INIT_FILES"] = ",".join(path_list) return config def clean(build_config, board=False): """Cleans the build workspace :param config: The environment variables used in the build process :type config: Dictionary :param board: This flag specifies specific board clean :type board: Bool :returns: nothing """ # patch the config build_config = patch_config(build_config) # get current environment variables config = os.environ.copy() # update it with the build variables config.update(build_config) if config.get('WORKSPACE') is None or not config.get('WORKSPACE'): config["WORKSPACE"] =\ os.path.abspath(os.path.join("..", "..", "..", "")) # build cleanall print("Cleaning directories...") if board: platform_pkg = config.get("PLATFORM_BOARD_PACKAGE", None) if platform_pkg is None or\ not os.path.isdir(os.path.join(config['WORKSPACE'], "Build", platform_pkg)): print("Platform package not found") sys.exit(1) else: print("Removing " + os.path.join(config['WORKSPACE'], "Build", platform_pkg)) shutil.rmtree(os.path.join(config['WORKSPACE'], "Build", platform_pkg)) else: if os.path.isdir(os.path.join(config['WORKSPACE'], "Build")): print("Removing " + os.path.join(config['WORKSPACE'], "Build")) shutil.rmtree(os.path.join(config['WORKSPACE'], "Build")) if os.path.isdir(os.path.join(config['WORKSPACE'], "Conf")): print("Removing " + os.path.join(config['WORKSPACE'], "Conf")) shutil.rmtree(os.path.join(config['WORKSPACE'], "Conf")) print("Cleaning files...") if os.path.isfile(os.path.join(config['WORKSPACE'], config.get("BUILD_REPORT", "BuildReport.log"))): print("Removing ", os.path.join(config['WORKSPACE'], config.get("BUILD_REPORT", "BuildReport.log"))) os.remove(os.path.join(config['WORKSPACE'], config.get("BUILD_REPORT", "BuildReport.log"))) print(" All done...") sys.exit(0) def update_target_file(config): """Updates Conf's target file that will be used in the build :param config: The environment variables used in the build process :type config: Dictionary :returns: True if update was successful and False if update fails :rtype: Boolean """ contents = None result = False with open(os.path.join(config["CONF_PATH"], "target.txt"), 'r') as target: contents = target.readlines() options_list = ['ACTIVE_PLATFORM', 'TARGET', 'TARGET_ARCH', 'TOOL_CHAIN_TAG', 'BUILD_RULE_CONF'] modified = [] # remove these options from the config file for line in contents: if line.replace(" ", "")[0] != '#' and\ any(opt in line for opt in options_list): continue modified.append(line) # replace with config options provided string = "{} = {}\n".format("ACTIVE_PLATFORM", os.path.join( config['WORKSPACE_PLATFORM'], config['PLATFORM_BOARD_PACKAGE'], config['BOARD'], config['PROJECT_DSC'])) modified.append(string) string = "{} = {}\n".format("TARGET", config['TARGET']) modified.append(string) string = "TARGET_ARCH = IA32 X64\n" modified.append(string) string = "{} = {}\n".format("TOOL_CHAIN_TAG", config['TOOL_CHAIN_TAG']) modified.append(string) string = "{} = {}\n".format("BUILD_RULE_CONF", os.path.join("Conf", "build_rule.txt")) modified.append(string) if modified is not None: with open(os.path.join(config["WORKSPACE"], "Conf", "target.txt"), 'w') as target: for line in modified: target.write(line) result = True return result def get_config(): """Reads the default projects config file :returns: The config defined in the the Build.cfg file :rtype: Dictionary """ config_file = configparser.RawConfigParser() config_file.optionxform = str config_file.read('build.cfg') config_dictionary = {} for section in config_file.sections(): dictionary = dict(config_file.items(section)) config_dictionary[section] = dictionary return config_dictionary def get_platform_config(platform_name, config_data): """ Reads the platform specifig config file param platform_name: The name of the platform to be built :type platform_name: String param configData: The environment variables to be used in the build process :type configData: Dictionary :returns: The config defined in the the Build.cfg file :rtype: Dictionary """ config = {} platform_data = config_data.get("PLATFORMS") path = platform_data.get(platform_name) config_file = configparser.RawConfigParser() config_file.optionxform = str config_file.read(path) for section in config_file.sections(): config[section] = dict(config_file.items(section)) return config def get_cmd_config_arguments(arguments): """Get commandline config arguments param arguments: The environment variables to be used in the build process :type arguments: argparse :returns: The config dictionary built from the commandline arguments :rtype: Dictionary """ result = {} if arguments.capsule is True: result["CAPSULE_BUILD"] = "1" if arguments.performance is True: result["PERFORMANCE_BUILD"] = "TRUE" if arguments.fsp is True: result["FSP_WRAPPER_BUILD"] = "TRUE" return result def get_cmd_arguments(build_config): """ Get commandline inputs from user param config_data: The environment variables to be used in the build process :type config_data: Dictionary :returns: The commandline arguments input by the user :rtype: argparse object """ class PrintPlatforms(argparse.Action): """ this is an argparse action that lists the available platforms """ def __call__(self, parser, namespace, values, option_string=None): print("Platforms:") for key in build_config.get("PLATFORMS"): print(" " + key) setattr(namespace, self.dest, values) sys.exit(0) # get the build commands parser = argparse.ArgumentParser(description="Build Help") parser.add_argument('--platform', '-p', dest="platform", help='the platform to build', choices=build_config.get("PLATFORMS"), required=('-l' not in sys.argv and '--cleanall' not in sys.argv)) parser.add_argument('--toolchain', '-t', dest="toolchain", help="using the Tool Chain Tagname to build \ the platform,overriding \ target.txt's TOOL_CHAIN_TAG definition") parser.add_argument("--DEBUG", '-d', help="debug flag", action='store_const', dest="target", const="DEBUG", default="DEBUG") parser.add_argument("--RELEASE", '-r', help="release flag", action='store_const', dest="target", const="RELEASE") parser.add_argument("--TEST_RELEASE", '-tr', help="test Release flag", action='store_const', dest="target", const="TEST_RELEASE") parser.add_argument("--RELEASE_PDB", '-rp', help="release flag", action='store_const', dest="target", const="RELEASE_PDB") parser.add_argument('--list', '-l', action=PrintPlatforms, help='lists available platforms', nargs=0) parser.add_argument('--cleanall', dest='clean_all', help='cleans all', action='store_true') parser.add_argument('--clean', dest='clean', help='cleans specific platform', action='store_true') parser.add_argument("--capsule", help="capsule build enabled", action='store_true', dest="capsule") parser.add_argument("--silent", help="silent build enabled", action='store_true', dest="silent") parser.add_argument("--performance", help="performance build enabled", action='store_true', dest="performance") parser.add_argument("--fsp", help="fsp build enabled", action='store_true', dest="fsp") return parser.parse_args() def keyboard_interruption(int_signal, int_frame): """ Catches a keyboard interruption handler param int_signal: The signal this handler is called with :type int_signal: Signal param int_frame: The signal this handler is called with :type int_frame: frame :rtype: nothing """ print("Signal #: {} Frame: {}".format(int_signal, int_frame)) print("Quiting...") sys.exit(0) def main(): """ The main function of this module :rtype: nothing """ # to quit the build signal.signal(signal.SIGINT, keyboard_interruption) # get general build configurations build_config = get_config() # get commandline parameters arguments = get_cmd_arguments(build_config) if arguments.clean_all: clean(build_config.get("DEFAULT_CONFIG")) # get platform specific config platform_config = get_platform_config(arguments.platform, build_config) # update general build config with platform specific config config = build_config.get("DEFAULT_CONFIG") config.update(platform_config.get("CONFIG")) # if user selected clean if arguments.clean: clean(config, board=True) # Override config with cmd arguments cmd_config_args = get_cmd_config_arguments(arguments) config.update(cmd_config_args) # get pre_build configurations config = pre_build(config, build_type=arguments.target, toolchain=arguments.toolchain, silent=arguments.silent) # build selected platform config = build(config) # post build post_build(config) if __name__ == "__main__": try: EXIT_CODE = 0 main() except Exception as error: EXIT_CODE = 1 traceback.print_exc() sys.exit(EXIT_CODE)