ctt ships prebuilt static libraries for the ISPC compression kernels so that a default build doesn't require ISPC. This document explains what the binaries are, where they come from, and how to verify them.
Two crates contain prebuilt binaries:
| Crate | Libraries | Source |
|---|---|---|
ctt-intel-texture-compressor-prebuilt |
kernel |
Intel ISPC Texture Compressor |
ctt-bc7enc-rdo-prebuilt |
bc7e |
bc7enc_rdo |
Each crate stores its binaries under bins/<platform>/:
prebuilt/bins/
linux-x86_64/
linux-aarch64/
windows-x86_64/
windows-aarch64/
macos-x86_64/
macos-aarch64/
The build script for each prebuilt crate copies the correct platform's .a or .lib into OUT_DIR and emits the cargo:rustc-link-lib=static=... directives. Nothing else from the prebuilt crate runs at build time.
The prebuilt feature is on by default. When it's on, the prebuilt crate is pulled in as a dependency and its static libraries are linked directly -- no compilation step.
When you use build-from-source instead, the prebuilt crate is not a dependency at all. It doesn't appear in the dependency tree and its binaries are never copied or linked. CI enforces this with a cargo tree check that fails if prebuilt appears in the build-from-source feature tree.
The two features are mutually exclusive. Enabling both produces a compile error.
To build from source instead of using the prebuilt binaries:
# CLI
cargo install ctt-cli --no-default-features --features ispc-build-from-source
# Library
cargo add ctt --no-default-features --features "encoder-intel,encoder-bc7enc,ispc-build-from-source"This requires ISPC and libclang on your PATH, plus a C++ compiler.
The prebuilt binaries are produced by the build-ispc.yml GitHub Actions workflow, triggered manually via workflow_dispatch. The workflow:
- Checks out the repository at the triggering commit.
- Downloads a pinned version of ISPC (see
ISPC_VERSIONin the workflow). - Runs
cargo xtask build-ispcfor each platform/target combination to compile the ISPC kernels into static libraries. - Uploads the libraries as build artifacts.
- In a second job (
attest-and-commit), downloads all artifacts and usesactions/attest-build-provenanceto generate a SLSA provenance attestation for every binary. - Downloads the attestation bundles (Sigstore
.jsonlfiles) and stores them next to each binary. - Commits the binaries and their attestation bundles back to the branch.
All GitHub Actions in the workflow are pinned to specific commit SHAs.
Every .a and .lib file has a corresponding .sigstore.jsonl file sitting next to it. This is a Sigstore bundle containing a signed SLSA provenance statement. The attestation cryptographically binds:
- The binary's content (via SHA-256 digest).
- The source repository (
cwfitzgerald/ctt). - The workflow that produced it (
.github/workflows/build-ispc.yml). - The commit the workflow ran against.
The signing key is an ephemeral key issued by GitHub's OIDC identity provider and recorded in the Sigstore transparency log. There is no long-lived signing key to compromise -- the trust root is GitHub Actions' workload identity.
In practical terms this means: if the attestation verifies, the binary was produced by GitHub Actions running the build-ispc.yml workflow in the cwfitzgerald/ctt repository. It was not built locally, and it was not modified after the workflow produced it.
The simplest way to verify all prebuilt binaries at once:
cargo xtask verify-binariesThis requires the gh CLI to be installed and authenticated (gh auth login).
The command walks both prebuilt directories, and for each .a/.lib file:
- Checks that a
.sigstore.jsonlattestation bundle exists next to it. - Runs
gh attestation verifywith:--bundle <path>.sigstore.jsonl-- the attestation bundle to check.--repo cwfitzgerald/ctt-- the expected source repository.--signer-workflow cwfitzgerald/ctt/.github/workflows/build-ispc.yml-- the expected workflow that produced the binary.
The output shows PASS or FAIL for each binary and a summary at the end. Any failure (missing attestation, signature mismatch, wrong signer) causes a non-zero exit.
You can verify individual files directly with gh:
gh attestation verify crates/ctt-intel-texture-compressor/prebuilt/bins/linux-x86_64/libkernel.a \
--bundle crates/ctt-intel-texture-compressor/prebuilt/bins/linux-x86_64/libkernel.a.sigstore.jsonl \
--repo cwfitzgerald/ctt \
--signer-workflow cwfitzgerald/ctt/.github/workflows/build-ispc.ymlA successful verification prints the attestation details including the commit SHA, workflow ref, and digest. A failure prints the reason (signature invalid, wrong signer, digest mismatch, etc.).
The CI pipeline (.github/workflows/ci.yml) includes a verify-attestations job that runs cargo xtask verify-binaries on every push. This ensures that binaries checked into the repository always have valid, up-to-date attestations.