diff --git a/go/scripts/package.sh b/go/scripts/package.sh index 0627bcefa..6585ae735 100755 --- a/go/scripts/package.sh +++ b/go/scripts/package.sh @@ -131,7 +131,13 @@ GO_LIBS=( "aarch64-apple-darwin:darwin_arm64:libmoq_ffi.a" "x86_64-pc-windows-msvc:windows_amd64:moq_ffi.lib" ) +# GitHub's pre-receive hook rejects any file >= 100 MiB. The mirror commits +# these libs into git, so an oversized lib fails the publish push (GH001). +# Catch it here, where the error names the file and points at the fix, rather +# than after a multi-target build burns an hour to die at `git push`. +GITHUB_FILE_LIMIT=$((100 * 1024 * 1024)) STAGED_ANY=false +OVERSIZED=() for entry in "${GO_LIBS[@]}"; do target="${entry%%:*}" rest="${entry#*:}" @@ -142,7 +148,9 @@ for entry in "${GO_LIBS[@]}"; do dest="$PKG_STAGE/moq/lib/$goarch" mkdir -p "$dest" cp "$src" "$dest/" - echo " go lib $goarch <- $target" + size=$(wc -c <"$src") + echo " go lib $goarch <- $target ($((size / 1024 / 1024)) MiB)" + [[ "$size" -ge "$GITHUB_FILE_LIMIT" ]] && OVERSIZED+=("$goarch/$libname: $((size / 1024 / 1024)) MiB") STAGED_ANY=true else echo " go lib $goarch: skipped, $src missing" @@ -154,6 +162,13 @@ if [[ "$STAGED_ANY" != true ]]; then exit 1 fi +if [[ "${#OVERSIZED[@]}" -gt 0 ]]; then + echo "Error: staged libs exceed GitHub's 100 MiB push limit:" >&2 + printf ' %s\n' "${OVERSIZED[@]}" >&2 + echo "The mirror push would be rejected (GH001). Shrink the staticlib in rs/moq-ffi/build.sh (LTO)." >&2 + exit 1 +fi + # --- 4. Minimal consumer-facing README rewrite --- # The full developer README lives in the monorepo; the staged copy # (which ends up on moq-dev/moq-go) gets a thin orientation pointer. diff --git a/nix/overlay.nix b/nix/overlay.nix index d6f3514de..0f8a82faa 100644 --- a/nix/overlay.nix +++ b/nix/overlay.nix @@ -83,6 +83,14 @@ in doCheck = false; nativeBuildInputs = with final; [ pkg-config ]; + # libmoq.a carries moq-ffi's whole dep tree, so an unstripped build is + # ~75 MB+. Thin LTO with a single codegen unit dead-strips the unused + # monomorphizations Rust bakes into a staticlib, halving the artifact + # with no source or ABI change, which keeps the release tarball and + # brew download small. Mirrors rs/libmoq/build.sh's Windows cargo path. + CARGO_PROFILE_RELEASE_LTO = "thin"; + CARGO_PROFILE_RELEASE_CODEGEN_UNITS = "1"; + # libmoq is a staticlib; crane's default install phase only handles # binaries. Lay out the artifact tree the way release tarballs and # downstream `find_package(moq)` consumers already expect. diff --git a/rs/libmoq/build.sh b/rs/libmoq/build.sh index 206e3fabf..a308ea03c 100755 --- a/rs/libmoq/build.sh +++ b/rs/libmoq/build.sh @@ -16,6 +16,17 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" WORKSPACE_DIR="$(cd "$RS_DIR/.." && pwd)" +# Shrink the release staticlib. libmoq.a carries the same heavy dep tree as +# moq-ffi, so an unstripped build is ~75 MB+. libmoq ships as a release +# tarball (not a git mirror, so no hard 100 MB limit like moq-go), but thin +# LTO with a single codegen unit dead-strips the unused monomorphizations Rust +# bakes into a staticlib, halving the artifact with no source or ABI changes. +# This covers the Windows cargo path below; the nix/crane path (Linux/macOS) +# sets the same vars in nix/overlay.nix. Scoped here so a plain +# `cargo build --release` stays fast; a caller can still override. +export CARGO_PROFILE_RELEASE_LTO="${CARGO_PROFILE_RELEASE_LTO:-thin}" +export CARGO_PROFILE_RELEASE_CODEGEN_UNITS="${CARGO_PROFILE_RELEASE_CODEGEN_UNITS:-1}" + TARGET="" VERSION="" OUTPUT_DIR="dist" diff --git a/rs/moq-ffi/build.sh b/rs/moq-ffi/build.sh index 37f00ee32..171f204d4 100755 --- a/rs/moq-ffi/build.sh +++ b/rs/moq-ffi/build.sh @@ -14,6 +14,19 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RS_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" WORKSPACE_DIR="$(cd "$RS_DIR/.." && pwd)" +# Shrink the release staticlib. The Go mirror commits the native libs straight +# into git, and GitHub's pre-receive hook hard-rejects any file over 100 MB +# (GH001). An unstripped moq-ffi staticlib is ~110 MB on Linux, which silently +# blocked every moq-go mirror push and pinned consumers to a stale release. +# Thin LTO with a single codegen unit dead-strips the unused monomorphizations +# Rust bakes into a staticlib, cutting it by ~60% (~110 MB to ~35 MB) with no +# source or ABI changes. (Swift ships an XCFramework release asset and Kotlin a +# Maven .so, so neither hits the git limit, but both still get smaller libs.) +# Scoped here via env vars so a plain `cargo build --release` stays fast; a +# caller can still override. +export CARGO_PROFILE_RELEASE_LTO="${CARGO_PROFILE_RELEASE_LTO:-thin}" +export CARGO_PROFILE_RELEASE_CODEGEN_UNITS="${CARGO_PROFILE_RELEASE_CODEGEN_UNITS:-1}" + # Resolve cargo target directory (respects CARGO_TARGET_DIR, .cargo/config, etc.) TARGET_BASE_DIR=$(cargo metadata --format-version 1 --manifest-path "$WORKSPACE_DIR/Cargo.toml" --no-deps 2>/dev/null | sed -n 's/.*"target_directory":"\([^"]*\)".*/\1/p' ||