2525import logging
2626import json
2727import sys
28+ import re
29+ import argparse
2830from typing import Set , Dict , Any
2931
3032LOGGER = logging .getLogger (__name__ )
3537TARGETS_JSON5_PATH = MBED_OS_DIR / "targets" / "targets.json5"
3638CMSIS_MCU_DESCRIPTIONS_JSON_PATH = MBED_OS_DIR / "targets" / "cmsis_mcu_descriptions.json5"
3739
38- CUSTOM_DIR = THIS_SCRIPT_DIR .parent .parent .parent .parent .parent
39- CUSTOM_TARGETS_JSON5_PATH = CUSTOM_DIR / "custom_targets" / "custom_targets.json5"
40+ PROJECT_ROOT = THIS_SCRIPT_DIR .parent .parent .parent .parent .parent
41+ CUSTOM_TARGETS_JSON_PATH = None
4042
4143# Top-level command
4244@click .group (
@@ -68,19 +70,58 @@ def open_cmsis_cache(*, must_exist: bool = True) -> cmsis_pack_manager.Cache:
6870
6971 return cmsis_cache
7072
73+ def find_json_files (root_dir , exclude_dirs = [], file_pattern = r".*\.(json|json5)" ):
74+ """
75+ Recursively searches for files matching the specified pattern in a given directory, excluding specified directories.
76+
77+ Args:
78+ root_dir (str): The root directory to search.
79+ exclude_dirs (list): A list of directory names to exclude.
80+ file_pattern (str): A regular expression pattern to match file names.
81+
82+ Returns:
83+ A list of paths to found files.
84+ """
85+ json_files = []
86+
87+ for root , dirs , files in os .walk (root_dir ):
88+ # Exclude specified directories
89+ for exclude_dir in exclude_dirs :
90+ if exclude_dir in dirs :
91+ dirs .remove (exclude_dir )
92+
93+ for file in files :
94+ if re .match (file_pattern , file ):
95+ json_files .append (pathlib .Path (os .path .join (root , file )))
96+
97+ return json_files
98+
7199
72100def get_mcu_names_used_by_targets_json5 () -> Set [str ]:
73101 """
74- Accumulate set of all `device_name` properties used by all targets defined in targets.json5 and custom_targets.json5
102+ Accumulate set of all `device_name` properties used by all targets defined in targets.json5 and custom_targets.json/ json5.
75103 """
104+
105+ # Search for files starting with "custom_targets" of type .json or .json5. Also exclude some folders like build and mbed-os
106+ exclude_dirs = ["build" , "mbed-os" , ".git" ]
107+ file_pattern = r"custom_targets\.(json|json5)"
108+ custom_targets_file = find_json_files (PROJECT_ROOT , exclude_dirs , file_pattern )
109+
110+ for file in custom_targets_file :
111+ if os .path .exists (file ):
112+ global CUSTOM_TARGETS_JSON_PATH
113+ CUSTOM_TARGETS_JSON_PATH = file
114+ print (f"File exist { CUSTOM_TARGETS_JSON_PATH } " )
115+
116+
76117 used_mcu_names = set ()
77118 LOGGER .info ("Scanning targets.json5 for used MCU names..." )
78- json5_contents = decode_json_file (TARGETS_JSON5_PATH )
79- if os . path . exists ( CUSTOM_TARGETS_JSON5_PATH ) :
80- LOGGER .info ("Scanning custom_targets.json5 for used MCU names..." )
81- json5_contents .update (decode_json_file (CUSTOM_TARGETS_JSON5_PATH ))
119+ json_contents = decode_json_file (TARGETS_JSON5_PATH )
120+ if custom_targets_file :
121+ LOGGER .info ("Scanning custom_targets.json/ json5. for used MCU names..." )
122+ json_contents .update (decode_json_file (CUSTOM_TARGETS_JSON_PATH ))
82123
83- for target_details in json5_contents .values ():
124+ for target_details in json_contents .values ():
84125 if "device_name" in target_details :
85126 used_mcu_names .add (target_details ["device_name" ])
86127 return used_mcu_names
@@ -159,26 +200,27 @@ def check_missing():
159200
160201@cmsis_mcu_descr .command (
161202 name = "fetch-missing" ,
162- short_help = "Fetch any missing MCU descriptions used by targets.json5 or custom_targets.json5."
203+ short_help = "Fetch any missing MCU descriptions used by targets.json5 or custom_targets.json/ json5. ."
163204)
164205def fetch_missing ():
165206 """
166- Scans through cmsis_mcu_descriptions.json for any missing MCU descriptions that are referenced by
167- targets.json5 or custom_targets.json5. If any are found, they are imported from the CMSIS cache.
207+ Scans through cmsis_mcu_descriptions.json5 for any missing MCU descriptions that are referenced by
208+ targets.json5 or custom_targets.json/ json5. If any are found, they are imported from the CMSIS cache.
168209
169210 Note that downloaded descriptions should be checked for accuracy before they are committed.
170211 """
212+
171213 used_mcu_names = get_mcu_names_used_by_targets_json5 ()
172214
173215 # Accumulate set of all keys in cmsis_mcu_descriptions.json
174- LOGGER .info ("Scanning cmsis_mcu_descriptions.json for missing MCUs..." )
216+ LOGGER .info ("Scanning cmsis_mcu_descriptions.json5 file for missing MCUs..." )
175217 cmsis_mcu_descriptions_json_contents : Dict [str , Any ] = decode_json_file (CMSIS_MCU_DESCRIPTIONS_JSON_PATH )
176218 available_mcu_names = cmsis_mcu_descriptions_json_contents .keys ()
177219
178220 # Are there any missing?
179221 missing_mcu_names = used_mcu_names - available_mcu_names
180222 if len (missing_mcu_names ) == 0 :
181- print ("No missing MCUs, no work to do." )
223+ LOGGER . info ("No missing MCUs, no work to do." )
182224 return
183225
184226 # Load CMSIS cache to access new MCUs
@@ -193,10 +235,10 @@ def fetch_missing():
193235 f"to be added manually?" )
194236 missing_mcus_dict [mcu ] = cmsis_cache .index [mcu ]
195237
196- if os .path .exists (CUSTOM_TARGETS_JSON5_PATH ):
197- print (f"Remove 'device_name' and add the 'memories' section as 'memory_banks' section\n from following entries to { CUSTOM_TARGETS_JSON5_PATH } :" )
238+ if os .path .exists (CUSTOM_TARGETS_JSON_PATH ):
239+ LOGGER . info (f"Remove 'device_name' and add the 'memories' section as 'memory_banks' section\n from following entries to { CUSTOM_TARGETS_JSON_PATH } :" )
198240 else :
199- print (f"Add the following entries to { CMSIS_MCU_DESCRIPTIONS_JSON_PATH } :" )
241+ LOGGER . info (f"Add the following entries to { CMSIS_MCU_DESCRIPTIONS_JSON_PATH } :" )
200242
201243 print (json .dumps (missing_mcus_dict , indent = 4 , sort_keys = True ))
202244 sys .exit (1 )
0 commit comments