2929SUPPORTED_PORTS = ["atmel-samd" , "nrf" ]
3030
3131
32+ def parse_port_config (contents , chip_keyword = None ):
33+ """ Compile a dictionary of port-wide module configs, which may
34+ be categorized by chipset.
35+ """
36+ chip_fam = "all"
37+ ifeq_found = False
38+ port_config_results = {"all" : []}
39+
40+ chip_pattern = ""
41+ if chip_keyword :
42+ chip_pattern = (
43+ re .compile ("(?<=ifeq\s\(\$\({}\)\,)(\w+)" .format (chip_keyword ))
44+ )
45+
46+ for line in contents :
47+ if chip_keyword :
48+ if not ifeq_found :
49+ check_ifeq = chip_pattern .search (line )
50+ if check_ifeq :
51+ ifeq_found = True
52+ chip_fam = check_ifeq .group (1 )
53+ print ("found chip:" , chip_fam )
54+ else :
55+ ifeq_found = False
56+ chip_fam = "all"
57+ else :
58+ if "endif" in line :
59+ ifeq_found = False
60+ chip_fam = "all"
61+
62+ if "CIRCUITPY_" in line :
63+ if chip_fam in port_config_results :
64+ port_config_results [chip_fam ].append (line .rstrip ("\n " ))
65+ else :
66+ port_config_results [chip_fam ] = [line .rstrip ("\n " )]
67+
68+ #print(port_config_results)
69+ return port_config_results
70+
3271def get_shared_bindings ():
3372 """ Get a list of modules in shared-bindings based on folder names
3473 """
@@ -45,13 +84,15 @@ def read_mpconfig():
4584 return configs
4685
4786
48- def build_module_map (modules , configs ):
87+ def build_module_map ():
4988 """ Establish the base of the JSON file, based on the contents from
5089 `configs`. Base will contain module names, if they're part of
5190 the `FULL_BUILD`, or their default value (0 | 1).
5291
5392 """
5493 base = dict ()
94+ modules = get_shared_bindings ()
95+ configs = read_mpconfig ()
5596 full_build = False
5697 for module in modules :
5798 full_name = module
@@ -71,55 +112,122 @@ def build_module_map(modules, configs):
71112 "name" : full_name ,
72113 "full_build" : str (full_build ),
73114 "default_value" : default_val ,
74- "excluded" : []
115+ "excluded" : {}
75116 }
76117
77- return get_excluded_boards ( base )
118+ return base
78119
79120
80121def get_excluded_boards (base ):
81122 """ Cycles through each board's `mpconfigboard.mk` file to determine
82123 if each module is included or not. Boards are selected by existence
83124 in a port listed in `SUPPORTED_PORTS` (e.g. `/port/nrf/feather_52840`)
125+
126+ Boards are further categorized by their respective chipset (SAMD21,
127+ SAMD51, nRF52840, etc.)
84128 """
85129 modules = list (base .keys ())
130+
131+ re_board_chip = None
132+ chip_keyword = None
86133 for port in SUPPORTED_PORTS :
87- port_dir = "ports/{}/boards" .format (port )
88- for entry in os .scandir (port_dir ):
134+ # each port appears to use its own define for the chipset
135+ if port in ["atmel-samd" ]:
136+ re_board_chip = re .compile ("CHIP_FAMILY\s=\s(\w+)" )
137+ chip_keyword = "CHIP_FAMILY"
138+ elif port in ["nrf" ]:
139+ re_board_chip = re .compile ("MCU_VARIANT\s=\s(\w+)" )
140+
141+ port_dir = "ports/{}" .format (port )
142+
143+ port_config_contents = ""
144+ with open (os .path .join (port_dir , "mpconfigport.mk" )) as port_config :
145+ port_config_contents = port_config .readlines ()
146+ port_config = parse_port_config (port_config_contents , chip_keyword )
147+
148+ for entry in os .scandir (os .path .join (port_dir , "boards" )):
89149 if not entry .is_dir ():
90150 continue
151+
91152 contents = ""
92153 board_dir = os .path .join (entry .path , "mpconfigboard.mk" )
93- #print(board_dir)
94154 with open (board_dir ) as board :
95155 contents = board .read ()
156+
157+ board_chip = re_board_chip .search (contents )
158+ #print(entry.name, board_chip.group(1))
159+ if not board_chip :
160+ board_chip = "Unknown Chip"
161+ else :
162+ board_chip = board_chip .group (1 )
163+
164+ # add port_config results to contents
165+ contents += "\n " + "\n " .join (port_config ["all" ])
166+ if board_chip in port_config :
167+ contents += "\n " + "\n " .join (port_config [board_chip ])
168+
96169 for module in modules :
170+ board_is_excluded = False
97171 # check if board uses `SMALL_BUILD`. if yes, and current
98172 # module is marked as `FULL_BUILD`, board is excluded
99173 small_build = re .search ("CIRCUITPY_SMALL_BUILD = 1" , contents )
100174 if small_build and base [module ]["full_build" ] == "1" :
101- base [module ]["excluded" ].append (entry .name )
102- continue
103-
175+ board_is_excluded = True
104176 # check if module is specifically disabled for this board
105177 re_pattern = "CIRCUITPY_{}\s=\s(\w)" .format (module .upper ())
106178 find_module = re .search (re_pattern , contents )
107179 if not find_module :
108180 # check if default inclusion is off ('0'). if the board doesn't
109181 # have it explicitly enabled, its excluded.
110182 if base [module ]["default_value" ] == "0" :
111- base [module ]["excluded" ].append (entry .name )
112- continue
113- if (find_module .group (1 ) == "0" and
114- find_module .group (1 ) != base [module ]["default_value" ]):
115- base [module ]["excluded" ].append (entry .name )
116-
183+ board_is_excluded = True
184+ else :
185+ if (find_module .group (1 ) == "0" and
186+ find_module .group (1 ) != base [module ]["default_value" ]):
187+ board_is_excluded = True
188+
189+ if board_is_excluded :
190+ if board_chip in base [module ]["excluded" ]:
191+ base [module ]["excluded" ][board_chip ].append (entry .name )
192+ else :
193+ base [module ]["excluded" ][board_chip ] = [entry .name ]
194+ #print(json.dumps(base, indent=2))
117195 return base
118196
119197
120- def support_matrix ():
121- modules = get_shared_bindings ()
122- configs = read_mpconfig ()
123- base = build_module_map (sorted (modules ), configs )
198+ def support_matrix_excluded_boards ():
199+ """ Compiles a list of available modules, and which board definitions
200+ do not include them.
201+ """
202+ base = build_module_map ()
124203
125- return base
204+ return get_excluded_boards (base )
205+
206+ def support_matrix_by_board ():
207+ """ Compiles a list of the available core modules available for each
208+ board.
209+ """
210+ base = build_module_map ()
211+ base_with_exclusions = get_excluded_boards (base )
212+
213+ boards = dict ()
214+ for port in SUPPORTED_PORTS :
215+ port_dir = "ports/{}/boards" .format (port )
216+ for entry in os .scandir (port_dir ):
217+ if not entry .is_dir ():
218+ continue
219+ board_modules = []
220+ for module in base_with_exclusions .keys ():
221+ #print(module)
222+ board_has_module = True
223+ if base_with_exclusions [module ]["excluded" ]:
224+ for port in base_with_exclusions [module ]["excluded" ].values ():
225+ #print(port)
226+ if entry .name in port :
227+ board_has_module = False
228+
229+ if board_has_module :
230+ board_modules .append (base_with_exclusions [module ]["name" ])
231+ boards [entry .name ] = sorted (board_modules )
232+
233+ return boards
0 commit comments