-
Notifications
You must be signed in to change notification settings - Fork 52
372 lines (345 loc) · 13.4 KB
/
build_test.yml
File metadata and controls
372 lines (345 loc) · 13.4 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
370
371
372
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Workflow for building and running tests.
name: Build/Test *nix
on:
merge_group:
push:
branches:
- main
- v*.*.x
pull_request:
types: [opened, reopened, labeled, unlabeled, synchronize]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
build_test:
name: ${{ startsWith(matrix.os, 'macos-') && 'MacOS' || 'Ubuntu' }} Build ${{ matrix.name }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'CI:none') }}
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
strategy:
fail-fast: false
matrix:
# We have one job per "name" in the matrix. Attributes are set on the
# specific job names.
name: [release, debug, asan, msan, tsan, scalar]
include:
- name: release
mode: release
run_bench: true
test_in_pr: true
cmake_args: >-
-DJPEGLI_TEST_TOOLS=ON
-DJPEGLI_LIBJPEG_LIBRARY_VERSION="8.2.2"
-DJPEGLI_LIBJPEG_LIBRARY_SOVERSION="8"
# Track static stack size on build and check it doesn't exceed 3 kB.
emit_stack_sizes: 1
max_stack: 2400
# Conformance tooling test requires numpy.
# jpegli tests require imagemagick and libjpeg-turbo-progs
apt_pkgs: imagemagick libjpeg-turbo-progs python3-numpy
- name: debug
# Build scalar-only hwy instructions.
- name: scalar
mode: release
cxxflags: -DHWY_COMPILE_ONLY_SCALAR
# Disabling optional features to speed up MSAN build a little bit.
- name: msan
os: ubuntu-24.04
skip_install: true
cmake_args: >-
-DJPEGLI_ENABLE_DEVTOOLS=OFF
cc: clang-18
cxx: clang++-18
- name: asan
skip_install: true
- name: tsan
skip_install: true
- name: coverage
skip_install: true
disable_tests:
- test_jpegli_jni_wrapper # TODO: why this does not work?
# Build with jpegli_cms based on lcms2 library.
- name: release-lcms2
mode: release
cmake_args: >-
-DJPEGLI_ENABLE_SKCMS=OFF
- name: release-system-lcms2
mode: release
cmake_args: >-
-DJPEGLI_ENABLE_SKCMS=OFF
-DJPEGLI_FORCE_SYSTEM_LCMS2=ON
apt_pkgs: liblcms2-dev
# static build is impossible
skip_install: true
# Build/test on arm64 CPU
- name: release:arm64
os: ubuntu-24.04-arm
mode: release
run_bench: true
test_in_pr: true
# Builds with gcc in release mode
- name: release:gcc
os: ubuntu-latest
mode: release
cc: gcc
cxx: g++
run_bench: true
test_in_pr: true
- name: release:gcc-old
os: ubuntu-24.04
mode: release
cc: gcc
cxx: g++
- name: release:gcc-old-old
os: ubuntu-22.04
mode: release
cc: gcc
cxx: g++
# Builds with old clang in release mode
- name: release:clang-old
os: ubuntu-24.04
mode: release
cc: clang
cxx: clang++
- name: release:clang-old-old
os: ubuntu-22.04
mode: release
cc: clang
cxx: clang++
# LTO builds
- name: release_lto
os: ubuntu-latest
mode: release
cc: clang-17
cxx: clang++-17
apt_pkgs: lld
cmake_args: >-
-DJPEGLI_ENABLE_LTO=ON
-DCMAKE_LINKER_TYPE=LLD
run_bench: true
test_in_pr: true
- name: release_lto:gcc
os: ubuntu-latest
mode: release
cc: gcc
cxx: g++
cmake_args: >-
-DJPEGLI_ENABLE_LTO=ON
run_bench: true
test_in_pr: true
# OSX builds
- name: release:osx
os: macos-latest
mode: release
cmake_args: >-
-DCMAKE_FIND_FRAMEWORK=NEVER
- name: release:osx-15
os: macos-15
mode: release
test_stack_limit: 128
cmake_args: >-
-DCMAKE_FIND_FRAMEWORK=NEVER
- name: debug:osx-15
# The last "free" X86 OSX runner
os: macos-15-intel
mode: debug
cmake_args: >-
-DCMAKE_FIND_FRAMEWORK=NEVER
# Android builds
- name: release_android
os: ubuntu-latest
mode: release
skip_install: true
skip_stats: true
skip_test: true # can't finish "linking" tests without emulator
cmake_args: >-
-DANDROID_ABI=arm64-v8a
-DANDROID_PLATFORM=28
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_LATEST_HOME}/build/cmake/android.toolchain.cmake
-DJPEGLI_ENABLE_BENCHMARK=OFF
-DJPEGLI_ENABLE_OPENEXR=OFF
-DSJPEG_ANDROID_NDK_PATH=${ANDROID_NDK_LATEST_HOME}
-DJPEGLI_BUNDLE_LIBPNG=ON
- name: release_ios
os: macos-latest
mode: release
skip_install: true
skip_stats: true
skip_test: true # can't finish "linking" tests without emulator
cmake_args: >-
-DCMAKE_SYSTEM_NAME=iOS
-DCMAKE_OSX_ARCHITECTURES=arm64
-DJPEGLI_ENABLE_BENCHMARK=OFF
-DJPEGLI_ENABLE_OPENEXR=OFF
-DJPEGLI_BUNDLE_LIBPNG=ON
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
# Whether we track the stack size.
EMIT_STACK_SIZES: ${{ matrix.emit_stack_sizes }}
TEST_STACK_LIMIT: ${{ matrix.test_stack_limit }}
WILL_TEST: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && matrix.name != 'coverage' && (matrix.test_in_pr || contains(github.event.pull_request.labels.*.name, 'CI:full'))) }}
WILL_BUILD: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && matrix.name != 'coverage') }}
WILL_BENCH: ${{ github.event_name != 'merge_group' && matrix.run_bench || false }}
WILL_COV: ${{ github.event_name == 'push' && matrix.name == 'coverage' }}
FASTER_MSAN_BUILD: 1
steps:
- name: Harden Runner
uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
with:
egress-policy: audit
- name: Check workflow configuration
run: |
if [[ "${{ matrix.run_bench && !matrix.test_in_pr }}" == "true" ]]; then
echo "::error title::Configuration Error::'run_bench' requires 'test_in_pr'"
exit 1
fi
- name: Install build deps MacOS
if: startsWith(matrix.os, 'macos-')
run: |
# Should be already installed:
# brew install giflib jpeg-turbo libpng zlib
# Not required, since we skip building documentation
# brew install doxygen graphviz
brew install binutils ccache coreutils googletest libavif ninja openexr sdl2 webp
if [[ "${WILL_BENCH}" == "true" ]]; then
brew install google-benchmark
fi
- name: Checkout the source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
fetch-depth: 2
- name: Install build deps Ubuntu
if: startsWith(matrix.os, 'macos-') == false
run: |
INSTALL_BENCHMARK=''
if [[ "${WILL_BENCH}" == "true" ]]; then
if [[ "${WILL_TEST}" == "true" ]]; then
INSTALL_BENCHMARK=benchmark
else
exit 1
fi
fi
sudo ./tools/scripts/install_deps.sh build extras plugins ${INSTALL_BENCHMARK} -- ${{ matrix.apt_pkgs }}
echo "CC=${{ matrix.cc || 'clang' }}" >> $GITHUB_ENV
echo "CXX=${{ matrix.cxx || 'clang++' }}" >> $GITHUB_ENV
- name: Setup the Homebrew prefixes
if: startsWith(matrix.os, 'macos-')
run: |
CMAKE_PREFIX_PATH=`brew --prefix giflib`:`brew --prefix google-benchmark`:`brew --prefix jpeg-turbo`:`brew --prefix libpng`:`brew --prefix sdl2`:`brew --prefix zlib`
echo "CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}" >> $GITHUB_ENV
- name: Setup the LLVM source path
if: matrix.name == 'msan' && env.WILL_BUILD == 'true'
run: |
LLVM_ROOT=${GITHUB_WORKSPACE}/llvm_root
mkdir -p ${LLVM_ROOT}
echo "LLVM_ROOT=${LLVM_ROOT}" >> $GITHUB_ENV
- name: Cache LLVM sources
if: matrix.name == 'msan' && env.WILL_BUILD == 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ env.LLVM_ROOT }}
key: llvm
- name: Checkout the LLVM source
if: matrix.name == 'msan' && env.WILL_BUILD == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: false
repository: llvm/llvm-project
ref: llvmorg-18.1.3 # NB: 15.0.0 does not build ¯\_(ツ)_/¯
path: llvm_root
- name: Git environment
id: git-env
run: |
echo "parent=$(git rev-parse ${{ github.sha }}^)" >> $GITHUB_OUTPUT
shell: bash
- name: ccache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ env.CCACHE_DIR }}
# When the cache hits the key it is not updated, so if this is a rebuild
# of the same Pull Request it will reuse the cache if still around. For
# either Pull Requests or new pushes to main, this will use the parent
# hash as the starting point from the restore-keys entry.
key: build-${{ runner.os }}-${{ github.sha }}-${{ matrix.name }}
restore-keys: |
build-${{ runner.os }}-${{ steps.git-env.outputs.parent }}-${{ matrix.name }}
- name: Build
if: env.WILL_BUILD == 'true'
run: |
mkdir -p ${CCACHE_DIR}
echo "max_size = 200M" > ${CCACHE_DIR}/ccache.conf
MODE="${{ matrix.mode }}"
BUILD_TESTS=$([ "${WILL_TEST}" == "true" ] && echo "ON" || echo "OFF")
[[ -n "${MODE}" ]] || MODE="${{ matrix.name }}"
SKIP_TEST=1 TARGETS=all CMAKE_CXX_FLAGS='${{ matrix.cxxflags }}' \
./ci.sh ${MODE} \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DBUILD_TESTING=${BUILD_TESTS} \
-DJPEGLI_ENABLE_HWY_AVX3_DL=false \
${{ matrix.cmake_args }}
- name: Build stats
if: env.WILL_BUILD == 'true'
run: |
awk '!/^#/ {total[$4]+=($2-$1);cntr[$4]+=1} END {for (key in total) print total[key]/cntr[key] " " key}' build/.ninja_log | sort -n | tail -n 25
- name: ccache stats
run: ccache --show-stats
#- name: Build stats ${{ matrix.name }}
# if: env.WILL_BUILD == 'true' && matrix.mode == 'release'
# run: |
# SHARED_LIB_EXT="${{ startsWith(matrix.os, 'macos-') && 'dylib' || 'so' }}"
# SELECT_BINUTILS="${{ startsWith(matrix.os, 'macos-') && '--binutils `brew --prefix binutils`/bin/' || '' }}"
# tools/scripts/build_stats.py --save build/stats.json \
# --max-stack ${{ matrix.max_stack || '0' }} ${SELECT_BINUTILS} \
# cjpegli djpegli libjpegli.${SHARED_LIB_EXT} libjpegli_dec.${SHARED_LIB_EXT}
# Check that we can build the example project against the installed libs.
#- name: Install and build examples
# if: env.WILL_BUILD == 'true' && matrix.mode == 'release' && !matrix.skip_install
# run: |
# set -x
# sudo cmake --build build -- install
# cmake -Bbuild-example -Hexamples -G Ninja
# cmake --build build-example
# Test that the built binaries run.
# echo -e -n "PF\n1 1\n-1.0\n\0\0\x80\x3f\0\0\x80\x3f\0\0\x80\x3f" > test.pfm
# build-example/encode_oneshot test.pfm test.jxl
# build-example/decode_oneshot test.jxl dec.pfm dec.icc
# Run the tests on push and when requested in pull_request.
- name: Test ${{ matrix.mode }}
if: env.WILL_TEST == 'true'
run: |
disabled_tests="${{ join(matrix.disable_tests, '|') }}"
if [[ -z "${disabled_tests}" ]]; then
disabled_tests="bash_test";
else
disabled_tests="bash_test|${disabled_tests}";
fi
./ci.sh test -E "${disabled_tests}"
# Print the running time summary for the slowest tests.
- name: Test runtime stats
if: env.WILL_TEST == 'true'
run: |
sort build/Testing/Temporary/CTestCostData.txt -k 3 -n | tail -n 20 || true
- name: Coverage report
if: env.WILL_COV == 'true'
run: |
./ci.sh coverage_report
- name: Coverage upload to Codecov
if: env.WILL_COV == 'true'
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
flags: unittests
files: build/coverage.xml
- name: Fast benchmark ${{ matrix.mode }}
if: env.WILL_BENCH == 'true'
run: |
cat /proc/cpuinfo | grep MHz | sort | uniq
lscpu
BENCHMARK_NUM_THREADS=3 STORE_IMAGES=0 ./ci.sh fast_benchmark