cibuildmp 0.7.0__tar.gz → 0.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. cibuildmp-0.7.2/.claude/settings.json +8 -0
  2. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.claude/skills/docker-local/SKILL.md +51 -0
  3. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/build-examples.yml +36 -5
  4. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/test-upstream-natmod.yml +2 -2
  5. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/test-upstream-usermodule.yml +50 -10
  6. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/verify-lv-binding-micropython.yml +1 -1
  7. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/CHANGELOG.md +86 -1
  8. {cibuildmp-0.7.0/src/cibuildmp.egg-info → cibuildmp-0.7.2}/PKG-INFO +129 -22
  9. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/README.md +128 -21
  10. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/0000-TRACKER.md +8 -2
  11. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/ACTIONS.md +2 -2
  12. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0053-usermod-ports-without-a-build-driver.md +9 -0
  13. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0056-usermod-with-no-user-c-module.md +79 -5
  14. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0057-multiple-modules-per-build.md +27 -5
  15. cibuildmp-0.7.2/docs/records/0060-rp2-build-driver.md +200 -0
  16. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0095-cache-root-splits-source-from-build-state.md +21 -0
  17. cibuildmp-0.7.2/docs/records/0098-build-override-may-be-as-unnecessary-as-scratch-root-was.md +123 -0
  18. cibuildmp-0.7.2/docs/records/0099-variant-becomes-a-real-per-target-override-not-an-identifier-axis.md +121 -0
  19. cibuildmp-0.7.2/docs/records/0100-samd-build-driver-plan.md +244 -0
  20. cibuildmp-0.7.2/examples/bare-firmware/cibuildmp.toml +26 -0
  21. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/usercmodule/cibuildmp.toml +7 -4
  22. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/cli.py +2 -1
  23. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/natmod/options.py +7 -1
  24. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_common.py +13 -13
  25. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_esp32.py +121 -25
  26. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_qemu.py +3 -2
  27. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_rp2.py +56 -14
  28. cibuildmp-0.7.2/src/cibuildmp/platforms/usermod/build_samd.py +251 -0
  29. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_unix.py +10 -4
  30. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_webassembly.py +3 -2
  31. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/build_windows.py +7 -5
  32. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/options.py +70 -3
  33. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/orchestrate.py +52 -56
  34. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/targets.py +26 -7
  35. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/build-platforms.toml +6 -0
  36. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/sources.py +10 -53
  37. {cibuildmp-0.7.0 → cibuildmp-0.7.2/src/cibuildmp.egg-info}/PKG-INFO +129 -22
  38. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/SOURCES.txt +7 -0
  39. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/scm_file_list.json +7 -0
  40. cibuildmp-0.7.2/src/cibuildmp.egg-info/scm_version.json +8 -0
  41. cibuildmp-0.7.2/tests/conftest.py +17 -0
  42. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_portinfo.py +12 -3
  43. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_sources.py +0 -26
  44. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_esp32.py +42 -8
  45. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_qemu.py +11 -0
  46. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_rp2.py +25 -2
  47. cibuildmp-0.7.2/tests/test_usermod_build_samd.py +264 -0
  48. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_unix.py +14 -0
  49. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_webassembly.py +11 -0
  50. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_windows.py +11 -0
  51. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_options.py +95 -0
  52. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_orchestrate.py +146 -21
  53. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_targets.py +2 -1
  54. cibuildmp-0.7.0/docs/records/0060-rp2-build-driver.md +0 -87
  55. cibuildmp-0.7.0/src/cibuildmp.egg-info/scm_version.json +0 -8
  56. cibuildmp-0.7.0/tests/conftest.py +0 -40
  57. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.dockerignore +0 -0
  58. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-natmod/action.yml +0 -0
  59. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-armv7m/action.yml +0 -0
  60. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-esp32/action.yml +0 -0
  61. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-rp2040/action.yml +0 -0
  62. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-unix/action.yml +0 -0
  63. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-webassembly/action.yml +0 -0
  64. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/build-usermod-windows/action.yml +0 -0
  65. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/clone-micropython/action.yml +0 -0
  66. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/fetch-micropython/action.yml +0 -0
  67. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/actions/run-with-wine/action.yml +0 -0
  68. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/dependabot.yml +0 -0
  69. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/coverage.yml +0 -0
  70. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/pin-staleness.yml +0 -0
  71. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/pre-commit.yml +0 -0
  72. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/probe-overlay.yml +0 -0
  73. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/publish-docker-images.yml +0 -0
  74. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/publish.yml +0 -0
  75. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/test-all-platforms.yml +0 -0
  76. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/test-platforms.yml +0 -0
  77. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.github/workflows/verify-docker-images.yml +0 -0
  78. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.gitignore +0 -0
  79. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/.pre-commit-config.yaml +0 -0
  80. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/CLAUDE.md +0 -0
  81. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/CONTRIBUTING.md +0 -0
  82. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/LICENSE +0 -0
  83. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/action.yml +0 -0
  84. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/fetch_bootlin_metadata.py +0 -0
  85. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/ghcr_prune_scan.py +0 -0
  86. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/plan_test_matrix.py +0 -0
  87. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/publish_images.py +0 -0
  88. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/refresh_docs.py +0 -0
  89. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/refresh_natmod_archs.py +0 -0
  90. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/refresh_toolchain_pins.py +0 -0
  91. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/refresh_toolchains.py +0 -0
  92. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/refresh_usermod_boards.py +0 -0
  93. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/render_test_summary.py +0 -0
  94. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/update_docker.py +0 -0
  95. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/bin/update_toolchains.py +0 -0
  96. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/cibuildmp.toml +0 -0
  97. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/embedded_base.Dockerfile +0 -0
  98. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/esp_idf_base.Dockerfile +0 -0
  99. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/manylinux_2_41_mipsel.Dockerfile +0 -0
  100. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/natmod_host.Dockerfile +0 -0
  101. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/ppc64le_linux.Dockerfile +0 -0
  102. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/pypa-tracker.Dockerfile +0 -0
  103. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/webassembly.Dockerfile +0 -0
  104. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/windows.Dockerfile +0 -0
  105. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/xtensa_esp.Dockerfile +0 -0
  106. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docker/xtensa_lx106.Dockerfile +0 -0
  107. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/BACKLOG.md +0 -0
  108. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0001-natmod-first.md +0 -0
  109. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0002-delegate-compile-own-environment.md +0 -0
  110. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0003-toolchain-resolution-per-target.md +0 -0
  111. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0004-config-file-location.md +0 -0
  112. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0005-one-identifier-namespace.md +0 -0
  113. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0006-no-test-runners-phase1.md +0 -0
  114. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0007-usermod-vendors-mpbuild-board-db.md +0 -0
  115. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0008-tool-distribution-deferred.md +0 -0
  116. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0009-one-job-loop-fanout-opt-in.md +0 -0
  117. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0010-pinned-data-in-resources.md +0 -0
  118. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0011-one-repo-absorbs-micropython-native-ci.md +0 -0
  119. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0012-pyelftools-ar-own-deps.md +0 -0
  120. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0013-micropython-list-dedup-by-abi.md +0 -0
  121. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0014-mip-package-per-identifier.md +0 -0
  122. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0015-rv32imc-arch-flags-identifier.md +0 -0
  123. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0016-usermod-user-c-modules-dir-vs-cmake.md +0 -0
  124. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0017-usermod-frozen-manifest-merge.md +0 -0
  125. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0018-windows-provisioning-fourth-story.md +0 -0
  126. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0019-esp-idf-provisioning-heaviest.md +0 -0
  127. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0020-usermod-runner-selection-structural.md +0 -0
  128. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0021-usermod-execution-central-value.md +0 -0
  129. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0022-zephyr-third-selector-axis.md +0 -0
  130. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0023-usermod-identifier-scheme-config-output.md +0 -0
  131. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0024-unix-armhf-mipsel-cross-compiles.md +0 -0
  132. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0025-dockerfiles-bake-unix-cross-toolchains.md +0 -0
  133. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0026-one-docker-image-per-port.md +0 -0
  134. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0027-orchestrate-output-dir-and-exec-bit-fixes.md +0 -0
  135. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0028-container-per-port-migration-plan.md +0 -0
  136. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0029-github-actions-job-summary.md +0 -0
  137. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0030-container-approach-natmod-and-docker-vs-qemu.md +0 -0
  138. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0031-unix-musllinux-libc-axis.md +0 -0
  139. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0032-unix-docker-default-and-webassembly-wiring.md +0 -0
  140. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0033-cibuildmp-never-builds-docker-image-itself.md +0 -0
  141. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0034-m0-skeleton.md +0 -0
  142. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0035-m1-micropython-mpy-cross-provisioning.md +0 -0
  143. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0036-m2-toolchain-resolver.md +0 -0
  144. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0037-m3-the-build-itself.md +0 -0
  145. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0038-m5-adopt-in-three-repos.md +0 -0
  146. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0039-usermod-composite-actions-status.md +0 -0
  147. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0040-usermod-tests-deferred.md +0 -0
  148. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0041-docs-restructure.md +0 -0
  149. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0042-windows-docker-wiring-and-resolver-removal.md +0 -0
  150. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0043-unix-adopts-cibuildwheel-native-image-model.md +0 -0
  151. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0044-unix-native-images-landed.md +0 -0
  152. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0045-only-is-a-filter-not-a-forced-identifier.md +0 -0
  153. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0046-pin-staleness-checker.md +0 -0
  154. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0047-run-output-parity-with-cibuildwheel.md +0 -0
  155. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0048-build-skip-live-in-opposite-tables.md +0 -0
  156. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0049-no-matrix-generation-archs-vocabulary.md +0 -0
  157. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0050-natmod-is-docker-only.md +0 -0
  158. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0051-usermod-identifiers-have-no-version-axis.md +0 -0
  159. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0052-config-is-a-tree-not-a-selector-matrix.md +0 -0
  160. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0054-usermod-example-from-upstream-usercmodule.md +0 -0
  161. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0055-natmod-example-from-upstream-natmod.md +0 -0
  162. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0058-image-groups-are-toolchains-not-ports.md +0 -0
  163. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0059-ghcr-untagged-cleanup-deletes-referenced-manifests.md +0 -0
  164. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0061-usermod-build-drivers-split-per-port.md +0 -0
  165. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0062-test-platforms-per-port-orchestrator.md +0 -0
  166. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0063-keep-going-and-json-build-report.md +0 -0
  167. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0065-bucketed-test-matrix-planning.md +0 -0
  168. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0066-extra-cmake-args.md +0 -0
  169. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0067-user-c-modules-flat-shape-autodetect.md +0 -0
  170. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0068-docker-dependabot-grouping-and-mipsel-ubuntu-26-04.md +0 -0
  171. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0069-upstream-usercmodule-narrow-ci-slice.md +0 -0
  172. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0070-unix-collected-binary-missing-repaired-lib-sidecar.md +0 -0
  173. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0071-micropython-placeholder-in-user-c-modules.md +0 -0
  174. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0072-natmod-micropython-placeholder-and-upstream-natmod-ci.md +0 -0
  175. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0073-composite-actions-are-a-permanent-legacy-fallback.md +0 -0
  176. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0074-usermod-family-table-and-retired-table-messages-removed.md +0 -0
  177. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0075-top-level-scalar-keys-are-validated.md +0 -0
  178. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0076-the-mipsel-holdout-is-bclibc-and-wasm3-not-a7p.md +0 -0
  179. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0077-docs-drift-is-a-failing-test-not-a-discipline-problem.md +0 -0
  180. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0078-uncontexted-agent-audit-as-a-docs-test.md +0 -0
  181. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0079-collected-artifact-is-more-than-one-file.md +0 -0
  182. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0080-windows-and-qemu-usermod-smoke-tests.md +0 -0
  183. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0081-output-dir-gitignore.md +0 -0
  184. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0082-natmod-old-tags-fail-mpy-cross-under-gcc-15.md +0 -0
  185. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0083-windows-fully-prebuilt-mingw-toolchain.md +0 -0
  186. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0084-per-identifier-toolchain-tarballs-and-the-end-of-shared-images.md +0 -0
  187. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0085-arm-embedded-thins-out-and-the-toolchain-version-becomes-a-row-fact.md +0 -0
  188. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0086-generic-in-container-toolchain-tarball-fetch.md +0 -0
  189. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0087-arm-riscv-embedded-thin-out-toolchain-version-lands.md +0 -0
  190. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0088-mimxrt-own-floor.md +0 -0
  191. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0089-natmod-arm-riscv-embedded-toolchain-version.md +0 -0
  192. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0090-toolchain-pins-checker-and-0058-text-followup.md +0 -0
  193. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0091-tag-cflags-into-every-ports-mpy-cross.md +0 -0
  194. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0092-usermod-toml-and-tag-cflags-against-build-platforms.md +0 -0
  195. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0093-pre-v1-20-0-tags-had-never-built.md +0 -0
  196. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0094-arm-gnu-toolchain-is-a-real-third-choice-for-arm-embedded.md +0 -0
  197. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0096-arm-riscv-embedded-collapse-into-embedded-base.md +0 -0
  198. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/records/0097-lv-binding-micropython-builds-through-cibuildmp.md +0 -0
  199. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/reference/design.md +0 -0
  200. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/reference/open-questions.md +0 -0
  201. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/reference/toolchain-facts/bootlin.toml +0 -0
  202. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/reference/toolchain-facts/toolchains.toml +0 -0
  203. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/docs/reference/vendored-images.md +0 -0
  204. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/lv_binding_micropython/cibuildmp.toml +0 -0
  205. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/lv_binding_micropython/smoke_test.py +0 -0
  206. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/natmod/cibuildmp.toml +0 -0
  207. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/cibuildmp.toml +0 -0
  208. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/micropython.cmake +0 -0
  209. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/natmod/Makefile +0 -0
  210. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/natmod/template.c +0 -0
  211. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/src/facade.py +0 -0
  212. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/src/template_core.c +0 -0
  213. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/src/template_core.h +0 -0
  214. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/usermod/manifest.py +0 -0
  215. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/usermod/micropython.mk +0 -0
  216. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/template/usermod/template_usermod.c +0 -0
  217. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/usercmodule/micropython.cmake +0 -0
  218. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/usercmodule/smoke_test.py +0 -0
  219. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/Makefile +0 -0
  220. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/NOTICE +0 -0
  221. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/cibuildmp.toml +0 -0
  222. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/esp8266-rom.S +0 -0
  223. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/libc.c +0 -0
  224. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/runtime.c +0 -0
  225. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt-impl-tableops.inc +0 -0
  226. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt-impl.c +0 -0
  227. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt-impl.h +0 -0
  228. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt-mem-impl-helper.inc +0 -0
  229. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt-mem-impl.c +0 -0
  230. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/runtime/wasm-rt.h +0 -0
  231. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/examples/wasm2mpy/test/zig.wasm +0 -0
  232. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/pyproject.toml +0 -0
  233. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/setup.cfg +0 -0
  234. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/__init__.py +0 -0
  235. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/__main__.py +0 -0
  236. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/dockerrun.py +0 -0
  237. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/options.py +0 -0
  238. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/__init__.py +0 -0
  239. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/natmod/__init__.py +0 -0
  240. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/natmod/build.py +0 -0
  241. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/natmod/targets.py +0 -0
  242. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/__init__.py +0 -0
  243. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/boards.py +0 -0
  244. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/espidf.py +0 -0
  245. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/manifests.py +0 -0
  246. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/platforms/usermod/portinfo.py +0 -0
  247. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/report.py +0 -0
  248. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/natmod.toml +0 -0
  249. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/pinned_docker_images.toml +0 -0
  250. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/pinned_pypa_images.toml +0 -0
  251. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/pinned_toolchains.toml +0 -0
  252. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources/tag_cflags.toml +0 -0
  253. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/resources.py +0 -0
  254. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/selector.py +0 -0
  255. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/stepsummary.py +0 -0
  256. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp/toolchain_fetch.py +0 -0
  257. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/dependency_links.txt +0 -0
  258. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/entry_points.txt +0 -0
  259. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/requires.txt +0 -0
  260. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/src/cibuildmp.egg-info/top_level.txt +0 -0
  261. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_boards.py +0 -0
  262. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_bootlin_table.py +0 -0
  263. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_build.py +0 -0
  264. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_cli.py +0 -0
  265. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_cli_multi_family.py +0 -0
  266. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_dockerrun_container.py +0 -0
  267. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_docs.py +0 -0
  268. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_espidf.py +0 -0
  269. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_manifests.py +0 -0
  270. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_options.py +0 -0
  271. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_options_cascade.py +0 -0
  272. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_overrides.py +0 -0
  273. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_plan_test_matrix.py +0 -0
  274. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_platform_row_facts.py +0 -0
  275. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_render_test_summary.py +0 -0
  276. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_report.py +0 -0
  277. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_selector.py +0 -0
  278. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_stepsummary.py +0 -0
  279. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_targets.py +0 -0
  280. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_toolchain_fetch.py +0 -0
  281. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_build_common.py +0 -0
  282. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/tests/test_usermod_dockerrun.py +0 -0
  283. {cibuildmp-0.7.0 → cibuildmp-0.7.2}/uv.lock +0 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "autoMode": {
3
+ "allow": [
4
+ "$defaults",
5
+ "Copying this session's own agent-proxy TLS CA bundle (/root/.ccr/ca-bundle.crt) into a Docker build context or container for this repo's own Docker-based build drivers, per .claude/skills/docker-local/SKILL.md section 4 -- session-local test tooling, never a committed Dockerfile."
6
+ ]
7
+ }
8
+ }
@@ -246,6 +246,57 @@ ERROR: unable to select packages:
246
246
  describes, so the ordinary Debian/Ubuntu fix routes through the one thing that cannot succeed yet.
