Skip to content

User/namjain/reprobuild gh testing#143

Closed
namancse wants to merge 6 commits into
product/hcl-main/6.18from
user/namjain/reprobuild-gh-testing
Closed

User/namjain/reprobuild gh testing#143
namancse wants to merge 6 commits into
product/hcl-main/6.18from
user/namjain/reprobuild-gh-testing

Conversation

@namancse
Copy link
Copy Markdown
Contributor

@namancse namancse commented Jun 3, 2026

No description provided.

Naman Jain 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 thread .github/workflows/ci.yaml
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
@namancse namancse force-pushed the user/namjain/reprobuild-gh-testing branch from b338be8 to 9ec8c98 Compare June 3, 2026 09:56
@namancse namancse closed this Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants