Clone of official tools
Diff: config.py
- Revision:
- 31:8ea194f6145b
- Parent:
- 30:f12ce67666d0
- Child:
- 35:da9c89f8be7d
--- 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: