forked from OpenNMT/CTranslate2
-
Notifications
You must be signed in to change notification settings - Fork 0
205 lines (192 loc) · 8.38 KB
/
Copy pathmobile.yml
File metadata and controls
205 lines (192 loc) · 8.38 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
# Builds the engine for the platforms upstream does not support.
#
# It is here rather than in the consuming app for the same reason the WebRTC
# engine is: this artifact takes minutes to produce, needs an NDK and an Xcode,
# and is then consumed as a prebuilt. What the app must never do is assume a
# prebuilt is current — every download is checked against what the caller
# actually looks up.
#
# The steps are deliberately thin. All the knowledge lives in mobile/*.sh,
# which run identically on a laptop, so a failure here can be reproduced
# without pushing anything. That is also why this file is a MATRIX over the
# knobs those scripts already take — ANDROID_ABI and --simulator — rather than
# a second copy of the build in YAML. Nothing here teaches the CI anything the
# scripts do not already know.
name: mobile engines
env:
# What the app actually releases. Everything else in the matrix is buildable
# on request and is not a promise.
SHIPPED_TARGETS: 'android-arm64 ios-arm64 ios-sim-arm64'
on:
push:
paths:
- 'mobile/**'
- 'CMakeLists.txt'
- '.github/workflows/mobile.yml'
workflow_dispatch:
inputs:
targets:
description: 'Space-separated. android-arm64 android-arm android-x64 | ios-arm64 ios-sim-arm64. Empty = the shipped set.'
required: false
type: string
default: ''
jobs:
android:
name: libctranslate2.so (${{ matrix.target }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# arm64-v8a is every phone sold in the last decade.
- target: android-arm64
abi: arm64-v8a
kind: android
# armeabi-v7a is what the cheap phones this project is for still run,
# and the ABI an APK silently omits if nobody builds it.
- target: android-arm
abi: armeabi-v7a
kind: android-arm
# x86_64 is every emulator. Without it the app cannot be run on a
# desktop at all, which is where most of its testing happens.
- target: android-x64
abi: x86_64
kind: android-x64
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
# A push builds everything; a manual run may ask for a subset. An empty
# input means all of them, so the push path and the "just rebuild one"
# path share one job definition.
# An empty ask means THE SHIPPED SET, not everything.
#
# The app releases arm64-v8a only, and says why in its own builder: the
# other two ABIs built and were published through v0.9.1, but neither can
# carry the media engine, so calls, voice messages and speech-to-text are
# dead in them. armeabi-v7a additionally does not build here at all —
# CTranslate2 has no 32-bit ARM entry in its CPU dispatch
# (`no member named 'NEON' in CpuIsa`), which is upstream's, not ours.
#
# So a push builds what is shipped and is green when that is true. The
# other ABIs stay ASKABLE — someone who wants one gets the real failure
# instead of a job quietly marked as passing.
- name: Skip targets not asked for
id: want
run: |
asked='${{ inputs.targets }}'
[ -n "$asked" ] || asked='${{ env.SHIPPED_TARGETS }}'
if echo "$asked" | grep -qw '${{ matrix.target }}'; then
echo "run=yes" >> "$GITHUB_OUTPUT"
else
echo "run=no" >> "$GITHUB_OUTPUT"
echo "${{ matrix.target }} was not requested"
fi
# The runners carry an NDK, but under a name the script does not know.
# Resolved here rather than in the script so the script keeps working
# unchanged on a laptop.
- name: Build
if: steps.want.outputs.run == 'yes'
run: |
set -euo pipefail
export ANDROID_NDK_HOME="${ANDROID_NDK_HOME:-${ANDROID_NDK_LATEST_HOME:-}}"
[ -d "$ANDROID_NDK_HOME" ] || { echo "::error::no NDK on this runner"; exit 1; }
echo "NDK: $ANDROID_NDK_HOME"
ANDROID_ABI='${{ matrix.abi }}' ./mobile/build-android.sh
# The script names its own output directory after the ABI, so assert the
# artifact is there rather than uploading whatever happens to exist: an
# upload of the wrong ABI's leftovers is the failure that looks like
# success.
- name: The artifact is the one this job built
if: steps.want.outputs.run == 'yes'
run: |
set -euo pipefail
d="dist/android-${{ matrix.abi }}"
[ -d "$d" ] || { echo "::error::no $d — the build produced nothing for this ABI"; exit 1; }
ls -la "$d"
# NOT best-effort. A cross build is exactly where a green build means
# least — the host cannot run what it just produced — so the artifact
# itself is the only evidence, and this script is what reads it.
bash mobile/verify-artifact.sh '${{ matrix.kind }}' "$d/libctranslate2.so"
- uses: actions/upload-artifact@v4
if: steps.want.outputs.run == 'yes'
with:
name: libctranslate2-${{ matrix.target }}
path: dist/android-${{ matrix.abi }}/
if-no-files-found: error
ios:
name: libctranslate2.a (${{ matrix.target }})
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
include:
- target: ios-arm64
flag: ''
dist: ios-arm64
kind: ios
# The simulator is a DIFFERENT target, not a debug flavour of the
# device one: same CPU, different SDK, and the triple carries a
# `-simulator` suffix. A device archive will not link a simulator app,
# so a developer without this one cannot run the app on a Mac.
- target: ios-sim-arm64
flag: '--simulator'
dist: ios-sim-arm64
kind: ios-simulator
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
# An empty ask means THE SHIPPED SET, not everything.
#
# The app releases arm64-v8a only, and says why in its own builder: the
# other two ABIs built and were published through v0.9.1, but neither can
# carry the media engine, so calls, voice messages and speech-to-text are
# dead in them. armeabi-v7a additionally does not build here at all —
# CTranslate2 has no 32-bit ARM entry in its CPU dispatch
# (`no member named 'NEON' in CpuIsa`), which is upstream's, not ours.
#
# So a push builds what is shipped and is green when that is true. The
# other ABIs stay ASKABLE — someone who wants one gets the real failure
# instead of a job quietly marked as passing.
- name: Skip targets not asked for
id: want
run: |
asked='${{ inputs.targets }}'
[ -n "$asked" ] || asked='${{ env.SHIPPED_TARGETS }}'
if echo "$asked" | grep -qw '${{ matrix.target }}'; then
echo "run=yes" >> "$GITHUB_OUTPUT"
else
echo "run=no" >> "$GITHUB_OUTPUT"
echo "${{ matrix.target }} was not requested"
fi
# Which Xcode built this. When a header goes missing on a consumer's
# machine the first question is which SDK it was compiled against, and a
# log that cannot answer costs a rebuild.
- name: Xcode
if: steps.want.outputs.run == 'yes'
run: |
xcode-select -p
xcodebuild -version
- name: Build
if: steps.want.outputs.run == 'yes'
run: |
set -euo pipefail
./mobile/build-ios.sh ${{ matrix.flag }}
- name: The artifact is the one this job built
if: steps.want.outputs.run == 'yes'
run: |
set -euo pipefail
d="dist/${{ matrix.dist }}"
[ -d "$d" ] || { echo "::error::no $d — the build produced nothing for this target"; exit 1; }
ls -la "$d"
# The KIND matters: a device archive and a simulator archive differ by
# the triple suffix alone, and mixing them up is the failure that
# links locally and dies on the other kind of machine.
bash mobile/verify-artifact.sh '${{ matrix.kind }}' "$d/libctranslate2.a"
- uses: actions/upload-artifact@v4
if: steps.want.outputs.run == 'yes'
with:
name: libctranslate2-${{ matrix.target }}
path: dist/${{ matrix.dist }}/
if-no-files-found: error