diff options
author | Craig Hesling <hesling@chromium.org> | 2020-03-08 20:29:51 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-24 21:15:16 +0000 |
commit | dc71caed2ee356da20d308f720dd281fc5826c4b (patch) | |
tree | ae045d87167b1e802c4313004a126d97474b6ff5 | |
parent | a847dd2e7a9feb8e584c31a9c491b5df4bf59c2c (diff) | |
download | chrome-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
-rwxr-xr-x | util/compare_build.sh | 174 |
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}" |