Add a system test to check the mk and ninja files generated by incremental build.
Bug: 358428180
Test: Run the test locally.
Change-Id: If1862ee44976216f3c5a5c62d50c6d688d38023b
diff --git a/android/init.go b/android/init.go
index d5b486b..b462292 100644
--- a/android/init.go
+++ b/android/init.go
@@ -18,5 +18,6 @@
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 24a44b4..577c6cc 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -212,7 +212,14 @@
}
// 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 0000000..981827d
--- /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