Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 7 additions & 18 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
# Target mechanics only; codegen policy lives in [profile.release].
# Rustflags here override the profile and apply to every profile,
# including test builds.

[target.aarch64-unknown-linux-musl]
rustflags = [
"-C", "linker=musl-gcc",
"-C", "target-feature=+crt-static", # Use static crt
"-C", "link-arg=-s", # Strip symbols
"-C", "opt-level=z", # Optimize for size
"-C", "codegen-units=1", # Enable better (though slower) optimization
"-C", "panic=abort", # Remove stack unwind code
]

linker = "musl-gcc"
rustflags = ["-C", "target-feature=+crt-static"]

[target.x86_64-unknown-linux-musl]
rustflags = [
"-C", "linker=musl-gcc",
"-C", "target-feature=+crt-static", # Use static crt
"-C", "link-arg=-s", # Strip symbols
"-C", "opt-level=z", # Optimize for size
"-C", "codegen-units=1", # Enable better (though slower) optimization
"-C", "panic=abort", # Remove stack unwind code
]

linker = "musl-gcc"
rustflags = ["-C", "target-feature=+crt-static"]
38 changes: 38 additions & 0 deletions .github/actions/rust-toolchain/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Install pinned Rust toolchain
description: >
Installs the toolchain pinned in rust-toolchain.toml.
dtolnay/rust-toolchain only sets the rustup default, which the file
outranks, so the channel is parsed from the file to keep the install and
the pin in lockstep.

inputs:
targets:
description: Comma-separated target triples to install
required: false
default: ""
components:
description: Comma-separated components to install
required: false
default: ""

runs:
using: composite
steps:
- name: Read pinned toolchain
id: toolchain
shell: bash
# Fail fast on an unparseable pin.
run: |
channel=$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml)
if [ -z "$channel" ]; then
echo "::error::cannot parse channel from rust-toolchain.toml" >&2
exit 1
fi
echo "channel=$channel" >> "$GITHUB_OUTPUT"

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master 2026-06-30
with:
toolchain: ${{ steps.toolchain.outputs.channel }}
targets: ${{ inputs.targets }}
components: ${{ inputs.components }}
7 changes: 3 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,16 @@ jobs:
ref: ${{ inputs.commit-hash != '' && inputs.commit-hash || github.sha }}
fetch-depth: 0 # This is needed in order to keep the commit ids history
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
toolchain: stable minus 2 releases
targets: aarch64-unknown-linux-musl
- name: Build NVRC
run: |
GIT_REV="$(git rev-parse --short HEAD)"
if [ -n "$(git status --porcelain)" ]; then GIT_REV="${GIT_REV}-dirty"; fi
export GIT_REV
cargo build --release --target=aarch64-unknown-linux-musl
Comment thread
zvonkok marked this conversation as resolved.
cargo build --release --locked --target=aarch64-unknown-linux-musl
sudo cp ./target/aarch64-unknown-linux-musl/release/NVRC "$ROOTFS_IMAGE_DIR/bin/NVRC-aarch64-unknown-linux-musl"
- name: Create Image with NVRC
run: |
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
toolchain: stable
components: llvm-tools-preview

# cargo-llvm-cov uses LLVM's native instrumentation for accurate coverage.
Expand All @@ -71,7 +70,7 @@ jobs:
# src/main.rs is exempt from coverage: dispatch-only plumbing (module
# wiring and the mode match) that only runs end-to-end as PID 1 in a VM.
- name: Generate coverage
run: sudo -E env "PATH=$PATH" cargo llvm-cov --all-features --workspace --ignore-filename-regex 'src/main\.rs$' --lcov --output-path lcov.info -- --include-ignored --test-threads=1
run: sudo -E env "PATH=$PATH" cargo llvm-cov --locked --all-features --workspace --ignore-filename-regex 'src/main\.rs$' --lcov --output-path lcov.info -- --include-ignored --test-threads=1

- name: Upload coverage to Coveralls
uses: coverallsapp/github-action@cfd0633edbd2411b532b808ba7a8b5e04f76d2c8 # v2.3.4
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/fuzzing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ jobs:

- name: Install Rust nightly
# WHY nightly: libFuzzer instrumentation requires nightly compiler features
uses: dtolnay/rust-toolchain@nightly
# WHY toolchain input: a SHA-pinned ref no longer selects the channel
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master 2026-06-30
with:
toolchain: nightly
components: llvm-tools-preview

- name: Install cargo-fuzz
Expand All @@ -50,8 +52,9 @@ jobs:
- name: Run fuzzer - ${{ matrix.target }}
# WHY max_total_time: prevent infinite runs, control CI costs
# WHY -jobs=2: parallel fuzzing instances for better coverage
# +nightly outranks rust-toolchain.toml; libFuzzer needs nightly rustc
run: |
cargo fuzz run ${{ matrix.target }} -- \
cargo +nightly fuzz run ${{ matrix.target }} -- \
-max_total_time=${{ env.FUZZ_DURATION }} \
-jobs=2

Expand Down
15 changes: 6 additions & 9 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,23 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master # v1.70
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
toolchain: stable minus 2 releases
targets: ${{ matrix.target }}


- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y musl-tools jq
# No apt-get update: the image index suffices; refreshing pulls
# third-party repos whose breakage fails the job.
run: sudo apt-get install -y musl-tools jq

- name: Build (${{ matrix.target }})
shell: bash
run: |
set -euxo pipefail
mkdir -p dist
SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)
export SOURCE_DATE_EPOCH
cargo build --release --target "${{ matrix.target }}"
./scripts/build-release.sh "${{ matrix.target }}"
cp "target/${{ matrix.target }}/release/NVRC" "dist/NVRC-${{ matrix.target }}"

