1#!/bin/bash -eu 2 3# Copyright (C) 2023 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17 18# Verifies that various intermediate outputs of the build have deterministic 19# outputs. Nondeterministic intermediate outputs have incremental performance 20# implications, so this is a critical test even if the determinism if the final 21# outputs is not in question. 22# 23# Determinism is verified by running several builds and comparing checksums of 24# outputs. This may provides confidence in determinism, but does not guarantee 25# it. "Flakiness" in this test should thus be treated as indicative of a 26# failure, and investigated promptly. 27if [[ -z ${OUT_DIR+x} ]]; then 28 OUT_DIR="out" 29fi 30 31if [[ -z ${DIST_DIR+x} ]]; then 32 echo "DIST_DIR not set. Using ${OUT_DIR}/dist. This should only be used for manual developer testing." 33 DIST_DIR="${OUT_DIR}/dist" 34fi 35 36if [[ -z ${TARGET_PRODUCT+x} ]]; then 37 echo "TARGET_PRODUCT not set. Using aosp_arm64" 38 TARGET_PRODUCT=aosp_arm64 39fi 40 41if [[ -z ${TARGET_BUILD_VARIANT+x} ]]; then 42 echo "TARGET_BUILD_VARIANT not set. Using userdebug" 43 TARGET_BUILD_VARIANT=userdebug 44fi 45 46UNAME="$(uname)" 47case "$UNAME" in 48Linux) 49 PREBUILTS="prebuilts/build-tools/path/linux-x86" 50 ;; 51Darwin) 52 PREBUILTS="prebuilts/build-tools/path/darwin-x86" 53 ;; 54*) 55 exit 1 56 ;; 57esac 58 59function clean_build { 60 build/soong/soong_ui.bash --make-mode clean 61 62 # Generate the ninja file with default setting. We expect Bazel to be enabled by 63 # default. 64 build/soong/soong_ui.bash --make-mode \ 65 --mk-metrics \ 66 BAZEL_STARTUP_ARGS="--max_idle_secs=5" \ 67 BAZEL_BUILD_ARGS="--color=no --curses=no --show_progress_rate_limit=5" \ 68 TARGET_PRODUCT=${TARGET_PRODUCT} \ 69 TARGET_BUILD_VARIANT=${TARGET_BUILD_VARIANT} \ 70 nothing \ 71 dist DIST_DIR=$DIST_DIR 72} 73 74function save_hash { 75 local -r filepath="$1" 76 find $OUT_DIR/soong/workspace -type f,l -iname "BUILD.bazel" -o -iname "*.bzl" | xargs "${PREBUILTS}"/md5sum > $filepath 77 find $OUT_DIR/soong/soong_injection -type f,l | xargs "${PREBUILTS}"/md5sum >> $filepath 78 "${PREBUILTS}"/md5sum $OUT_DIR/soong/Android-${TARGET_PRODUCT}.mk >> $filepath 79 if [[ -z ${SKIP_NINJA_CHECK+x} ]]; then 80 "${PREBUILTS}"/md5sum $OUT_DIR/soong/build.${TARGET_PRODUCT}.ninja >> $filepath 81 fi 82} 83 84TESTDIR=$(mktemp -t testdir.XXXXXX -d) 85FIRST_FILE=$TESTDIR/first_hashes 86TEST_FILE=$TESTDIR/hashes_to_test 87 88clean_build 89save_hash $FIRST_FILE 90 91for i in {1..4} ; do 92 clean_build 93 save_hash $TEST_FILE 94 if cmp -s "$FIRST_FILE" "$TEST_FILE" 95 then 96 echo "Comparison $i succeeded." 97 else 98 cp $FIRST_FILE $TEST_FILE $DIST_DIR 99 >&2 echo "Comparison $i failed. This likely indicates nondeterminism in the differing files." 100 >&2 echo "\n\nFirst file hashes:\n" 101 >&2 cat $FIRST_FILE 102 >&2 echo "\n\nRerun $i:\n" 103 >&2 cat $TEST_FILE 104 exit 1 105 fi 106done 107