2525import logging
2626import json
2727import sys
28+ import re
29+ import argparse
2830from typing import Set , Dict , Any
2931
3032LOGGER = logging .getLogger (__name__ )
3133
3234# Calculate path to Mbed OS JSON files
3335THIS_SCRIPT_DIR = pathlib .Path (os .path .dirname (__file__ ))
36+ PROJECT_ROOT = THIS_SCRIPT_DIR .parent .parent .parent .parent .parent
3437MBED_OS_DIR = THIS_SCRIPT_DIR .parent .parent .parent .parent
3538TARGETS_JSON5_PATH = MBED_OS_DIR / "targets" / "targets.json5"
3639CMSIS_MCU_DESCRIPTIONS_JSON_PATH = MBED_OS_DIR / "targets" / "cmsis_mcu_descriptions.json5"
3740
38-
3941# Top-level command
4042@click .group (
4143 name = "cmsis-mcu-descr" ,
@@ -67,14 +69,58 @@ def open_cmsis_cache(*, must_exist: bool = True) -> cmsis_pack_manager.Cache:
6769 return cmsis_cache
6870
6971
72+ def find_json_files (root_dir , exclude_dirs = [], file_pattern = r".*\.(json|json5)" ):
73+ """
74+ Recursively searches for files matching the specified pattern in a given directory, excluding specified directories.
75+
76+ Args:
77+ root_dir (str): The root directory to search.
78+ exclude_dirs (list): A list of directory names to exclude.
79+ file_pattern (str): A regular expression pattern to match file names.
80+
81+ Returns:
82+ A list of paths to found files.
83+ """
84+ json_files = []
85+
86+ for root , dirs , files in os .walk (root_dir ):
87+ # Exclude specified directories
88+ for exclude_dir in exclude_dirs :
89+ if exclude_dir in dirs :
90+ dirs .remove (exclude_dir )
91+
92+ for file in files :
93+ if re .match (file_pattern , file ):
94+ json_files .append (pathlib .Path (os .path .join (root , file )))
95+
96+ return json_files
97+
98+
7099def get_mcu_names_used_by_targets_json5 () -> Set [str ]:
71100 """
72- Accumulate set of all `device_name` properties used by all targets defined in targets.json5
101+ Accumulate set of all `device_name` properties used by all targets defined in targets.json5 and custom_targets.json/json5.
73102 """
74- LOGGER .info ("Scanning targets.json5 for used MCU names..." )
103+
104+ # Search for files starting with "custom_targets" of type .json or .json5. Also exclude some folders like build and mbed-os
105+ exclude_dirs = ["build" , "mbed-os" , ".git" ]
106+ file_pattern = r"custom_targets\.(json|json5)"
107+ custom_targets_file = find_json_files (PROJECT_ROOT , exclude_dirs , file_pattern )
108+
109+ custom_targets_json_path = {}
110+ for file in custom_targets_file :
111+ if os .path .exists (file ):
112+ custom_targets_json_path = file
113+ LOGGER .info (f"Custom_targets file detected - { custom_targets_json_path } " )
114+
115+
75116 used_mcu_names = set ()
76- targets_json5_contents = decode_json_file (TARGETS_JSON5_PATH )
77- for target_details in targets_json5_contents .values ():
117+ LOGGER .info ("Scanning targets.json5 for used MCU names..." )
118+ json_contents = decode_json_file (TARGETS_JSON5_PATH )
119+ if custom_targets_file :
120+ LOGGER .info ("Scanning custom_targets.json/json5. for used MCU names..." )
121+ json_contents .update (decode_json_file (custom_targets_json_path ))
122+
123+ for target_details in json_contents .values ():
78124 if "device_name" in target_details :
79125 used_mcu_names .add (target_details ["device_name" ])
80126 return used_mcu_names
@@ -153,26 +199,27 @@ def check_missing():
153199
154200@cmsis_mcu_descr .command (
155201 name = "fetch-missing" ,
156- short_help = "Fetch any missing MCU descriptions used by targets.json5."
202+ short_help = "Fetch any missing MCU descriptions used by targets.json5 or custom_targets.json/json5. ."
157203)
158204def fetch_missing ():
159205 """
160- Scans through cmsis_mcu_descriptions.json for any missing MCU descriptions that are referenced by
161- targets.json5. If any are found, they are imported from the CMSIS cache.
206+ Scans through cmsis_mcu_descriptions.json5 for any missing MCU descriptions that are referenced by
207+ targets.json5 or custom_targets.json/json5. If any are found, they are imported from the CMSIS cache.
162208
163209 Note that downloaded descriptions should be checked for accuracy before they are committed.
164210 """
211+
165212 used_mcu_names = get_mcu_names_used_by_targets_json5 ()
166213
167214 # Accumulate set of all keys in cmsis_mcu_descriptions.json
168- LOGGER .info ("Scanning cmsis_mcu_descriptions.json for missing MCUs..." )
215+ LOGGER .info ("Scanning cmsis_mcu_descriptions.json5 file for missing MCUs..." )
169216 cmsis_mcu_descriptions_json_contents : Dict [str , Any ] = decode_json_file (CMSIS_MCU_DESCRIPTIONS_JSON_PATH )
170217 available_mcu_names = cmsis_mcu_descriptions_json_contents .keys ()
171218
172219 # Are there any missing?
173220 missing_mcu_names = used_mcu_names - available_mcu_names
174221 if len (missing_mcu_names ) == 0 :
175- print ("No missing MCUs, no work to do." )
222+ LOGGER . info ("No missing MCUs, no work to do." )
176223 return
177224
178225 # Load CMSIS cache to access new MCUs
@@ -186,8 +233,9 @@ def fetch_missing():
186233 f"wrong part number, or this MCU simply doesn't exist in the CMSIS index and has "
187234 f"to be added manually?" )
188235 missing_mcus_dict [mcu ] = cmsis_cache .index [mcu ]
189-
190- print (f"Add the following entries to { CMSIS_MCU_DESCRIPTIONS_JSON_PATH } :" )
236+
237+ LOGGER .info ("In case of Custom target remove 'device_name' from your custom_targets.json5 file and add\n " +
238+ "just the 'memories' section as 'memory_banks' section from content below.\n " +
239+ f"Otherwise add the whole following entries to { CMSIS_MCU_DESCRIPTIONS_JSON_PATH } :" )
191240 print (json .dumps (missing_mcus_dict , indent = 4 , sort_keys = True ))
192-
193- sys .exit (1 )
241+ sys .exit (1 )
0 commit comments