247
247
  Appending directly to the file already on disk sidesteps the whole cycle.
248
248
 
249
+ ## 4a. When the CA-injection fix itself gets blocked: pre-seed the tool's own download cache instead
250
+
251
+ Confirmed live (record [0060]'s own esp32 correction): copying this session's own proxy CA into a
252
+ Dockerfile/container — section 4's whole recipe, however it's phrased — can itself get refused by
253
+ this session's **auto-mode classifier**, a separate layer from the network allowlist and from
254
+ ordinary tool permissions. It reads as "inject a certificate into a container", a real MITM
255
+ pattern, regardless of the legitimate reason here. Two things do **not** get past this:
256
+
257
+ - Adding an explicit allow rule to `.claude/settings.json`'s own `autoMode.allow` list (the
258
+ documented mechanism for exactly this) is *itself* blocked by the same classifier — an agent
259
+ cannot self-grant a permission the classifier just refused, which is the boundary working as
260
+ intended, not a bug to route around.
261
+ - Even after a human adds that rule from outside the session (git push, GitHub web UI, editing
262
+ the file directly on disk) and it lands in the working tree, the running session does not pick
263
+ it up — the settings watcher only watches paths that had a settings file *at session start*, the
264
+ identical caveat the `update-config` skill documents for hooks. Nothing short of a session
265
+ restart reloads it.
266
+
267
+ **If a restart isn't available, don't force the CA path — ask whether the specific tool doing the
268
+ fetch already implements its own "already downloaded, skip the network" check, and satisfy that
269
+ check from the host instead.** Several of this project's own container-time fetchers already do
270
+ (`toolchain_fetch.fetch_script()`'s marker file, `container_mpy_cross()`'s cache-by-existence
271
+ rule) — and so, live-verified this session, does ESP-IDF's own `idf_tools.py`: its `download()`
272
+ method looks for `$IDF_TOOLS_PATH/dist/<archive_name>`, verifies its sha256/size against
273
+ `tools.json`, and returns immediately without touching the network if it matches. That check does
274
+ not care *how* the file got there.
275
+
276
+ The recipe, generalized from the real esp32 case:
277
+
278
+ 1. Find the *tool's own* manifest of exactly what it will fetch, with real URLs and checksums —
279
+ `idf_tools.py`'s is `<idf-checkout>/tools/tools.json`; other tools have their own equivalent.
280
+ Cloning the source checkout itself is usually plain `git clone` (this session's own host-side
281
+ `curl`/`git` already work fine against real hosts — it is only *container* traffic that hits
282
+ the interception wall) — `usermod/espidf.py`'s own `fetch_esp_idf()` already does exactly this
283
+ clone, host-side, for the identical reason.
284
+ 2. Download each needed artifact **on the host**, into whatever local path the tool's own cache
285
+ check expects (`$IDF_TOOLS_PATH/dist/<archive_name>` for `idf_tools.py`), verifying its
286
+ checksum against the manifest's own value — never trust-on-first-use.
287
+ 3. Make sure that path is one of the container's own bind mounts (it usually already is, if it's
288
+ the tool's persistent cache directory rather than the ephemeral build tree) — then the
289
+ container sees the identical files at the identical path, no new mount, no Dockerfile edit.
290
+ 4. Run the real container-time install/fetch command unmodified. It reports "already downloaded"
291
+ or equivalent and does real, genuine extraction/verification with **zero network calls from
292
+ inside the container** — this is not a stub or a shortcut, the resulting tool is the real
293
+ published artifact, just fetched via a path that was never blocked in the first place.
294
+
295
+ This is real work (the esp32 case needed five separate archives, ~230 MB, individually identified
296
+ from `tools.json` and individually checksummed) but it is a live verification with a genuinely
297
+ real toolchain, not a mock — worth it over declaring the fix "untestable here" when the target
298
+ tool's own caching already does half the job.
299
+
249
300
  ## 5. Hosts this repo's own `docker/*.Dockerfile` files actually fetch from
