From 5834c02e75d699ce5debda85f9a38cb2356c8d08 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 19 Sep 2026 00:22:26 -0400 Subject: [PATCH 1/3] zephyr-cp: do not reconfigure for every language build The Makefile gave west cmake arguments on every build, and west reruns the whole sysbuild configure whenever it gets any. The release build does that 17 times per board, once per language, for a change that only affects `build_circuitpython.py`. Pass `TRANSLATION` to `build_circuitpython.py` in the environment instead of as a cmake variable, and run the configure only when the build directory is new or the west arguments differ from the ones recorded at the last configure. ninja still reconfigures on its own when a Kconfig, overlay or CMake file changes. The record is written before west runs and removed if it fails, so a failed configure cannot leave the directory configured with arguments the record does not show. Co-Authored-By: Claude Fable 5.1 --- ports/zephyr-cp/Makefile | 25 +++++++++++++++++-- .../zephyr-cp/cptools/build_circuitpython.py | 7 +++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/ports/zephyr-cp/Makefile b/ports/zephyr-cp/Makefile index 1fc5040fefa..a58692146f5 100644 --- a/ports/zephyr-cp/Makefile +++ b/ports/zephyr-cp/Makefile @@ -13,7 +13,7 @@ ifneq ($(strip $(BOARD)),) WEST_SHIELD_ARGS := $(shell SHIELD_ORIGIN="$(origin SHIELD)" SHIELDS_ORIGIN="$(origin SHIELDS)" SHIELD="$(SHIELD)" SHIELDS="$(SHIELDS)" python cptools/get_west_shield_args.py $(BOARD)) endif -WEST_CMAKE_ARGS := -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake -Dzephyr-cp_TRANSLATION=$(TRANSLATION) +WEST_CMAKE_ARGS := -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake # Board files live in the board's own folder as board.overlay / board.conf. Zephyr only auto-applies # boards/.overlay and boards/.conf named after the RESOLVED Zephyr board, so it finds @@ -49,9 +49,30 @@ endif export BSIM_COMPONENTS_PATH := $(CURDIR)/tools/bsim/components export BSIM_OUT_PATH := $(CURDIR)/tools/bsim +# The translation reaches build_circuitpython.py through the environment rather than as a +# cmake argument, so that building another language does not reconfigure. +export TRANSLATION + +# Giving west any cmake argument makes it rerun the whole sysbuild configure, which takes +# longer than an incremental build. So configure only when the build directory is new or +# the arguments differ from the ones recorded at the last configure; otherwise let ninja +# decide. ninja still reconfigures by itself when a Kconfig, overlay or CMake file changes. +# The record is written before west runs and removed if west fails, so a failed configure +# cannot leave the directory configured with arguments the record does not show. +WEST_CONFIGURE_ARGS := -b $(BOARD) $(WEST_SHIELD_ARGS) --sysbuild -- $(WEST_CMAKE_ARGS) +WEST_ARGS_STAMP := $(BUILD)/west_configure_args.txt + $(BUILD)/zephyr-cp/zephyr/zephyr.elf: python cptools/pre_zephyr_build_prep.py $(BOARD) - west build -b $(BOARD) -d $(BUILD) $(WEST_SHIELD_ARGS) --sysbuild -- $(WEST_CMAKE_ARGS) + @mkdir -p $(BUILD) + @if [ ! -f $(BUILD)/build.ninja ] || [ "$$(cat $(WEST_ARGS_STAMP) 2>/dev/null)" != '$(WEST_CONFIGURE_ARGS)' ]; then \ + echo west build -d $(BUILD) $(WEST_CONFIGURE_ARGS); \ + echo '$(WEST_CONFIGURE_ARGS)' > $(WEST_ARGS_STAMP); \ + west build -d $(BUILD) $(WEST_CONFIGURE_ARGS) || { rm -f $(WEST_ARGS_STAMP); exit 1; }; \ + else \ + echo west build -d $(BUILD); \ + west build -d $(BUILD); \ + fi python ../../tools/build_memory_info.py $(BUILD)/zephyr-cp/zephyr/zephyr.map $(BUILD) --image $(BUILD)/zephyr-cp/zephyr/zephyr.bin $(BUILD)/firmware.elf: $(BUILD)/zephyr-cp/zephyr/zephyr.elf diff --git a/ports/zephyr-cp/cptools/build_circuitpython.py b/ports/zephyr-cp/cptools/build_circuitpython.py index 01e96d5ccdc..47f0b295aae 100644 --- a/ports/zephyr-cp/cptools/build_circuitpython.py +++ b/ports/zephyr-cp/cptools/build_circuitpython.py @@ -367,9 +367,10 @@ async def build_circuitpython(): # noqa: C901 board = cmake_args["BOARD_ALIAS"] if not board: board = zephyr_board - translation = cmake_args["TRANSLATION"] - if not translation: - translation = "en_US" + # The Makefile passes the translation in the environment so that switching languages + # does not need a cmake reconfigure. The cmake argument is the fallback for builds + # run with west directly. + translation = os.environ.get("TRANSLATION") or cmake_args["TRANSLATION"] or "en_US" for module in ALWAYS_ON_MODULES: circuitpython_flags.append(f"-DCIRCUITPY_{module.upper()}=1") lto = cmake_args.get("LTO", "n") == "y" From f220b8edfa9cb61359230b0c710d87b705cc0810 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 20 Sep 2026 11:52:59 -0400 Subject: [PATCH 2/3] Apply batched suggestions from code review Co-authored-by: Mikey Sklar --- ports/zephyr-cp/Makefile | 11 +++-------- ports/zephyr-cp/cptools/build_circuitpython.py | 4 +--- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/ports/zephyr-cp/Makefile b/ports/zephyr-cp/Makefile index a58692146f5..76188f4e536 100644 --- a/ports/zephyr-cp/Makefile +++ b/ports/zephyr-cp/Makefile @@ -49,16 +49,11 @@ endif export BSIM_COMPONENTS_PATH := $(CURDIR)/tools/bsim/components export BSIM_OUT_PATH := $(CURDIR)/tools/bsim -# The translation reaches build_circuitpython.py through the environment rather than as a -# cmake argument, so that building another language does not reconfigure. +# In the environment, not a cmake argument, so a new language does not reconfigure. export TRANSLATION -# Giving west any cmake argument makes it rerun the whole sysbuild configure, which takes -# longer than an incremental build. So configure only when the build directory is new or -# the arguments differ from the ones recorded at the last configure; otherwise let ninja -# decide. ninja still reconfigures by itself when a Kconfig, overlay or CMake file changes. -# The record is written before west runs and removed if west fails, so a failed configure -# cannot leave the directory configured with arguments the record does not show. +# west reruns the whole sysbuild configure whenever it gets a cmake argument, so pass +# them only when the build directory is new or they changed since the last configure. WEST_CONFIGURE_ARGS := -b $(BOARD) $(WEST_SHIELD_ARGS) --sysbuild -- $(WEST_CMAKE_ARGS) WEST_ARGS_STAMP := $(BUILD)/west_configure_args.txt diff --git a/ports/zephyr-cp/cptools/build_circuitpython.py b/ports/zephyr-cp/cptools/build_circuitpython.py index 47f0b295aae..21d95c530dd 100644 --- a/ports/zephyr-cp/cptools/build_circuitpython.py +++ b/ports/zephyr-cp/cptools/build_circuitpython.py @@ -367,9 +367,7 @@ async def build_circuitpython(): # noqa: C901 board = cmake_args["BOARD_ALIAS"] if not board: board = zephyr_board - # The Makefile passes the translation in the environment so that switching languages - # does not need a cmake reconfigure. The cmake argument is the fallback for builds - # run with west directly. + # The environment wins, so the Makefile can switch languages without a reconfigure. translation = os.environ.get("TRANSLATION") or cmake_args["TRANSLATION"] or "en_US" for module in ALWAYS_ON_MODULES: circuitpython_flags.append(f"-DCIRCUITPY_{module.upper()}=1") From cce234f2092655808dd906c6c43a99df5cac6d01 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sun, 20 Sep 2026 12:17:56 -0400 Subject: [PATCH 3/3] allow undo of DEBUG=1 without rm -rf _build/* rm -rf autoapi rm -rf circuitpython-stubs dist *.egg-info --- ports/zephyr-cp/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/zephyr-cp/Makefile b/ports/zephyr-cp/Makefile index a58692146f5..909cdf157d3 100644 --- a/ports/zephyr-cp/Makefile +++ b/ports/zephyr-cp/Makefile @@ -40,9 +40,8 @@ else CP_BOARD_CONF := $(DEBUG_CONF_FILE) endif endif -ifneq ($(CP_BOARD_CONF),) +# Always pass the conf file, even if empty. This undoes DEBUG=1 when it's omitted on a later run. WEST_CMAKE_ARGS += -Dzephyr-cp_EXTRA_CONF_FILE=$(CP_BOARD_CONF) -endif .PHONY: $(BUILD)/zephyr-cp/zephyr/zephyr.elf flash recover debug debug-jlink debugserver attach run run-sim clean menuconfig all clean-all sim clean-sim test fetch-port-submodules