diff --git a/android/init.go b/android/init.go index d5b486b10..b46229282 100644 --- a/android/init.go +++ b/android/init.go @@ -18,5 +18,6 @@ import "encoding/gob" func init() { gob.Register(ModuleOutPath{}) + gob.Register(PhonyPath{}) gob.Register(unstableInfo{}) } diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 24a44b4da..577c6cc74 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -212,7 +212,14 @@ func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDe } // Check if there are changes to the environment file, product variable file and -// soong_build binary, in which case no incremental will be performed. +// soong_build binary, in which case no incremental will be performed. For env +// variables we check the used env file, which will be removed in soong ui if +// there is any changes to the env variables used last time, in which case the +// check below will fail and a full build will be attempted. If any new env +// variables are added in the new run, soong ui won't be able to detect it, the +// used env file check below will pass. But unless there is a soong build code +// change, in which case the soong build binary check will fail, otherwise the +// new env variables shouldn't have any affect. func incrementalValid(config android.Config, configCacheFile string) (*ConfigCache, bool) { var newConfigCache ConfigCache data, err := os.ReadFile(shared.JoinPath(topDir, usedEnvFile)) diff --git a/tests/build_action_caching_test.sh b/tests/build_action_caching_test.sh new file mode 100755 index 000000000..981827d6f --- /dev/null +++ b/tests/build_action_caching_test.sh @@ -0,0 +1,110 @@ +#!/bin/bash -u + +set -o pipefail + +# Test that the mk and ninja files generated by Soong don't change if some +# incremental modules are restored from cache. + +OUTPUT_DIR="$(mktemp -d tmp.XXXXXX)" +echo ${OUTPUT_DIR} + +function cleanup { + rm -rf "${OUTPUT_DIR}" +} +trap cleanup EXIT + +function run_soong_build { + USE_RBE=false TARGET_PRODUCT=aosp_arm TARGET_RELEASE=trunk_staging TARGET_BUILD_VARIANT=userdebug build/soong/soong_ui.bash --make-mode --incremental-build-actions nothing +} + +function run_soong_clean { + build/soong/soong_ui.bash --make-mode clean +} + +function assert_files_equal { + if [ $# -ne 2 ]; then + echo "Usage: assert_files_equal file1 file2" + exit 1 + fi + + if ! cmp -s "$1" "$2"; then + echo "Files are different: $1 $2" + exit 1 + fi +} + +function compare_mtimes() { + if [ $# -ne 2 ]; then + echo "Usage: compare_mtimes file1 file2" + exit 1 + fi + + file1_mtime=$(stat -c '%Y' $1) + file2_mtime=$(stat -c '%Y' $2) + + if [ "$file1_mtime" -eq "$file2_mtime" ]; then + return 1 + else + return 0 + fi +} + +function test_build_action_restoring() { + run_soong_clean + cat > ${OUTPUT_DIR}/Android.bp <<'EOF' +python_binary_host { + name: "my_little_binary_host", + srcs: ["my_little_binary_host.py"], +} +EOF + touch ${OUTPUT_DIR}/my_little_binary_host.py + run_soong_build + mkdir -p "${OUTPUT_DIR}/before" + cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm.*.ninja ${OUTPUT_DIR}/before + # add a comment to the bp file, this should force a new analysis but no module + # should be really impacted, so all the incremental modules should be skipped. + cat >> ${OUTPUT_DIR}/Android.bp <<'EOF' +// new comments +EOF + run_soong_build + mkdir -p "${OUTPUT_DIR}/after" + cp -pr out/soong/build_aosp_arm_ninja_incremental out/soong/*.mk out/soong/build.aosp_arm.*.ninja ${OUTPUT_DIR}/after + + compare_files +} + +function compare_files() { + for file_before in ${OUTPUT_DIR}/before/*.ninja; do + file_after="${OUTPUT_DIR}/after/$(basename "$file_before")" + assert_files_equal $file_before $file_after + compare_mtimes $file_before $file_after + if [ $? -ne 0 ]; then + echo "Files have identical mtime: $file_before $file_after" + exit 1 + fi + done + + for file_before in ${OUTPUT_DIR}/before/*.mk; do + file_after="${OUTPUT_DIR}/after/$(basename "$file_before")" + assert_files_equal $file_before $file_after + compare_mtimes $file_before $file_after + # mk files shouldn't be regenerated + if [ $? -ne 1 ]; then + echo "Files have different mtimes: $file_before $file_after" + exit 1 + fi + done + + for file_before in ${OUTPUT_DIR}/before/build_aosp_arm_ninja_incremental/*.ninja; do + file_after="${OUTPUT_DIR}/after/build_aosp_arm_ninja_incremental/$(basename "$file_before")" + assert_files_equal $file_before $file_after + compare_mtimes $file_before $file_after + # ninja files of skipped modules shouldn't be regenerated + if [ $? -ne 1 ]; then + echo "Files have different mtimes: $file_before $file_after" + exit 1 + fi + done +} + +test_build_action_restoring