#!/bin/bash # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2021 Intel Corporation. All rights reserved. # This builds SOF twice with some environment variations and then # compares the binary outputs. # Big caveats: # # - Only -g0 is supported, no BUILD_PATH_PREFIX_MAP # - rimage uses the current date (day month year) in the # signature. # - Starting from TGL, signatures also include a random salt. # # rimage makes sof.ri non-deterministic even when sof.elf is # deterministic. See https://github.com/thesofproject/rimage/issues/41 # and below for more details and future directions. # The following, basic environment variations are currently tested: # # - timestamps (obviously) # - source directory # - disorderfs # For a list of other, non-tested environment variations check the # "Achieve deterministic builds" list found at # https://reproducible-builds.org/docs/ set -e SOF_TOP=$(cd "$(dirname "$0")"/.. && /bin/pwd) SOF_PARENT=$(cd "$SOF_TOP"/.. && /bin/pwd) SOF2="$SOF_PARENT"/sof-bind-mount-DO-NOT-DELETE # To avoid ripple effects and reduce the number of differences # considerably, replace "sof" with something of the same length: # SOF2="$SOF_PARENT"/sog PLATFS=(rmb) # diffoscope is great but it has hundreds of dependencies, too long to # install for CI so we don't use it here. This is just an alias # suggestion for local use. Requires less -R. diffo () { # Omitting $2 ("and") allows copy/paste of the output of diff -r diffoscope --exclude-directory-metadata=recursive \ --text-color=always "$1" "$3" } hexdiff () { # cut -b10 removes the offset diff --color=auto -U20 \ <(hexdump -vC "$1" | cut -b10- ) \ <(hexdump -vC "$2" | cut -b10- ) | less } init() { # -E(xtended) regex local excluded_endings=( '\.log' /deps '\.c?make' '\.ninja' /TargetDirectories.txt /CMakeCache.txt /progress.marks /CMakeRulesHashes.txt /Makefile /CMakeRuleHashes.txt /Makefile2 '/depend\.internal' /link.txt '\.includecache' '/.ninja_deps' '/.ninja_log' '.*\.c\.o\.d' '/rimage_ep.*' '/smex_ep.*' ) # The signing process is not deterministic. # Keep 'reproducible.ri' INCLUDED! excluded_endings+=('/sof-[a-z-]{,6}\.rix?') excluded_endings+=('/sof\.ri' '/sof-no-xman\.ri' ) GREP_EXCLUDE_ARGS=() for fpath in "${excluded_endings[@]}"; do GREP_EXCLUDE_ARGS+=('-e' "$fpath differ\$") done # For debug # declare -p GREP_EXCLUDE_ARGS # exit } trap _unmount EXIT _unmount() { set +e if mount | grep -q "${SOF2}.*fuse"; then umount "$SOF2" rmdir "$SOF2" fi } diff_some_files() { local p f ( set +e for p in "${PLATFS[@]}"; do # Compare some ELF section headers. Look at the smallest .c.o # first for f in CMakeFiles/sof.dir/src/arch/xtensa/init.c.o sof; do diff --report-identical-files \ {b0,b1}/build_"$p"_?cc/"$f" || diff -u --ignore-matching-lines='file format ' \ <(objdump -h b0/build_"$p"_?cc/"$f") \ <(objdump -h b1/build_"$p"_?cc/"$f") done for f in generated/include/sof_versions.h sof.ri \ src/arch/xtensa/reproducible.ri; do diff -u --report-identical-files \ {b0,b1}/build_"$p"_?cc/"$f" # report unsupported reproducible.ri test -s b0/build_"$p"_?cc/"$f" || printf '\t%s is EMPTY\n' b0/build_"$p"_?cc/"$f" done done true ) | sed -e 's/differ/DIFFER/g' } main() { init test -e "$SOF2"/CMakeLists.txt || { mkdir -p "$SOF2" # This will fail in Docker; Docker should provide this bind # mount for us. disorderfs "${SOF_TOP}" "$SOF2" } # Chances of name collisions with the user should be pretty small rm -rf reprobld/b0/ reprobld/b1/ mkdir -p reprobld/b0/ reprobld/b1/ local oldTZ="$TZ" # typically undefined, coming from some /etc file # instead. export EXTRA_CFLAGS='-g0' # Going once export TZ='Pacific/Midway' # -11:00 "${SOF_TOP}"/scripts/xtensa-build-all.sh "${PLATFS[@]}" mv build_*_?cc reprobld/b0/ # Going twice # Use this to "break" rimage that makes the date (in local time! # BIOS fans?) part of the CSS signature. See caveats above. # +14:00 - -11:00 = +25:00 = always on a different date export TZ='Pacific/Kiritimati' # +14:00 "$SOF2"/scripts/xtensa-build-all.sh "${PLATFS[@]}" mv build_*_?cc reprobld/b1/ # Restore TZ just in case we want to use dates later. TZ="$oldTZ" cd reprobld diff -qr b0 b1/ | grep -E -v "${GREP_EXCLUDE_ARGS[@]}" || { printf \ "\n\n ---- PASS: no unexpected difference found between %s/b0/ and b1/ --- \n\n" "$(pwd)" exit 0 } printf "\n\n ---- FAIL: differences found between %s/b0/ and b1/ --- \n\n" "$(pwd)" diff_some_files printf "\n\n ---- FAIL: differences found between %s/b0/ and b1/ --- \n\n" "$(pwd)" } main "$@"