1
0
mirror of https://github.com/raspberrypi/pico-sdk.git synced 2025-08-07 17:02:52 +03:00

Extend build system checks (#2039)

* Adds check that ensures the Bazel and CMake Pico SDK version strings
  stay in sync.
* Adds check that ensures the Bazel pins for external dependencies stays
  in sync with the git submodule pins.
* Updates cyw43-driver pin in Bazel.
* Makes the checks for some build configurability options non-blocking.
This commit is contained in:
armandomontanez
2024-11-13 12:11:49 -08:00
committed by GitHub
parent 06b7c1cf9e
commit 1b64cac8d6
3 changed files with 156 additions and 71 deletions

View File

@@ -43,34 +43,33 @@ jobs:
# Checks that the current BCR-requested version of Picotool builds. # Checks that the current BCR-requested version of Picotool builds.
- name: Bazel Picotool backwards compatibility - name: Bazel Picotool backwards compatibility
run: bazel build @picotool//:picotool run: bazel build @picotool//:picotool
# Add back when it begins to pass. other-bazel-checks:
# other-bazel-checks: runs-on: ubuntu-latest
# runs-on: ubuntu-latest steps:
# steps: - name: Checkout
# - name: Checkout uses: actions/checkout@v4
# uses: actions/checkout@v4 with:
# with: fetch-depth: 0
# fetch-depth: 0 - name: Get Bazel
# - name: Get Bazel uses: bazel-contrib/setup-bazel@0.9.0
# uses: bazel-contrib/setup-bazel@0.9.0 with:
# with: # Avoid downloading Bazel every time.
# # Avoid downloading Bazel every time. bazelisk-cache: true
# bazelisk-cache: true # Store build cache per workflow.
# # Store build cache per workflow. disk-cache: ${{ github.workflow }}
# disk-cache: ${{ github.workflow }} # Share repository cache between workflows.
# # Share repository cache between workflows. repository-cache: true
# repository-cache: true # Only needed to drive the presbumit scripts.
# # Only needed to drive the presbumit scripts. - name: Setup Python
# - name: Setup Python uses: actions/setup-python@v5
# uses: actions/setup-python@v5 with:
# with: python-version: '3.10'
# python-version: '3.10' - name: Fetch latest Picotool
# - name: Fetch latest Picotool uses: actions/checkout@v4
# uses: actions/checkout@v4 with:
# with: repository: raspberrypi/picotool
# repository: raspberrypi/picotool ref: develop
# ref: develop fetch-depth: 0
# fetch-depth: 0 path: lib/picotool
# path: lib/picotool - name: Other Bazel checks
# - name: Other Bazel checks run: python3 tools/run_all_bazel_checks.py --program=other --picotool-dir=lib/picotool
# run: python3 tools/run_all_bazel_checks.py --program=other --picotool-dir=lib/picotool

View File

@@ -84,40 +84,38 @@ http_archive(
url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-arm64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026", url = "https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/mac-arm64/+/git_revision:2b0a708f41dd6291ee744704d43febc975e3d026",
) )
new_git_repository = use_repo_rule("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
# TODO: Provide tinyusb as a proper Bazel module. # TODO: Provide tinyusb as a proper Bazel module.
http_archive( new_git_repository(
name = "tinyusb", name = "tinyusb",
build_file = "//src/rp2_common/tinyusb:tinyusb.BUILD", build_file = "//src/rp2_common/tinyusb:tinyusb.BUILD",
sha256 = "d64728aef58b80d5ce3747cad133f520da46e2b7ea3aadfda0e981aba6b658b3", commit = "4232642899362fa5e9cf0dc59bad6f1f6d32c563", # keep-in-sync-with-submodule: tinyusb
strip_prefix = "tinyusb-4232642899362fa5e9cf0dc59bad6f1f6d32c563", remote = "https://github.com/hathach/tinyusb.git",
url = "https://github.com/hathach/tinyusb/archive/4232642899362fa5e9cf0dc59bad6f1f6d32c563.tar.gz",
) )
# TODO: Provide btstack as a proper Bazel module. # TODO: Provide btstack as a proper Bazel module.
http_archive( new_git_repository(
name = "btstack", name = "btstack",
build_file = "//src/rp2_common/pico_btstack:btstack.BUILD", build_file = "//src/rp2_common/pico_btstack:btstack.BUILD",
sha256 = "64e86d9cf82b346e743fe1d4818b9380712b17abdb3f2c3524e92464b5ef3d19", commit = "2b49e57bd1fae85ac32ac1f41cdb7c794de335f6", # keep-in-sync-with-submodule: btstack
strip_prefix = "btstack-2b49e57bd1fae85ac32ac1f41cdb7c794de335f6", remote = "https://github.com/bluekitchen/btstack.git",
url = "https://github.com/bluekitchen/btstack/archive/2b49e57bd1fae85ac32ac1f41cdb7c794de335f6.tar.gz",
) )
# TODO: Provide btstack as a proper Bazel module. # TODO: Provide cyw43-driver as a proper Bazel module.
http_archive( new_git_repository(
name = "cyw43-driver", name = "cyw43-driver",
build_file = "//src/rp2_common/pico_cyw43_driver:cyw43-driver.BUILD", build_file = "//src/rp2_common/pico_cyw43_driver:cyw43-driver.BUILD",
sha256 = "0fcc7707fef95dd562d5572604713266613a27caeeae2f10afeccee9592a53ce", commit = "cf924bb04c8984675ca0fc2178f082e404e048c3", # keep-in-sync-with-submodule: cyw43-driver
strip_prefix = "cyw43-driver-faf36381bad1f668a30172b6336c9a970966ef4c", remote = "https://github.com/georgerobotics/cyw43-driver.git",
url = "https://github.com/georgerobotics/cyw43-driver/archive/faf36381bad1f668a30172b6336c9a970966ef4c.tar.gz",
) )
# TODO: Provide lwip as a proper Bazel module. # TODO: Provide lwip as a proper Bazel module.
http_archive( new_git_repository(
name = "lwip", name = "lwip",
build_file = "//src/rp2_common/pico_lwip:lwip.BUILD", build_file = "//src/rp2_common/pico_lwip:lwip.BUILD",
sha256 = "72856d557f72911cf6826ef745c23c54822df83a474557823241164a1d1361aa", commit = "0a0452b2c39bdd91e252aef045c115f88f6ca773", # keep-in-sync-with-submodule: lwip
strip_prefix = "lwip-0a0452b2c39bdd91e252aef045c115f88f6ca773", remote = "https://github.com/lwip-tcpip/lwip.git",
url = "https://github.com/lwip-tcpip/lwip/archive/0a0452b2c39bdd91e252aef045c115f88f6ca773.tar.gz",
) )
register_toolchains( register_toolchains(

View File

@@ -16,7 +16,9 @@ from dataclasses import dataclass
import glob import glob
import logging import logging
import os import os
from pathlib import Path
import re import re
import subprocess
import sys import sys
from typing import Dict from typing import Dict
@@ -37,6 +39,12 @@ BAZEL_FILE_TYPES = (
ATTR_REGEX = re.compile(r",?\s*(?P<key>[^=]+)=(?P<value>[^,]+)") ATTR_REGEX = re.compile(r",?\s*(?P<key>[^=]+)=(?P<value>[^,]+)")
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*)')
BAZEL_VERSION_REGEX = re.compile(r'module\(\s*name\s*=\s*"pico-sdk",\s*version\s*=\s*"(?P<sdk_version>[^"]+)",?\s*\)')
CMAKE_VERSION_REGEX = re.compile(r'^[^#]*set\(PICO_SDK_VERSION_(?P<part>\S+)\s+(?P<value>\S+)\)')
# Sometimes the build systems are supposed to be implemented differently. This # Sometimes the build systems are supposed to be implemented differently. This
# allowlist permits the descriptions to differ between CMake and Bazel. # allowlist permits the descriptions to differ between CMake and Bazel.
BUILD_SYSTEM_DESCRIPTION_DIFFERENCE_ALLOWLIST = ( BUILD_SYSTEM_DESCRIPTION_DIFFERENCE_ALLOWLIST = (
@@ -60,7 +68,7 @@ CMAKE_ONLY_ALLOWLIST = (
"PICO_TOOLCHAIN_PATH", "PICO_TOOLCHAIN_PATH",
# Bazel uses native --platforms mechanics. # Bazel uses native --platforms mechanics.
"PICO_PLATFORM", "PICO_PLATFORM",
# TODO: No built-in, pre-configured clang offering for Bazel yet. # Named PICO_TOOLCHAIN in Bazel.
"PICO_COMPILER", "PICO_COMPILER",
# Entirely irrelevant to Bazel, use Bazel platforms: # Entirely irrelevant to Bazel, use Bazel platforms:
# https://bazel.build/extending/platforms # https://bazel.build/extending/platforms
@@ -87,14 +95,17 @@ CMAKE_ONLY_ALLOWLIST = (
"PICO_DEFAULT_PIOASM_OUTPUT_FORMAT", "PICO_DEFAULT_PIOASM_OUTPUT_FORMAT",
# Bazel always has picotool. # Bazel always has picotool.
"PICO_NO_PICOTOOL", "PICO_NO_PICOTOOL",
# TODO: Eventualy support. # These aren't supported as build flags in Bazel. Prefer to
"PICO_NO_COPRO_DIS", # set these in board header files like other SDK defines.
"PICO_DEFAULT_RP2350_PLATFORM", "CYW43_DEFAULT_PIN_WL_REG_ON",
"PICO_GCC_TRIPLE", "CYW43_DEFAULT_PIN_WL_DATA_OUT",
"PICO_NO_FLASH", "CYW43_DEFAULT_PIN_WL_DATA_IN",
"PICO_COPY_TO_RAM", "CYW43_DEFAULT_PIN_WL_HOST_WAKE",
"PICO_RP2350_ARM_S_CONFIG_HEADER_FILES", "CYW43_DEFAULT_PIN_WL_CLOCK",
"PICO_RP2350_RISCV_CONFIG_HEADER_FILES", "CYW43_DEFAULT_PIN_WL_CS",
"CYW43_PIO_CLOCK_DIV_INT",
"CYW43_PIO_CLOCK_DIV_FRAC",
"CYW43_PIO_CLOCK_DIV_DYNAMIC",
) )
BAZEL_ONLY_ALLOWLIST = ( BAZEL_ONLY_ALLOWLIST = (
@@ -181,17 +192,17 @@ def FindKnownOptions(option_pattern_matcher, file_paths):
return options return options
def OptionsAreEqual(bazel_option, cmake_option): def OptionsAreEqual(bazel_option, cmake_option, warnings_as_errors):
if bazel_option is None: if bazel_option is None:
if cmake_option.name in CMAKE_ONLY_ALLOWLIST: if cmake_option.name in CMAKE_ONLY_ALLOWLIST:
return True return True
_LOG.warning(f" {cmake_option.name} does not exist in Bazel") _LOG.warning(f" {cmake_option.name} does not exist in Bazel")
return False return not warnings_as_errors
elif cmake_option is None: elif cmake_option is None:
if bazel_option.name in BAZEL_ONLY_ALLOWLIST: if bazel_option.name in BAZEL_ONLY_ALLOWLIST:
return True return True
_LOG.warning(f" {bazel_option.name} does not exist in CMake") _LOG.warning(f" {bazel_option.name} does not exist in CMake")
return False return not warnings_as_errors
elif not bazel_option.matches(cmake_option): elif not bazel_option.matches(cmake_option):
_LOG.error(" Bazel and CMAKE definitions do not match:") _LOG.error(" Bazel and CMAKE definitions do not match:")
_LOG.error(f" [CMAKE] {bazel_option}") _LOG.error(f" [CMAKE] {bazel_option}")
@@ -201,7 +212,7 @@ def OptionsAreEqual(bazel_option, cmake_option):
return True return True
def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files): def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files, warnings_as_errors=True):
bazel_options = FindKnownOptions(bazel_pattern, bazel_files) bazel_options = FindKnownOptions(bazel_pattern, bazel_files)
cmake_options = FindKnownOptions(cmake_pattern, cmake_files) cmake_options = FindKnownOptions(cmake_pattern, cmake_files)
@@ -210,10 +221,72 @@ def CompareOptions(bazel_pattern, bazel_files, cmake_pattern, cmake_files):
both.update(bazel_options) both.update(bazel_options)
both.update(cmake_options) both.update(cmake_options)
for k in both.keys(): for k in both.keys():
if not OptionsAreEqual(bazel_options.get(k, None), cmake_options.get(k, None)): if not OptionsAreEqual(
bazel_options.get(k, None),
cmake_options.get(k, None),
warnings_as_errors,
):
are_equal = False are_equal = False
return are_equal return are_equal
def CompareExternalDependencyVersions():
pattern = re.compile(BAZEL_MODULE_REGEX)
all_okay = True
with open(Path(SDK_ROOT) / "MODULE.bazel", "r") as bazel_module_file:
for line in bazel_module_file:
maybe_match = pattern.match(line)
if not maybe_match:
continue
current_submodule_pin = subprocess.run(
("git", "-C", SDK_ROOT, "rev-parse", f'HEAD:lib/{maybe_match.group("dependency")}'),
text=True,
check=True,
capture_output=True,
).stdout.strip()
if current_submodule_pin != maybe_match.group("commit"):
_LOG.error(" External pins for %s do not match:", maybe_match.group("dependency"))
_LOG.error(" [CMAKE] %s", current_submodule_pin)
_LOG.error(" [BAZEL] %s", maybe_match.group("commit"))
all_okay = False
else:
_LOG.info(" External pins for %s match!", maybe_match.group("dependency"))
return all_okay
def CompareSdkVersion():
# Find version string specified in Bazel.
bazel_module_file_path = Path(SDK_ROOT) / "MODULE.bazel"
bazel_module_file_contents = bazel_module_file_path.read_text()
bazel_sdk_version = BAZEL_VERSION_REGEX.search(bazel_module_file_contents)
if not bazel_sdk_version:
_LOG.error(" Failed to find Bazel Pico SDK version string")
return False
bazel_version_string = bazel_sdk_version.group("sdk_version")
# Find version string specified in CMake.
cmake_version_parts = {}
with open(Path(SDK_ROOT) / "pico_sdk_version.cmake", "r") as cmake_version_file:
for line in cmake_version_file:
match = CMAKE_VERSION_REGEX.match(line)
if match:
cmake_version_parts[match.group("part")] = match.group("value")
if len(cmake_version_parts) < 3:
_LOG.error(" Failed to find CMake Pico SDK version string")
return False
cmake_version_string = ".".join((
cmake_version_parts["MAJOR"],
cmake_version_parts["MINOR"],
cmake_version_parts["REVISION"],
))
if "PRE_RELEASE_ID" in cmake_version_parts:
cmake_version_string += "-" + cmake_version_parts["PRE_RELEASE_ID"]
if cmake_version_string != bazel_version_string:
_LOG.error(" Declared CMake SDK version is %s and Bazel is %s", cmake_version_string, bazel_version_string)
return False
return True
def compare_build_systems(): def compare_build_systems():
cmake_files = [ cmake_files = [
@@ -227,20 +300,35 @@ def compare_build_systems():
for f in glob.glob(os.path.join(SDK_ROOT, p), recursive=True) for f in glob.glob(os.path.join(SDK_ROOT, p), recursive=True)
] ]
_LOG.info("[1/2] Checking build system configuration flags...") results = []
build_options_ok = CompareOptions( _LOG.info("[1/3] Checking build system configuration flags...")
"PICO_BAZEL_CONFIG", bazel_files, "PICO_CMAKE_CONFIG", cmake_files results.append(CompareOptions(
) "PICO_BAZEL_CONFIG",
bazel_files,
"PICO_CMAKE_CONFIG",
cmake_files,
# For now, allow CMake and Bazel to go out of sync when it comes to
# build configurability since it's a big ask to make contributors
# implement the same functionality in both builds.
warnings_as_errors=False,
))
_LOG.info("[2/2] Checking build system defines...") _LOG.info("[2/4] Checking build system defines...")
build_defines_ok = CompareOptions( results.append(CompareOptions(
"PICO_BUILD_DEFINE", bazel_files, "PICO_BUILD_DEFINE", cmake_files "PICO_BUILD_DEFINE", bazel_files, "PICO_BUILD_DEFINE", cmake_files
) ))
if build_options_ok and build_defines_ok: _LOG.info("[3/4] Checking submodule pins...")
_LOG.info("OK") results.append(CompareExternalDependencyVersions())
_LOG.info("[4/4] Checking version strings...")
results.append(CompareSdkVersion())
if False not in results:
_LOG.info("Passed with no blocking failures")
return 0 return 0
_LOG.error("One or more blocking failures detected")
return 1 return 1