Repository navigation
266 lines (242 loc) · 11.3 KB
/
Copy pathcircuitpython.yml
File metadata and controls
266 lines (242 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# The CircuitPython-compatible path from a bare clone, the way a user builds
# it: build_mp.py fetches CircuitPython at its deps.lock tag and pygraphics at
# its modules.lock commit, builds the unix port with pygraphics as a user C
# module, and the result has to import it, draw, and read the pixels back.
# The second job builds the unix port with every C module that builds there
# and imports and runs each one.
name: circuitpython
on:
push:
branches: [main]
paths:
- 'build_mp.py'
- 'deps.lock'
- 'modules.lock'
- 'patches/circuitpython/**'
- 'modules/**'
- '.github/workflows/circuitpython.yml'
pull_request:
paths:
- 'build_mp.py'
- 'deps.lock'
- 'modules.lock'
- 'patches/circuitpython/**'
- 'modules/**'
- '.github/workflows/circuitpython.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
unix:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Install the unix port's build dependencies
run: |
sudo apt-get update
sudo apt-get install -y libffi-dev pkg-config
- name: Build CircuitPython's unix port with pygraphics
run: python3 build_mp.py --interpreter circuitpython --port unix --modules pygraphics
- name: pygraphics imports, draws and reads back
run: |
cat > check.py <<'PY'
import sys
import pygraphics
from pygraphics import FrameBuffer, RGB565
fb = FrameBuffer(bytearray(32 * 32 * 2), 32, 32, RGB565)
fb.fill(0)
fb.fill_rect(4, 4, 8, 8, 0xF800)
fb.circle(20, 20, 6, 0x07E0, True)
fb.line(0, 31, 31, 31, 0x001F)
got = (fb.pixel(5, 5), fb.pixel(20, 20), fb.pixel(16, 31), fb.pixel(0, 0))
print(sys.implementation.name, pygraphics.implementation(), [hex(p) for p in got])
assert sys.implementation.name == "circuitpython"
assert pygraphics.implementation() == "native_cmod"
assert pygraphics.capabilities()["framebuf"] == "native"
assert got == (0xF800, 0x07E0, 0x001F, 0), got
PY
./builds/circuitpython/unix/coverage/micropython check.py
# The build names the pinned tag, not the patch series laid on it.
- name: The version is the pinned tag, not -dirty
run: |
want=$(awk '$1 == "circuitpython" {print $3}' deps.lock)
got=$(./builds/circuitpython/unix/coverage/micropython -c "import os; print(os.uname().version.split(' on ')[0])")
echo "version: $got (deps.lock: $want)"
test "$got" = "$want"
- name: A looping source that comes back empty does not hang the delay nodes
run: |
cat > empty_source.py <<'PY'
import audiocore, audiodelays
from array import array
kw = dict(buffer_size=512, sample_rate=8000, channel_count=1)
for node in (audiodelays.Echo(max_delay_ms=50, **kw),
audiodelays.PitchShift(**kw),
audiodelays.GranularPitchShift(**kw),
audiodelays.Flanger(**kw),
audiodelays.MultiTapDelay(max_delay_ms=50, delay_ms=20, decay=0.5, mix=0.5, **kw)):
node.play(audiocore.RawSample(array("h"), sample_rate=8000), loop=True)
for _ in range(4):
audiocore.get_buffer(node)
print(type(node).__name__, "returned, playing", node.playing)
assert not node.playing
PY
timeout 60 ./builds/circuitpython/unix/coverage/micropython empty_source.py
unix-modules:
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Install the unix port's build dependencies, and SDL2 for displayif
run: |
sudo apt-get update
sudo apt-get install -y libffi-dev pkg-config libsdl2-dev
# castif and h264enc build to nothing here (they are the ESP32-P4's); they
# are named so their micropython.mk is checked on a port without them.
# pydevices comes with displayif for its SDLDisplay. With pdwidgets and
# palettes the frozen strings pass CircuitPython's 64 KB pool, so the
# unix build uses four-byte qstr offsets (build_mp.py sets them).
- name: Build CircuitPython's unix port with our C modules
run: |
python3 build_mp.py --interpreter circuitpython --port unix \
--modules pygraphics,audiodsp,displayif,pydevices,pdwidgets,palettes,pngio,tsmux,ppa,jpegio,cameraif,mdns,usbhost,castif,h264enc
- name: Every module imports
run: |
cat > imports.py <<'PY'
import sys
assert sys.implementation.name == "circuitpython"
import pygraphics, usdl2, pngio, tsmux, ppa, cameraif, mdns, _usbhost
import jpegio, audiodynamics, audiograph
# audiopump.Ring is the stream sample: Python-made audio CircuitPython's mixer can play.
from audiopump import Ring
# jpegio is CircuitPython's own decoder there: ours adds only the encoder's C API.
assert hasattr(jpegio, "JpegDecoder")
assert cameraif.available() is False
# pydevices freezes CircuitPython's asyncio and the ticks under it.
import asyncio, adafruit_ticks, bledev
# pdwidgets and palettes are frozen with it: more names than a 64 KB pool holds.
import pdwidgets, palettes
# castif and h264enc are the ESP32-P4's: named here, they build to nothing.
for name in ("castif", "h264enc"):
try:
__import__(name)
except ImportError:
pass
else:
raise AssertionError(name + " should exist only on the ESP32-P4")
print("imported: pygraphics usdl2 pngio tsmux ppa cameraif mdns _usbhost jpegio audiodynamics audiograph audiopump.Ring")
PY
./builds/circuitpython/unix/coverage/micropython imports.py
# The stream sample, pulled through CircuitPython's own audiomixer and
# checked sample by sample.
- name: audiopump.Ring through audiomixer
run: timeout 300 ./builds/circuitpython/unix/coverage/micropython modules/audiodsp/tests/circuitpython/ring_through_mixer.py
# audiograph renders the same samples here as on CPython: the probe runs
# on both, and the comparison is the gate, at 0 counts. The planted
# faults are run first and must each be caught, or the gate proves
# nothing.
- name: audiograph renders what CPython's audiograph renders
run: |
python3 -m venv .graph-venv
./.graph-venv/bin/python -m pip install -q ./modules/audiodsp
cd modules/audiodsp
for fault in lsb late; do
if ../../.graph-venv/bin/python tests/parity/verify_graph.py \
--circuitpython "$GITHUB_WORKSPACE/builds/circuitpython/unix/coverage/micropython" \
--fault $fault; then
echo "the planted fault $fault passed, so this gate proves nothing" >&2
exit 1
fi
done
../../.graph-venv/bin/python tests/parity/verify_graph.py \
--circuitpython "$GITHUB_WORKSPACE/builds/circuitpython/unix/coverage/micropython"
- name: displayif, headless - usdl2 opens a window, the lifecycle API holds
env:
SDL_VIDEODRIVER: dummy
run: |
MP=./builds/circuitpython/unix/coverage/micropython
timeout 60 $MP -c "
import usdl2
assert usdl2.SDL_Init(usdl2.SDL_INIT_VIDEO) == 0, usdl2.SDL_GetError()
win = usdl2.SDL_CreateWindow(
'displayif smoke', usdl2.SDL_WINDOWPOS_UNDEFINED, usdl2.SDL_WINDOWPOS_UNDEFINED,
320, 240, usdl2.SDL_WINDOW_SHOWN)
assert win, usdl2.SDL_GetError()
print('usdl2 window created:', win)
usdl2.SDL_DestroyWindow(win)
usdl2.SDL_Quit()"
timeout 60 $MP modules/displayif/tests/test_lifecycle_api.py
- name: pydevices' SDLDisplay draws on it
env:
SDL_VIDEODRIVER: dummy
run: |
cat > sdl_display.py <<'PY'
import sys
from displaydev.sdldisplay import SDLDisplay
d = SDLDisplay(width=160, height=120)
d.fill_rect(0, 0, 160, 120, 0x0000)
d.fill_rect(0, 0, 10, 10, 0xF800)
d.show()
print(sys.implementation.name, type(d).__name__, d.width, d.height)
assert (d.width, d.height) == (160, 120)
d.deinit()
PY
timeout 60 ./builds/circuitpython/unix/coverage/micropython sdl_display.py
- name: pngio, tsmux and ppa pass their own tests
run: |
MP=./builds/circuitpython/unix/coverage/micropython
timeout 300 $MP -X heapsize=32M modules/pngio/tests/test_pngio.py
timeout 300 $MP modules/tsmux/tests/test_tsmux.py
timeout 300 $MP -X heapsize=16M modules/ppa/tests/test_ppa.py
- name: mdns - the API, and a service found by the process that advertised it
run: timeout 300 ./builds/circuitpython/unix/coverage/micropython modules/mdns/tests/test_mdns.py
# The ESP32-P4 host engine on CircuitPython: usbhost's C compiled against
# CircuitPython's own ESP-IDF 6 and Espressif's usb component, for the
# DEV-KIT's board cell. Nothing else in CI compiles this path, since the
# unix port builds usbhost to nothing, and a change to the shared engine
# sources (modules/usbhost/src) can break it with every other check green.
esp32p4-usbhost:
runs-on: ubuntu-latest
timeout-minutes: 90
env:
CCACHE_DIR: /home/runner/.cache/ccache
CCACHE_MAXSIZE: 400M
CCACHE_COMPILERCHECK: content
CCACHE_BASEDIR: ${{ github.workspace }}
CMAKE_C_COMPILER_LAUNCHER: ccache
CMAKE_CXX_COMPILER_LAUNCHER: ccache
CMAKE_ASM_COMPILER_LAUNCHER: ccache
IDF_CCACHE_ENABLE: '1'
steps:
- uses: actions/checkout@v7
- name: Packages the build needs
run: |
sudo apt-get update
sudo apt-get install -y ccache gettext cmake ninja-build pkg-config libffi-dev
- name: Cache the toolchains
uses: actions/cache@v6
with:
path: |
deps/circuitpython
deps/circuitpython-venv
~/.espressif
key: deps-cp-esp32p4-${{ hashFiles('deps.lock', 'patches/circuitpython/**') }}
- name: Cache compiler output
uses: actions/cache@v6
with:
path: /home/runner/.cache/ccache
key: ccache-cp-esp32p4-usbhost-${{ hashFiles('UPSTREAM', 'modules.lock') }}-${{ github.run_id }}
restore-keys: |
ccache-cp-esp32p4-usbhost-${{ hashFiles('UPSTREAM', 'modules.lock') }}-
ccache-cp-esp32p4-usbhost-
- name: Build CircuitPython for the WIFI6 DEV-KIT with usbhost
run: |
python3 build_mp.py --interpreter circuitpython --port espressif \
--board waveshare_esp32p4_wifi6_dev_kit --modules usbhost
- name: The host engine is in the image
run: |
out=builds/circuitpython/espressif/waveshare_esp32p4_wifi6_dev_kit
test -s "$out/firmware.bin"
for o in mod_usbhost usbhost_host usbhost_host_xfer usbhost_host_stream; do
grep -q "/$o.o" "$out/firmware.objs" || { echo "$o.o was not linked"; exit 1; }
done