- name: Compute digest (sha256sum format)
Expand Down
65 changes: 65 additions & 0 deletions .github/workflows/reproducible.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Reproducible build

# Build the tree twice, varying the inputs a verifier cannot copy from CI
# (workspace directory, CARGO_HOME), and require identical sha256. Guards
# the dmesg <-> Rekor correlation promised in VERIFY.md and ARCHITECTURE.md.

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
double-build:
strategy:
matrix:
include:
- target: x86_64-unknown-linux-musl
runner: ubuntu-24.04
- target: aarch64-unknown-linux-musl
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
targets: ${{ matrix.target }}

- name: Install dependencies
# No apt-get update: the image index suffices; refreshing pulls
# third-party repos whose breakage fails the job.
run: sudo apt-get install -y musl-tools

- name: Build twice from different locations
shell: bash
# Same script the release workflow runs.
run: |
set -euxo pipefail
for build in first second-deliberately-longer-path; do
src="${RUNNER_TEMP}/${build}/src"
mkdir -p "$src" "${RUNNER_TEMP}/${build}/cargo-home"
cp -a . "$src"
(cd "$src" && CARGO_HOME="${RUNNER_TEMP}/${build}/cargo-home" \
./scripts/build-release.sh "${{ matrix.target }}")
done

- name: Require identical sha256
shell: bash
run: |
set -euo pipefail
a="${RUNNER_TEMP}/first/src/target/${{ matrix.target }}/release/NVRC"
b="${RUNNER_TEMP}/second-deliberately-longer-path/src/target/${{ matrix.target }}/release/NVRC"
sha256sum "$a" "$b"
if [ "$(sha256sum < "$a")" != "$(sha256sum < "$b")" ]; then
echo "::error::release binary is not reproducible across build locations"
# The offending path is usually visible in the strings diff.
diff <(strings "$a") <(strings "$b") | head -50 || true
exit 1
fi
52 changes: 24 additions & 28 deletions .github/workflows/static-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain

- run: sudo -E env "PATH=$PATH" cargo test --all-features -- --include-ignored
- run: sudo -E env "PATH=$PATH" cargo test --locked --all-features -- --include-ignored

# Check code formatting against Rust style guidelines
formatting:
Expand All @@ -64,10 +62,9 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
toolchain: stable
components: rustfmt

- run: cargo fmt --all -- --check
Expand All @@ -83,13 +80,12 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain
with:
toolchain: stable
components: clippy

- run: cargo clippy --all-features -- -D warnings
- run: cargo clippy --locked --all-features -- -D warnings

# Check dependencies for known security vulnerabilities
security:
Expand All @@ -102,10 +98,8 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain

- run: cargo install cargo-audit
- run: cargo audit
Expand All @@ -121,10 +115,8 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain

- run: cargo install cargo-deny
- run: cargo deny check
Expand All @@ -141,12 +133,13 @@ jobs:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master 2026-06-30
with:
toolchain: nightly

- run: cargo install cargo-udeps --locked
- run: cargo udeps --all-features
# +nightly outranks rust-toolchain.toml; udeps needs nightly-only -Z flags
- run: cargo +nightly udeps --locked --all-features

# Analyze binary size and identify largest functions
bloat:
Expand All @@ -159,17 +152,16 @@ jobs:
with:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install pinned Rust toolchain
uses: ./.github/actions/rust-toolchain

- run: cargo install cargo-bloat
- run: cargo bloat --release --all-features -n 20

# Detect undefined behavior in unsafe code using Miri interpreter
miri:
name: cargo miri
timeout-minutes: 30
needs: changes
if: ${{ needs.changes.outputs.code == 'true' || github.event_name == 'schedule' }}
runs-on: ubuntu-latest
Expand All @@ -179,9 +171,13 @@ jobs:
fetch-depth: 0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master 2026-06-30
with:
toolchain: nightly
components: miri

- run: cargo miri test || true # ignore errors since miri is still experimental and complains about the std toolchain
# +nightly outranks rust-toolchain.toml; miri only exists on nightly.
# -Zmiri-disable-isolation: tests touch the real filesystem.
- run: cargo +nightly miri test --locked
env:
MIRIFLAGS: -Zmiri-disable-isolation
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ once_cell = "1.21.3"
sha2 = { version = "0.10", default-features = false }

[profile.release]
opt-level = "s"
opt-level = "z" # PID 1 runs once per boot: size beats speed
lto = true
codegen-units = 1 # one unit gives fat LTO full visibility and a smaller binary
strip = true
panic = 'abort'

Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ nvrc.mode=gpu nvrc.fm.mode=0 nvrc.log=debug

## Build

NVRC is compiled as a statically-linked musl binary for minimal dependencies:
NVRC is compiled as a statically-linked musl binary for minimal dependencies.
The compiler version is pinned in `rust-toolchain.toml`; rustup installs it,
musl targets included, on first use. Requires `musl-gcc` (Debian/Ubuntu:
`musl-tools`).

```bash
# x86_64
Expand All @@ -149,8 +152,13 @@ cargo build --release --target x86_64-unknown-linux-musl
cargo build --release --target aarch64-unknown-linux-musl
```

Build configuration in `.cargo/config.toml` enables aggressive size
optimization and static linking.
Release artifacts are built with `./scripts/build-release.sh <target>`, which
additionally remaps machine-specific paths so the binary is byte-reproducible;
see [VERIFY.md](VERIFY.md) for reproducing and verifying a release.

Codegen policy (size optimization, LTO, `panic=abort`) lives in
`[profile.release]` in `Cargo.toml`; `.cargo/config.toml` holds the musl
linker and static-linking flags.

## Testing

Expand Down
Loading
Loading