User/namjain/reprobuild gh testing#143
Closed
namancse wants to merge 6 commits into
Closed
Conversation
added 5 commits
June 3, 2026 09:18
Add NixOS flake configuration and helper scripts for reproducible kernel builds. Files added: - flake.nix: Nix environment with pinned toolchain (GCC 13.2.0, binutils, etc.) - flake.lock: Locked package versions for reproducibility - Microsoft/nix-setup.sh: One-time Nix installation helper - Microsoft/nix-clean.sh: Build artifact cleanup - .gitignore: Add Nix-related entries This establishes the foundation for bit-reproducible kernel builds across different machines by providing a hermetic build environment with pinned dependencies. Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
Add nix-build.sh that orchestrates reproducible kernel builds using the Nix environment established in the previous commit. Features: - Pure Nix environment with --ignore-environment flag - Fixed build paths for reproducible absolute path embeddings - Reproducible environment variables: - SOURCE_DATE_EPOCH= timestamp of top git commit embedded - KBUILD_BUILD_USER=builder - KBUILD_BUILD_HOST=nixos - KBUILD_BUILD_VERSION=1 - Copies source to fixed path to ensure identical embedded paths - Invokes build-hcl-kernel.sh within the controlled environment - Copies artifacts back to original location - Cleanup on exit Usage: ./Microsoft/nix-build.sh x64 # Build x64 kernel ./Microsoft/nix-build.sh arm64 # Build arm64 kernel ./Microsoft/nix-build.sh x64 cvm # Build x64 cvm kernel ./Microsoft/nix-build.sh arm64 cvm # Build arm64 cvm kernel Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
Enhance build-hcl-kernel.sh to support reproducible builds when invoked from nix-build.sh or other reproducible environments. Changes: - Detect host architecture to avoid unnecessary cross-compilation - Set CC explicitly to gcc/cross-compiler for Nix toolchain - Add LOCALVERSION= to prevent '+' suffix in version string - Add KCFLAGS=-fdebug-prefix-map to normalize debug paths - Add SHA256 checksum output of vmlinux for verification - Remove KBUILD_BUILD_ID=none (not needed) When REPRODUCIBLE_BUILD=1: - Uses Nix's gcc instead of system gcc for native builds - Only uses cross-compiler when actually cross-compiling - Ensures consistent compiler identification in kernel binary Otherwise, let users continue using this script for dev work as before. Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
Add build-hcl-kernel-pipeline.sh for Azure DevOps CI integration with reproducible build support. Features: - Supports amd64 and arm64 architectures - CVM config merge support via merge_cvm_config() - Optional reproducible build mode (--reproducible flag) - Generates kernel, headers, modules, and debug symbols - Progress indicators for build stages [1/5] through [5/5] - SHA256 checksum output for reproducibility verification Key differences from build-hcl-kernel.sh: - Standalone script that doesn't depend on nix-build.sh wrapper - Implements complete build workflow in one script - Uses KBUILD_OUTPUT=$BUILD_DIR/linux subdirectory structure - Handles CVM config merging inline - Moves artifacts from /linux subdirectory to BUILD_DIR root for pipeline - When --reproducible: sets up Nix environment and reproducible variables Build directory structure: - $BUILD_DIR/linux/ # KBUILD_OUTPUT during build - $BUILD_DIR/vmlinux # Final artifacts at root - $BUILD_DIR/linux-headers/ - $BUILD_DIR/debug_symbols/ Usage: ./build-hcl-kernel-pipeline.sh -s <source> -b <build> -c <config> -a <arch> ./build-hcl-kernel-pipeline.sh ... --reproducible ./build-hcl-kernel-pipeline.sh ... --cvm-config <config> Signed-off-by: Naman Jain <namjain@linux.microsoft.com>
Use the Nix-pinned toolchain in build_linux so x64, cvm-x64, and arm64 produce deterministic outputs for a given commit. - Build via Microsoft/build-hcl-kernel-pipeline.sh --reproducible. - Set SOURCE_DATE_EPOCH from the commit timestamp. - Add Microsoft/package-ci-artifacts.sh for deterministic packaging and sha256 reporting. - Keep build_perf and create_release behavior unchanged.
Comment on lines
+15
to
+129
| name: Build Linux kernel (reproducible, run ${{ matrix.repro_run }}) | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| arch: ['x64', 'cvm-x64', 'arm64'] | ||
| repro_run: [1, 2] | ||
| env: | ||
| # Stable build identity used to derive SOURCE_DATE_EPOCH and metadata. | ||
| KBUILD_BUILD_USER: builder | ||
| KBUILD_BUILD_HOST: nixos | ||
| steps: | ||
| - name: Checkout source | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| # Need the HEAD commit's timestamp for SOURCE_DATE_EPOCH; depth=1 is sufficient. | ||
| fetch-depth: 1 | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev | ||
| [ "${{ matrix.arch }}" == "arm64" ] && sudo apt-get install -y gcc-aarch64-linux-gnu || true | ||
| - name: Install Nix | ||
| uses: cachix/install-nix-action@v27 | ||
| with: | ||
| extra_nix_config: | | ||
| experimental-features = nix-command flakes | ||
| accept-flake-config = true | ||
|
|
||
| - name: Build kernel | ||
| - name: Map ci arch to build args | ||
| id: args | ||
| run: | | ||
| if [ "${{ matrix.arch }}" == "x64" ] || [ "${{ matrix.arch }}" == "cvm-x64" ]; then | ||
| export makeargs="ARCH=x86_64 KCONFIG_CONFIG=Microsoft/hcl-x64.config INSTALL_MOD_PATH=$PWD/out/modules" | ||
| export targets="olddefconfig vmlinux modules modules_install" | ||
| elif [ "${{ matrix.arch }}" == "arm64" ]; then | ||
| export makeargs="ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- KCONFIG_CONFIG=Microsoft/hcl-arm64.config INSTALL_MOD_PATH=$PWD/out/modules" | ||
| export targets="olddefconfig vmlinux Image modules modules_install" | ||
| fi | ||
| case "${{ matrix.arch }}" in | ||
| x64) | ||
| echo "build_arch=amd64" >> "$GITHUB_OUTPUT" | ||
| echo "config=Microsoft/hcl-x64.config" >> "$GITHUB_OUTPUT" | ||
| echo "is_cvm=0" >> "$GITHUB_OUTPUT" | ||
| ;; | ||
| cvm-x64) | ||
| echo "build_arch=amd64" >> "$GITHUB_OUTPUT" | ||
| echo "config=Microsoft/hcl-x64.config" >> "$GITHUB_OUTPUT" | ||
| echo "is_cvm=1" >> "$GITHUB_OUTPUT" | ||
| ;; | ||
| arm64) | ||
| echo "build_arch=arm64" >> "$GITHUB_OUTPUT" | ||
| echo "config=Microsoft/hcl-arm64.config" >> "$GITHUB_OUTPUT" | ||
| echo "is_cvm=0" >> "$GITHUB_OUTPUT" | ||
| ;; | ||
| esac | ||
|
|
||
| [ "${{ matrix.arch }}" == "cvm-x64" ] && ./Microsoft/merge-cvm-config.sh | ||
| make $makeargs -j$(nproc) $targets | ||
| - name: Merge CVM config fragment | ||
| if: steps.args.outputs.is_cvm == '1' | ||
| run: | | ||
| # Run the merge inside the Nix dev shell so flex/bison/gcc are present | ||
| # and so that scripts/kconfig builds against the same toolchain that | ||
| # will be used for the actual kernel compile. | ||
| nix develop -i \ | ||
| -k HOME -k USER -k TERM \ | ||
| --command bash -ec './Microsoft/merge-cvm-config.sh' | ||
|
|
||
| - name: Prepare for packaging | ||
| - name: Build kernel reproducibly | ||
| env: | ||
| # SOURCE_DATE_EPOCH is derived from the HEAD commit by the pipeline | ||
| # script when not pre-set; exporting it here makes it visible in logs. | ||
| GIT_SHA: ${{ github.sha }} | ||
| run: | | ||
| export artifacts_dir="release_artifacts/${{ matrix.arch }}" | ||
| if [ "${{ matrix.arch }}" == "arm64" ]; then | ||
| export objcopy="aarch64-linux-gnu-objcopy" | ||
| else | ||
| export objcopy="objcopy" | ||
| fi | ||
| # The pipeline script copies the source into /tmp/ohcl-kernel-build/src | ||
| # to normalise embedded paths. Place the build dir OUTSIDE the source | ||
| # so it survives that rsync (which excludes ./build, ./out, ./compare). | ||
| BUILD_DIR="${RUNNER_TEMP:-/tmp}/build-output-${{ matrix.arch }}-run${{ matrix.repro_run }}" | ||
| rm -rf "$BUILD_DIR" | ||
| mkdir -p "$BUILD_DIR" | ||
| echo "BUILD_DIR=$BUILD_DIR" >> "$GITHUB_ENV" | ||
|
|
||
| mkdir -p $artifacts_dir | ||
| cp vmlinux $artifacts_dir | ||
| $objcopy --only-keep-debug --compress-debug-sections $artifacts_dir/vmlinux $artifacts_dir/vmlinux.dbg | ||
| $objcopy --strip-all --add-gnu-debuglink=$artifacts_dir/vmlinux.dbg $artifacts_dir/vmlinux | ||
| [ "${{ matrix.arch }}" == "arm64" ] && cp arch/arm64/boot/Image $artifacts_dir/Image || true | ||
| export SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)" | ||
| echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" | ||
| echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH" >> "$GITHUB_ENV" | ||
|
|
||
| if [ "${{ matrix.arch }}" == "cvm-x64" ]; then | ||
| cp Microsoft/hcl-x64.config $artifacts_dir/kernel_config | ||
| else | ||
| cp Microsoft/hcl-${{ matrix.arch }}.config $artifacts_dir/kernel_config | ||
| fi | ||
| ./Microsoft/build-hcl-kernel-pipeline.sh \ | ||
| --source-dir "$PWD" \ | ||
| --build-dir "$BUILD_DIR" \ | ||
| --config "${{ steps.args.outputs.config }}" \ | ||
| --arch "${{ steps.args.outputs.build_arch }}" \ | ||
| --reproducible | ||
|
|
||
| echo "{" > $artifacts_dir/kernel_build_metadata.json | ||
| echo " \"git_branch\": \"${{ github.ref_name }}\"," >> $artifacts_dir/kernel_build_metadata.json | ||
| echo " \"git_revision\": \"${{ github.sha }}\"," >> $artifacts_dir/kernel_build_metadata.json | ||
| echo " \"build_id\": \"${{ github.run_id }}\"," >> $artifacts_dir/kernel_build_metadata.json | ||
| echo " \"build_name\": \"$(date +"%Y%m%d")\"" >> $artifacts_dir/kernel_build_metadata.json | ||
| echo "}" >> $artifacts_dir/kernel_build_metadata.json | ||
|
|
||
| mv out/modules/lib/modules/*/ $artifacts_dir/modules | ||
| rm $artifacts_dir/modules/build | ||
| mkdir $artifacts_dir/modules/debug-files/ | ||
| find $artifacts_dir/modules -name '*.ko' | while read -r mod; do | ||
| export outmod="$artifacts_dir/modules/debug-files/$(basename $mod)" | ||
| $objcopy --only-keep-debug --compress-debug-sections "$mod" "$outmod.dbg" | ||
| $objcopy --strip-unneeded --add-gnu-debuglink "$outmod.dbg" "$mod" | ||
| done | ||
| - name: Package artifacts | ||
| run: | | ||
| # Packaging runs inside the Nix shell so the cross objcopy is on PATH | ||
| # for arm64 module stripping. | ||
| nix develop -i \ | ||
| -k HOME -k USER -k TERM \ | ||
| -k BUILD_DIR \ | ||
| --command bash -ec ' | ||
| bash ./Microsoft/package-ci-artifacts.sh \ | ||
| "$BUILD_DIR" \ | ||
| "${{ matrix.arch }}" \ | ||
| "$PWD" \ | ||
| "$PWD/release_artifacts" \ | ||
| "${{ github.ref_name }}" \ | ||
| "${{ github.sha }}" \ | ||
| "${{ github.run_id }}" | ||
| ' | ||
|
|
||
| - name: Print reproducibility hashes | ||
| run: | | ||
| ART="release_artifacts/${{ matrix.arch }}" | ||
| echo "## Reproducibility hashes (${{ matrix.arch }} / run ${{ matrix.repro_run }})" >> "$GITHUB_STEP_SUMMARY" | ||
| echo '```' >> "$GITHUB_STEP_SUMMARY" | ||
| ( cd "$ART" && sha256sum vmlinux vmlinux.dbg kernel_config \ | ||
| $( [ -f Image ] && echo Image ) ) | tee -a "$GITHUB_STEP_SUMMARY" | ||
| echo '```' >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| - name: Upload build artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ matrix.arch }}-build | ||
| name: ${{ matrix.arch }}-build-run${{ matrix.repro_run }} | ||
| path: release_artifacts/${{ matrix.arch }}/ | ||
|
|
||
| compare_repro: |
- Build each Linux arch variant twice in parallel (run1/run2) - Preserve per-run logs and artifact uploads - Add compare_repro job to diff full artifact hashes across runs - Keep release creation tag-gated and publish artifacts from run1
b338be8 to
9ec8c98
Compare
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.
No description provided.