16
16
import glob
17
17
import logging
18
18
import os
19
+ from pathlib import Path
19
20
import re
21
+ import subprocess
20
22
import sys
21
23
from typing import Dict
22
24
37
39
38
40
ATTR_REGEX = re .compile (r",?\s*(?P<key>[^=]+)=(?P<value>[^,]+)" )
39
41
42
+ BAZEL_MODULE_REGEX = re .compile (r'\s*commit\s*=\s*\"(?P<commit>[0-9a-fA-F]+)\"\s*,\s*#\s*keep-in-sync-with-submodule:\s*(?P<dependency>\S*)' )
43
+
44
+ BAZEL_VERSION_REGEX = re .compile (r'module\(\s*name\s*=\s*"pico-sdk",\s*version\s*=\s*"(?P<sdk_version>[^"]+)",?\s*\)' )
45
+
46
+ CMAKE_VERSION_REGEX = re .compile (r'^[^#]*set\(PICO_SDK_VERSION_(?P<part>\S+)\s+(?P<value>\S+)\)' )
47
+
40
48
# Sometimes the build systems are supposed to be implemented differently. This
41
49
# allowlist permits the descriptions to differ between CMake and Bazel.
42
50
BUILD_SYSTEM_DESCRIPTION_DIFFERENCE_ALLOWLIST = (
60
68
"PICO_TOOLCHAIN_PATH" ,
61
69
# Bazel uses native --platforms mechanics.
62
70
"PICO_PLATFORM" ,
63
- # TODO: No built-in, pre-configured clang offering for Bazel yet .
71
+ # Named PICO_TOOLCHAIN in Bazel.
64
72
"PICO_COMPILER" ,
65
73
# Entirely irrelevant to Bazel, use Bazel platforms:
66
74
# https://bazel.build/extending/platforms
87
95
"PICO_DEFAULT_PIOASM_OUTPUT_FORMAT" ,
88
96
# Bazel always has picotool.
89
97
"PICO_NO_PICOTOOL" ,
90
- # TODO: Eventualy support.
91
- "PICO_NO_COPRO_DIS" ,
92
- "PICO_DEFAULT_RP2350_PLATFORM" ,
93
- "PICO_GCC_TRIPLE" ,
94
- "PICO_NO_FLASH" ,
95
- "PICO_COPY_TO_RAM" ,
96
- "PICO_RP2350_ARM_S_CONFIG_HEADER_FILES" ,
97
- "PICO_RP2350_RISCV_CONFIG_HEADER_FILES" ,
98
+ # These aren't supported as build flags in Bazel. Prefer to
99
+ # set these in board header files like other SDK defines.
100
+ "CYW43_DEFAULT_PIN_WL_REG_ON" ,
101
+ "CYW43_DEFAULT_PIN_WL_DATA_OUT" ,
102
+ "CYW43_DEFAULT_PIN_WL_DATA_IN" ,
103
+ "CYW43_DEFAULT_PIN_WL_HOST_WAKE" ,
104
+ "CYW43_DEFAULT_PIN_WL_CLOCK" ,
105
+ "CYW43_DEFAULT_PIN_WL_CS" ,
106
+ "CYW43_PIO_CLOCK_DIV_INT" ,
107
+ "CYW43_PIO_CLOCK_DIV_FRAC" ,
108
+ "CYW43_PIO_CLOCK_DIV_DYNAMIC" ,
98
109
)
99
110
100
111
BAZEL_ONLY_ALLOWLIST = (
@@ -181,17 +192,17 @@ def FindKnownOptions(option_pattern_matcher, file_paths):
181
192
return options
182
193
183
194
184
- def OptionsAreEqual (bazel_option , cmake_option ):
195
+ def OptionsAreEqual (bazel_option , cmake_option , warnings_as_errors ):
185
196
if bazel_option is None :
186
197
if cmake_option .name in CMAKE_ONLY_ALLOWLIST :
187
198
return True
188
199
_LOG .warning (f" { cmake_option .name } does not exist in Bazel" )
189
- return False
200
+ return not warnings_as_errors
190
201
elif cmake_option is None :
191
202
if bazel_option .name in BAZEL_ONLY_ALLOWLIST :
192
203
return True
193
204
_LOG .warning (f" { bazel_option .name } does not exist in CMake" )
194
- return False
205
+ return not warnings_as_errors
195
206
elif not bazel_option .matches (cmake_option ):
196
207
_LOG .error (" Bazel and CMAKE definitions do not match:" )
197
208
_LOG .error (f" [CMAKE] { bazel_option } " )
@@ -201,7 +212,7 @@ def OptionsAreEqual(bazel_option, cmake_option):
201
212
return True
202
213
203
214
204
- def CompareOptions (bazel_pattern , bazel_files , cmake_pattern , cmake_files ):
215
+ def CompareOptions (bazel_pattern , bazel_files , cmake_pattern , cmake_files , warnings_as_errors = True ):
205
216
bazel_options = FindKnownOptions (bazel_pattern , bazel_files )
206
217
cmake_options = FindKnownOptions (cmake_pattern , cmake_files )
207
218
@@ -210,10 +221,72 @@ def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files):
210
221
both .update (bazel_options )
211
222
both .update (cmake_options )
212
223
for k in both .keys ():
213
- if not OptionsAreEqual (bazel_options .get (k , None ), cmake_options .get (k , None )):
224
+ if not OptionsAreEqual (
225
+ bazel_options .get (k , None ),
226
+ cmake_options .get (k , None ),
227
+ warnings_as_errors ,
228
+ ):
214
229
are_equal = False
215
230
return are_equal
216
231
232
+ def CompareExternalDependencyVersions ():
233
+ pattern = re .compile (BAZEL_MODULE_REGEX )
234
+ all_okay = True
235
+ with open (Path (SDK_ROOT ) / "MODULE.bazel" , "r" ) as bazel_module_file :
236
+ for line in bazel_module_file :
237
+ maybe_match = pattern .match (line )
238
+ if not maybe_match :
239
+ continue
240
+
241
+ current_submodule_pin = subprocess .run (
242
+ ("git" , "-C" , SDK_ROOT , "rev-parse" , f'HEAD:lib/{ maybe_match .group ("dependency" )} ' ),
243
+ text = True ,
244
+ check = True ,
245
+ capture_output = True ,
246
+ ).stdout .strip ()
247
+ if current_submodule_pin != maybe_match .group ("commit" ):
248
+ _LOG .error (" External pins for %s do not match:" , maybe_match .group ("dependency" ))
249
+ _LOG .error (" [CMAKE] %s" , current_submodule_pin )
250
+ _LOG .error (" [BAZEL] %s" , maybe_match .group ("commit" ))
251
+ all_okay = False
252
+ else :
253
+ _LOG .info (" External pins for %s match!" , maybe_match .group ("dependency" ))
254
+
255
+ return all_okay
256
+
257
+ def CompareSdkVersion ():
258
+ # Find version string specified in Bazel.
259
+ bazel_module_file_path = Path (SDK_ROOT ) / "MODULE.bazel"
260
+ bazel_module_file_contents = bazel_module_file_path .read_text ()
261
+ bazel_sdk_version = BAZEL_VERSION_REGEX .search (bazel_module_file_contents )
262
+ if not bazel_sdk_version :
263
+ _LOG .error (" Failed to find Bazel Pico SDK version string" )
264
+ return False
265
+ bazel_version_string = bazel_sdk_version .group ("sdk_version" )
266
+
267
+ # Find version string specified in CMake.
268
+ cmake_version_parts = {}
269
+ with open (Path (SDK_ROOT ) / "pico_sdk_version.cmake" , "r" ) as cmake_version_file :
270
+ for line in cmake_version_file :
271
+ match = CMAKE_VERSION_REGEX .match (line )
272
+ if match :
273
+ cmake_version_parts [match .group ("part" )] = match .group ("value" )
274
+ if len (cmake_version_parts ) < 3 :
275
+ _LOG .error (" Failed to find CMake Pico SDK version string" )
276
+ return False
277
+ cmake_version_string = "." .join ((
278
+ cmake_version_parts ["MAJOR" ],
279
+ cmake_version_parts ["MINOR" ],
280
+ cmake_version_parts ["REVISION" ],
281
+ ))
282
+ if "PRE_RELEASE_ID" in cmake_version_parts :
283
+ cmake_version_string += "-" + cmake_version_parts ["PRE_RELEASE_ID" ]
284
+
285
+ if cmake_version_string != bazel_version_string :
286
+ _LOG .error (" Declared CMake SDK version is %s and Bazel is %s" , cmake_version_string , bazel_version_string )
287
+ return False
288
+
289
+ return True
217
290
218
291
def compare_build_systems ():
219
292
cmake_files = [
@@ -227,20 +300,35 @@ def compare_build_systems():
227
300
for f in glob .glob (os .path .join (SDK_ROOT , p ), recursive = True )
228
301
]
229
302
230
- _LOG .info ("[1/2] Checking build system configuration flags..." )
231
- build_options_ok = CompareOptions (
232
- "PICO_BAZEL_CONFIG" , bazel_files , "PICO_CMAKE_CONFIG" , cmake_files
233
- )
303
+ results = []
304
+ _LOG .info ("[1/3] Checking build system configuration flags..." )
305
+ results .append (CompareOptions (
306
+ "PICO_BAZEL_CONFIG" ,
307
+ bazel_files ,
308
+ "PICO_CMAKE_CONFIG" ,
309
+ cmake_files ,
310
+ # For now, allow CMake and Bazel to go out of sync when it comes to
311
+ # build configurability since it's a big ask to make contributors
312
+ # implement the same functionality in both builds.
313
+ warnings_as_errors = False ,
314
+ ))
234
315
235
- _LOG .info ("[2/2 ] Checking build system defines..." )
236
- build_defines_ok = CompareOptions (
316
+ _LOG .info ("[2/4 ] Checking build system defines..." )
317
+ results . append ( CompareOptions (
237
318
"PICO_BUILD_DEFINE" , bazel_files , "PICO_BUILD_DEFINE" , cmake_files
238
- )
319
+ ))
320
+
321
+ _LOG .info ("[3/4] Checking submodule pins..." )
322
+ results .append (CompareExternalDependencyVersions ())
323
+
324
+ _LOG .info ("[4/4] Checking version strings..." )
325
+ results .append (CompareSdkVersion ())
239
326
240
- if build_options_ok and build_defines_ok :
241
- _LOG .info ("OK " )
327
+ if False not in results :
328
+ _LOG .info ("Passed with no blocking failures " )
242
329
return 0
243
330
331
+ _LOG .error ("One or more blocking failures detected" )
244
332
return 1
245
333
246
334
0 commit comments