diff --git a/.github/workflows/build-libstylus.yml b/.github/workflows/build-libstylus.yml new file mode 100644 index 000000000..443a92934 --- /dev/null +++ b/.github/workflows/build-libstylus.yml @@ -0,0 +1,93 @@ +name: "Build libstylus" + +# Publishes libstylus.so as a COPY-only image for each GitHub Release so +# leafage-evm can pull the native Stylus runtime by release tag or latest. +on: + release: + types: + - published + +concurrency: + group: ${{ github.workflow }}-${{ github.event.release.tag_name }} + cancel-in-progress: false + +env: + AWS_REGION: us-east-1 + REGISTRY: public.ecr.aws/b2h7a5c4/chaintable + IMAGE: libstylus + DOCKERFILE: Dockerfile.libstylus + REVISION: ${{ github.event.release.tag_name }} + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-latest + arch: amd64 + - runner: ubuntu-24.04-arm + arch: arm64 + runs-on: ${{ matrix.runner }} + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + clean: true + ref: ${{ github.event.release.tag_name }} + # crates/tools/wasmer and brotli are submodules the build links against. + submodules: recursive + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@v2 + with: + registry-type: public + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v5 + with: + file: ${{ env.DOCKERFILE }} + context: . + push: true + tags: ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ matrix.arch }}-${{ env.REVISION }} + provenance: false + + merge-manifest: + runs-on: ubuntu-latest + needs: build + permissions: + id-token: write + steps: + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + uses: aws-actions/amazon-ecr-login@v2 + with: + registry-type: public + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Merge manifest + run: | + docker buildx imagetools create \ + --tag "${REGISTRY}/${IMAGE}:${REVISION}" \ + --tag "${REGISTRY}/${IMAGE}:latest" \ + "${REGISTRY}/${IMAGE}:amd64-${REVISION}" \ + "${REGISTRY}/${IMAGE}:arm64-${REVISION}" diff --git a/Dockerfile.libstylus b/Dockerfile.libstylus new file mode 100644 index 000000000..c1f3bd010 --- /dev/null +++ b/Dockerfile.libstylus @@ -0,0 +1,49 @@ +# libstylus.so — the native Stylus runtime that leafage-evm dlopens to execute +# WASM contracts (via LEAFAGE_ARB_STYLUS_LIB). The result is a COPY-only image: +# it has no entrypoint and is never meant to run. Consumers pull the library out +# with `COPY --from=: /libstylus.so ...`. +# +# The builder is pinned to bookworm (glibc 2.36) deliberately: leafage-evm runs +# on ubuntu:24.04 (glibc 2.39), and a library built against an older glibc loads +# on a newer one but not the other way round. If leafage-evm's runtime base ever +# moves, this base must stay at or below it. +ARG RUST_VERSION=1.93 + +FROM rust:${RUST_VERSION}-bookworm AS builder + +RUN apt-get update && apt-get install -y --no-install-recommends \ + cmake \ + make \ + g++ \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /src + +# Only what the Rust workspace needs — every workspace member lives under +# crates/, and the Go tree plays no part in this build. +COPY rust-toolchain.toml Cargo.toml Cargo.lock ./ +COPY scripts/build-brotli.sh scripts/ +COPY brotli brotli +COPY crates crates + +# crates/brotli links the C static libs, so they have to be built first; +# without this the stylus build fails on `brotlienc-static not found`. +RUN ./scripts/build-brotli.sh -l + +RUN cargo build --release --lib -p stylus + +# The release profile carries debuginfo, which leaves the library around 237MB +# and would land whole in every consumer's image. --strip-debug drops only the +# DWARF sections; the dynamic symbol table leafage resolves against survives. +RUN strip --strip-debug target/release/libstylus.so + +# The symbols leafage resolves at runtime, checked *after* stripping so the +# assertion covers what actually ships. Turns ABI drift into a failed build +# rather than a failed dlopen in production. +RUN for sym in stylus_activate stylus_compile stylus_call stylus_target_set free_rust_bytes; do \ + nm -D target/release/libstylus.so | grep -q " ${sym}\$" \ + || { echo "libstylus.so is missing exported symbol: ${sym}" >&2; exit 1; }; \ + done + +FROM scratch +COPY --from=builder /src/target/release/libstylus.so /libstylus.so diff --git a/crates/stylus/Cargo.toml b/crates/stylus/Cargo.toml index e91a9dbf7..df10164fd 100644 --- a/crates/stylus/Cargo.toml +++ b/crates/stylus/Cargo.toml @@ -45,4 +45,4 @@ rayon = ["prover/rayon"] cc_brotli = ["brotli/cc_brotli"] [lib] -crate-type = ["lib", "staticlib"] +crate-type = ["lib", "staticlib", "cdylib"]