diff --git a/tools/build_api.py b/tools/build_api.py index 0be79824969..9ef249f9637 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -217,8 +217,8 @@ def build_project(src_path, build_path, target, toolchain_name, # Load resources into the config system which might expand/modify resources based on config data resources = config.load_resources(resources) - # Set the toolchain's config header with the config data - toolchain.set_config_header_content(config.get_config_data_header()) + # Set the toolchain's configuration data + toolchain.set_config_data(config.get_config_data()) # Compile Sources objects = toolchain.compile_sources(resources, build_path, resources.inc_dirs) @@ -361,8 +361,8 @@ def build_library(src_paths, build_path, target, toolchain_name, # Load resources into the config system which might expand/modify resources based on config data resources = config.load_resources(resources) - # Set the toolchain's config header with the config data - toolchain.set_config_header_content(config.get_config_data_header()) + # Set the toolchain's configuration data + toolchain.set_config_data(config.get_config_data()) # Copy headers, objects and static libraries - all files needed for static lib toolchain.copy_files(resources.headers, build_path, resources=resources) diff --git a/tools/config.py b/tools/config.py index 80cfad70ea9..ddab6df3abc 100644 --- a/tools/config.py +++ b/tools/config.py @@ -354,7 +354,8 @@ def get_config_data(self): return all_params, macros # Helper: verify if there are any required parameters without a value in 'params' - def _check_required_parameters(self, params): + @staticmethod + def _check_required_parameters(params): for p in params.values(): if p.required and (p.value is None): raise ConfigException("Required parameter '%s' defined by '%s' doesn't have a value" % (p.name, p.defined_by)) @@ -371,11 +372,18 @@ def parameters_to_macros(params): def config_macros_to_macros(macros): return [m.name for m in macros.values()] + # Return the configuration data converted to a list of C macros + # config - configuration data as (ConfigParam instances, ConfigMacro instances) tuple + # (as returned by get_config_data()) + @staticmethod + def config_to_macros(config): + params, macros = config[0], config[1] + Config._check_required_parameters(params) + return Config.config_macros_to_macros(macros) + Config.parameters_to_macros(params) + # Return the configuration data converted to a list of C macros def get_config_data_macros(self): - params, macros = self.get_config_data() - self._check_required_parameters(params) - return self.config_macros_to_macros(macros) + self.parameters_to_macros(params) + return self.config_to_macros(self.get_config_data()) # Returns any features in the configuration data def get_features(self): @@ -419,14 +427,16 @@ def load_resources(self, resources): return resources - # Return the configuration data converted to the content of a C header file, # meant to be included to a C/C++ file. The content is returned as a string. # If 'fname' is given, the content is also written to the file called "fname". # WARNING: if 'fname' names an existing file, that file will be overwritten! - def get_config_data_header(self, fname = None): - params, macros = self.get_config_data() - self._check_required_parameters(params) + # config - configuration data as (ConfigParam instances, ConfigMacro instances) tuple + # (as returned by get_config_data()) + @staticmethod + def config_to_header(config, fname = None): + params, macros = config[0], config[1] + Config._check_required_parameters(params) header_data = "// Automatically generated configuration file.\n" header_data += "// DO NOT EDIT, content will be overwritten.\n\n" header_data += "#ifndef __MBED_CONFIG_DATA__\n" @@ -459,3 +469,10 @@ def get_config_data_header(self, fname = None): with open(fname, "wt") as f: f.write(header_data) return header_data + + # Return the configuration data converted to the content of a C header file, + # meant to be included to a C/C++ file. The content is returned as a string. + # If 'fname' is given, the content is also written to the file called "fname". + # WARNING: if 'fname' names an existing file, that file will be overwritten! + def get_config_data_header(self, fname = None): + return self.config_to_header(self.get_config_data(), fname) diff --git a/tools/toolchains/__init__.py b/tools/toolchains/__init__.py index dd0f92a3870..7587a36efd9 100644 --- a/tools/toolchains/__init__.py +++ b/tools/toolchains/__init__.py @@ -25,6 +25,7 @@ from os.path import join, splitext, exists, relpath, dirname, basename, split, abspath from inspect import getmro from copy import deepcopy +from tools.config import Config from multiprocessing import Pool, cpu_count from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path @@ -245,8 +246,8 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, # Labels generated from toolchain and target rules/features (used for selective build) self.labels = None - # config_header_content will hold the content of the config header (if used) - self.config_header_content = None + # This will hold the configuration data (as returned by Config.get_config_data()) + self.config_data = None # Non-incremental compile self.build_all = False @@ -892,11 +893,9 @@ def mem_stats(self, map): map_csv = splitext(map)[0] + "_map.csv" memap.generate_output('csv-ci', map_csv) - # "Prefix headers" are automatically included by the compiler at the beginning of - # each source file. They are used to provide configuration data. - # header_content - the content of the config header file. - def set_config_header_content(self, header_content): - self.config_header_content = header_content + # Set the configuration data + def set_config_data(self, config_data): + self.config_data = config_data # Return the location of the config header. This function will create the config # header first if needed. The header will be written in a file called "mbed_conf.h" @@ -904,14 +903,17 @@ def set_config_header_content(self, header_content): # If config headers are not used (self.config_header_content is None), the function # returns None def get_config_header(self): - if self.config_header_content is None: + if self.config_data is None: return None config_file = join(self.build_dir, "mbed_config.h") if not exists(config_file): with open(config_file, "wt") as f: - f.write(self.config_header_content) + f.write(Config.config_to_header(self.config_data)) return config_file + # Return the list of macros geenrated by the build system + def get_config_macros(self): + return Config.config_to_macros(self.config_data) if self.config_data else [] from tools.settings import ARM_BIN from tools.settings import GCC_ARM_PATH, GCC_CR_PATH diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index f6662b3ee12..605a13350be 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -126,17 +126,22 @@ def cc_extra(self, object): base, _ = splitext(object) return ["-l", base + '.s.txt'] - def get_compile_options(self, defines, includes): + def get_compile_options(self, defines, includes, for_asm=False): opts = ['-D%s' % d for d in defines] + ['-f', self.get_inc_file(includes)] - config_header = self.get_config_header() - if config_header is not None: - opts = opts + ['--preinclude', config_header] + if for_asm: + # The assembler doesn't support '--preinclude', so we need to add + # the macros directly + opts = opts + ['-D%s' % d for d in self.get_config_macros()] + else: + config_header = self.get_config_header() + if config_header is not None: + opts = opts + ['--preinclude', config_header] return opts @hook_tool def assemble(self, source, object, includes): # Build assemble command - cmd = self.asm + self.get_compile_options(self.get_symbols(), includes) + ["-o", object, source] + cmd = self.asm + self.get_compile_options(self.get_symbols(), includes, for_asm=True) + ["-o", object, source] # Call cmdline hook cmd = self.hook.get_cmdline_assembler(cmd)