-
-
Notifications
You must be signed in to change notification settings - Fork 21
369 lines (358 loc) · 16.5 KB
/
Copy pathbuild-native.yml
File metadata and controls
369 lines (358 loc) · 16.5 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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# Reusable workflow that builds every native artifact the npm packages ship:
#
# artifact name contents destination in the repo
# --------------------- ------------------------------------ ---------------------------------------------
# canvas-android canvas-release.aar packages/canvas/platforms/android/
# canvas-ios CanvasNative.xcframework (tar.gz) packages/canvas/platforms/ios/
# canvas-svg-android canvassvg-release.aar packages/canvas-svg/platforms/android/
# canvas-svg-ios CanvasSVG.xcframework (tar.gz) packages/canvas-svg/platforms/ios/
# audio-context-android audiocontext-release.aar packages/audio-context/platforms/android/
# audio-context-ios AudioContextNative.xcframework packages/audio-context/platforms/ios/
# (tar.gz)
# canvas-windows-<arch> canvasnative.node + ANGLE DLLs packages/canvas/platforms/windows/<arch>/
# canvas-svg-windows- canvassvg.node packages/canvas-svg/platforms/windows/<arch>/
# <arch>
# audio-context-windows- audiocontext.node packages/audio-context/platforms/windows/<arch>/
# <arch>
# canvas-media-windows- canvasmedia.node packages/canvas-media/platforms/windows/<arch>/
# <arch>
#
# xcframeworks are tarred before upload because upload-artifact does not
# preserve file permissions.
#
# The canvas build mirrors the local flow:
# iOS: make ios && make visionos && make tvos, then tools/scripts/canvas-build.sh
# (what `npm run build.canvas.ios.framework.release` runs, minus nx)
# Android: make android, then gradle :canvas:assembleRelease and copy the aar
#
# Windows: tools/scripts/build-napi.sh <triple> release-napi [<crate>] (`make windows`,
# `make windows-svg`, `make windows-audio`, `make windows-media`); the modules other
# than canvasnative.node share one matrix job (napi-windows). Skia builds from source
# with the runner's LLVM and ninja, as locally with .tools/env.sh
# (.github/actions/setup-windows-native). arm64 is cross-compiled; the x64 jobs also
# run the Node-API test suites on the shipped modules (on WARP: runners have no GPU;
# audio renders offline and on the 'none' sink: they have no audio device either).
#
# The napi-windows modules and the canvas-svg / audio-context mobile builds change rarely, so
# their jobs cache the final artifact keyed on a hash of their sources and skip the whole build
# on a hit.
name: Build Native
permissions:
contents: read
on:
workflow_call:
inputs:
ref:
description: Git ref to build. Empty means the ref that triggered the caller.
required: false
type: string
default: ''
workflow_dispatch:
inputs:
ref:
description: Git ref to build
required: false
type: string
default: ''
env:
# bump to invalidate the canvas-svg / audio-context / canvas-media artifact caches
NATIVE_CACHE_VERSION: v1
jobs:
canvas-android:
name: Canvas Android
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.repository.default_branch || inputs.ref }}
- uses: ./.github/actions/setup-android-native
- name: Fetch V8 + NativeScript runtime headers
run: ./tools/scripts/download-v8.sh
- name: Build libNativeScript.so stub for linking
run: ./tools/scripts/build-android-v8-stub.sh
- name: Build Rust libraries
run: make android
- name: Build canvas AAR
working-directory: packages/canvas/src-native/canvas-android
run: ./gradlew :canvas:assembleRelease
- name: Copy AAR into platforms/android
run: cp packages/canvas/src-native/canvas-android/canvas/build/outputs/aar/canvas-release.aar packages/canvas/platforms/android/canvas-release.aar
- uses: actions/upload-artifact@v4
with:
name: canvas-android
path: packages/canvas/platforms/android/canvas-release.aar
if-no-files-found: error
canvas-ios:
name: Canvas iOS + visionOS + tvOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.repository.default_branch || inputs.ref }}
- uses: ./.github/actions/setup-apple-native
- name: Fetch V8 + NativeScript runtime headers
run: ./tools/scripts/download-v8.sh
- name: Build Rust libraries (iOS)
run: make ios
- name: Build Rust libraries (visionOS)
run: make visionos
# canvas-build.sh requires the tvOS static libs whenever the runner has a
# usable tvOS destination, which the macOS images do.
- name: Build Rust libraries (tvOS)
run: make tvos
# same as `npm run build.canvas.ios.framework.release`, without needing node_modules
- name: Build CanvasNative.xcframework
working-directory: tools/scripts
run: sh canvas-build.sh
- name: Pack xcframework
run: tar -czf canvas-ios.tar.gz -C packages/canvas/platforms/ios CanvasNative.xcframework
- uses: actions/upload-artifact@v4
with:
name: canvas-ios
path: canvas-ios.tar.gz
if-no-files-found: error
canvas-svg-android:
name: Canvas SVG Android
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
- name: Restore cached AAR
id: svg-aar
uses: actions/cache@v4
with:
path: packages/canvas-svg/platforms/android/canvassvg-release.aar
key: ${{ env.NATIVE_CACHE_VERSION }}-canvas-svg-android-${{ hashFiles('crates/canvas-svg/**', 'crates/canvas-svg-android/**', 'packages/canvas-svg/src-native/android/**', '!packages/canvas-svg/src-native/android/**/build/**', '!packages/canvas-svg/src-native/android/**/jniLibs/**', 'Cargo.lock', 'tools/scripts/build-svg-android.sh', 'tools/scripts/copy-svg-android.sh', 'Makefile') }}
- uses: ./.github/actions/setup-android-native
if: steps.svg-aar.outputs.cache-hit != 'true'
- name: Build Rust libraries
if: steps.svg-aar.outputs.cache-hit != 'true'
run: make android-svg
- name: Copy .so files into jniLibs
if: steps.svg-aar.outputs.cache-hit != 'true'
run: sh tools/scripts/copy-svg-android.sh
- name: Build canvassvg AAR
if: steps.svg-aar.outputs.cache-hit != 'true'
working-directory: packages/canvas-svg/src-native/android
run: ./gradlew :canvassvg:assembleRelease
- name: Copy AAR into platforms/android
if: steps.svg-aar.outputs.cache-hit != 'true'
run: cp packages/canvas-svg/src-native/android/canvassvg/build/outputs/aar/canvassvg-release.aar packages/canvas-svg/platforms/android/canvassvg-release.aar
- uses: actions/upload-artifact@v4
with:
name: canvas-svg-android
path: packages/canvas-svg/platforms/android/canvassvg-release.aar
if-no-files-found: error
canvas-svg-ios:
name: Canvas SVG iOS + visionOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
- name: Restore cached xcframework
id: svg-xcframework
uses: actions/cache@v4
with:
path: canvas-svg-ios.tar.gz
key: ${{ env.NATIVE_CACHE_VERSION }}-canvas-svg-ios-${{ hashFiles('crates/canvas-svg/**', 'crates/canvas-svg-ios/**', 'packages/canvas-svg/src-native/ios/**', '!packages/canvas-svg/src-native/ios/dist/**', 'Cargo.lock', 'tools/scripts/canvas-svg-build.sh', 'Makefile') }}
- uses: ./.github/actions/setup-apple-native
if: steps.svg-xcframework.outputs.cache-hit != 'true'
- name: Build Rust libraries (iOS + visionOS)
if: steps.svg-xcframework.outputs.cache-hit != 'true'
run: make svg
# same as `npm run build.canvas.svg.ios.framework.release`
- name: Build CanvasSVG.xcframework
if: steps.svg-xcframework.outputs.cache-hit != 'true'
working-directory: tools/scripts
run: sh canvas-svg-build.sh
- name: Pack xcframework
if: steps.svg-xcframework.outputs.cache-hit != 'true'
run: tar -czf canvas-svg-ios.tar.gz -C packages/canvas-svg/platforms/ios CanvasSVG.xcframework
- uses: actions/upload-artifact@v4
with:
name: canvas-svg-ios
path: canvas-svg-ios.tar.gz
if-no-files-found: error
audio-context-android:
name: AudioContext Android
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
- name: Restore cached AAR
id: audio-aar
uses: actions/cache@v4
with:
path: packages/audio-context/platforms/android/audiocontext-release.aar
key: ${{ env.NATIVE_CACHE_VERSION }}-audio-context-android-${{ hashFiles('packages/audio-context/src-native/android/**', '!packages/audio-context/src-native/android/**/build/**') }}
- uses: actions/setup-java@v4
if: steps.audio-aar.outputs.cache-hit != 'true'
with:
distribution: temurin
java-version: '17'
cache: gradle
- name: Setup Android SDK
if: steps.audio-aar.outputs.cache-hit != 'true'
uses: android-actions/setup-android@v3
- name: Build audiocontext AAR
if: steps.audio-aar.outputs.cache-hit != 'true'
working-directory: packages/audio-context/src-native/android
run: ./gradlew :audiocontext:assembleRelease
- name: Copy AAR into platforms/android
if: steps.audio-aar.outputs.cache-hit != 'true'
run: cp packages/audio-context/src-native/android/audiocontext/build/outputs/aar/audiocontext-release.aar packages/audio-context/platforms/android/audiocontext-release.aar
- uses: actions/upload-artifact@v4
with:
name: audio-context-android
path: packages/audio-context/platforms/android/audiocontext-release.aar
if-no-files-found: error
audio-context-ios:
name: AudioContext iOS + visionOS + tvOS
runs-on: macos-15
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
- name: Restore cached xcframework
id: audio-xcframework
uses: actions/cache@v4
with:
path: audio-context-ios.tar.gz
key: ${{ env.NATIVE_CACHE_VERSION }}-audio-context-ios-${{ hashFiles('packages/audio-context/src-native/ios/**', 'tools/scripts/audio-context-build.sh') }}
- uses: ./.github/actions/setup-apple-native
if: steps.audio-xcframework.outputs.cache-hit != 'true'
with:
install-rust: 'false'
# same as `npm run build.audiocontext.ios.framework.release`
- name: Build AudioContextNative.xcframework
if: steps.audio-xcframework.outputs.cache-hit != 'true'
working-directory: tools/scripts
run: sh audio-context-build.sh
- name: Pack xcframework
if: steps.audio-xcframework.outputs.cache-hit != 'true'
run: tar -czf audio-context-ios.tar.gz -C packages/audio-context/platforms/ios AudioContextNative.xcframework
- uses: actions/upload-artifact@v4
with:
name: audio-context-ios
path: audio-context-ios.tar.gz
if-no-files-found: error
canvas-windows:
name: Canvas Windows (${{ matrix.arch }})
runs-on: windows-2025
strategy:
fail-fast: false
matrix:
include:
- arch: x64
target: x86_64-pc-windows-msvc
- arch: arm64
target: aarch64-pc-windows-msvc
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.repository.default_branch || inputs.ref }}
- uses: ./.github/actions/setup-windows-native
with:
target: ${{ matrix.target }}
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Build canvasnative.node (and fetch ANGLE)
run: ./tools/scripts/build-napi.sh ${{ matrix.target }} release-napi
# arm64 is cross-compiled, so only x64 runs them. The runners have no GPU: D3D12 and ANGLE
# fall back to WARP, and the WebGPU suites skip without an adapter.
- name: Node-API tests
if: matrix.arch == 'x64'
env:
CANVAS_NAPI_ADDON: ${{ github.workspace }}\packages\canvas\platforms\windows\x64\canvasnative.node
run: node --expose-gc --test "crates/canvas-napi/__test__/*.test.mjs"
- uses: actions/upload-artifact@v4
with:
name: canvas-windows-${{ matrix.arch }}
path: packages/canvas/platforms/windows/${{ matrix.arch }}/
if-no-files-found: error
# The Node-API modules other than canvasnative.node (no Skia, no ANGLE): one entry per module.
napi-windows:
name: ${{ matrix.module.name }} Windows (${{ matrix.arch }})
runs-on: windows-2025
strategy:
fail-fast: false
matrix:
module:
# `sources`: every tracked directory the module is built from (its cache key).
- name: canvas-svg
crate: canvas-svg-napi
file: canvassvg.node
addon-env: CANVAS_SVG_NAPI_ADDON
sources: crates/canvas-svg crates/canvas-svg-c crates/canvas-svg-napi crates/canvas-2d crates/canvas-core
# Runners have no audio device: its suite renders offline and on the 'none' sink.
- name: audio-context
crate: audio-context-napi
file: audiocontext.node
addon-env: AUDIO_CONTEXT_NAPI_ADDON
sources: crates/audio-context-napi
- name: canvas-media
crate: canvas-media-napi
file: canvasmedia.node
addon-env: CANVAS_MEDIA_NAPI_ADDON
sources: crates/canvas-media-napi
arch: [x64, arm64]
include:
- arch: x64
target: x86_64-pc-windows-msvc
- arch: arm64
target: aarch64-pc-windows-msvc
defaults:
run:
shell: bash
env:
MODULE_DIR: packages/${{ matrix.module.name }}/platforms/windows/${{ matrix.arch }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.event.repository.default_branch || inputs.ref }}
# The tree hashes of what the module is built from: equal hashes, equal module.
- name: Source key
id: sources
run: |
key=$(for path in ${{ matrix.module.sources }} crates/vendor/napi-sys Cargo.toml tools/scripts/build-napi.sh; do git rev-parse "HEAD:$path" || exit 1; done | sha256sum | cut -c1-32)
echo "key=$key" >> "$GITHUB_OUTPUT"
# Not on manual runs (CodeQL: cache poisoning via untrusted files); those always build.
- name: Restore cached module
if: github.event_name != 'workflow_dispatch'
id: cache
uses: actions/cache@v4
with:
path: ${{ env.MODULE_DIR }}/${{ matrix.module.file }}
key: ${{ env.NATIVE_CACHE_VERSION }}-${{ matrix.module.name }}-windows-${{ matrix.arch }}-${{ steps.sources.outputs.key }}
# No Skia here; the action's Rust toolchain and cargo cache are what these need.
- uses: ./.github/actions/setup-windows-native
if: steps.cache.outputs.cache-hit != 'true'
with:
target: ${{ matrix.target }}
- uses: actions/setup-node@v4
if: steps.cache.outputs.cache-hit != 'true' && matrix.arch == 'x64'
with:
node-version: '22'
- name: Build ${{ matrix.module.file }}
if: steps.cache.outputs.cache-hit != 'true'
run: ./tools/scripts/build-napi.sh ${{ matrix.target }} release-napi ${{ matrix.module.crate }}
# arm64 is cross-compiled, so only x64 runs them. The timeout bounds a test process that
# hangs on exit (an addon releasing Media Foundation / D3D objects during process shutdown).
- name: Node-API tests
if: steps.cache.outputs.cache-hit != 'true' && matrix.arch == 'x64'
timeout-minutes: 5
run: |
export ${{ matrix.module.addon-env }}="$(cygpath -w "$PWD/$MODULE_DIR/${{ matrix.module.file }}")"
node --expose-gc --test "crates/${{ matrix.module.crate }}/__test__/*.test.mjs"
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.module.name }}-windows-${{ matrix.arch }}
path: ${{ env.MODULE_DIR }}/
if-no-files-found: error