#!/bin/bash # RHEL Build Normalization Script # Sprint: SPRINT_1227_0002_0001 (Reproducible Builders) # # Normalizes RPM build environment for reproducibility set -euo pipefail # Normalize environment export TZ=UTC export LC_ALL=C.UTF-8 export LANG=C.UTF-8 # Deterministic compiler flags export CFLAGS="${CFLAGS:--fno-record-gcc-switches -fdebug-prefix-map=$(pwd)=/buildroot -O2 -g}" export CXXFLAGS="${CXXFLAGS:-${CFLAGS}}" # Disable debug info that varies export DEB_BUILD_OPTIONS="nostrip noopt" # RPM-specific reproducibility export RPM_BUILD_NCPUS=1 # Normalize timestamps in archives normalize_ar() { local archive="$1" if command -v llvm-ar &>/dev/null; then llvm-ar --format=gnu --enable-deterministic-archives rcs "${archive}.new" "${archive}" mv "${archive}.new" "${archive}" fi } # Normalize timestamps in tar archives normalize_tar() { local archive="$1" local mtime="${SOURCE_DATE_EPOCH:-0}" # Repack with deterministic settings local tmp_dir=$(mktemp -d) tar -xf "${archive}" -C "${tmp_dir}" tar --sort=name \ --mtime="@${mtime}" \ --owner=0 --group=0 \ --numeric-owner \ -cf "${archive}.new" -C "${tmp_dir}" . mv "${archive}.new" "${archive}" rm -rf "${tmp_dir}" } # Normalize __pycache__ timestamps normalize_python() { find . -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true find . -name '*.pyc' -delete 2>/dev/null || true } # Strip build paths from binaries strip_build_paths() { local binary="$1" if command -v objcopy &>/dev/null; then # Remove .note.gnu.build-id if it contains build path objcopy --remove-section=.note.gnu.build-id "${binary}" 2>/dev/null || true fi } # Main normalization normalize_build() { echo "Normalizing build environment..." # Normalize Python bytecode normalize_python # Find and normalize archives find . -name '*.a' -type f | while read -r ar; do normalize_ar "${ar}" done echo "Normalization complete" } # If sourced, export functions; if executed, run normalization if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then normalize_build fi