@@ -137,6 +137,40 @@ def __init__(self, name, unit_name, unit_kind):
137137 self .macro_name = name
138138 self .macro_value = None
139139
140+ # Representation of overrides for cumulative attributes
141+ class ConfigCumulativeOverride :
142+ def __init__ (self , name , additions = set (), removals = set (), strict = False ):
143+ self .name = name
144+ self .additions = set (additions )
145+ self .removals = set (removals )
146+ self .strict = strict
147+
148+ # Add attr to the cumulative override
149+ def remove_cumulative_override (self , overrides ):
150+ for override in overrides :
151+ if override in self .additions :
152+ raise ConfigException ("Configuration conflict. The %s %s both added and removed." % (self .name , override ))
153+
154+ self .removals |= set (overrides )
155+
156+ # Remove attr from the cumulative overrides
157+ def add_cumulative_overrides (self , overrides ):
158+ for override in overrides :
159+ if (override in self .removals or (self .strict and override not in self .additions )):
160+ raise ConfigException ("Configuration conflict. The %s %s both added and removed." % (self .name , override ))
161+
162+ self .additions |= set (overrides )
163+
164+ # Enable strict set of cumulative overrides for the specified attr
165+ def strict_cumulative_overrides (self , overrides ):
166+ self .remove_cumulative_override (self .additions - set (overrides ))
167+ self .add_cumulative_override (overrides )
168+ self .strict = True
169+
170+ def get_cumulative_overrides (self , target ):
171+ return set (getattr (target , self .name )) | self .additions - self .removals
172+
173+
140174# 'Config' implements the mbed configuration mechanism
141175class Config :
142176 # Libraries and applications have different names for their configuration files
@@ -184,9 +218,9 @@ def __init__(self, target, top_level_dirs = []):
184218 self .processed_configs = {}
185219 self .target = target if isinstance (target , basestring ) else target .name
186220 self .target_labels = Target .get_target (self .target ).get_labels ()
187- self . added_features = set ()
188- self .removed_features = set ()
189- self . removed_unecessary_features = False
221+
222+ self .cumulative_overrides = { key : ConfigCumulativeOverride ( key )
223+ for key in Target . _Target__cumulative_attributes }
190224
191225 # Add one or more configuration files
192226 def add_config_files (self , flist ):
@@ -222,23 +256,6 @@ def _process_config_parameters(self, data, params, unit_name, unit_kind):
222256 params [full_name ] = ConfigParameter (name , v if isinstance (v , dict ) else {"value" : v }, unit_name , unit_kind )
223257 return params
224258
225- # Add features to the available features
226- def remove_features (self , features ):
227- for feature in features :
228- if feature in self .added_features :
229- raise ConfigException ("Configuration conflict. Feature %s both added and removed." % feature )
230-
231- self .removed_features |= set (features )
232-
233- # Remove features from the available features
234- def add_features (self , features ):
235- for feature in features :
236- if (feature in self .removed_features
237- or (self .removed_unecessary_features and feature not in self .added_features )):
238- raise ConfigException ("Configuration conflict. Feature %s both added and removed." % feature )
239-
240- self .added_features |= set (features )
241-
242259 # Helper function: process "config_parameters" and "target_config_overrides" in a given dictionary
243260 # data: the configuration data of the library/appliation
244261 # params: storage for the discovered configuration parameters
@@ -250,21 +267,19 @@ def _process_config_and_overrides(self, data, params, unit_name, unit_kind):
250267 for label , overrides in data .get ("target_overrides" , {}).items ():
251268 # If the label is defined by the target or it has the special value "*", process the overrides
252269 if (label == '*' ) or (label in self .target_labels ):
253- # Parse out features
254- if 'target.features' in overrides :
255- features = overrides ['target.features' ]
256- self .remove_features (self .added_features - set (features ))
257- self .add_features (features )
258- self .removed_unecessary_features = True
259- del overrides ['target.features' ]
260-
261- if 'target.features_add' in overrides :
262- self .add_features (overrides ['target.features_add' ])
263- del overrides ['target.features_add' ]
264-
265- if 'target.features_remove' in overrides :
266- self .remove_features (overrides ['target.features_remove' ])
267- del overrides ['target.features_remove' ]
270+ # Parse out cumulative overrides
271+ for attr , cumulatives in self .cumulative_overrides .iteritems ():
272+ if 'target.' + attr in overrides :
273+ cumulatives .strict_cumulative_overrides (overrides ['target.' + attr ])
274+ del overrides ['target.' + attr ]
275+
276+ if 'target.' + attr + '_add' in overrides :
277+ cumulatives .add_cumulative_overrides (overrides ['target.' + attr + '_add' ])
278+ del overrides ['target.' + attr + '_add' ]
279+
280+ if 'target.' + attr + '_remove' in overrides :
281+ cumulatives .remove_cumulative_overrides (overrides ['target.' + attr + '_remove' ])
282+ del overrides ['target.' + attr + '_remove' ]
268283
269284 # Consider the others as overrides
270285 for name , v in overrides .items ():
@@ -385,12 +400,20 @@ def config_to_macros(config):
385400 def get_config_data_macros (self ):
386401 return self .config_to_macros (self .get_config_data ())
387402
388- # Returns any features in the configuration data
389- def get_features (self ):
403+ # Returns any cumulative overrides in the configuration data
404+ def get_cumulative_overrides (self , attr ):
405+ if attr not in self .cumulative_overrides :
406+ return None
407+
390408 params , _ = self .get_config_data ()
391409 self ._check_required_parameters (params )
392- features = ((set (Target .get_target (self .target ).features )
393- | self .added_features ) - self .removed_features )
410+
411+ return self .cumulative_overrides [attr ].get_cumulative_overrides (
412+ Target .get_target (self .target ))
413+
414+ # Returns any features in the configuration data
415+ def get_features (self ):
416+ features = self .get_cumulative_overrides ('features' )
394417
395418 for feature in features :
396419 if feature not in self .__allowed_features :
0 commit comments