Compile and pack on images chosen for the job - #13
Open
henrikottesorensen wants to merge 1 commit into
Open
Conversation
dotnet appears exactly once in the native build, to pack an already-compiled binary into a .nupkg. Everything else is gcc and clang. Building C on a dotnet/sdk image therefore meant apt-getting a toolchain onto an image picked for something else, and pulling in packages the build never uses - which is how a 404 on linux-libc-dev, a dependency of build-essential, once failed CI. Now: gcc-build ubuntu:noble installs the cross toolchains llvm-build mstorsjo/llvm-mingw installs nothing pack dotnet/sdk:10.0-noble installs nothing win-arm64 comes from the image llvm-mingw's own author publishes, pinned to a dated release, rather than downloading and checksumming the tarball by hand. That image already has make, m4, curl and the toolchain on PATH, so it needs no apt at all, and it removes an 82MB download from every uncached build along with a pair of values that had to be bumped together. The toolchain images have no SDK, so compiling and packing had to split: SKIP_PACK leaves binaries staged, and pack_runtime_packages.sh packs whatever is staged rather than a list kept alongside it, which cannot then fall out of step with the RIDs the build stages produce. Finding nothing staged is an error, since a stage that copied no binaries would otherwise look like a success. The pack stage moves to the .NET 10 SDK. Which SDK does the packing barely affects the output - netstandard2.0 metadata around an already-compiled binary - but .NET 8 goes out of support in November 2026. The Dockerfile is excluded from the build context. It is not needed inside any image, and excluding it means editing the build definition no longer invalidates every COPY . /source and forces a full recompile. All six RIDs build and verify unchanged. Co-Authored-By: Claude Opus 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dotnet appears exactly once in the native build, at
build/common.sh:94, to pack an already-compiled binary into a.nupkg. Everything else is gcc and clang. Building C on adotnet/sdkimage therefore meant apt-getting a toolchain onto an image picked for something else, and pulling in packages the build never uses — which is how a 404 onlinux-libc-dev, a dependency ofbuild-essential, failed CI on #6.gcc-buildubuntu:noblellvm-buildmstorsjo/llvm-mingw:20260616packdotnet/sdk:10.0-nobleThe
basestage is gone.build-essentialnow comes from an image chosen for compiling, and the SDK image doesdotnet packand nothing else.win-arm64 comes from the toolchain author's own image
Ubuntu ships no aarch64 mingw-w64 gcc, so this target used a hand-downloaded, SHA-256 pinned llvm-mingw tarball. It now uses the image its own author publishes, pinned to the same dated release. That image already carries
make,m4,curland the toolchain onPATH, so the stage installs nothing, and it removes an 82 MB download from every uncached build plus a pair of values that had to be bumped together.Keeping it a separate stage from the gcc targets remains load bearing: llvm-mingw also ships
i686-w64-mingw32-gccandx86_64-w64-mingw32-gcc, and having those onPATHalongside the Ubuntu cross compilers silently takes overwin-x86andwin-x64. That is not hypothetical — it happened, and it brokewin-x86.Splitting compile from pack
The toolchain images have no SDK, so
SKIP_PACK=1leaves binaries staged and a later stage packs them.build/pack_runtime_packages.shpacks whatever is staged rather than a list kept beside it, so it cannot fall out of step with the RIDs the build stages actually produce. Finding nothing staged is an error — a stage that copied no binaries would otherwise produce an empty package set and look like a success.Two smaller things
The pack stage moves to the .NET 10 SDK. Which SDK does the packing barely affects the output — these are
netstandard2.0metadata around an already-compiled binary, withIncludeBuildOutputoff — but .NET 8 goes out of support in November 2026. This is the change that was dropped from #7, which is now purely multi-targeting.The
Dockerfileis excluded from the build context. It is not needed inside any image, and excluding it means editing the build definition no longer invalidates everyCOPY . /sourceand forces a full recompile of all six targets. I hit that while developing this: changing only the final stage's base image triggered a complete rebuild.Verified
All six RIDs build, and all pass the binary verification from #6 unchanged — same architectures, same 18 exported P/Invoke symbols, same dependency allowlists, same glibc floor.
Packed 6 runtime package(s)confirms the discovery found exactly what the toolchain stages staged.Note on #6
#6's verification runs inside
pack_runtime_package, which now executes in the SDK stage — and that stage deliberately installs nothing, so it has noreadelf,nmorllvm-readobj. Whichever of these merges second needs to resolve that. The better resolution is moving verification into the toolchain stages, where those tools already exist, so a binary is checked where it was made rather than after crossing a stage boundary.🤖 Generated with Claude Code