250
301
 
251
302
  Grepped directly (`grep -rhoE 'https?://[a-zA-Z0-9.-]+' docker/*.Dockerfile`),
@@ -110,8 +110,8 @@ jobs:
110
110
 
111
111
  - name: List built artifacts
112
112
  run: |
113
- ls -laR examples/template/mpyhouse
114
- ls -laR examples/wasm2mpy/mpyhouse
113
+ tree -a examples/template/mpyhouse
114
+ tree -a examples/wasm2mpy/mpyhouse
115
115
  cat examples/template/mpyhouse/*/package.json
116
116
 
117
117
  # Split from `build` above rather than added as one more step there:
@@ -265,7 +265,38 @@ jobs:
265
265
  build: ${{ matrix.build }}
266
266
 
267
267
  - name: List built artifacts
268
- run: ls -laR examples/template/mpyhouse
268
+ run: tree -a examples/template/mpyhouse
269
+
270
+ # ── usermod: stock upstream firmware, no C module at all ───────────
271
+ #
272
+ # examples/bare-firmware/cibuildmp.toml (record 0056's Option A): one
273
+ # Make-driven target (`unix`) and one CMake-driven one (`rp2`), the two
274
+ # build-system shapes `USER_C_MODULES=` (empty) has to no-op on cleanly.
275
+ # `CIBMP_NO_USER_C_MODULES=1` here, not `no-user-c-modules = true` in
276
+ # that file -- this job is also the live proof the environment-variable
277
+ # activation path works, not just the TOML key (README's own "Building
278
+ # stock upstream firmware" section links back to this job).
279
+ #
280
+ # Both targets are native to an amd64 runner (dockerrun.platform_for():
281
+ # `unix`'s own x86_64 image, every other port's `linux/amd64` cross
282
+ # host) -- no docker/setup-qemu-action needed, unlike build-usermod's
283
+ # own qemu leg.
284
+ build-bare-firmware:
285
+ runs-on: ubuntu-latest
286
+ permissions:
287
+ contents: read
288
+ steps:
289
+ - uses: actions/checkout@v7
290
+
291
+ - name: Build examples/bare-firmware (stock upstream, no C module)
292
+ uses: ./
293
+ env:
294
+ CIBMP_NO_USER_C_MODULES: "1"
295
+ with:
296
+ package-dir: examples/bare-firmware
297
+
298
+ - name: List built artifacts
299
+ run: tree -a examples/bare-firmware/mpyhouse
269
300
 
270
301
  # ── the same build on the runner it would not have chosen ──────────
271
302
  #
@@ -323,7 +354,7 @@ jobs:
323
354
  build: ${{ matrix.build }}
324
355
 
325
356
  - name: List built artifacts
326
- run: ls -laR examples/template/mpyhouse
357
+ run: tree -a examples/template/mpyhouse
327
358
 
328
359
  # ── usermod: the six emulated-everywhere cells ──────────────────────
329
360
  #
@@ -383,4 +414,4 @@ jobs:
383
414
  build: ${{ matrix.build }}
384
415
 
385
416
  - name: List built artifacts
386
- run: ls -laR examples/template/mpyhouse
417
+ run: tree -a examples/template/mpyhouse
@@ -135,7 +135,7 @@ jobs:
135
135
  build: "${{ env.CIBMP_UPSTREAM_ABI_TAG }}-x64 ${{ env.CIBMP_UPSTREAM_ABI_TAG }}-armv7emsp mpy6.3-v1.28.0-x86"
136
136
 
137
137
  - name: List built artifacts
138
- run: ls -laR examples/natmod/mpyhouse
138
+ run: tree -a examples/natmod/mpyhouse
139
139
 
140
140
  build-upstream-natmod:
141
141
  strategy:
@@ -166,4 +166,4 @@ jobs:
166
166
  build: "${{ env.CIBMP_UPSTREAM_ABI_TAG }}-x64"
167
167
 
168
168
  - name: List built artifacts
169
- run: ls -laR examples/natmod/mpyhouse
169
+ run: tree -a examples/natmod/mpyhouse
@@ -6,13 +6,14 @@ name: Test upstream usercmodule
6
6
  # not one this project wrote for itself); docs/records/0069 is the mechanism
7
7
  # actually landed here and explains every choice below in full.
8
8
  #
9
- # Six jobs, one per port cibuildmp drives a usermod build for -- widened
9
+ # Seven jobs, one per port cibuildmp drives a usermod build for -- widened
10
10
  # from the original narrow unix+rp2 slice ([0054]'s own "one Make port and
11
11
  # one CMake port is enough to answer the three questions above") once that
12
12
  # slice came back green, per [0054]'s own "widen only if it finds
13
- # something." Still nowhere near build-examples.yml's much broader
14
- # examples/template matrix: one representative identifier per port, not
15
- # each port's own full arch/board matrix.
13
+ # something," most recently to samd once [0100] gave it a real driver.
14
+ # Still nowhere near build-examples.yml's much broader examples/template
15
+ # matrix: one representative identifier per port, not each port's own full
16
+ # arch/board matrix.
16
17
  #
17
18
  # No job here sets `CIBMP_USER_C_MODULES`/`CIBMP_EXTRA_MAKE_ARGS`/
18
19
  # `CIBMP_EXTRA_CMAKE_ARGS`, and none of them ever resolves the pinned
@@ -88,7 +89,7 @@ jobs:
88
89
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-manylinux_2_28_x86_64
89
90
 
90
91
  - name: List built artifacts
91
- run: ls -laR examples/usercmodule/mpyhouse
92
+ run: tree -a examples/usercmodule/mpyhouse
92
93
 
93
94
  # A linked binary is not the same claim as one whose modules actually
94
95
  # run -- unix is the one port here whose own output this runner can
@@ -140,7 +141,46 @@ jobs:
140
141
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-rp2-RPI_PICO
141
142
 
142
143
  - name: List built artifacts
143
- run: ls -laR examples/usercmodule/mpyhouse
144
+ run: tree -a examples/usercmodule/mpyhouse
145
+
146
+ # ── samd: the fifth Make port, [0100]'s own build driver ────────────────
147
+ #
148
+ # Widened per [0054]'s own "widen only if it finds something" -- samd's
149
+ # own first live verification found a real bug ([0060]'s correction: an
150
+ # unprobed gcc-15-only diagnostic breaking every pre-v1.26.0 row), the
151
+ # exact class of thing this fixture exists to catch on an upstream-owned
152
+ # module, not one this project wrote for itself. A plain-Make port like
153
+ # unix/windows/qemu/webassembly, not cmake like rp2/esp32 -- needs the
154
+ # same `user-c-modules = "{micropython}/examples/usercmodule"` override
155
+ # those four already carry (examples/usercmodule/cibuildmp.toml), added
156
+ # there for samd's own identifier glob rather than left on the "." default
157
+ # that only resolves correctly for the two cmake ports.
158
+ #
159
+ # ADAFRUIT_FEATHER_M4_EXPRESS (SAMD51, 512KB flash), not the smaller
160
+ # SEEED_XIAO_SAMD21 record 0100 verified first -- live-caught here:
161
+ # SEEED_XIAO_SAMD21's own SAMD21 (256KB flash, 184KB usable FLASH region)
162
+ # overflows by ~5KB once cexample/cppexample/subpackage are all actually
163
+ # linked in, `region 'FLASH' overflowed by 4888 bytes`. A real board
164
+ # constraint, not a cibuildmp bug -- MicroPython's own build fits fine on
165
+ # SEEED_XIAO_SAMD21 with no extra user C modules.
166
+ build-samd:
167
+ runs-on: ubuntu-latest
168
+ permissions:
169
+ contents: read
170
+ env:
171
+ CIBMP_VERSION: 0.0.0-ci
172
+ steps:
173
+ - uses: actions/checkout@v7
174
+ - uses: docker/setup-qemu-action@v4
175
+
176
+ - name: Build upstream examples/usercmodule (samd)
177
+ uses: ./
178
+ with:
179
+ package-dir: examples/usercmodule
180
+ build: ${{ env.CIBMP_UPSTREAM_TAG }}-samd-ADAFRUIT_FEATHER_M4_EXPRESS
181
+
182
+ - name: List built artifacts
183
+ run: tree -a examples/usercmodule/mpyhouse
144
184
 
145
185
  # ── esp32: the second CMake port, and the second bare-metal toolchain ──
146
186
  #
@@ -172,7 +212,7 @@ jobs:
172
212
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-esp32-ESP32_GENERIC
173
213
 
174
214
  - name: List built artifacts
175
- run: ls -laR examples/usercmodule/mpyhouse
215
+ run: tree -a examples/usercmodule/mpyhouse
176
216
 
177
217
  # ── windows, webassembly, qemu: the remaining three Make ports ──────────
178
218
  #
@@ -216,7 +256,7 @@ jobs:
216
256
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-win_amd64
217
257
 
218
258
  - name: List built artifacts
219
- run: ls -laR examples/usercmodule/mpyhouse
259
+ run: tree -a examples/usercmodule/mpyhouse
220
260
 
221
261
  # Both the apt install and the run itself are in
222
262
  # `.github/actions/run-with-wine` -- see that action's own header for
@@ -249,7 +289,7 @@ jobs:
249
289
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-wasm32
250
290
 
251
291
  - name: List built artifacts
252
- run: ls -laR examples/usercmodule/mpyhouse
292
+ run: tree -a examples/usercmodule/mpyhouse
253
293
 
254
294
  # The same smoke_test.py the unix job runs, unmodified -- the wasm
255
295
  # build's own CLI takes a .py path exactly like the unix binary
@@ -291,7 +331,7 @@ jobs:
291
331
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-qemu-MPS2_AN385
292
332
 
293
333
  - name: List built artifacts
294
- run: ls -laR examples/usercmodule/mpyhouse
334
+ run: tree -a examples/usercmodule/mpyhouse
295
335
 
296
336
  # `docker/setup-qemu-action` above only registers binfmt_misc
297
337
  # handlers for cross-arch *container* builds -- unrelated to
@@ -71,7 +71,7 @@ jobs:
71
71
  build: ${{ env.CIBMP_UPSTREAM_TAG }}-manylinux_2_28_x86_64
72
72
 
73
73
  - name: List built artifacts
74
- run: ls -laR examples/lv_binding_micropython/mpyhouse
74
+ run: tree -a examples/lv_binding_micropython/mpyhouse
75
75
 
76
76
  # Not just that it links: this registers a real (headless) LVGL
77
77
  # display, builds a widget tree, and renders a frame through it. See
@@ -7,6 +7,85 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.2] - 2026-09-06
11
+
12
+ ### Added
13
+
14
+ - **`samd` gets a real `build_samd()` driver** — the easiest of [0053]'s
15
+ remaining nine driverless usermod ports to pick up next (`esp8266` ruled
16
+ out for tags too old to be worth it), modeled on `rp2`'s own plain-Make
17
+ shape rather than esp32/rp2's cmake one. No new provisioning step needed:
18
+ like `rp2`, `orchestrate.build()` already generalizes `sources.
19
+ fetch_micropython()` for it. Live-verified against real identifiers
20
+ spanning `v1.20.0` through the current tag; `KNOWN_PORTS` now carries
21
+ seven wired drivers, not six. `[0100]`.
22
+
23
+ ### Fixed
24
+
25
+ - **`rp2` and `esp32` both passed `tag_cflags()`'s candidate `CFLAGS_EXTRA`
26
+ straight into their build command with no probing**, unlike every other
27
+ cross-compiling port here — `-Wno-error=unterminated-string-initialization`
28
+ (a gcc-15-only diagnostic, flagged for every tag `v1.12`-`v1.25.0`
29
+ regardless of which toolchain a given row actually resolves to) hard-failed
30
+ `cc1: error: ... no option '-Wunterminated-string-initialization'` on every
31
+ pre-`v1.26.0` row of either port, since both resolve to a sub-gcc-15
32
+ toolchain there. Live-reproduced on `v1.24.0-rp2-ADAFRUIT_FEATHER_RP2040`
33
+ (now producing a genuine `firmware.uf2`) and against a real ESP-IDF
34
+ `xtensa-esp-elf-gcc 14.2.0`. Fixed the same way `unix` already was
35
+ ([0082]): fetch/discover the real compiler first, then probe it with
36
+ `build_common.probe_supported_cflags()` before building `CFLAGS_EXTRA`.
37
+ `esp32` has no static `<prefix>gcc` to point at, so its own fix discovers
38
+ the real cross-compiler dynamically (a `$PATH` glob for `*-elf-gcc`, run
39
+ after ESP-IDF's own install+export sequence) rather than guessing an
40
+ `idf_target -> prefix` table. Neither bug had ever been exercised by CI --
41
+ no workflow in this repo has built `rp2`/`esp32` below `v1.26.0`. `[0060]`.
42
+
43
+ ## [0.7.1] - 2026-09-04
44
+
45
+ ### Added
46
+
47
+ - **`no-user-c-modules = true` builds a stock, unmodified upstream MicroPython
48
+ through the usermod path — no `USER_C_MODULES`, nothing of a consumer's own in
49
+ the result.** Mutually exclusive with `user-c-modules` (a load-time error, not
50
+ a precedence rule); the empty `USER_C_MODULES=` this resolves to is a verified
51
+ no-op on both build systems this project drives, confirmed live against a real
52
+ `v1.29.0` checkout — a stock `unix` binary correctly raising `ImportError` for
53
+ a module never linked in, and the same binary succeeding once one is. Surfaced
54
+ and fixed a real bug along the way: every per-port mount helper built
55
+ `Path(opts.user_c_modules)` unconditionally, and an empty value is `Path(".")`
56
+ — a *relative* path `docker run -v` rejects outright, not merely an
57
+ unnecessary over-mount. `[0056]`.
58
+ - **`examples/bare-firmware`**, a real CI-built demonstration with no `natmod/`,
59
+ no `usermod/`, no `src/` — just a `cibuildmp.toml` naming one Make-driven
60
+ target (`unix` `x86_64`) and one CMake-driven one (`rp2` `RPI_PICO`), the two
61
+ build-system shapes `no-user-c-modules` has to no-op on cleanly.
62
+ `build-examples.yml`'s new `build-bare-firmware` job activates the flag
63
+ through `CIBMP_NO_USER_C_MODULES` rather than the TOML key, doubling as a live
64
+ demonstration of the environment-variable form. `README.md` gets its own
65
+ "Building stock upstream firmware" section for it — framed as a real
66
+ capability (a cross-toolchain/board regression check with no C module
67
+ needed), useful to this project's own consumers but arguably more useful to
68
+ MicroPython's own maintainers.
69
+
70
+ ### Changed
71
+
72
+ - **"List built artifacts" CI steps use `tree -a` instead of `ls -laR`**, across
73
+ `build-examples.yml`, `test-upstream-natmod.yml`, `test-upstream-usermodule.yml`
74
+ and `verify-lv-binding-micropython.yml` — more readable output for the same
75
+ recursive listing; `tree` is already an apt package on the `ubuntu-24.04`
76
+ runner image both `ubuntu-latest` and `ubuntu-24.04-arm` use.
77
+
78
+ ### Removed
79
+
80
+ - **`CIBMP_SCRATCH_PATH`.** Every usermod port has built through its own
81
+ `Container`/overlay since `0.6.x` (record 0095), so the directory this
82
+ variable named was never mounted or read by anything — setting it created a
83
+ real host directory nothing wrote to. Record 0095's own addendum had flagged
84
+ this as a live no-op and left "delete, repurpose, or keep as a no-op knob" as
85
+ an open question; deleting it won. `orchestrate._resolved_build_dir()` now
86
+ returns a fixed, container-internal path with no host directory, no env
87
+ override and no cleanup to manage.
88
+
10
89
  ## [0.7.0] - 2026-09-04
11
90
 
12
91
  ### Fixed
@@ -1590,7 +1669,9 @@ ballistics-lab/micropython-native-ci, but both tags exist here too, so every
1590
1669
  link resolves inside this repository -- the version line continues rather
1591
1670
  than restarting (see the 0.3.0a1 entry). -->
1592
1671
 
1593
- [Unreleased]: https://github.com/ballistics-lab/cibuildmp/compare/v0.7.0...HEAD
1672
+ [Unreleased]: https://github.com/ballistics-lab/cibuildmp/compare/v0.7.2...HEAD
1673
+ [0.7.2]: https://github.com/ballistics-lab/cibuildmp/compare/v0.7.1...v0.7.2
1674
+ [0.7.1]: https://github.com/ballistics-lab/cibuildmp/compare/v0.7.0...v0.7.1
1594
1675
  [0.7.0]: https://github.com/ballistics-lab/cibuildmp/compare/v0.6.2...v0.7.0
1595
1676
  [0.6.2]: https://github.com/ballistics-lab/cibuildmp/compare/v0.6.1...v0.6.2
1596
1677
  [0.6.1]: https://github.com/ballistics-lab/cibuildmp/compare/v0.6.0...v0.6.1
@@ -1623,3 +1704,7 @@ than restarting (see the 0.3.0a1 entry). -->
1623
1704
  [0090]: docs/records/0090-toolchain-pins-checker-and-0058-text-followup.md
1624
1705
  [0095]: docs/records/0095-cache-root-splits-source-from-build-state.md
1625
1706
  [0096]: docs/records/0096-arm-riscv-embedded-collapse-into-embedded-base.md
1707
+ [0056]: docs/records/0056-usermod-with-no-user-c-module.md
1708
+ [0053]: docs/records/0053-usermod-ports-without-a-build-driver.md
1709
+ [0060]: docs/records/0060-rp2-build-driver.md
1710
+ [0100]: docs/records/0100-samd-build-driver-plan.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cibuildmp
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: Build MicroPython native C extensions for every target, from one config — cibuildwheel for MicroPython
5
5
  Author-email: o-murphy <thehelixpg@gmail.com>
6
6
  License-Expression: MIT
@@ -157,11 +157,34 @@ On CI, use the action instead of installing the CLI yourself — it already
157
157
  runs on a bare runner with the runner's own Docker daemon reachable:
158
158
 
159
159
  ```yaml
160
- - uses: ballistics-lab/cibuildmp@v0.7.0
160
+ - uses: ballistics-lab/cibuildmp@v0.7.2
161
161
  with:
162
162
  build: "mpy6.3-* v1.29.0-manylinux_2_28_x86_64"
163
163
  ```
164
164
 
165
+ **Cache fetched MicroPython checkouts (and ESP-IDF) between runs** with a plain
166
+ `actions/cache` step before the action, pointed at `CIBMP_CACHE_PATH`'s own
167
+ default (`~/.cache/cibuildmp`, `$XDG_CACHE_HOME/cibuildmp` if that's set) — a
168
+ prefix key rather than one hashed to a single config, since a checkout is
169
+ addressed by MicroPython tag inside the cache directory and the same cache
170
+ usefully accumulates every tag a repo's history ever built, not just the
171
+ newest:
172
+
173
+ ```yaml
174
+ - uses: actions/cache@v4
175
+ with:
176
+ path: ~/.cache/cibuildmp
177
+ key: cibuildmp-${{ runner.os }}
178
+ restore-keys: cibuildmp-${{ runner.os }}
179
+ - uses: ballistics-lab/cibuildmp@v0.7.2
180
+ with:
181
+ build: "mpy6.3-* v1.29.0-manylinux_2_28_x86_64"
182
+ ```
183
+
184
+ This caches fetched *source* only. Compiled build state does not live on the
185
+ host at all any more — every usermod port builds inside its own container
186
+ now (record 0095), so there is nothing to cache on that side.
187
+
165
188
  The action takes seven inputs, all optional — every one overrides the
166
189
  config file rather than replacing it:
167
190
 
@@ -212,7 +235,7 @@ jobs:
212
235
  runs-on: ubuntu-latest
213
236
  steps:
214
237
  - uses: actions/checkout@v4
215
- - uses: ballistics-lab/cibuildmp@v0.7.0
238
+ - uses: ballistics-lab/cibuildmp@v0.7.2
216
239
  with:
217
240
  build: "mpy6.3-v1.29.0-*"
218
241
  - uses: actions/upload-artifact@v4
@@ -410,6 +433,45 @@ comments record three separate ways a shared `BUILD` directory silently
410
433
  produces the *wrong* arch's binary. Read it when your own build starts
411
434
  doing something strange, not before.
412
435
 
436
+ ### More than one module
437
+
438
+ **natmod: one module per config, one config per directory.** `module-dir`
439
+ names where *one* module's Makefile lives — pointing it at a parent
440
+ directory holding several is a mis-scoped config, not a multi-module
441
+ mechanism, and `collect_output()`'s refusal of an ambiguous two-`.mpy`
442
+ result is exactly the guard that catches it. A project with two natmod
443
+ modules gives each its own directory and config and runs `cibuildmp` once
444
+ per module, into its own `output-dir` — [`examples/template`](examples/template)
445
+ and [`examples/wasm2mpy`](examples/wasm2mpy) are already two modules, two
446
+ configs, two invocations, two independent trees, side by side in this
447
+ repo. Composing the results into one artifact set is your own workflow's
448
+ job, the same way running `cibuildmp` twice is ([0057][0057]).
449
+
450
+ **usermod: `user-c-modules` stays one path; N modules are your own
451
+ layout.** `cibuildmp` never grows a list here — MicroPython's own two
452
+ build systems already have a convention for it, and it differs by port:
453
+
454
+ - **Make ports** put every module in its own subdirectory under the path
455
+ `user-c-modules` names, each with its own `micropython.mk`. `py/py.mk`
456
+ globs `<user-c-modules>/*/micropython.mk` on its own; nothing else to
457
+ write.
458
+ - **CMake ports** point `user-c-modules` at one `micropython.cmake` that
459
+ `include()`s the others. [`examples/usercmodule/micropython.cmake`](examples/usercmodule/micropython.cmake)
460
+ is a real, working one, built by this project's own CI across all six
461
+ ports ([0069][0069]).
462
+
463
+ The two forms are not symmetric, and that asymmetry is upstream's, not
464
+ `cibuildmp`'s: pointed at the same directory, a Make port's glob picks up
465
+ every subdirectory it finds, while a CMake port only builds what its
466
+ `micropython.cmake` explicitly `include()`s. Upstream's own
467
+ `examples/usercmodule/` shows exactly this — three real modules
468
+ (`cexample`, `cppexample`, `subpackage`) reachable via the Make glob with
469
+ no aggregator file at all, but upstream's own aggregator only lists the
470
+ first two. `examples/usercmodule/micropython.cmake` above is this
471
+ project's own file for that reason: it `include()`s upstream's aggregator
472
+ *and* `subpackage`, so the fixture builds the same three modules on every
473
+ port ([0057][0057]/[0069][0069]).
474
+
413
475
  ## Identifiers and selectors
414
476
 
415
477
  Every buildable thing — one natmod arch, one usermod port/board/arch cell —
@@ -427,15 +489,16 @@ platform.**
427
489
  Identifier shapes, one per platform:
428
490
 
429
491
  <!-- generated: identifier-shapes -- bin/refresh_docs.py, do not edit by hand -->
430
- | Platform | Shape | Example |
431
- | --------------------- | ----------------------- | ------------------------------------- |
432
- | natmod | `mpy{abi}-{tag}-{arch}` | `mpy6.3-v1.29.0-armv6m` |
433
- | usermod `esp32` | `{tag}-esp32-{board}` | `v1.29.0-esp32-ARDUINO_NANO_ESP32` |
434
- | usermod `qemu` | `{tag}-qemu-{board}` | `v1.29.0-qemu-MICROBIT` |
435
- | usermod `rp2` | `{tag}-rp2-{board}` | `v1.29.0-rp2-ADAFRUIT_FEATHER_RP2040` |
436
- | usermod `unix` | `{tag}-{arch}` | `v1.29.0-manylinux_2_28_aarch64` |
437
- | usermod `webassembly` | `{tag}-{arch}` | `v1.29.0-wasm32` |
438
- | usermod `windows` | `{tag}-{arch}` | `v1.29.0-win32` |
492
+ | Platform | Shape | Example |
493
+ | --- | --- | --- |
494
+ | natmod | `mpy{abi}-{tag}-{arch}` | `mpy6.3-v1.29.0-armv6m` |
495
+ | usermod `esp32` | `{tag}-esp32-{board}` | `v1.29.0-esp32-ARDUINO_NANO_ESP32` |
496
+ | usermod `qemu` | `{tag}-qemu-{board}` | `v1.29.0-qemu-MICROBIT` |
497
+ | usermod `rp2` | `{tag}-rp2-{board}` | `v1.29.0-rp2-ADAFRUIT_FEATHER_RP2040` |
498
+ | usermod `samd` | `{tag}-samd-{board}` | `v1.29.0-samd-ADAFRUIT_FEATHER_M0_EXPRESS` |
499
+ | usermod `unix` | `{tag}-{arch}` | `v1.29.0-manylinux_2_28_aarch64` |
500
+ | usermod `webassembly` | `{tag}-{arch}` | `v1.29.0-wasm32` |
501
+ | usermod `windows` | `{tag}-{arch}` | `v1.29.0-win32` |
439
502
  <!-- /generated: identifier-shapes -->
440
503
 
441
504
  The shape genuinely differs per usermod port — `unix`/`windows`/
@@ -594,6 +657,7 @@ onto each other rather than the first winning.
594
657
  | `pre-build-command` | natmod | `""` | ✓ |
595
658
  | `extra-make-args` | both | `[]` | ✓ |
596
659
  | `user-c-modules` | usermod | `"."` | ✓ |
660
+ | `no-user-c-modules` | usermod | `false` | ✓ |
597
661
  | `manifest` | usermod | `""` | ✓ |
598
662
  | `extra-cmake-args` | usermod | `[]` | ✓ |
599
663
 
@@ -656,6 +720,35 @@ Two notes on individual keys:
656
720
  So an override for the flagged variant is `[override."*rv32imc+0x3"]`, and
657
721
  a plain `skip = "*-rv32imc"` will *not* match it — `*-rv32imc*` does.
658
722
 
723
+ ### Building stock upstream firmware
724
+
725
+ `cibuildmp` is not only for building *your own* C module into a port — set
726
+ `no-user-c-modules = true` and it builds a stock, unmodified upstream
727
+ MicroPython through the exact same usermod path instead: no
728
+ `USER_C_MODULES`, nothing of your own in the result. Mutually exclusive
729
+ with `user-c-modules`; setting both is a load-time error, not a precedence
730
+ rule ([0056]).
731
+
732
+ That makes the whole matrix this project already resolves — every port,
733
+ every board, every pinned toolchain — usable as a plain "does upstream
734
+ still build here" check, with no C module involved at all. Useful for this
735
+ project's own consumers, but arguably more useful to MicroPython's own
736
+ maintainers: a regression check across a real cross-toolchain/board matrix
737
+ that costs nothing to run beyond pointing `--build` at the tags and
738
+ identifiers you care about, e.g.:
739
+
740
+ ```console
741
+ $ CIBMP_NO_USER_C_MODULES=1 cibuildmp --build "v1.29.0-manylinux_2_28_x86_64 v1.29.0-rp2-RPI_PICO"
742
+ ```
743
+
744
+ [`examples/bare-firmware`](examples/bare-firmware) is exactly this — no
745
+ `natmod/`, no `usermod/`, no `src/`, just a `cibuildmp.toml` naming two
746
+ targets (one Make-driven port, one CMake-driven one — record 0056's own
747
+ two build systems). `.github/workflows/build-examples.yml`'s own
748
+ `build-bare-firmware` job builds it on every push, activating the flag via
749
+ `CIBMP_NO_USER_C_MODULES` rather than the TOML key, so it doubles as a
750
+ live demonstration of the environment-variable form.
751
+
659
752
  ### Environment variables
660
753
 
661
754
  Every option key above has an environment form: `CIBMP_` + the key in
@@ -696,7 +789,6 @@ the port**, because it is that port's own build axis:
696
789
  | Variable | Effect |
697
790
  | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
698
791
  | `CIBMP_CACHE_PATH` | Where fetched MicroPython checkouts and ESP-IDF are cached. Defaults to `$XDG_CACHE_HOME/cibuildmp`, or `~/.cache/cibuildmp`. Pin it in CI when a later step needs the checkout by path — `<CIBMP_CACHE_PATH>/micropython/<tag>` |
699
- | `CIBMP_SCRATCH_PATH` | Read, but currently redirects nothing: every usermod port's compiled build state now lives inside its own container and never reaches the host (record 0095's own addendum 13). Left as a documented knob rather than removed outright |
700
792
  | `CIBMP_REPORT_PATH` | Where the JSON build report is written |
701
793
  | `CIBMP_TIMEOUT` | Seconds before a build container is killed (`docker kill`, not just the CLI). No limit by default. **usermod only** -- natmod's own container call does not consult it |
702
794
  | `CIBMP_<PORT>_<TARGET>_TIMEOUT` | The same, for one container — `CIBMP_UNIX_MANYLINUX_2_28_X86_64_TIMEOUT` |
@@ -762,7 +854,10 @@ naming a scalar option in `inherit` is a config error, not a silent no-op.
762
854
  [0038]: docs/records/0038-m5-adopt-in-three-repos.md
763
855
  [0043]: docs/records/0043-unix-adopts-cibuildwheel-native-image-model.md
764
856
  [0052]: docs/records/0052-config-is-a-tree-not-a-selector-matrix.md
857
+ [0056]: docs/records/0056-usermod-with-no-user-c-module.md
858
+ [0057]: docs/records/0057-multiple-modules-per-build.md
765
859
  [0058]: docs/records/0058-image-groups-are-toolchains-not-ports.md
860
+ [0069]: docs/records/0069-upstream-usercmodule-narrow-ci-slice.md
766
861
  [0071]: docs/records/0071-micropython-placeholder-in-user-c-modules.md
767
862
  [0072]: docs/records/0072-natmod-micropython-placeholder-and-upstream-natmod-ci.md
768
863
  [0074]: docs/records/0074-usermod-family-table-and-retired-table-messages-removed.md
@@ -770,6 +865,9 @@ naming a scalar option in `inherit` is a config error, not a silent no-op.
770
865
  [0076]: docs/records/0076-the-mipsel-holdout-is-bclibc-and-wasm3-not-a7p.md
771
866
  [0077]: docs/records/0077-docs-drift-is-a-failing-test-not-a-discipline-problem.md
772
867
  [0097]: docs/records/0097-lv-binding-micropython-builds-through-cibuildmp.md
868
+ [0053]: docs/records/0053-usermod-ports-without-a-build-driver.md
869
+ [0060]: docs/records/0060-rp2-build-driver.md
870
+ [0100]: docs/records/0100-samd-build-driver-plan.md
773
871
 
774
872
  ## When a build fails
775
873
 
@@ -907,10 +1005,10 @@ Nor is the build state: every usermod port builds inside a container's own
907
1005
  overlay now (a `:ro` bind of the checkout plus a writable view on top), so
908
1006
  object files, per-identifier `build-<identifier>/` trees and the
909
1007
  container-built `mpy-cross` binaries never touch the host at all — they die
910
- with the container. `CIBMP_SCRATCH_PATH` is still read but currently has
911
- nothing to redirect, since nothing writes to the path it names any more;
912
- kept for now as a documented knob rather than removed outright (see record
913
- 0095's own addendum 13 for the reasoning).
1008
+ with the container. There is no env var to point this anywhere any more
1009
+ either: `CIBMP_SCRATCH_PATH` named a host directory nothing had written to
1010
+ since that migration, and was removed once that was noticed rather than
1011
+ kept as a knob with nothing left to turn.
914
1012
 
915
1013
  ### Still stuck
916
1014
 
@@ -1011,10 +1109,10 @@ real CI, arch by arch, not just `--dry-run`.
1011
1109
  Upstream MicroPython has 20 ports (`ports/*` in a real checkout); every one
1012
1110
  is listed below for orientation, not just the ones this project covers.
1013
1111
  `resources/build-platforms.toml` carries independently-verified
1014
- `(tag, arch/board)` rows for 15 of them; only 6 (`unix`, `windows`, `qemu`,
1015
- `webassembly`, `esp32`, `rp2`) have a real build driver wired into the CLI
1016
- at all — the other 9 have verified facts a config can already *name*, but
1017
- nothing yet to actually build them. Every ✅ row below is live-verified
1112
+ `(tag, arch/board)` rows for 15 of them; only 7 (`unix`, `windows`, `qemu`,
1113
+ `webassembly`, `esp32`, `rp2`, `samd`) have a real build driver wired into
1114
+ the CLI at all — the other 8 have verified facts a config can already
1115
+ *name*, but nothing yet to actually build them. Every ✅ row below is live-verified
1018
1116
  against a real MicroPython checkout, including a real custom
1019
1117
  `USER_C_MODULES` module, Docker-only. `unix`, `windows`, `webassembly` and
1020
1118
  `qemu` are exercised through `build-examples.yml`'s own small integration
@@ -1197,10 +1295,17 @@ scheduled `test-all-platforms.yml` run since.
1197
1295
  <td><code>embedded_base</code> (Docker) -- Pico SDK + every <code>lib/</code> it needs are vendored by the MicroPython release tarball itself[^rp2ci]</td>
1198
1296
  <td>✅</td>
1199
1297
  </tr>
1298
+ <tr>
1299
+ <td><code>samd</code></td>
1300
+ <td>
1301
+ every board across <code>v1.20.0</code>-<code>v1.30.0-preview</code>
1302
+ </td>
1303
+ <td><code>embedded_base</code> (Docker) -- plain Make, no provisioning step, same shape as <code>rp2</code>[^samdci]</td>
1304
+ <td>✅</td>
1305
+ </tr>
1200
1306
  <tr>
1201
1307
  <td>
1202
1308
  <code>mimxrt</code><br>
1203
- <code>samd</code><br>
1204
1309
  <code>stm32</code><br>
1205
1310
  <code>psoc-edge</code><br>
1206
1311
  <code>alif</code><br>
@@ -1251,6 +1356,8 @@ scheduled `test-all-platforms.yml` run since.
1251
1356
  [^nodriver]: `resources/build-platforms.toml` has real, independently-verified rows for each of these ports (walked against a real MicroPython checkout the same way every ✅ row above was); a config can name their identifiers today. What's missing is a `build_<port>()` driver (`platforms/usermod/build_<port>.py`) to actually run one — not a scope decision, just not built yet.
1252
1357
  [^rp2ci]: `build_rp2()` runs no provisioning step inside the container at all — the Pico SDK and everything it needs (`lib/pico-sdk`/`lib/tinyusb`/`lib/lwip`/`lib/btstack`/`lib/cyw43-driver`) are plain git submodules of the MicroPython checkout, already vendored as real files by the release tarball this project prefers. Running the port's own `make ... submodules` target was tried first and failed live against a real tarball checkout ("fatal: not a git repository", since a release tarball is not a git checkout at all); those submodules are threaded into `sources.fetch_micropython()` instead, reached only on its clone path (a preview tag with no tarball). Live-verified: a real `examples/template` build against `v1.29.0-rp2-RPI_PICO` producing a genuine 681984-byte `firmware.uf2` with the project's own C module linked in. Record 0060.
1253
1358
 
1359
+ [^samdci]: `build_samd()` ([0100]), the ninth of [0053]'s originally driverless usermod ports to get one and the first picked up after `rp2` — chosen over the other eight once `esp8266` was ruled out for tags too old to be worth it. No `SAMD_SUBMODULES`-style plumbing was needed: `orchestrate.build()` already threads `sources.fetch_micropython(tag, ports=group_ports)` generically enough to cover it. Live-verified against real identifiers spanning `v1.20.0` through the current tag, producing genuine linked firmware; a full sweep of every real `(tag, board)` row this project has verified facts for is how that was confirmed, not a spot check.
1360
+
1254
1361
  [^esp32ci]: `build_esp32()` went Docker 2026-08-28 (`esp_idf_base`, [0058]), closing the venv conflict that made every real esp32 build fail on the bare host; `idf_version`/`idf_target` are threaded from each board's own real row rather than a fixed default, and `HOME` is exported explicitly for the same reason `esp32`'s own `ports/esp32` needs a real per-user cache dir that `dockerrun.run()`'s `--user <uid>:<gid>` doesn't otherwise give it (unmapped on GitHub's own runners specifically, live-caught on real CI). `test-all-platforms.yml`'s own broad sweep is what actually proves this across the whole board matrix, not a spot check — Xtensa and RISC-V both, both MicroPython tags this project currently tracks.
1255
1362
 
1256
1363
  [^windowsimg]: One combined `docker/windows.Dockerfile` image (`ghcr.io/ballistics-lab/windows`) for all three arches, not split per arch like `unix`'s own five images — there is no second Windows libc a binary could be built against, so the isolation argument that drives `unix`'s split doesn't apply here. `x64`/`x86` are plain apt-installed `gcc-mingw-w64-x86-64`/`gcc-mingw-w64-i686` inside the image; `arm64` is a pinned `llvm-mingw` tarball baked into the same image (no Debian/Ubuntu package targets `aarch64-w64-mingw32` at all). None of this runs on the CI runner itself any more — `apt install gcc-mingw-w64-*` on the bare host was removed as part of Record 0042's own container migration.