Skip to content

CI

CI #4513

Workflow file for this run

name: CI
permissions:
contents: read
on:
pull_request:
push:
branches:
- main
- dev
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
env:
CARGO_INCREMENTAL: 0
CARGO_NET_GIT_FETCH_WITH_CLI: true
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUST_TEST_THREADS: 1
RUSTDOCFLAGS: -D warnings
RUSTFLAGS: -D warnings
RUSTUP_MAX_RETRIES: 10
PORTABLE_ATOMIC_DENY_WARNINGS: 1
# NB: sync with:
# - docs.rs metadata in Cargo.toml
# - test_features list in tools/build.sh and tools/test.sh.
TEST_FEATURES: float,std,serde,critical-section
defaults:
run:
shell: bash --noprofile --norc -CeEuxo pipefail {0}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
jobs:
msrv:
needs: tidy
uses: taiki-e/github-actions/.github/workflows/msrv.yml@main
with:
# NB: sync with env.TEST_FEATURES
# Exclude serde and critical-section features because the MSRV when it is enabled depends on the MSRV of them
args: --features float,std --ignore-unknown-features
tidy:
uses: taiki-e/github-actions/.github/workflows/tidy.yml@main
permissions:
contents: read
pull-requests: write # for gh pr edit --add-assignee
repository-projects: read # for gh pr edit --add-assignee
secrets: inherit
with:
clippy: false # covered by TESTS=1 ./tools/build.sh
docs-target: x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu,powerpc64le-unknown-linux-gnu,s390x-unknown-linux-gnu,armv5te-unknown-linux-gnueabi
prepare:
runs-on: ubuntu-slim
timeout-minutes: 15 # Max execution time of ubuntu-slim runner.
steps:
- uses: taiki-e/checkout-action@v1
- name: Prepare
id: prepare
run: printf 'test-matrix=%s\n' "$(jq -c . .github/workflows/test-matrix.json)" >>"${GITHUB_OUTPUT}"
outputs:
test-matrix: ${{ steps.prepare.outputs.test-matrix }}
test:
needs: [prepare, tidy]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.test-matrix) }}
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
timeout-minutes: 120 # TODO: reduce
steps:
- uses: taiki-e/checkout-action@v1
# - run: sudo apt-get -o Acquire::Retries=10 -qq update && sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends moreutils
# if: startsWith(matrix.os, 'ubuntu') || matrix.os == ''
# - run: brew install moreutils
# if: startsWith(matrix.os, 'macos')
# - run: C:/msys64/usr/bin/pacman -S --noconfirm moreutils
# if: startsWith(matrix.os, 'windows')
- uses: taiki-e/install-action@cargo-hack
- uses: taiki-e/install-action@cargo-minimal-versions
- uses: taiki-e/install-action@cargo-careful
# 0.4.8 fails with at least nightly-2023-05-09 to nightly-2024-01-05
if: startsWith(matrix.rust, 'nightly') && !(startsWith(matrix.rust, 'nightly-2023') || startsWith(matrix.rust, 'nightly-2024'))
- uses: taiki-e/install-action@v2
with:
tool: cargo-careful@0.4.7
if: startsWith(matrix.rust, 'nightly-2023') || startsWith(matrix.rust, 'nightly-2024')
- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: ${{ matrix.rust }}
- id: prepare
run: |
if [[ "${TARGET}" == '' ]]; then
printf 'matrix.target must be set\n'
exit 1
fi
host="$(rustc -vV | grep -E '^host:' | cut -d' ' -f2)"
if [[ "${host}" != "${TARGET}" ]]; then
printf '%s\n' "TARGET=--target=${TARGET}" >>"${GITHUB_ENV}"
printf '%s\n' "target-not-host=true" >>"${GITHUB_OUTPUT}"
fi
cfgs=",$(RUSTC_BOOTSTRAP=1 rustc --print cfg --target "${TARGET}" | tr '\n' ',')"
printf 'cfgs=%s\n' "${cfgs}" >>"${GITHUB_OUTPUT}"
env:
TARGET: ${{ matrix.target }}
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
if: steps.prepare.outputs.target-not-host == 'true'
- run: |
target_lower="${TARGET//-/_}"
target_lower="${target_lower//./_}"
target_upper=$(tr '[:lower:]' '[:upper:]' <<<"${target_lower}")
flags=''
if [[ "$(eval "printf '%s\n' \${CARGO_TARGET_${target_upper}_RUNNER:-}")" == *"qemu"* ]]; then
flags+=" --cfg qemu"
fi
if [[ -n "${FLAGS}" ]]; then
flags+=" ${FLAGS}"
fi
if [[ "${RUST}" == "nightly" ]]; then
case "${TARGET}" in
# TODO(windows): error: linker stdout: C:\a\portable-atomic\portable-atomic\target\debug\deps\portable_atomic-6f0d7f05900c9263.exe : warning LNK4072: section count 101 exceeds max (96); image may not run
*-darwin* | aarch64*-windows-* | csky*) ;;
*) flags+=" -D linker_messages" ;;
esac
fi
if [[ -n "${flags}" ]]; then
printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} ${flags}" >>"${GITHUB_ENV}"
printf '%s\n' "RUSTDOCFLAGS=${RUSTDOCFLAGS} ${flags}" >>"${GITHUB_ENV}"
fi
env:
TARGET: ${{ matrix.target }}
FLAGS: ${{ matrix.flags }}
RUST: ${{ matrix.rust }}
# for f16 and f128
# https://github.com/rust-lang/rust/blob/ffb9d94dcf4ade0d534842be3672d5e9f47e1333/compiler/rustc_codegen_llvm/src/llvm_util.rs#L373
# https://github.com/rust-lang/rust/blob/ffb9d94dcf4ade0d534842be3672d5e9f47e1333/compiler/rustc_codegen_cranelift/src/lib.rs#L203
# https://github.com/rust-lang/rust/blob/ffb9d94dcf4ade0d534842be3672d5e9f47e1333/compiler/rustc_codegen_gcc/src/builder.rs#L1916
- run: |
rustflags="${RUSTFLAGS:-}"
if rustc --print cfg ${TARGET:-} | grep -Fq has_reliable_f16; then
rustflags+=' --cfg portable_atomic_unstable_f16 --cfg quickcheck_unstable_f16 --cfg rand_unstable_f16'
fi
if rustc --print cfg ${TARGET:-} | grep -Fq has_reliable_f128; then
rustflags+=' --cfg portable_atomic_unstable_f128 --cfg quickcheck_unstable_f128 --cfg rand_unstable_f128'
fi
if [[ "${rustflags}" != "${RUSTFLAGS:-}" ]]; then
printf '%s\n' "RUSTFLAGS=${rustflags}" >>"${GITHUB_ENV}"
fi
if: matrix.rust == 'nightly' && !contains(matrix.flags, 'codegen-backend=cranelift') && !contains(matrix.flags, 'codegen-backend=gcc')
# TODO(gcc): for disabling some failing tests
- run: printf '%s\n' "RUSTC_CODEGEN_GCC=1" >>"${GITHUB_ENV}"
if: contains(matrix.flags, 'codegen-backend=gcc')
# for serde on old nightly
- run: printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} --cfg no_diagnostic_namespace" >>"${GITHUB_ENV}"
if: matrix.rust == 'nightly-2024-02-13'
- run: tools/test.sh -vv ${TARGET:-} ${DOCTEST_XCOMPILE:-} ${BUILD_STD:-} ${RELEASE:-}
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_unstable_coerce_unsized
if: startsWith(matrix.rust, 'nightly')
# We test doctest only once with the default build conditions because doctest is slow. Both api-test
# and src/tests have extended copies of doctest, so this will not reduce test coverage.
# {,no-}outline-atomics
# portable_atomic_no_outline_atomics only affects x86_64, AArch64, Arm, powerpc64, and RISC-V Linux.
# outline-atomics is disabled by default on AArch64/powerpc64 musl with static linking, AArch64 illumos, and AIX.
# powerpc64le- (little-endian) is skipped because it is pwr8 by default
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_no_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_no_outline_atomics
if: startsWith(matrix.target, 'x86_64') || ((startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) || startsWith(matrix.target, 'powerpc64-')) && !(contains(matrix.target, '-musl') && matrix.flags == '') || startsWith(matrix.target, 'armv5te') || matrix.target == 'arm-linux-androideabi' || startsWith(matrix.target, 'riscv')
# powerpc64 and RISC-V are skipped because tested below.
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
# Note: detect_false cfg is intended to make it easy for developers to test
# cases where features usually available is not available, and is not a public API.
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_test_detect_false
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_test_detect_false
# TODO(arm-linux-androideabi): hang
if: startsWith(matrix.target, 'x86_64') || (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && !(contains(matrix.target, '-musl') && matrix.flags == '') || startsWith(matrix.target, 'armv5te')
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
QEMU_CPU: power7 # no quadword-atomics
if: startsWith(matrix.target, 'powerpc64-')
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }}
RUSTFLAGS: ${{ env.RUSTFLAGS }}
QEMU_CPU: sifive-u34 # no zacas
if: startsWith(matrix.target, 'riscv32')
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }}
RUSTFLAGS: ${{ env.RUSTFLAGS }}
QEMU_CPU: sifive-u54 # no zacas
if: startsWith(matrix.target, 'riscv64')
# portable_atomic_outline_atomics only affects AArch64 non-glibc-Linux/illumos, powerpc64, and RISC-V Linux.
# powerpc64le- (little-endian) is skipped because it is pwr8 by default
# RISC-V Linux is skipped because outline-atomics is enabled by default.
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_outline_atomics
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && contains(matrix.target, '-musl') && matrix.flags == '' || startsWith(matrix.target, 'powerpc64-')
# powerpc64 is skipped because tested below.
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
# Note: detect_false cfg is intended to make it easy for developers to test
# cases where features usually available is not available, and is not a public API.
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_outline_atomics --cfg portable_atomic_test_detect_false
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_outline_atomics --cfg portable_atomic_test_detect_false
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && contains(matrix.target, '-musl') && matrix.flags == ''
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_outline_atomics
QEMU_CPU: power7 # no quadword-atomics
if: startsWith(matrix.target, 'powerpc64-')
# x86_64 +cmpxchg16b
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
# cmpxchg16b + outline-atomics (vmovdqa load/store) path is tested in first 2 runs on macOS.
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
if: startsWith(matrix.target, 'x86_64') && !contains(steps.prepare.outputs.cfgs, ',target_feature="cmpxchg16b",')
# x86_64 +cmpxchg16b,+avx
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+cmpxchg16b,+avx
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+cmpxchg16b,+avx
if: startsWith(matrix.target, 'x86_64')
# x86_64 +avx
# macOS is skipped because it is +cmpxchg16b by default (+cmpxchg16b,+avx is tested above)
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+avx
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+avx
if: startsWith(matrix.target, 'x86_64') && !contains(matrix.target, '-darwin')
# aarch64 +lse
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+lse
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+lse
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && !contains(steps.prepare.outputs.cfgs, ',target_feature="lse",')
# aarch64 +lse,+lse2
# macOS is skipped because it is +lse,+lse2 by default
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+lse,+lse2
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+lse,+lse2
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && !contains(matrix.target, '-darwin')
# aarch64 +lse2,+lse128
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+lse2,+lse128
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+lse2,+lse128
# Only QEMU supports this, so skip other runners.
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64')) && !(startsWith(matrix.os, 'macos') || contains(matrix.os, '-arm'))
# powerpc64 pwr7
# powerpc64- (big-endian) is skipped because it is pre-pwr8 by default
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-cpu=pwr7
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-cpu=pwr7
if: startsWith(matrix.target, 'powerpc64le-')
# powerpc64 pwr8
# powerpc64le- (little-endian) is skipped because it is pwr8 by default
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-cpu=pwr8
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-cpu=pwr8
if: startsWith(matrix.target, 'powerpc64-')
# riscv +zabha
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+zabha
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+zabha
if: startsWith(matrix.target, 'riscv')
# riscv +zacas
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+zacas
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+zacas
if: startsWith(matrix.target, 'riscv')
# s390x z196 (arch9)
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-cpu=z196
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-cpu=z196
if: startsWith(matrix.target, 's390x')
# s390x z15 (arch13)
- run: tools/test.sh -vv --tests ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-cpu=z15
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-cpu=z15
if: startsWith(matrix.target, 's390x')
# Skip targets that also checked by "build" job.
- run: tools/build.sh "${TARGET}"
env:
SKIP_DEFAULT_TARGET: 1
TARGET: ${{ matrix.target }}
- run: TESTS=1 tools/build.sh "${TARGET}"
env:
SKIP_DEFAULT_TARGET: 1
TARGET: ${{ matrix.target }}
- run: cargo minimal-versions build --workspace --no-private --detach-path-deps=skip-exact --features "${TEST_FEATURES}" --ignore-unknown-features ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-}
if: matrix.rust != 'nightly-2021-08-21'
- run: cargo minimal-versions build --workspace --no-private --detach-path-deps=skip-exact --features "${TEST_FEATURES}" --ignore-unknown-features ${TARGET:-} ${BUILD_STD:-} ${RELEASE:-} --direct
# -Z direct-minimal-versions requires Cargo 1.70.
if: (!(startsWith(matrix.rust, '1.5') || startsWith(matrix.rust, '1.6') || startsWith(matrix.rust, 'nightly-2021') || startsWith(matrix.rust, 'nightly-2022') || startsWith(matrix.rust, 'nightly-2023')))
test-bsd:
needs: tidy
name: test (${{ matrix.target }}${{ matrix.version }})
strategy:
fail-fast: false
matrix:
include:
# TODO: pkg: sqlite error while executing grmbl in file update.c:154: NOT NULL constraint failed: packages.path
# - target: aarch64-unknown-freebsd
# os: freebsd
# version: '13.5'
- target: aarch64-unknown-freebsd
os: freebsd
version: '14.3'
- target: aarch64-unknown-freebsd
os: freebsd
version: '15.0'
- target: aarch64-unknown-netbsd
os: netbsd
version: '10.1'
- target: aarch64-unknown-openbsd
os: openbsd
version: '7.6'
runs-on: ubuntu-latest
timeout-minutes: 120 # TODO: build on OpenBSD is too slow
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/cross-platform-actions-action@neoverse-v1
with:
environment_variables: CARGO_INCREMENTAL CARGO_NET_RETRY CARGO_TERM_COLOR RUST_BACKTRACE RUST_TEST_THREADS RUSTDOCFLAGS RUSTFLAGS RUSTUP_MAX_RETRIES PORTABLE_ATOMIC_DENY_WARNINGS TEST_FEATURES
operating_system: ${{ matrix.os }}
# We don't test x86_64 here because there is no OS-specific code on x86_64.
architecture: aarch64
version: ${{ matrix.version }}
shell: bash
sync_files: runner-to-vm
run: |
set -CeEuxo pipefail
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
export CI=true
export RUSTFLAGS="${RUSTFLAGS} --cfg qemu"
# AArch64 FreeBSD/NetBSD/OpenBSD are tier 3 targets, so install Rust from package manager instead of rustup.
case "$(uname -s)" in
FreeBSD) retry sudo pkg install -y rust ;;
NetBSD) retry sudo pkgin -y install rust ;;
OpenBSD) retry sudo pkg_add rust ;;
esac
rustc -vV
# VM is very slow, so only test OS-specific code and code using them.
cargo test --features std --tests -- aarch64
case "$(uname -s)" in
FreeBSD)
RUSTFLAGS="${RUSTFLAGS} -C target-feature=+crt-static" \
cargo test --features std --tests --target aarch64-unknown-freebsd -- aarch64
;;
esac
build:
needs: tidy
name: build (${{ matrix.name || matrix.rust }})
strategy:
fail-fast: false
matrix:
include:
- rust: '1.34'
- rust: '1.36'
- rust: '1.59'
- rust: stable
- rust: beta
- rust: nightly
# The oldest nightly that can compile this crate is nightly-2019-01-27
# which Atomic{I,U}{8,16,32,64} stabilized.
# https://github.com/rust-lang/rust/pull/57425
# Note: Old nightly compilers are essentially fragile, so support for
# them is on a best-effort basis.
- rust: nightly-2019-01-27
# https://github.com/taiki-e/portable-atomic/pull/52
- rust: nightly-2020-06-21
# for AVR: https://github.com/rust-lang/compiler-builtins/issues/400
- rust: nightly-2020-12-26
# Check that test suite can be built
- name: nightly, --tests
rust: nightly
tests: 1
# Check that this crate can be built for all builtin targets
- name: stable, all tier1/tier2
rust: stable
target-group: tier1/tier2
# Skip targets that also checked by other matrix.
skip-default-target: 1
- name: nightly, all tier1/tier2
rust: nightly
target-group: tier1/tier2
skip-default-target: 1
- name: nightly, all tier3
rust: nightly
target-group: tier3
skip-default-target: 1
runs-on: ubuntu-latest
timeout-minutes: 120 # TODO: nightly builds take a long time because there are too many targets
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/free-device-space@main
- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: ${{ matrix.rust }}
- uses: taiki-e/install-action@cargo-hack
- run: tools/build.sh
env:
TESTS: ${{ matrix.tests }}
TARGET_GROUP: ${{ matrix.target-group }}
SKIP_DEFAULT_TARGET: ${{ matrix.skip-default-target }}
ALL_TARGETS_MUST_BE_AVAILABLE: ${{ matrix.rust == 'nightly' || '' }}
no-std:
needs: tidy
strategy:
fail-fast: false
matrix:
rust:
- '1.64' # LLVM 14
# - '1.69' # LLVM 15
- '1.72' # LLVM 16
# - '1.77' # LLVM 17
# - '1.81' # LLVM 18
# - '1.86' # LLVM 19
# - '1.90' # LLVM 20
- stable
# - nightly-2022-08-12 # Rust 1.65, LLVM 14
# - nightly-2023-03-25 # Rust 1.70, LLVM 15
# - nightly-2023-08-08 # Rust 1.73, LLVM 16
# - nightly-2024-02-13 # Rust 1.78, LLVM 17
# - nightly-2024-07-31 # Rust 1.82, LLVM 18
# - nightly-2025-02-17 # Rust 1.87, LLVM 19
# - nightly-2025-08-06 # Rust 1.91, LLVM 20
- nightly
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/free-device-space@main
- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: ${{ matrix.rust }}
- uses: taiki-e/install-action@cargo-hack
if: matrix.rust == 'stable'
- uses: taiki-e/install-action@espup
if: matrix.rust == 'stable'
- run: |
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
if [[ "${{ matrix.rust }}" == "nightly"* ]]; then
apt_packages=(
avr-libc
gcc-avr
libelf-dev
mspdebug
simavr
)
retry sudo apt-get -o Acquire::Retries=10 -qq update
retry sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends "${apt_packages[@]}"
fi
if [[ "${{ matrix.rust }}" == "nightly"* ]]; then
mkdir -p -- "${HOME}"/msp430-gcc "${HOME}"/aarch64-l4re-gcc
# https://www.ti.com/tool/MSP430-GCC-OPENSOURCE
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 --retry-connrefused https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-LlCjWuAbzH/9.3.1.2/msp430-gcc-9.3.1.11_linux64.tar.bz2 \
| tar xjf - --strip-components 1 -C "${HOME}"/msp430-gcc
printf '%s\n' "${HOME}"/msp430-gcc/bin >>"${GITHUB_PATH}"
# https://l4re.org/download/snapshots
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 --retry-connrefused https://l4re.org/download/snapshots/toolchain/toolchain-l4re-arm64-gcc-15.tar.xz \
| tar xJf - -C "${HOME}"/aarch64-l4re-gcc
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 --retry-connrefused -o "${HOME}"/aarch64-l4re-gcc/bin/l4image https://l4re.org/download/snapshots/pre-built-images/l4image
chmod +x "${HOME}"/aarch64-l4re-gcc/bin/l4image
printf '%s\n' "${HOME}"/aarch64-l4re-gcc/bin >>"${GITHUB_PATH}"
elif [[ "${{ matrix.rust }}" == "stable" ]]; then
# Use the latest toolchain once upstream bug fixed.
retry espup install --targets esp32s2 --toolchain-version 1.90.0
fi
# https://github.com/taiki-e/dockerfiles/pkgs/container/qemu-system
retry docker create --name qemu-system ghcr.io/taiki-e/qemu-system
mkdir -p -- qemu-system
docker cp -- qemu-system:/qemu qemu-system/qemu
docker rm -f -- qemu-system >/dev/null
sudo cp -r -- qemu-system/qemu/. /usr/local/
rm -rf -- ./qemu-system
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: taiki-e/cache-cargo-install-action@v3
with:
# https://github.com/agbrs/agb/tree/5fb928a/mgba-test-runner
# To install locally:
# apt install libelf-dev
# cargo install mgba-test-runner --git https://github.com/agbrs/agb.git --rev 5fb928a
tool: mgba-test-runner
git: https://github.com/agbrs/agb.git
rev: 5fb928a
env:
RUSTFLAGS: -W warnings
if: startsWith(matrix.rust, 'nightly')
- run: rm -- tests/avr/rust-toolchain.toml
if: startsWith(matrix.rust, 'nightly-')
# syn 2.0.107 & quote 1.0.42 & proc-macro2 1.0.104 requires Rust 1.68.
- run: |
cargo generate-lockfile
cargo update -p proc-macro2 --precise 1.0.103
cargo update -p quote --precise 1.0.41
cargo update -p syn --precise 2.0.106
working-directory: tests/no-std-qemu
if: matrix.rust == '1.64'
- run: tools/no-std.sh
env:
ALL_TARGETS_MUST_BE_AVAILABLE: ${{ matrix.rust == 'nightly' || '' }}
# TODO: xtensa-esp32-none-elf with assume-privileged
- run: tools/build.sh +esp xtensa-esp32s2-none-elf
if: matrix.rust == 'stable'
# TODO: exit with 1 without message
# - run: tools/build.sh +esp xtensa-esp32s2-none-elf
# env:
# TESTS: 1
# if: matrix.rust == 'stable'
- run: tools/no-std.sh +esp xtensa-esp32s2-none-elf
if: matrix.rust == 'stable'
miri:
needs: tidy
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
- target: x86_64-unknown-linux-gnu
flags: -C target-feature=+cmpxchg16b
- target: x86_64-pc-windows-msvc
- target: aarch64-unknown-linux-gnu
- target: aarch64-apple-darwin
- target: i686-unknown-linux-gnu
- target: powerpc64le-unknown-linux-gnu
- target: riscv64gc-unknown-linux-gnu
- target: s390x-unknown-linux-gnu
runs-on: ubuntu-latest
timeout-minutes: 180
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/install-rust@nightly
with:
component: miri
- uses: taiki-e/install-action@cargo-hack
# - run: sudo apt-get -o Acquire::Retries=10 -qq update && sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends moreutils
- run: printf '%s\n' "TARGET=--target=${{ matrix.target }}" >>"${GITHUB_ENV}"
if: matrix.target != 'x86_64-unknown-linux-gnu'
- run: printf '%s\n' "MIRIFLAGS=-Zmiri-many-seeds=0..16" >>"${GITHUB_ENV}"
if: github.event_name == 'schedule' && matrix.target == 'x86_64-unknown-linux-gnu'
- run: tools/test.sh miri ${TARGET:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} ${{ matrix.flags }}
RUSTFLAGS: ${{ env.RUSTFLAGS }} ${{ matrix.flags }}
san:
needs: tidy
strategy:
fail-fast: false
matrix:
sanitizer:
- address
- memory
- thread
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/install-rust@nightly
- uses: taiki-e/install-action@cargo-hack
# - run: sudo apt-get -o Acquire::Retries=10 -qq update && sudo apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends moreutils
- run: |
printf 'ASAN_OPTIONS=detect_stack_use_after_return=1\n' >>"${GITHUB_ENV}"
printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} -Z sanitizer=address" >>"${GITHUB_ENV}"
printf '%s\n' "RUSTDOCFLAGS=${RUSTDOCFLAGS} -Z sanitizer=address" >>"${GITHUB_ENV}"
if: matrix.sanitizer == 'address'
- run: |
printf 'MSAN_OPTIONS=verbosity=2\n' >>"${GITHUB_ENV}"
printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} -Z sanitizer=memory -Z sanitizer-memory-track-origins" >>"${GITHUB_ENV}"
printf '%s\n' "RUSTDOCFLAGS=${RUSTDOCFLAGS} -Z sanitizer=memory -Z sanitizer-memory-track-origins" >>"${GITHUB_ENV}"
if: matrix.sanitizer == 'memory'
- run: |
printf '%s\n' "RUSTFLAGS=${RUSTFLAGS} -Z sanitizer=thread" >>"${GITHUB_ENV}"
printf '%s\n' "RUSTDOCFLAGS=${RUSTDOCFLAGS} -Z sanitizer=thread" >>"${GITHUB_ENV}"
if: matrix.sanitizer == 'thread'
- run: tools/test.sh -Z build-std -vv
# We test doctest only once with the default build conditions because doctest is slow. Both api-test
# and src/tests have extended copies of doctest, so this will not reduce test coverage.
# +cmpxchg16b
- run: tools/test.sh -Z build-std -vv --tests
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
valgrind:
needs: tidy
name: valgrind (${{ matrix.target }})
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
- target: i686-unknown-linux-gnu
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
- target: armv7-unknown-linux-gnueabihf
os: ubuntu-24.04-arm
# TODO: "unhandled instruction: 0x4508 0xD103" in atomic_sub in Arc::drop (as of Valgrind 3.26)
# - target: thumbv7neon-unknown-linux-gnueabihf
# os: ubuntu-24.04-arm
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/install-rust@nightly
- uses: taiki-e/install-action@cargo-hack
- id: prepare
run: |
if [[ "${TARGET}" == '' ]]; then
printf 'matrix.target must be set\n'
exit 1
fi
host="$(rustc -vV | grep -E '^host:' | cut -d' ' -f2)"
if [[ "${host}" != "${TARGET}" ]]; then
printf '%s\n' "TARGET=--target=${TARGET}" >>"${GITHUB_ENV}"
fi
env:
TARGET: ${{ matrix.target }}
# - run: apt-get -o Acquire::Retries=10 -qq update && apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends moreutils
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
runner: valgrind
- run: tools/test.sh valgrind -vv ${TARGET:-}
# x86_64 +cmpxchg16b
- run: tools/test.sh valgrind -vv ${TARGET:-}
env:
# outline-atomics (vmovdqa load/store) path has been tested above, disable outline-atomics and test cmpxchg16b load/store path.
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+cmpxchg16b --cfg portable_atomic_no_outline_atomics
if: startsWith(matrix.target, 'x86_64')
# x86_64 +cmpxchg16b,+avx
- run: tools/test.sh valgrind -vv ${TARGET:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+cmpxchg16b,+avx
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+cmpxchg16b,+avx
if: startsWith(matrix.target, 'x86_64')
# On AArch64 linux-gnu, outline-atomics is enabled by default.
- run: tools/test.sh valgrind -vv ${TARGET:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} --cfg portable_atomic_no_outline_atomics
RUSTFLAGS: ${{ env.RUSTFLAGS }} --cfg portable_atomic_no_outline_atomics
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64'))
# aarch64 +lse
# As of Valgrind 3.26, Valgrind supports atomic instructions of Armv8.0, Armv8.1 (FEAT_LSE), and Armv8.3 (FEAT_LRCPC).
- run: tools/test.sh valgrind -vv ${TARGET:-}
env:
RUSTDOCFLAGS: ${{ env.RUSTDOCFLAGS }} -C target-feature=+lse
RUSTFLAGS: ${{ env.RUSTFLAGS }} -C target-feature=+lse
if: (startsWith(matrix.target, 'aarch64') || startsWith(matrix.target, 'arm64'))
valgrind-cross:
needs: tidy
name: valgrind (${{ matrix.target }})
strategy:
fail-fast: false
matrix:
include:
- target: powerpc64le-unknown-linux-gnu
arch: ppc64le
- target: riscv64gc-unknown-linux-gnu
arch: riscv64
- target: s390x-unknown-linux-gnu
arch: s390x
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/install-rust@nightly
# - run: sudo apt-get -o Acquire::Retries=10 -qq update && apt-get -o Acquire::Retries=10 -o Dpkg::Use-Pty=0 install -y --no-install-recommends moreutils
- uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
runner: valgrind
- run: |
export CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS=true
# Skip debug mode because it's slow.
binary_path=$(
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release
binary_path=$(
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \
CARGO_PROFILE_RELEASE_LTO=fat \
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release-fat-lto
case "${TARGET}" in
s390x*)
# s390x z196 (arch9)
binary_path=$(
RUSTFLAGS="${RUSTFLAGS:-} -C target-cpu=z196" \
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release-z196
binary_path=$(
RUSTFLAGS="${RUSTFLAGS:-} -C target-cpu=z196" \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \
CARGO_PROFILE_RELEASE_LTO=fat \
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release-z196-fat-lto
# s390x z15 (arch13)
binary_path=$(
RUSTFLAGS="${RUSTFLAGS:-} -C target-cpu=z15" \
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release-z15
binary_path=$(
RUSTFLAGS="${RUSTFLAGS:-} -C target-cpu=z15" \
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \
CARGO_PROFILE_RELEASE_LTO=fat \
./tools/test.sh build-valgrind --target "${TARGET}" --release
)
mv -- "${binary_path}" ./release-z15-fat-lto
;;
esac
env:
TARGET: ${{ matrix.target }}
- uses: uraimo/run-on-arch-action@v3
with:
arch: none
distro: none
base_image: --platform=linux/${{ matrix.arch }} ghcr.io/taiki-e/valgrind:${{ matrix.arch }}-cross
shell: /bin/bash
run: |
set -CeEuxo pipefail
export RUST_BACKTRACE=1
export RUST_TEST_THREADS=1
export PORTABLE_ATOMIC_DENY_WARNINGS=1
# NB: Sync with arguments in tools/test.sh.
args=(-v --error-exitcode=1 --error-limit=no --leak-check=full --track-origins=yes --fair-sched=yes --gen-suppressions=all)
target="${{ matrix.target }}"
supp="$(pwd)/tools/valgrind/${target%%-*}.supp"
if [[ -f "${supp}" ]]; then
args+=(--suppressions="${supp}")
fi
for bin in ./release*; do
valgrind "${args[@]}" "${bin}"
done
asm-test:
needs: tidy
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/github-actions/install-rust@nightly
with:
component: rust-src
- uses: taiki-e/install-action@espup
- run: |
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
# Use the latest toolchain once upstream bug fixed.
retry espup install --targets esp32s2 --toolchain-version 1.90.0
- run: cargo test --manifest-path tests/asm-test/Cargo.toml
- run: cargo +esp test --manifest-path tests/asm-test/Cargo.toml