summaryrefslogtreecommitdiff
path: root/util/compare_build.sh
diff options
context:
space:
mode:
authorCraig Hesling <hesling@chromium.org>2020-03-08 20:29:51 -0700
committerCommit Bot <commit-bot@chromium.org>2020-03-24 21:15:16 +0000
commitdc71caed2ee356da20d308f720dd281fc5826c4b (patch)
treeae045d87167b1e802c4313004a126d97474b6ff5 /util/compare_build.sh
parenta847dd2e7a9feb8e584c31a9c491b5df4bf59c2c (diff)
downloadchrome-ec-dc71caed2ee356da20d308f720dd281fc5826c4b.tar.gz
compare_builds.sh: Changed to parallel operation
This completely changes the way compare_build.sh operates. * The test checkouts are done in /tmp directories. This detaches the test environment from your local EC workspace and allows builds for all references to occur at the same time. * Builds for all board and all references happen in parallel, unless disabled from command-line args. * New arguments: -k Allows the tmp dir to be preserved after compare -j 8 Number of jobs that will run concurrently (make -j) -o Forces only one EC ref to be built at a time. Although -j is always enforced, this option limits memory usage. BRANCH=none BUG=none TEST=time ./util/compare_build.sh TEST=time ./util/compare_build.sh -k -o -j 1 TEST=time ./util/compare_build.sh -k -o -j 4 TEST=time ./util/compare_build.sh -k -o TEST=# Introduce syntax error to board/nocturne_fp/board.c # Commit it time ./util/compare_build.sh # Ensure that the script detected the build error Signed-off-by: Craig Hesling <hesling@chromium.org> Change-Id: I3453f58a0ce08988e86572e6979f1a75a553f9b3 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2094695
Diffstat (limited to 'util/compare_build.sh')
-rwxr-xr-xutil/compare_build.sh174
1 files changed, 105 insertions, 69 deletions
diff --git a/util/compare_build.sh b/util/compare_build.sh
index 2d353b5154..793715134a 100755
--- a/util/compare_build.sh
+++ b/util/compare_build.sh
@@ -9,10 +9,19 @@
. /usr/share/misc/shflags
-DEFINE_string 'board' "nocturne_fp" 'Board to build (\"all\" for all boards)' \
+DEFINE_string 'boards' "nocturne_fp" 'Board to build (\"all\" for all boards)' \
'b'
DEFINE_string 'ref1' "HEAD" 'Git reference (commit, branch, etc)'
DEFINE_string 'ref2' "HEAD^" 'Git reference (commit, branch, etc)'
+DEFINE_boolean 'keep' "${FLAGS_FALSE}" \
+ 'Remove the temp directory after comparison.' 'k'
+# Integer type can still be passed blank ("")
+DEFINE_integer 'jobs' "-1" 'Number of jobs to pass to make' 'j'
+# When compiling both refs for all boards, mem usage was larger than 32GB.
+# If you don't have more than 32GB, you probably don't want to build both
+# refs at the same time. Use the -o flag.
+DEFINE_boolean 'oneref' "${FLAGS_FALSE}" \
+ 'Build only one set of boards at a time. This limits mem.' 'o'
# Process commandline flags.
FLAGS "${@}" || exit 1
@@ -20,7 +29,6 @@ eval set -- "${FLAGS_ARGV}"
set -e
-BOARD="${FLAGS_board}"
BOARDS_TO_SKIP="$(grep -E '^skip_boards =' Makefile.rules)"
BOARDS_TO_SKIP="${BOARDS_TO_SKIP//skip_boards = /}"
# Cr50 doesn't have reproducible builds.
@@ -30,68 +38,25 @@ BOARDS_TO_SKIP="${BOARDS_TO_SKIP//skip_boards = /}"
BOARDS_TO_SKIP+=" cr50"
# Can specify any valid git ref (e.g., commits or branches).
-OLD_REF="$(git rev-parse --short "${FLAGS_ref1}")"
-NEW_REF="$(git rev-parse --short "${FLAGS_ref2}")"
-
-# Save current cute branch name
-SAVED_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
-# If we are in a detached HEAD state, grab the exact commit hash
-if [[ "${SAVED_BRANCH}" == "HEAD" ]]; then
- SAVED_BRANCH="$(git rev-parse HEAD)"
+# We need the long sha for fetching changes
+OLD_REF="$(git rev-parse "${FLAGS_ref1}")"
+NEW_REF="$(git rev-parse "${FLAGS_ref2}")"
+
+MAKE_FLAGS=( )
+# Specify -j 1 for sequential
+if (( FLAGS_jobs > 0 )); then
+ MAKE_FLAGS+=( "-j" "${FLAGS_jobs}" )
+else
+ MAKE_FLAGS+=( "-j" )
fi
-on_exit() {
- # Intentionally not removing TMP_DIR on failure so that it can be
- # inspected.
- git checkout "${SAVED_BRANCH}" >/dev/null 2>&1
-}
-trap on_exit EXIT
-
-do_build() {
- local ref="$1"
- local result_dir="$2"
- local board="$3"
- git checkout "${ref}" >/dev/null 2>&1
- echo "Testing commit: $(git rev-parse --short HEAD)"
- rm -rf "build/${board}"
- # STATIC_VERSION makes sure the generated ec_version.h is constant.
- # See util/getversion.sh.
- make STATIC_VERSION=1 V=1 BOARD="${board}" -j >./build.out 2>&1
- rm -rf "${result_dir}"
- mv "build/${board}" "${result_dir}"
- mv build.out "${result_dir}"
-}
-
-compare_board() {
- local board="$1"
- local old_ref="$2"
- local new_ref="$3"
- local tmp_dir="$4"
-
- local old_build_dir="${tmp_dir}/build.${board}_${old_ref}"
- local new_build_dir="${tmp_dir}/build.${board}_${new_ref}"
-
- echo "BOARD: ${board}, ${old_build_dir}, ${new_build_dir}"
- do_build "${old_ref}" "${old_build_dir}" "${board}"
- do_build "${new_ref}" "${new_build_dir}" "${board}"
-
- if ! diff "${old_build_dir}/ec.bin" "${new_build_dir}/ec.bin" >/dev/null 2>&1;
- then
- echo "ec.bin FAILURE"
- exit 1
- fi
-
- rm -rf "${old_build_dir}"
- rm -rf "${new_build_dir}"
-}
+BOARDS=( "${FLAGS_boards}" )
-if [[ "${BOARD}" == "all" ]]; then
- BOARD=""
+if [[ "${FLAGS_boards}" == "all" ]]; then
+ BOARDS=( )
echo "Skipping boards: ${BOARDS_TO_SKIP}"
- for b in board/*; do
- b=${b//board\//}
+ for b in $(make print-boards); do
skipped=0
- echo "b: ${b}"
for skip in ${BOARDS_TO_SKIP}; do
if [[ "${skip}" == "${b}" ]]; then
skipped=1
@@ -99,19 +64,90 @@ if [[ "${BOARD}" == "all" ]]; then
fi
done
if [[ ${skipped} == 0 ]]; then
- BOARD+=" ${b}"
+ BOARDS+=( "${b}" )
fi
done
fi
-echo "BOARD: ${BOARD}"
-
-TMP_DIR="$(mktemp -d)"
-
-for board in ${BOARD}; do
- compare_board "${board}" "${OLD_REF}" "${NEW_REF}" "${TMP_DIR}"
-done
+echo "BOARDS: ${BOARDS[*]}"
+
+TMP_DIR="$(mktemp -d -t compare_build.XXXX)"
+
+# We want make to initiate the builds for ref1 and ref2 so that a
+# single jobserver manages the process.
+# We should do the build comparison in the Makefile to allow for easier
+# debugging when --keep is enabled.
+echo "# Preparing Makefile"
+cat > "${TMP_DIR}/Makefile" <<HEREDOC
+ORIGIN ?= $(realpath .)
+CRYPTOC_DIR ?= $(realpath ../../third_party/cryptoc)
+BOARDS ?= ${BOARDS[*]}
+
+.PHONY: all
+all: build-${OLD_REF} build-${NEW_REF}
+
+ec-%:
+ git clone --quiet --no-checkout \$(ORIGIN) \$@
+ git -C \$@ checkout --quiet \$(@:ec-%=%)
+
+build-%: ec-%
+ \$(MAKE) --no-print-directory -C \$(@:build-%=ec-%) \\
+ STATIC_VERSION=1 \\
+ CRYPTOCLIB=\$(CRYPTOC_DIR) \\
+ \$(addprefix proj-,\$(BOARDS))
+ @printf " MKDIR %s\n" "\$@"
+ @mkdir -p \$@
+ @for b in \$(BOARDS); do \\
+ printf " CP -l '%s' to '%s'\n" \\
+ "\$(@:build-%=ec-%)/build/\$\$b/ec.bin" \\
+ "\$@/\$\$b-ec.bin"; \\
+ cp -l \$(@:build-%=ec-%)/build/\$\$b/ec.bin \$@/\$\$b-ec.bin; \\
+ done
+
+# So that make doesn't try to remove them
+ec-${OLD_REF}:
+ec-${NEW_REF}:
+HEREDOC
+
+
+build() {
+ echo make --no-print-directory -C "${TMP_DIR}" "${MAKE_FLAGS[@]}" "$@"
+ make --no-print-directory -C "${TMP_DIR}" "${MAKE_FLAGS[@]}" "$@"
+ return $?
+}
-rm -rf "${TMP_DIR}"
+echo "# Launching build. Cover your eyes."
+result=0
+if [[ "${FLAGS_oneref}" == "${FLAGS_FALSE}" ]]; then
+ build "build-${OLD_REF}" "build-${NEW_REF}" || result=$?
+else
+ build "build-${OLD_REF}" && build "build-${NEW_REF}" || result=$?
+fi
+if [[ ${result} -ne 0 ]]; then
+ echo >&2
+ echo "# Failed to make one or more of the refs." >&2
+ exit 1
+fi
+echo
+
+echo "# Comparing Files"
+echo
+if diff "${TMP_DIR}/build-"{"${OLD_REF}","${NEW_REF}"}; then
+ echo "# Verdict: MATCH"
+ result=0
+else
+ echo "# Verdict: FAILURE"
+ result=1
+fi
+echo
+
+# Do keep in mind that temp directory take a few GB if all boards are built.
+if [[ "${FLAGS_keep}" == "${FLAGS_TRUE}" ]]; then
+ echo "# Keeping temp directory around for your inspection."
+ echo "# ${TMP_DIR}"
+else
+ echo "# Removing temp directory"
+ rm -rf "${TMP_DIR}"
+fi
-echo "ec.bin MATCH"
+exit "${result}"