cibuildmp 0.3.0__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.
- cibuildmp-0.3.0/.github/actions/build-natmod/action.yml +133 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-armv7m/action.yml +98 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-esp32/action.yml +162 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-rp2040/action.yml +145 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-unix/action.yml +177 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-webassembly/action.yml +114 -0
- cibuildmp-0.3.0/.github/actions/build-usermod-windows/action.yml +133 -0
- cibuildmp-0.3.0/.github/actions/cibuildmp-matrix/action.yml +73 -0
- cibuildmp-0.3.0/.github/actions/clone-micropython/action.yml +45 -0
- cibuildmp-0.3.0/.github/actions/fetch-micropython/action.yml +24 -0
- cibuildmp-0.3.0/.github/dependabot.yml +33 -0
- cibuildmp-0.3.0/.github/workflows/build-examples.yml +65 -0
- cibuildmp-0.3.0/.github/workflows/publish.yml +207 -0
- cibuildmp-0.3.0/.gitignore +28 -0
- cibuildmp-0.3.0/CHANGELOG.md +311 -0
- cibuildmp-0.3.0/LICENSE +21 -0
- cibuildmp-0.3.0/PKG-INFO +528 -0
- cibuildmp-0.3.0/README.md +496 -0
- cibuildmp-0.3.0/action.yml +66 -0
- cibuildmp-0.3.0/cibuildmp.toml +137 -0
- cibuildmp-0.3.0/docs/BACKLOG.md +889 -0
- cibuildmp-0.3.0/examples/template/cibuildmp.toml +43 -0
- cibuildmp-0.3.0/examples/template/natmod/Makefile +35 -0
- cibuildmp-0.3.0/examples/template/natmod/template.c +21 -0
- cibuildmp-0.3.0/examples/template/src/facade.py +13 -0
- cibuildmp-0.3.0/examples/wasm2mpy/Makefile +66 -0
- cibuildmp-0.3.0/examples/wasm2mpy/NOTICE +32 -0
- cibuildmp-0.3.0/examples/wasm2mpy/cibuildmp.toml +33 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/esp8266-rom.S +562 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/libc.c +100 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/runtime.c +131 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt-impl-tableops.inc +78 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt-impl.c +294 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt-impl.h +66 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt-mem-impl-helper.inc +169 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt-mem-impl.c +176 -0
- cibuildmp-0.3.0/examples/wasm2mpy/runtime/wasm-rt.h +624 -0
- cibuildmp-0.3.0/examples/wasm2mpy/test/zig.wasm +0 -0
- cibuildmp-0.3.0/pyproject.toml +85 -0
- cibuildmp-0.3.0/setup.cfg +4 -0
- cibuildmp-0.3.0/src/cibuildmp/__init__.py +19 -0
- cibuildmp-0.3.0/src/cibuildmp/__main__.py +4 -0
- cibuildmp-0.3.0/src/cibuildmp/build.py +300 -0
- cibuildmp-0.3.0/src/cibuildmp/cli.py +367 -0
- cibuildmp-0.3.0/src/cibuildmp/options.py +267 -0
- cibuildmp-0.3.0/src/cibuildmp/resources/natmod.toml +167 -0
- cibuildmp-0.3.0/src/cibuildmp/resources.py +22 -0
- cibuildmp-0.3.0/src/cibuildmp/sources.py +275 -0
- cibuildmp-0.3.0/src/cibuildmp/targets.py +259 -0
- cibuildmp-0.3.0/src/cibuildmp/toolchains.py +302 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/PKG-INFO +528 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/SOURCES.txt +63 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/dependency_links.txt +1 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/entry_points.txt +2 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/requires.txt +2 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/scm_file_list.json +59 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/scm_version.json +8 -0
- cibuildmp-0.3.0/src/cibuildmp.egg-info/top_level.txt +1 -0
- cibuildmp-0.3.0/tests/test_build.py +328 -0
- cibuildmp-0.3.0/tests/test_cli.py +76 -0
- cibuildmp-0.3.0/tests/test_options.py +230 -0
- cibuildmp-0.3.0/tests/test_sources.py +112 -0
- cibuildmp-0.3.0/tests/test_targets.py +154 -0
- cibuildmp-0.3.0/tests/test_toolchains.py +97 -0
- cibuildmp-0.3.0/uv.lock +166 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
name: Build natmod arch
|
|
2
|
+
description: >
|
|
3
|
+
Installs whatever cross toolchain a single dynruntime.mk ARCH needs (a
|
|
4
|
+
plain apt package, the xtensa-lx106 tarball, or esp-idf -- picked per
|
|
5
|
+
ARCH, matching dynruntime.mk's own CROSS choices), builds mpy-cross, then
|
|
6
|
+
runs `make ARCH=<arch> dist` in the natmod directory.
|
|
7
|
+
|
|
8
|
+
Requires MPY_DIR to already be exported (e.g. by the fetch-micropython or
|
|
9
|
+
clone-micropython action from this same repo) and the calling repo's own
|
|
10
|
+
checkout to already have happened, submodules included if the natmod
|
|
11
|
+
Makefile needs any.
|
|
12
|
+
|
|
13
|
+
inputs:
|
|
14
|
+
arch:
|
|
15
|
+
description: >
|
|
16
|
+
dynruntime.mk ARCH to build: x64, x86, armv6m, armv7m, armv7emsp,
|
|
17
|
+
armv7emdp, rv32imc, rv64imc, xtensa, or xtensawin. (aarch64 has no
|
|
18
|
+
dynruntime.mk ARCH at all as of MicroPython <= v1.28 -- build it via
|
|
19
|
+
a usermod instead.)
|
|
20
|
+
required: true
|
|
21
|
+
natmod_dir:
|
|
22
|
+
description: Path to the directory containing natmod/Makefile, relative to the workspace root.
|
|
23
|
+
required: false
|
|
24
|
+
default: natmod
|
|
25
|
+
esp_idf_ver:
|
|
26
|
+
description: esp-idf tag to install for the xtensawin toolchain.
|
|
27
|
+
required: false
|
|
28
|
+
default: v5.4
|
|
29
|
+
extra_pip:
|
|
30
|
+
description: >
|
|
31
|
+
Extra space-separated pip packages to install alongside pyelftools/ar
|
|
32
|
+
(both always installed -- mpy_ld.py needs them for every ARCH).
|
|
33
|
+
required: false
|
|
34
|
+
default: ''
|
|
35
|
+
pre_build_command:
|
|
36
|
+
description: >
|
|
37
|
+
Optional shell command run once inside natmod_dir, after mpy-cross is
|
|
38
|
+
built and before `make dist` -- e.g. a7p's `make fetch-nanopb`, which
|
|
39
|
+
the natmod Makefile needs vendored in before it can build any ARCH.
|
|
40
|
+
required: false
|
|
41
|
+
default: ''
|
|
42
|
+
|
|
43
|
+
runs:
|
|
44
|
+
using: composite
|
|
45
|
+
steps:
|
|
46
|
+
- name: Install cross-compiler
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
set -e
|
|
50
|
+
case "${{ inputs.arch }}" in
|
|
51
|
+
x64|xtensa|xtensawin)
|
|
52
|
+
# x64 needs no cross toolchain at all; xtensa/xtensawin are
|
|
53
|
+
# handled by their own steps below, not a plain apt package.
|
|
54
|
+
exit 0
|
|
55
|
+
;;
|
|
56
|
+
x86)
|
|
57
|
+
PKGS="gcc-multilib"
|
|
58
|
+
;;
|
|
59
|
+
armv6m|armv7m|armv7emsp|armv7emdp)
|
|
60
|
+
PKGS="gcc-arm-none-eabi libnewlib-arm-none-eabi"
|
|
61
|
+
;;
|
|
62
|
+
rv32imc|rv64imc)
|
|
63
|
+
PKGS="gcc-riscv64-unknown-elf picolibc-riscv64-unknown-elf"
|
|
64
|
+
;;
|
|
65
|
+
*)
|
|
66
|
+
echo "::error::build-natmod: unknown ARCH '${{ inputs.arch }}'"
|
|
67
|
+
exit 1
|
|
68
|
+
;;
|
|
69
|
+
esac
|
|
70
|
+
# apt-get update first: the runner image's baked-in package index
|
|
71
|
+
# can already be stale by the time a job runs, pointing at a
|
|
72
|
+
# gcc/glibc revision the mirror has since superseded (404 Not Found
|
|
73
|
+
# on install rather than a version error) -- seen for real on the
|
|
74
|
+
# x86 leg across every repo this action was extracted from.
|
|
75
|
+
sudo apt-get update -q
|
|
76
|
+
sudo apt-get install -y $PKGS
|
|
77
|
+
|
|
78
|
+
- name: Install xtensa (esp8266) toolchain
|
|
79
|
+
if: inputs.arch == 'xtensa'
|
|
80
|
+
shell: bash
|
|
81
|
+
# Same tarball MicroPython's own ci_esp8266_setup uses -- no apt
|
|
82
|
+
# package exists for this target.
|
|
83
|
+
run: |
|
|
84
|
+
wget -q https://micropython.org/resources/xtensa-lx106-elf-standalone.tar.gz
|
|
85
|
+
tar xzf xtensa-lx106-elf-standalone.tar.gz
|
|
86
|
+
echo "$PWD/xtensa-lx106-elf/bin" >> "$GITHUB_PATH"
|
|
87
|
+
|
|
88
|
+
- name: Install esp-idf (xtensawin toolchain)
|
|
89
|
+
if: inputs.arch == 'xtensawin'
|
|
90
|
+
shell: bash
|
|
91
|
+
# Deliberately not `git clone --recursive`: this only ever wants the
|
|
92
|
+
# xtensa-esp32s3-elf- toolchain that install.sh downloads separately
|
|
93
|
+
# from GitHub releases, not a full esp32 port build against IDF's own
|
|
94
|
+
# components (bt/mbedtls/lwip/openthread/...) -- so nothing here
|
|
95
|
+
# touches IDF_PATH or any esp-idf header/component, and the
|
|
96
|
+
# submodule init (most of a --recursive clone's cost) buys nothing.
|
|
97
|
+
env:
|
|
98
|
+
IDF_VER: ${{ inputs.esp_idf_ver }}
|
|
99
|
+
run: |
|
|
100
|
+
git clone --depth 1 --branch "$IDF_VER" https://github.com/espressif/esp-idf.git
|
|
101
|
+
./esp-idf/install.sh
|
|
102
|
+
|
|
103
|
+
- name: Install Python deps for mpy_ld.py
|
|
104
|
+
shell: bash
|
|
105
|
+
run: pip install pyelftools ar ${{ inputs.extra_pip }}
|
|
106
|
+
|
|
107
|
+
- name: Build mpy-cross
|
|
108
|
+
shell: bash
|
|
109
|
+
run: make -C "$MPY_DIR/mpy-cross"
|
|
110
|
+
|
|
111
|
+
- name: Build ${{ inputs.arch }}
|
|
112
|
+
shell: bash
|
|
113
|
+
working-directory: ${{ inputs.natmod_dir }}
|
|
114
|
+
# esp-idf's own venv shadows the system pip install above the moment
|
|
115
|
+
# export.sh is sourced -- mpy_ld.py then runs under *that* python, so
|
|
116
|
+
# pyelftools/ar have to be reinstalled inside this same shell right
|
|
117
|
+
# before the build, not just once earlier in the job. A real failure
|
|
118
|
+
# without it: "RuntimeError: Please run 'pip install ar' to link .a
|
|
119
|
+
# files" even though the step above already ran.
|
|
120
|
+
# pre_build_command runs via `${{ ... || ':' }}` rather than an
|
|
121
|
+
# `if [ -n ... ]; then ... fi` guard: when the input is empty, that
|
|
122
|
+
# guard's then-body would be blank text with nothing else on the
|
|
123
|
+
# line, and bash rejects an empty compound-command body at parse
|
|
124
|
+
# time ("syntax error near unexpected token `fi'") even though the
|
|
125
|
+
# condition is false and the body would never run. `:` is a real,
|
|
126
|
+
# always-present no-op command, so the line is never empty.
|
|
127
|
+
run: |
|
|
128
|
+
if [ "${{ inputs.arch }}" = "xtensawin" ]; then
|
|
129
|
+
source "$GITHUB_WORKSPACE/esp-idf/export.sh"
|
|
130
|
+
pip install pyelftools ar ${{ inputs.extra_pip }}
|
|
131
|
+
fi
|
|
132
|
+
${{ inputs.pre_build_command || ':' }}
|
|
133
|
+
make ARCH=${{ inputs.arch }} MPY_DIR="$MPY_DIR" dist
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
name: Build usermod armv7m
|
|
2
|
+
description: >
|
|
3
|
+
Builds a MicroPython ports/qemu "usermod" (a C module compiled straight
|
|
4
|
+
into the port via USER_C_MODULES=) into a firmware.elf for the given
|
|
5
|
+
BOARD= (default MPS2_AN385, a Cortex-M3). Installs the arm-none-eabi
|
|
6
|
+
toolchain, builds mpy-cross, then runs the port build under it.
|
|
7
|
+
|
|
8
|
+
QEMU itself is deliberately NOT installed here: it is a runtime emulator
|
|
9
|
+
for testing the resulting firmware.elf, not a build dependency -- same
|
|
10
|
+
split build-usermod-rp2040 uses for the rp2040py emulator. Callers
|
|
11
|
+
install qemu-system-arm (and whatever their own test harness needs,
|
|
12
|
+
e.g. pyserial) themselves, alongside their own run_qemu.py-equivalent.
|
|
13
|
+
|
|
14
|
+
Requires MPY_DIR to already be exported (fetch-micropython or
|
|
15
|
+
clone-micropython) and the calling repo already checked out, same
|
|
16
|
+
contract as build-usermod-unix/build-usermod-rp2040.
|
|
17
|
+
|
|
18
|
+
inputs:
|
|
19
|
+
board:
|
|
20
|
+
description: Value for BOARD=. Defaults to MPS2_AN385 (Cortex-M3, no FPU).
|
|
21
|
+
required: false
|
|
22
|
+
default: MPS2_AN385
|
|
23
|
+
user_c_modules:
|
|
24
|
+
description: Value for USER_C_MODULES=. Defaults to the workspace root.
|
|
25
|
+
required: false
|
|
26
|
+
default: ''
|
|
27
|
+
frozen_manifest:
|
|
28
|
+
description: >
|
|
29
|
+
Value for FROZEN_MANIFEST=. Defaults to usermod/manifest.py under the
|
|
30
|
+
workspace root. ports/qemu ships no boards/manifest.py of its own --
|
|
31
|
+
unlike unix/rp2/esp32, there is no port default to combine with, so a
|
|
32
|
+
caller-written manifest here only ever needs to freeze its own module.
|
|
33
|
+
required: false
|
|
34
|
+
default: ''
|
|
35
|
+
extra_make_args:
|
|
36
|
+
description: >
|
|
37
|
+
Extra space-separated VAR=value pairs appended to the build command,
|
|
38
|
+
e.g. a module's own precision define.
|
|
39
|
+
required: false
|
|
40
|
+
default: ''
|
|
41
|
+
build_dir:
|
|
42
|
+
description: >
|
|
43
|
+
Value for BUILD=. Defaults to usermod/build/armv7m under the
|
|
44
|
+
workspace root. A bare relative value (no leading /) resolves against
|
|
45
|
+
$MPY_DIR/ports/qemu instead, same as make -C's own relative-path
|
|
46
|
+
handling -- pass one when the caller wants the port's own
|
|
47
|
+
board-named default (build-$(BOARD)) instead.
|
|
48
|
+
required: false
|
|
49
|
+
default: ''
|
|
50
|
+
|
|
51
|
+
outputs:
|
|
52
|
+
build_dir:
|
|
53
|
+
description: >
|
|
54
|
+
The BUILD= directory actually used (resolved default included), so
|
|
55
|
+
the caller can find firmware.elf without recomputing it.
|
|
56
|
+
value: ${{ steps.vars.outputs.build_dir }}
|
|
57
|
+
|
|
58
|
+
runs:
|
|
59
|
+
using: composite
|
|
60
|
+
steps:
|
|
61
|
+
- name: Resolve build settings
|
|
62
|
+
id: vars
|
|
63
|
+
shell: bash
|
|
64
|
+
run: |
|
|
65
|
+
set -e
|
|
66
|
+
BUILD="${{ inputs.build_dir }}"
|
|
67
|
+
FM="${{ inputs.frozen_manifest }}"
|
|
68
|
+
UCM="${{ inputs.user_c_modules }}"
|
|
69
|
+
{
|
|
70
|
+
echo "user_c_modules=${UCM:-$GITHUB_WORKSPACE}"
|
|
71
|
+
echo "frozen_manifest=${FM:-$GITHUB_WORKSPACE/usermod/manifest.py}"
|
|
72
|
+
echo "build_dir=${BUILD:-$GITHUB_WORKSPACE/usermod/build/armv7m}"
|
|
73
|
+
} >> "$GITHUB_OUTPUT"
|
|
74
|
+
|
|
75
|
+
- name: Install toolchain
|
|
76
|
+
shell: bash
|
|
77
|
+
# apt-get update first -- a bare apt-get install against the runner
|
|
78
|
+
# image's stale package index intermittently 404s on a mirror.
|
|
79
|
+
run: |
|
|
80
|
+
sudo apt-get update -q
|
|
81
|
+
sudo apt-get install -y --no-install-recommends \
|
|
82
|
+
gcc-arm-none-eabi libnewlib-arm-none-eabi
|
|
83
|
+
|
|
84
|
+
- name: Build mpy-cross
|
|
85
|
+
shell: bash
|
|
86
|
+
# Explicitly, before FROZEN_MANIFEST ever appears on a command line --
|
|
87
|
+
# py/mkenv.mk's auto-build rule for it races/leaks under -j. Same fix
|
|
88
|
+
# every other action here uses.
|
|
89
|
+
run: make -C "$MPY_DIR/mpy-cross" -j"$(nproc)"
|
|
90
|
+
|
|
91
|
+
- name: Build usermod (armv7m, ${{ inputs.board }})
|
|
92
|
+
shell: bash
|
|
93
|
+
run: |
|
|
94
|
+
make -C "$MPY_DIR/ports/qemu" BOARD="${{ inputs.board }}" \
|
|
95
|
+
BUILD="${{ steps.vars.outputs.build_dir }}" \
|
|
96
|
+
USER_C_MODULES="${{ steps.vars.outputs.user_c_modules }}" \
|
|
97
|
+
FROZEN_MANIFEST="${{ steps.vars.outputs.frozen_manifest }}" \
|
|
98
|
+
${{ inputs.extra_make_args }} -j"$(nproc)"
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
name: Build usermod esp32
|
|
2
|
+
description: >
|
|
3
|
+
Builds a MicroPython ports/esp32 "usermod" (a C module compiled straight
|
|
4
|
+
into the port via USER_C_MODULES=) into a firmware.bin/micropython.bin
|
|
5
|
+
for the given BOARD= (default ESP32_GENERIC). Installs ESP-IDF, builds
|
|
6
|
+
mpy-cross, then runs the port build under it.
|
|
7
|
+
|
|
8
|
+
--recursive on the esp-idf clone, unlike a natmod build of the same
|
|
9
|
+
chip: a natmod only borrows the xtensa compiler install.sh downloads,
|
|
10
|
+
while a usermod compiles into a firmware built against IDF's own
|
|
11
|
+
components. install.sh <idf_target> limits the toolchain download to
|
|
12
|
+
the one chip family rather than every one IDF supports.
|
|
13
|
+
|
|
14
|
+
idf_target and board are deliberately separate inputs, not derived from
|
|
15
|
+
one another: install.sh's argument is the chip family (esp32, esp32s3,
|
|
16
|
+
...), while BOARD= is the actual MicroPython board definition -- more
|
|
17
|
+
than one board can exist per chip family, so string-deriving one from
|
|
18
|
+
the other would silently break the day a second board per chip shows up.
|
|
19
|
+
|
|
20
|
+
No caching yet: every consumer's original recipe had none either, so
|
|
21
|
+
this preserves behavior exactly rather than mixing an extraction with a
|
|
22
|
+
new capability. Left as a known follow-up, not forgotten -- see this
|
|
23
|
+
repo's own README/CHANGELOG.
|
|
24
|
+
|
|
25
|
+
Requires MPY_DIR to already be exported (fetch-micropython or
|
|
26
|
+
clone-micropython) and the calling repo already checked out, same
|
|
27
|
+
contract as build-usermod-unix/build-usermod-rp2040.
|
|
28
|
+
|
|
29
|
+
inputs:
|
|
30
|
+
board:
|
|
31
|
+
description: Value for BOARD=. Defaults to ESP32_GENERIC, the mainstream target.
|
|
32
|
+
required: false
|
|
33
|
+
default: ESP32_GENERIC
|
|
34
|
+
idf_target:
|
|
35
|
+
description: >
|
|
36
|
+
Chip family passed to esp-idf's install.sh (e.g. esp32, esp32s3).
|
|
37
|
+
Defaults to esp32. Kept separate from board -- see this action's own
|
|
38
|
+
header for why they must not be derived from one another.
|
|
39
|
+
required: false
|
|
40
|
+
default: esp32
|
|
41
|
+
idf_ver:
|
|
42
|
+
description: ESP-IDF version tag to clone (e.g. v5.5.1).
|
|
43
|
+
required: false
|
|
44
|
+
default: v5.5.1
|
|
45
|
+
user_c_modules:
|
|
46
|
+
description: >
|
|
47
|
+
Value for USER_C_MODULES=. Defaults to usermod/micropython.cmake
|
|
48
|
+
under the workspace root -- a *file*, like build-usermod-rp2040's own
|
|
49
|
+
user_c_modules: CMake's USER_C_MODULES takes a single .cmake entry
|
|
50
|
+
point, not a directory to glob.
|
|
51
|
+
required: false
|
|
52
|
+
default: ''
|
|
53
|
+
frozen_manifest:
|
|
54
|
+
description: Value for FROZEN_MANIFEST=. Defaults to usermod/manifest.py under the workspace root.
|
|
55
|
+
required: false
|
|
56
|
+
default: ''
|
|
57
|
+
extra_make_args:
|
|
58
|
+
description: >
|
|
59
|
+
Extra space-separated VAR=value pairs appended to the build command,
|
|
60
|
+
e.g. a module's own precision define.
|
|
61
|
+
required: false
|
|
62
|
+
default: ''
|
|
63
|
+
|
|
64
|
+
outputs:
|
|
65
|
+
build_dir:
|
|
66
|
+
description: >
|
|
67
|
+
The port's own default build-$(BOARD) directory (relative to
|
|
68
|
+
$MPY_DIR/ports/esp32), so the caller can find
|
|
69
|
+
micropython.bin/firmware.bin without recomputing it. No build_dir
|
|
70
|
+
input to override this: see the "Build usermod" step's own comment
|
|
71
|
+
for why passing BUILD= at all -- not what it's set to -- breaks the
|
|
72
|
+
port's internal CMake-driven mpy-cross sub-build.
|
|
73
|
+
value: ${{ steps.vars.outputs.build_dir }}
|
|
74
|
+
|
|
75
|
+
runs:
|
|
76
|
+
using: composite
|
|
77
|
+
steps:
|
|
78
|
+
- name: Resolve build settings
|
|
79
|
+
id: vars
|
|
80
|
+
shell: bash
|
|
81
|
+
run: |
|
|
82
|
+
set -e
|
|
83
|
+
FM="${{ inputs.frozen_manifest }}"
|
|
84
|
+
UCM="${{ inputs.user_c_modules }}"
|
|
85
|
+
{
|
|
86
|
+
echo "user_c_modules=${UCM:-$GITHUB_WORKSPACE/usermod/micropython.cmake}"
|
|
87
|
+
echo "frozen_manifest=${FM:-$GITHUB_WORKSPACE/usermod/manifest.py}"
|
|
88
|
+
echo "build_dir=build-${{ inputs.board }}"
|
|
89
|
+
} >> "$GITHUB_OUTPUT"
|
|
90
|
+
|
|
91
|
+
- name: Install esp-idf
|
|
92
|
+
shell: bash
|
|
93
|
+
run: |
|
|
94
|
+
git clone --depth 1 --recursive --branch "${{ inputs.idf_ver }}" \
|
|
95
|
+
https://github.com/espressif/esp-idf.git
|
|
96
|
+
./esp-idf/install.sh "${{ inputs.idf_target }}"
|
|
97
|
+
|
|
98
|
+
- name: Build mpy-cross
|
|
99
|
+
shell: bash
|
|
100
|
+
# Before export.sh is sourced anywhere: mpy-cross is a host tool and
|
|
101
|
+
# has no business being built inside IDF's own python/toolchain
|
|
102
|
+
# environment. Explicit for the usual reason -- see build-usermod-unix's
|
|
103
|
+
# own comment on py/mkenv.mk's auto-build rule.
|
|
104
|
+
run: make -C "$MPY_DIR/mpy-cross" -j"$(nproc)"
|
|
105
|
+
|
|
106
|
+
- name: Build usermod (esp32, ${{ inputs.board }})
|
|
107
|
+
shell: bash
|
|
108
|
+
# source + make in the same step, not two: export.sh's env doesn't
|
|
109
|
+
# survive a composite action step boundary (each step is a fresh
|
|
110
|
+
# shell invocation), unlike $GITHUB_ENV-based exports.
|
|
111
|
+
# No BUILD= override, even though it would resolve to the exact same
|
|
112
|
+
# value (build-$(BOARD)) the port already defaults to: a real CI
|
|
113
|
+
# failure showed that passing it explicitly -- not what it's set to,
|
|
114
|
+
# the mere presence of BUILD= on the command line -- makes the port's
|
|
115
|
+
# own internal CMake-driven mpy-cross sub-build (build-$(BOARD)/mpy-cross,
|
|
116
|
+
# a separate copy from $MPY_DIR/mpy-cross above) pick up
|
|
117
|
+
# FROZEN_MANIFEST through MAKEFLAGS and fail with "undefined reference
|
|
118
|
+
# to mp_qstr_frozen_const_pool" -- the same symptom the explicit
|
|
119
|
+
# pre-build of $MPY_DIR/mpy-cross exists to prevent, just not reachable
|
|
120
|
+
# by that fix here since this is CMake's own separate copy, not
|
|
121
|
+
# py/mkrules.mk's auto-build rule. Every real caller wants the port's
|
|
122
|
+
# own default anyway (see build_dir's own description above), so this
|
|
123
|
+
# isn't a capability loss in practice.
|
|
124
|
+
run: |
|
|
125
|
+
source esp-idf/export.sh
|
|
126
|
+
make -C "$MPY_DIR/ports/esp32" \
|
|
127
|
+
BOARD="${{ inputs.board }}" \
|
|
128
|
+
USER_C_MODULES="${{ steps.vars.outputs.user_c_modules }}" \
|
|
129
|
+
FROZEN_MANIFEST="${{ steps.vars.outputs.frozen_manifest }}" \
|
|
130
|
+
${{ inputs.extra_make_args }}
|
|
131
|
+
|
|
132
|
+
- name: Dump the IDF build logs on failure
|
|
133
|
+
if: failure()
|
|
134
|
+
shell: bash
|
|
135
|
+
# idf.py redirects the compiler's own stderr into
|
|
136
|
+
# build-*/log/idf_py_stderr_output_<pid> and prints only "ninja failed
|
|
137
|
+
# with exit code 1" to the console, so a failing compile leaves no
|
|
138
|
+
# diagnostic in the Actions log at all -- found on a real failure
|
|
139
|
+
# (o-murphy/micropython-wasm3's esp32 job, stopped in
|
|
140
|
+
# wasm3/source/m3_compile.c with nothing to say why). Surfaced here so
|
|
141
|
+
# every caller gets this for free, not just the one that hit it first.
|
|
142
|
+
#
|
|
143
|
+
# The log files turned out not to carry the diagnostic at all: idf.py's
|
|
144
|
+
# idf_py_stderr_output_* holds only its own bookkeeping ("Command:
|
|
145
|
+
# ninja all"), and the stdout copy of ninja's stream shows the failing
|
|
146
|
+
# target and then "ninja: build stopped" with nothing in between. So
|
|
147
|
+
# dump them for context, then get the real answer by re-running ninja
|
|
148
|
+
# verbosely in the same build directory: everything is already built
|
|
149
|
+
# except the one object that failed, so this recompiles just that and
|
|
150
|
+
# prints both the exact command line and the compiler's own output.
|
|
151
|
+
# `|| true` so this step reports rather than re-failing the job.
|
|
152
|
+
run: |
|
|
153
|
+
BUILD="${{ steps.vars.outputs.build_dir }}"
|
|
154
|
+
for f in "$BUILD"/log/idf_py_std*_output_*; do
|
|
155
|
+
[ -f "$f" ] || continue
|
|
156
|
+
echo "::group::$f"
|
|
157
|
+
tail -n 60 "$f"
|
|
158
|
+
echo "::endgroup::"
|
|
159
|
+
done
|
|
160
|
+
echo "--- re-running ninja verbosely to surface the diagnostic:"
|
|
161
|
+
source esp-idf/export.sh
|
|
162
|
+
ninja -C "$BUILD" -v -k 0 2>&1 | tail -n 120 || true
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
name: Build usermod rp2040
|
|
2
|
+
description: >
|
|
3
|
+
Builds a MicroPython ports/rp2 "usermod" (a C module compiled straight
|
|
4
|
+
into the port via USER_C_MODULES=) into a firmware.uf2 for the given
|
|
5
|
+
BOARD=. Installs the arm-none-eabi + CMake toolchain, builds mpy-cross,
|
|
6
|
+
then runs the port build under it.
|
|
7
|
+
|
|
8
|
+
Requires MPY_DIR to already be exported (fetch-micropython -- proven
|
|
9
|
+
sufficient for this port, see below -- or clone-micropython) and the
|
|
10
|
+
calling repo already checked out, same contract as build-usermod-unix
|
|
11
|
+
and build-usermod-webassembly.
|
|
12
|
+
|
|
13
|
+
Checkout note for callers migrating off clone-micropython +
|
|
14
|
+
pico_sdk_submodules: neither is required. ports/rp2/CMakeLists.txt
|
|
15
|
+
redirects PICO_TINYUSB_PATH/PICO_LWIP_PATH/PICO_BTSTACK_PATH/
|
|
16
|
+
PICO_CYW43_DRIVER_PATH at ${MICROPY_DIR}/lib/<name> -- MicroPython's own
|
|
17
|
+
top-level submodules, which the release tarball already vendors -- not
|
|
18
|
+
at pico-sdk's own nested vendored copies, so pico-sdk's internal
|
|
19
|
+
submodule tree is never actually touched by this build. Proven green
|
|
20
|
+
first on o-murphy/micropython-wasm3's rp2 row (plain fetch-micropython,
|
|
21
|
+
no submodule handling at all), then on ballistics-lab/micropython-bclibc
|
|
22
|
+
and o-murphy/a7p after switching off their original clone-micropython +
|
|
23
|
+
explicit submodule list + pico_sdk_submodules: "true".
|
|
24
|
+
|
|
25
|
+
inputs:
|
|
26
|
+
board:
|
|
27
|
+
description: Value for BOARD=. Defaults to RPI_PICO.
|
|
28
|
+
required: false
|
|
29
|
+
default: RPI_PICO
|
|
30
|
+
user_c_modules:
|
|
31
|
+
description: >
|
|
32
|
+
Value for USER_C_MODULES=. Defaults to usermod/micropython.cmake
|
|
33
|
+
under the workspace root -- unlike build-usermod-unix/
|
|
34
|
+
build-usermod-webassembly's own user_c_modules, this one is a *file*,
|
|
35
|
+
not a directory: CMake's USER_C_MODULES takes a single .cmake entry
|
|
36
|
+
point to include, not a directory to glob.
|
|
37
|
+
required: false
|
|
38
|
+
default: ''
|
|
39
|
+
frozen_manifest:
|
|
40
|
+
description: Value for FROZEN_MANIFEST=. Defaults to usermod/manifest.py under the workspace root.
|
|
41
|
+
required: false
|
|
42
|
+
default: ''
|
|
43
|
+
extra_make_args:
|
|
44
|
+
description: >
|
|
45
|
+
Extra space-separated VAR=value pairs appended to the build command,
|
|
46
|
+
e.g. a module's own precision define.
|
|
47
|
+
required: false
|
|
48
|
+
default: ''
|
|
49
|
+
extra_cmake_args:
|
|
50
|
+
description: >
|
|
51
|
+
Extra arguments for a direct `cmake -S . -B <build_dir>` reconfigure
|
|
52
|
+
step run after the port's own first configure. Left empty (the
|
|
53
|
+
default), this action runs the port build in a single make
|
|
54
|
+
invocation. Needed because ports/rp2/Makefile builds its own cmake
|
|
55
|
+
arguments with `CMAKE_ARGS +=`, so a define passed straight on the
|
|
56
|
+
make command line replaces the whole accumulated set -- including
|
|
57
|
+
MICROPY_BOARD, USER_C_MODULES and MICROPY_FROZEN_MANIFEST -- rather
|
|
58
|
+
than adding to it. o-murphy/micropython-wasm3 needs
|
|
59
|
+
-DMICROPY_C_HEAP_SIZE=131072 here: rp2 defaults that to 0, and its
|
|
60
|
+
module allocates through the port's calloc(), which fails the
|
|
61
|
+
configure outright at 0.
|
|
62
|
+
required: false
|
|
63
|
+
default: ''
|
|
64
|
+
build_dir:
|
|
65
|
+
description: >
|
|
66
|
+
Value for BUILD=. Defaults to usermod/build/rp2040 under the
|
|
67
|
+
workspace root. A bare relative value (no leading /) resolves
|
|
68
|
+
against $MPY_DIR/ports/rp2 instead, same as make -C's own
|
|
69
|
+
relative-path handling -- pass one when the caller wants the port's
|
|
70
|
+
own board-named default (e.g. build-RPI_PICO) instead.
|
|
71
|
+
required: false
|
|
72
|
+
default: ''
|
|
73
|
+
|
|
74
|
+
outputs:
|
|
75
|
+
build_dir:
|
|
76
|
+
description: >
|
|
77
|
+
The BUILD= directory actually used (resolved default included), so
|
|
78
|
+
the caller can find firmware.uf2 without recomputing it.
|
|
79
|
+
value: ${{ steps.vars.outputs.build_dir }}
|
|
80
|
+
|
|
81
|
+
runs:
|
|
82
|
+
using: composite
|
|
83
|
+
steps:
|
|
84
|
+
- name: Resolve build settings
|
|
85
|
+
id: vars
|
|
86
|
+
shell: bash
|
|
87
|
+
run: |
|
|
88
|
+
set -e
|
|
89
|
+
BUILD="${{ inputs.build_dir }}"
|
|
90
|
+
FM="${{ inputs.frozen_manifest }}"
|
|
91
|
+
UCM="${{ inputs.user_c_modules }}"
|
|
92
|
+
{
|
|
93
|
+
echo "user_c_modules=${UCM:-$GITHUB_WORKSPACE/usermod/micropython.cmake}"
|
|
94
|
+
echo "frozen_manifest=${FM:-$GITHUB_WORKSPACE/usermod/manifest.py}"
|
|
95
|
+
echo "build_dir=${BUILD:-$GITHUB_WORKSPACE/usermod/build/rp2040}"
|
|
96
|
+
} >> "$GITHUB_OUTPUT"
|
|
97
|
+
|
|
98
|
+
- name: Install toolchain
|
|
99
|
+
shell: bash
|
|
100
|
+
# apt-get update first -- a bare apt-get install against the runner
|
|
101
|
+
# image's stale package index intermittently 404s on a mirror.
|
|
102
|
+
#
|
|
103
|
+
# libstdc++-arm-none-eabi-newlib: pico-sdk compiles one .cpp of its
|
|
104
|
+
# own, which fails with "cstdlib: No such file or directory" without
|
|
105
|
+
# it (a real CI failure on o-murphy/micropython-wasm3's rp2 row) --
|
|
106
|
+
# included here even though not every caller's build happens to
|
|
107
|
+
# exercise that file, since whether it does depends on pico-sdk
|
|
108
|
+
# internals no caller should have to know.
|
|
109
|
+
run: |
|
|
110
|
+
sudo apt-get update -q
|
|
111
|
+
sudo apt-get install -y \
|
|
112
|
+
cmake \
|
|
113
|
+
gcc-arm-none-eabi \
|
|
114
|
+
libnewlib-arm-none-eabi \
|
|
115
|
+
libstdc++-arm-none-eabi-newlib \
|
|
116
|
+
python3
|
|
117
|
+
|
|
118
|
+
- name: Build mpy-cross
|
|
119
|
+
shell: bash
|
|
120
|
+
# Explicitly, before FROZEN_MANIFEST ever appears on a command line --
|
|
121
|
+
# py/mkenv.mk's auto-build rule for mpy-cross resets USER_C_MODULES=
|
|
122
|
+
# for that recursive make but not FROZEN_MANIFEST=, which leaks
|
|
123
|
+
# through MAKEFLAGS and fails the sub-build. Same fix as
|
|
124
|
+
# build-usermod-unix/build-usermod-webassembly.
|
|
125
|
+
run: make -C "$MPY_DIR/mpy-cross"
|
|
126
|
+
|
|
127
|
+
- name: Build usermod (rp2040, ${{ inputs.board }})
|
|
128
|
+
shell: bash
|
|
129
|
+
# cd, not make -C: the extra_cmake_args branch below needs `cmake -S
|
|
130
|
+
# . -B $BUILD` to run from inside ports/rp2, same as
|
|
131
|
+
# o-murphy/micropython-wasm3's own recipe this was extracted from.
|
|
132
|
+
run: |
|
|
133
|
+
cd "$MPY_DIR/ports/rp2"
|
|
134
|
+
if [ -n "${{ inputs.extra_cmake_args }}" ]; then
|
|
135
|
+
make BOARD="${{ inputs.board }}" \
|
|
136
|
+
BUILD="${{ steps.vars.outputs.build_dir }}" \
|
|
137
|
+
USER_C_MODULES="${{ steps.vars.outputs.user_c_modules }}" \
|
|
138
|
+
FROZEN_MANIFEST="${{ steps.vars.outputs.frozen_manifest }}" || true
|
|
139
|
+
cmake -S . -B "${{ steps.vars.outputs.build_dir }}" ${{ inputs.extra_cmake_args }}
|
|
140
|
+
fi
|
|
141
|
+
make BOARD="${{ inputs.board }}" \
|
|
142
|
+
BUILD="${{ steps.vars.outputs.build_dir }}" \
|
|
143
|
+
USER_C_MODULES="${{ steps.vars.outputs.user_c_modules }}" \
|
|
144
|
+
FROZEN_MANIFEST="${{ steps.vars.outputs.frozen_manifest }}" \
|
|
145
|
+
${{ inputs.extra_make_args }} -j"$(nproc)"
|