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