@@ -48,27 +48,31 @@ class HookError(Exception):
48
48
caches = {}
49
49
def cached (func ):
50
50
def wrapper (* args , ** kwargs ):
51
- if not caches .has_key (func ):
52
- caches [func ] = func (* args , ** kwargs )
53
- return caches [func ]
51
+ if not caches .has_key (( func . __name__ , args ) ):
52
+ caches [( func . __name__ , args ) ] = func (* args , ** kwargs )
53
+ return caches [( func . __name__ , args ) ]
54
54
return wrapper
55
55
56
56
class Target :
57
57
# Cumulative attributes can have values appended to them, so they
58
58
# need to be computed differently than regular attributes
59
59
__cumulative_attributes = ['extra_labels' , 'macros' , 'device_has' , 'features' ]
60
60
61
- # {target_name: target_instance} map for all the targets in the system
62
- __target_map = {}
63
-
64
- # List of targets that were added dynamically using "add_py_targets" (see below)
65
- __py_targets = set ()
61
+ # Location of the 'targets.json' file
62
+ __targets_json_location = os .path .join (os .path .dirname (os .path .abspath (__file__ )), '..' , 'hal' , 'targets.json' )
66
63
67
64
# Load the description of JSON target data
68
65
@staticmethod
69
66
@cached
70
67
def get_json_target_data ():
71
- return json_file_to_dict (os .path .join (os .path .dirname (os .path .abspath (__file__ )), '..' , 'hal' , 'targets.json' ))
68
+ return json_file_to_dict (Target .__targets_json_location )
69
+
70
+ # Set the location of the targets.json file
71
+ @staticmethod
72
+ def set_targets_json_location (location ):
73
+ Target .__targets_json_location = location
74
+ # Invalidate caches, since the location of the JSON file changed
75
+ caches .clear ()
72
76
73
77
# Get the members of this module using Python's "inspect" module
74
78
@staticmethod
@@ -168,42 +172,26 @@ def __getattr__(self, attrname):
168
172
return v
169
173
170
174
# Add one or more new target(s) represented as a Python dictionary in 'new_targets'
171
- # It it an error to add a target with a name that exists in "targets.json"
172
- # However, it is OK to add a target that was previously added via "add_py_targets"
173
- # (this makes testing easier without changing the regular semantics)
175
+ # It is an error to add a target with a name that already exists.
174
176
@staticmethod
175
177
def add_py_targets (new_targets ):
176
178
crt_data = Target .get_json_target_data ()
177
- # First add all elemnts to the internal dictionary
178
179
for tk , tv in new_targets .items ():
179
- if crt_data .has_key (tk ) and ( not tk in Target . __py_targets ) :
180
+ if crt_data .has_key (tk ):
180
181
raise Exception ("Attempt to add target '%s' that already exists" % tk )
182
+ # Add target data to the internal target dictionary
181
183
crt_data [tk ] = tv
182
- Target .__py_targets .add (tk )
183
- # Then create the new instances and update global variables if needed
184
- for tk , tv in new_targets .items ():
185
- # Is the target already created?
186
- old_target = Target .__target_map .get (tk , None )
187
- # Instantiate this target. If it is public, update the data in
188
- # in TARGETS, TARGET_MAP, TARGET_NAMES
184
+ # Create the new target and add it to the relevant data structures
189
185
new_target = Target (tk )
190
- if tv .get ("public" , True ):
191
- if old_target : # remove the old target from TARGETS and TARGET_NAMES
192
- TARGETS .remove (old_target )
193
- TARGET_NAMES .remove (tk )
194
- # Add the new target
195
- TARGETS .append (new_target )
196
- TARGET_MAP [tk ] = new_target
197
- TARGET_NAMES .append (tk )
198
- # Update the target cache
199
- Target .__target_map [tk ] = new_target
186
+ TARGETS .append (new_target )
187
+ TARGET_MAP [tk ] = new_target
188
+ TARGET_NAMES .append (tk )
200
189
201
190
# Return the target instance starting from the target name
202
191
@staticmethod
192
+ @cached
203
193
def get_target (name ):
204
- if not Target .__target_map .has_key (name ):
205
- Target .__target_map [name ] = Target (name )
206
- return Target .__target_map [name ]
194
+ return Target (name )
207
195
208
196
def __init__ (self , name ):
209
197
self .name = name
@@ -414,3 +402,15 @@ def get_target_detect_codes():
414
402
for detect_code in target .detect_code :
415
403
result [detect_code ] = target .name
416
404
return result
405
+
406
+ # Sets the location of the JSON file that contains the targets
407
+ def set_targets_json_location (location ):
408
+ # First instruct Target about the new location
409
+ Target .set_targets_json_location (location )
410
+ # Then re-initialize TARGETS, TARGET_MAP and TARGET_NAMES
411
+ # The re-initialization does not create new variables, it keeps the old ones instead
412
+ # This ensures compatibility with code that does "from tools.targets import TARGET_NAMES"
413
+ TARGETS [:] = [Target .get_target (name ) for name , value in Target .get_json_target_data ().items () if value .get ("public" , True )]
414
+ TARGET_MAP .clear ()
415
+ TARGET_MAP .update (dict ([(t .name , t ) for t in TARGETS ]))
416
+ TARGET_NAMES [:] = TARGET_MAP .keys ()
0 commit comments