Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
Diff: config.py
- Revision:
- 32:8ea194f6145b
- Parent:
- 30:f12ce67666d0
diff -r f12ce67666d0 -r 8ea194f6145b config.py --- a/config.py Mon Aug 29 11:56:59 2016 +0100 +++ b/config.py Wed Jan 04 11:58:24 2017 -0600 @@ -15,10 +15,13 @@ limitations under the License. """ +from copy import deepcopy +import os +import sys # Implementation of mbed configuration mechanism from tools.utils import json_file_to_dict -from tools.targets import Target -import os +from tools.targets import CUMULATIVE_ATTRIBUTES, TARGET_MAP, \ + generate_py_target, get_resolution_order # Base class for all configuration exceptions class ConfigException(Exception): @@ -339,16 +342,18 @@ __allowed_keys = { "library": set(["name", "config", "target_overrides", "macros", "__config_path"]), - "application": set(["config", "custom_targets", "target_overrides", + "application": set(["config", "target_overrides", "macros", "__config_path"]) } # Allowed features in configurations __allowed_features = [ - "UVISOR", "BLE", "CLIENT", "IPV4", "IPV6", "COMMON_PAL", "STORAGE" - ] + "UVISOR", "BLE", "CLIENT", "IPV4", "LWIP", "COMMON_PAL", "STORAGE", "NANOSTACK", + # Nanostack configurations + "LOWPAN_BORDER_ROUTER", "LOWPAN_HOST", "LOWPAN_ROUTER", "NANOSTACK_FULL", "THREAD_BORDER_ROUTER", "THREAD_END_DEVICE", "THREAD_ROUTER" + ] - def __init__(self, target, top_level_dirs=None): + def __init__(self, tgt, top_level_dirs=None, app_config=None): """Construct a mbed configuration Positional arguments: @@ -357,27 +362,32 @@ Keyword argumets: top_level_dirs - a list of top level source directories (where - mbed_abb_config.json could be found) + mbed_app_config.json could be found) + app_config - location of a chosen mbed_app.json file NOTE: Construction of a Config object will look for the application - configuration file in top_level_dirs. If found once, it'll parse it and - check if it has a custom_targets function. If it does, it'll update the - list of targets as needed. If more than one config file is found, an - exception is raised. top_level_dirs may be None (in this case, - the constructor will not search for a configuration file) + configuration file in top_level_dirs. If found once, it'll parse it. + top_level_dirs may be None (in this case, the constructor will not + search for a configuration file). """ - app_config_location = None - for directory in top_level_dirs or []: - full_path = os.path.join(directory, self.__mbed_app_config_name) - if os.path.isfile(full_path): - if app_config_location is not None: - raise ConfigException("Duplicate '%s' file in '%s' and '%s'" - % (self.__mbed_app_config_name, - app_config_location, full_path)) - else: - app_config_location = full_path - self.app_config_data = json_file_to_dict(app_config_location) \ - if app_config_location else {} + app_config_location = app_config + if app_config_location is None: + for directory in top_level_dirs or []: + full_path = os.path.join(directory, self.__mbed_app_config_name) + if os.path.isfile(full_path): + if app_config_location is not None: + raise ConfigException("Duplicate '%s' file in '%s' and '%s'" + % (self.__mbed_app_config_name, + app_config_location, full_path)) + else: + app_config_location = full_path + try: + self.app_config_data = json_file_to_dict(app_config_location) \ + if app_config_location else {} + except ValueError as exc: + sys.stderr.write(str(exc) + "\n") + self.app_config_data = {} + # Check the keys in the application configuration data unknown_keys = set(self.app_config_data.keys()) - \ self.__allowed_keys["application"] @@ -387,20 +397,26 @@ self.__mbed_app_config_name)) # Update the list of targets with the ones defined in the application # config, if applicable - Target.add_py_targets(self.app_config_data.get("custom_targets", {})) self.lib_config_data = {} # Make sure that each config is processed only once self.processed_configs = {} - self.target = target if isinstance(target, basestring) else target.name - self.target_labels = Target.get_target(self.target).get_labels() + if isinstance(tgt, basestring): + if tgt in TARGET_MAP: + self.target = TARGET_MAP[tgt] + else: + self.target = generate_py_target( + self.app_config_data.get("custom_targets", {}), tgt) + + else: + self.target = tgt + self.target = deepcopy(self.target) + self.target_labels = self.target.labels self.cumulative_overrides = {key: ConfigCumulativeOverride(key) - for key in - Target.cumulative_attributes} + for key in CUMULATIVE_ATTRIBUTES} self._process_config_and_overrides(self.app_config_data, {}, "app", "application") - self.target_labels = Target.get_target(self.target).get_labels() self.config_errors = None def add_config_files(self, flist): @@ -419,7 +435,12 @@ self.processed_configs[full_path] = True # Read the library configuration and add a "__full_config_path" # attribute to it - cfg = json_file_to_dict(config_file) + try: + cfg = json_file_to_dict(config_file) + except ValueError as exc: + sys.stderr.write(str(exc) + "\n") + continue + cfg["__config_path"] = full_path if "name" not in cfg: @@ -498,7 +519,7 @@ label))))) for cumulatives in self.cumulative_overrides.itervalues(): - cumulatives.update_target(Target.get_target(self.target)) + cumulatives.update_target(self.target) return params @@ -517,10 +538,10 @@ Arguments: None """ - params, json_data = {}, Target.get_json_target_data() + params, json_data = {}, self.target.json_data resolution_order = [e[0] for e in sorted( - Target.get_target(self.target).resolution_order, + self.target.resolution_order, key=lambda e: e[1], reverse=True)] for tname in resolution_order: # Read the target data directly from its description @@ -536,9 +557,11 @@ # in the target inheritance tree, raise an error We need to use # 'defined_by[7:]' to remove the "target:" prefix from # defined_by + rel_names = [tgt for tgt, _ in + get_resolution_order(self.target.json_data, tname, + [])] if (full_name not in params) or \ - (params[full_name].defined_by[7:] not in - Target.get_target(tname).resolution_order_names): + (params[full_name].defined_by[7:] not in rel_names): raise ConfigException( "Attempt to override undefined parameter '%s' in '%s'" % (name, @@ -669,15 +692,9 @@ params, _ = self.get_config_data() self._check_required_parameters(params) self.cumulative_overrides['features']\ - .update_target(Target.get_target(self.target)) - features = Target.get_target(self.target).features + .update_target(self.target) - for feature in features: - if feature not in self.__allowed_features: - raise ConfigException( - "Feature '%s' is not a supported features" % feature) - - return features + return self.target.features def validate_config(self): """ Validate configuration settings. This either returns True or @@ -774,14 +791,15 @@ if macro.macro_value: header_data += ("#define {0:<{1}} {2!s:<{3}}" + " // defined by {4}\n")\ - .format(m.macro_name, max_macro_name_len, m.macro_value, - max_macro_val_len, m.defined_by) + .format(macro.macro_name, max_macro_name_len, + macro.macro_value, max_macro_val_len, + macro.defined_by) else: header_data += ("#define {0:<{1}}" + " // defined by {2}\n")\ - .format(m.macro_name, + .format(macro.macro_name, max_macro_name_len + max_macro_val_len + 1, - m.defined_by) + macro.defined_by) header_data += "\n#endif\n" # If fname is given, write "header_data" to it if fname: