1name: CI
2
3on:
4  merge_group:
5  pull_request:
6    branches:
7      - libc-0.2
8
9env:
10  CARGO_TERM_COLOR: always
11  CARGO_TERM_VERBOSE: true
12  LIBC_CI: 1
13  RUSTDOCFLAGS: -Dwarnings
14  RUSTFLAGS: -Dwarnings
15  RUST_BACKTRACE: full
16
17defaults:
18  run:
19    shell: bash
20
21jobs:
22  style_check:
23    name: Style check
24    runs-on: ubuntu-24.04
25    timeout-minutes: 10
26    steps:
27      - uses: actions/checkout@v4
28      - name: Setup Rust toolchain
29        run: ./ci/install-rust.sh && rustup component add rustfmt
30      - name: Check style
31        run: ./ci/style.sh
32
33  clippy:
34    name: Clippy on ${{ matrix.os }}
35    strategy:
36      matrix:
37        os: [ubuntu-24.04, macos-14, windows-2022]
38    runs-on: ${{ matrix.os }}
39    timeout-minutes: 10
40    steps:
41      - uses: actions/checkout@v4
42      - run: rustup update stable --no-self-update
43      - uses: Swatinem/rust-cache@v2
44      # Here we use the latest stable Rust toolchain already installed by GitHub
45      # Ideally we should run it for every target, but we cannot rely on unstable toolchains
46      # due to Clippy not being consistent between them.
47      - run: cargo clippy --workspace --exclude libc-test --exclude ctest-test --all-targets -- -D warnings
48
49  # This runs `cargo build --target ...` for all T1 and T2 targets`
50  verify_build:
51    name: Verify build
52    strategy:
53      matrix:
54        toolchain: [stable, nightly, 1.63.0]
55        os: [ubuntu-24.04, macos-14, windows-2022]
56        include:
57          - toolchain: beta
58            os: ubuntu-24.04
59    runs-on: ${{ matrix.os }}
60    timeout-minutes: 25
61    env:
62      TOOLCHAIN: ${{ matrix.toolchain }}
63    steps:
64      - uses: actions/checkout@v4
65      # Remove `-Dwarnings` at the MSRV since lints may be different or buffier
66      - name: Update RUSTFLAGS
67        run: |
68          set -eux
69          [ "${{ matrix.toolchain }}" = "1.63.0" ] && echo 'RUSTFLAGS=' >> "$GITHUB_ENV" || true
70
71      - name: Setup Rust toolchain
72        run: ./ci/install-rust.sh
73
74      # FIXME(ci): These `du` statements are temporary for debugging cache
75      - name: Target size before restoring cache
76        run: du -sh target | sort -k 2 || true
77      - uses: Swatinem/rust-cache@v2
78        with:
79          key: ${{ matrix.os }}-${{ matrix.toolchain }}
80      - name: Target size after restoring cache
81        run: du -sh target | sort -k 2 || true
82
83      - name: Execute build.sh
84        run: ./ci/verify-build.sh
85      - name: Target size after job completion
86        run: du -sh target | sort -k 2
87
88  test_tier1:
89    name: Test tier1
90    strategy:
91      matrix:
92        include:
93          - target: i686-unknown-linux-gnu
94            docker: true
95            os: ubuntu-24.04
96          - target: i686-unknown-linux-gnu
97            docker: true
98            os: ubuntu-24.04
99            artifact-tag: offset-bits64
100            env:
101              RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS: 64
102          - target: i686-unknown-linux-gnu
103            docker: true
104            os: ubuntu-24.04
105            artifact-tag: time-bits64
106            env:
107              RUST_LIBC_UNSTABLE_GNU_TIME_BITS: 64
108          - target: x86_64-unknown-linux-gnu
109            docker: true
110            os: ubuntu-24.04
111          - target: aarch64-apple-darwin
112            os: macos-14
113          - target: x86_64-pc-windows-gnu
114            os: windows-2022
115            env:
116              ARCH_BITS: 64
117              ARCH: x86_64
118          - target: x86_64-pc-windows-msvc
119            os: windows-2022
120          # FIXME: It currently causes segfaults.
121          #- target: i686-pc-windows-gnu
122          #  env:
123          #    ARCH_BITS: 32
124          #    ARCH: i686
125          - target: i686-pc-windows-msvc
126            os: windows-2022
127    runs-on: ${{ matrix.os }}
128    timeout-minutes: 25
129    env:
130      TARGET: ${{ matrix.target }}
131    steps:
132      - uses: actions/checkout@v4
133      - name: Setup Rust toolchain
134        run: ./ci/install-rust.sh
135      - uses: Swatinem/rust-cache@v2
136        with:
137          key: ${{ matrix.target }}
138
139      - name: Add matrix env variables to the environment
140        if: matrix.env
141        run: |
142          echo '${{ toJson(matrix.env) }}' |
143            jq -r 'to_entries | map("\(.key)=\(.value|tostring)") | .[]' >>$GITHUB_ENV
144        shell: bash
145
146      - name: Run natively
147        if: "!matrix.docker"
148        run: ./ci/run.sh ${{ matrix.target }}
149      - name: Run in Docker
150        if: "matrix.docker"
151        run: ./ci/run-docker.sh ${{ matrix.target }}
152
153      - name: Create CI artifacts
154        id: create_artifacts
155        if: always()
156        run: ./ci/create-artifacts.py
157      - uses: actions/upload-artifact@v4
158        if: always() && steps.create_artifacts.outcome == 'success'
159        with:
160          name: ${{ env.ARCHIVE_NAME }}-${{ matrix.target }}${{ matrix.artifact-tag && format('-{0}', matrix.artifact-tag) }}
161          path: ${{ env.ARCHIVE_PATH }}
162          retention-days: 5
163
164  test_tier2:
165    name: Test tier2
166    needs: [test_tier1, style_check]
167    runs-on: ubuntu-24.04
168    strategy:
169      fail-fast: true
170      max-parallel: 12
171      matrix:
172        target:
173          # FIXME(sparc): this takes much longer to run than any other job, put
174          # it first to make sure it gets a head start.
175          - sparc64-unknown-linux-gnu
176          - aarch64-linux-android
177          - aarch64-unknown-linux-gnu
178          - aarch64-unknown-linux-musl
179          - arm-linux-androideabi
180          - arm-unknown-linux-musleabihf
181          # FIXME(#4297): Disabled due to spurious failueSome android jobs are disabled because of high rates of
182          # - i686-linux-android
183          - i686-unknown-linux-musl
184          - loongarch64-unknown-linux-gnu
185          - loongarch64-unknown-linux-musl
186          - powerpc64-unknown-linux-gnu
187          - powerpc64le-unknown-linux-gnu
188          - riscv64gc-unknown-linux-gnu
189          - s390x-unknown-linux-gnu
190          - wasm32-unknown-emscripten
191          - wasm32-wasip1
192          - wasm32-wasip2
193          - x86_64-linux-android
194          # FIXME: Exec format error (os error 8)
195          # - x86_64-unknown-linux-gnux32
196          - x86_64-unknown-linux-musl
197          # FIXME: It seems some items in `src/unix/mod.rs`
198          # aren't defined on redox actually.
199          # - x86_64-unknown-redox
200        include:
201          - target: arm-unknown-linux-gnueabihf
202          - target: arm-unknown-linux-gnueabihf
203            env:
204              RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS: 64
205            artifact-tag: offset-bits64
206          - target: arm-unknown-linux-gnueabihf
207            env:
208              RUST_LIBC_UNSTABLE_GNU_TIME_BITS: 64
209            artifact-tag: time-bits64
210          - target: aarch64-unknown-linux-musl
211            env:
212              RUST_LIBC_UNSTABLE_MUSL_V1_2_3: 1
213          - target: arm-unknown-linux-musleabihf
214            env:
215              RUST_LIBC_UNSTABLE_MUSL_V1_2_3: 1
216          - target: i686-unknown-linux-musl
217            env:
218              RUST_LIBC_UNSTABLE_MUSL_V1_2_3: 1
219          - target: loongarch64-unknown-linux-musl
220            env:
221              RUST_LIBC_UNSTABLE_MUSL_V1_2_3: 1
222          # FIXME(ppc): SIGILL running tests, see
223          # https://github.com/rust-lang/libc/pull/4254#issuecomment-2636288713
224          # - target: powerpc-unknown-linux-gnu
225          # - target: powerpc-unknown-linux-gnu
226          #   env:
227          #     RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS: 64
228          #   artifact-tag: offset-bits64
229          # - target: powerpc-unknown-linux-gnu
230          #   env:
231          #     RUST_LIBC_UNSTABLE_GNU_TIME_BITS: 64
232          #   artifact-tag: time-bits64
233    timeout-minutes: 25
234    env:
235      TARGET: ${{ matrix.target }}
236    steps:
237      - uses: actions/checkout@v4
238      - name: Setup Rust toolchain
239        run: ./ci/install-rust.sh
240      - uses: Swatinem/rust-cache@v2
241        with:
242          key: ${{ matrix.target }}
243
244      - name: Add matrix env variables to the environment
245        if: matrix.env
246        run: |
247          echo '${{ toJson(matrix.env) }}' |
248            jq -r 'to_entries | map("\(.key)=\(.value|tostring)") | .[]' >>$GITHUB_ENV
249        shell: bash
250
251      - name: Execute run-docker.sh
252        run: ./ci/run-docker.sh ${{ matrix.target }}
253
254      - name: Create CI artifacts
255        id: create_artifacts
256        if: always()
257        run: ./ci/create-artifacts.py
258      - uses: actions/upload-artifact@v4
259        if: always() && steps.create_artifacts.outcome == 'success'
260        with:
261          name: ${{ env.ARCHIVE_NAME }}-${{ matrix.target }}${{ matrix.artifact-tag && format('-{0}', matrix.artifact-tag) }}
262          path: ${{ env.ARCHIVE_PATH }}
263          retention-days: 5
264
265  test_tier2_vm:
266    name: Test tier2 VM
267    needs: [test_tier1, style_check]
268    runs-on: ubuntu-latest
269    strategy:
270      fail-fast: true
271      matrix:
272        target:
273          - x86_64-pc-solaris
274    timeout-minutes: 25
275    steps:
276      - uses: actions/checkout@v4
277      - name: test on Solaris
278        uses: vmactions/solaris-vm@v1.1.4
279        with:
280          release: "11.4-gcc"
281          usesh: true
282          mem: 4096
283          copyback: false
284          prepare: |
285            set -x
286            source <(curl -s https://raw.githubusercontent.com/psumbera/solaris-rust/refs/heads/main/sh.rust-web-install)
287            rustc --version
288            uname -a
289          run: |
290            export PATH=$HOME/.rust_solaris/bin:$PATH
291            ./ci/run.sh ${{ matrix.target }}
292
293  # One job that "summarizes" the success state of this pipeline. This can then be added to branch
294  # protection, rather than having to add each job separately.
295  success:
296    name: success
297    runs-on: ubuntu-24.04
298    needs:
299      - style_check
300      - test_tier1
301      - test_tier2
302      - test_tier2_vm
303      - verify_build
304      - clippy
305    # GitHub branch protection is exceedingly silly and treats "jobs skipped because a dependency
306    # failed" as success. So we have to do some contortions to ensure the job fails if any of its
307    # dependencies fails.
308    if: always() # make sure this is never "skipped"
309    steps:
310      # Manually check the status of all dependencies. `if: failure()` does not work.
311      - name: check if any dependency failed
312        run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
313