08e90c2718
This script runs some useful integration tests, but is currently broken at ToT. This CL enables us to rerun this script successfully. Details 1. Remove the scripts related to bp2build/b/mixed_builds. These modes have been/are on the verge of deletion from soong 2. Remove the comparisision scripts for soong and bazel built artifcats, for the same reason 3. Add a TARGET_RELEASE to androidmk_test.sh 4. Add a TARGET_PRODUCT to o/s/build.ninja, since the generated .ninja files now have a product-specific suffix. 5. Remove a test that checks that globs are not generated in the first clean run. We always generate the glob file now (aosp/2893286) Test: build/soong/tests/run_integration_tests.sh Change-Id: I39f6706ab2a81a7b1b2e90d43195bc3e2c7a5c08
644 lines
16 KiB
Bash
Executable file
644 lines
16 KiB
Bash
Executable file
#!/bin/bash -eu
|
|
|
|
set -o pipefail
|
|
|
|
# This test exercises the bootstrapping process of the build system
|
|
# in a source tree that only contains enough files for Bazel and Soong to work.
|
|
|
|
source "$(dirname "$0")/lib.sh"
|
|
|
|
readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
|
|
|
|
readonly target_product="${TARGET_PRODUCT:-aosp_arm}"
|
|
|
|
function test_smoke {
|
|
setup
|
|
run_soong
|
|
}
|
|
|
|
function test_null_build() {
|
|
setup
|
|
run_soong
|
|
local -r bootstrap_mtime1=$(stat -c "%y" out/soong/bootstrap.ninja)
|
|
local -r output_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
run_soong
|
|
local -r bootstrap_mtime2=$(stat -c "%y" out/soong/bootstrap.ninja)
|
|
local -r output_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
if [[ "$bootstrap_mtime1" == "$bootstrap_mtime2" ]]; then
|
|
# Bootstrapping is always done. It doesn't take a measurable amount of time.
|
|
fail "Bootstrap Ninja file did not change on null build"
|
|
fi
|
|
|
|
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
|
|
fail "Output Ninja file changed on null build"
|
|
fi
|
|
}
|
|
|
|
function test_soong_build_rebuilt_if_blueprint_changes() {
|
|
setup
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/bootstrap.ninja)
|
|
|
|
sed -i 's/pluginGenSrcCmd/pluginGenSrcCmd2/g' build/blueprint/bootstrap/bootstrap.go
|
|
|
|
run_soong
|
|
local -r mtime2=$(stat -c "%y" out/soong/bootstrap.ninja)
|
|
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Bootstrap Ninja file did not change"
|
|
fi
|
|
}
|
|
|
|
function test_change_android_bp() {
|
|
setup
|
|
mkdir -p a
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_little_binary_host",
|
|
srcs: ["my_little_binary_host.py"]
|
|
}
|
|
EOF
|
|
touch a/my_little_binary_host.py
|
|
run_soong
|
|
|
|
grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja || fail "module not found"
|
|
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_great_binary_host",
|
|
srcs: ["my_great_binary_host.py"]
|
|
}
|
|
EOF
|
|
touch a/my_great_binary_host.py
|
|
run_soong
|
|
|
|
grep -q "^# Module:.*my_little_binary_host" out/soong/build."${target_product}".ninja && fail "old module found"
|
|
grep -q "^# Module:.*my_great_binary_host" out/soong/build."${target_product}".ninja || fail "new module not found"
|
|
}
|
|
|
|
function test_add_android_bp() {
|
|
setup
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
mkdir -p a
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_little_binary_host",
|
|
srcs: ["my_little_binary_host.py"]
|
|
}
|
|
EOF
|
|
touch a/my_little_binary_host.py
|
|
run_soong
|
|
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Output Ninja file did not change"
|
|
fi
|
|
|
|
grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "New module not in output"
|
|
|
|
run_soong
|
|
}
|
|
|
|
function test_delete_android_bp() {
|
|
setup
|
|
mkdir -p a
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_little_binary_host",
|
|
srcs: ["my_little_binary_host.py"]
|
|
}
|
|
EOF
|
|
touch a/my_little_binary_host.py
|
|
run_soong
|
|
|
|
grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja || fail "Module not in output"
|
|
|
|
rm a/Android.bp
|
|
run_soong
|
|
|
|
if grep -q "^# Module:.*my_little_binary_host$" out/soong/build."${target_product}".ninja; then
|
|
fail "Old module in output"
|
|
fi
|
|
}
|
|
|
|
# Test that an incremental build with a glob doesn't rerun soong_build, and
|
|
# only regenerates the globs on the first but not the second incremental build.
|
|
function test_glob_noop_incremental() {
|
|
setup
|
|
|
|
# This test needs to start from a clean build, but setup creates an
|
|
# initialized tree that has already been built once. Clear the out
|
|
# directory to start from scratch (see b/185591972)
|
|
rm -rf out
|
|
|
|
mkdir -p a
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_little_binary_host",
|
|
srcs: ["*.py"],
|
|
}
|
|
EOF
|
|
touch a/my_little_binary_host.py
|
|
run_soong
|
|
local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
local glob_deps_file=out/soong/globs/"${target_product}"/0.d
|
|
|
|
run_soong
|
|
local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
# There is an ineffiencency in glob that requires bpglob to rerun once for each glob to update
|
|
# the entry in the .ninja_log. It doesn't update the output file, but we can detect the rerun
|
|
# by checking if the deps file was created.
|
|
if [ ! -e "$glob_deps_file" ]; then
|
|
fail "Glob deps file missing after second build"
|
|
fi
|
|
|
|
local -r glob_deps_mtime2=$(stat -c "%y" "$glob_deps_file")
|
|
|
|
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
|
|
fail "Ninja file rewritten on null incremental build"
|
|
fi
|
|
|
|
run_soong
|
|
local -r ninja_mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
local -r glob_deps_mtime3=$(stat -c "%y" "$glob_deps_file")
|
|
|
|
if [[ "$ninja_mtime2" != "$ninja_mtime3" ]]; then
|
|
fail "Ninja file rewritten on null incremental build"
|
|
fi
|
|
|
|
# The bpglob commands should not rerun after the first incremental build.
|
|
if [[ "$glob_deps_mtime2" != "$glob_deps_mtime3" ]]; then
|
|
fail "Glob deps file rewritten on second null incremental build"
|
|
fi
|
|
}
|
|
|
|
function test_add_file_to_glob() {
|
|
setup
|
|
|
|
mkdir -p a
|
|
cat > a/Android.bp <<'EOF'
|
|
python_binary_host {
|
|
name: "my_little_binary_host",
|
|
srcs: ["*.py"],
|
|
}
|
|
EOF
|
|
touch a/my_little_binary_host.py
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
touch a/my_little_library.py
|
|
run_soong
|
|
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Output Ninja file did not change"
|
|
fi
|
|
|
|
grep -q my_little_library.py out/soong/build."${target_product}".ninja || fail "new file is not in output"
|
|
}
|
|
|
|
function test_soong_build_rerun_iff_environment_changes() {
|
|
setup
|
|
|
|
mkdir -p build/soong/cherry
|
|
cat > build/soong/cherry/Android.bp <<'EOF'
|
|
bootstrap_go_package {
|
|
name: "cherry",
|
|
pkgPath: "android/soong/cherry",
|
|
deps: [
|
|
"blueprint",
|
|
"soong",
|
|
"soong-android",
|
|
],
|
|
srcs: [
|
|
"cherry.go",
|
|
],
|
|
pluginFor: ["soong_build"],
|
|
}
|
|
EOF
|
|
|
|
cat > build/soong/cherry/cherry.go <<'EOF'
|
|
package cherry
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"github.com/google/blueprint"
|
|
)
|
|
|
|
var (
|
|
pctx = android.NewPackageContext("cherry")
|
|
)
|
|
|
|
func init() {
|
|
android.RegisterSingletonType("cherry", CherrySingleton)
|
|
}
|
|
|
|
func CherrySingleton() android.Singleton {
|
|
return &cherrySingleton{}
|
|
}
|
|
|
|
type cherrySingleton struct{}
|
|
|
|
func (p *cherrySingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
cherryRule := ctx.Rule(pctx, "cherry",
|
|
blueprint.RuleParams{
|
|
Command: "echo CHERRY IS " + ctx.Config().Getenv("CHERRY") + " > ${out}",
|
|
CommandDeps: []string{},
|
|
Description: "Cherry",
|
|
})
|
|
|
|
outputFile := android.PathForOutput(ctx, "cherry", "cherry.txt")
|
|
var deps android.Paths
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: cherryRule,
|
|
Output: outputFile,
|
|
Inputs: deps,
|
|
})
|
|
}
|
|
EOF
|
|
|
|
export CHERRY=TASTY
|
|
run_soong
|
|
grep -q "CHERRY IS TASTY" out/soong/build."${target_product}".ninja \
|
|
|| fail "first value of environment variable is not used"
|
|
|
|
export CHERRY=RED
|
|
run_soong
|
|
grep -q "CHERRY IS RED" out/soong/build."${target_product}".ninja \
|
|
|| fail "second value of environment variable not used"
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
run_soong
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" != "$mtime2" ]]; then
|
|
fail "Output Ninja file changed when environment variable did not"
|
|
fi
|
|
|
|
}
|
|
|
|
function test_create_global_include_directory() {
|
|
setup
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
# Soong needs to know if top level directories like hardware/ exist for use
|
|
# as global include directories. Make sure that doesn't cause regens for
|
|
# unrelated changes to the top level directory.
|
|
mkdir -p system/core
|
|
|
|
run_soong
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" != "$mtime2" ]]; then
|
|
fail "Output Ninja file changed when top level directory changed"
|
|
fi
|
|
|
|
# Make sure it does regen if a missing directory in the path of a global
|
|
# include directory is added.
|
|
mkdir -p system/core/include
|
|
|
|
run_soong
|
|
local -r mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime2" = "$mtime3" ]]; then
|
|
fail "Output Ninja file did not change when global include directory created"
|
|
fi
|
|
|
|
}
|
|
|
|
function test_add_file_to_soong_build() {
|
|
setup
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
mkdir -p vendor/foo/picard
|
|
cat > vendor/foo/picard/Android.bp <<'EOF'
|
|
bootstrap_go_package {
|
|
name: "picard-soong-rules",
|
|
pkgPath: "android/soong/picard",
|
|
deps: [
|
|
"blueprint",
|
|
"soong",
|
|
"soong-android",
|
|
],
|
|
srcs: [
|
|
"picard.go",
|
|
],
|
|
pluginFor: ["soong_build"],
|
|
}
|
|
EOF
|
|
|
|
cat > vendor/foo/picard/picard.go <<'EOF'
|
|
package picard
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"github.com/google/blueprint"
|
|
)
|
|
|
|
var (
|
|
pctx = android.NewPackageContext("picard")
|
|
)
|
|
|
|
func init() {
|
|
android.RegisterSingletonType("picard", PicardSingleton)
|
|
}
|
|
|
|
func PicardSingleton() android.Singleton {
|
|
return &picardSingleton{}
|
|
}
|
|
|
|
type picardSingleton struct{}
|
|
|
|
func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
picardRule := ctx.Rule(pctx, "picard",
|
|
blueprint.RuleParams{
|
|
Command: "echo Make it so. > ${out}",
|
|
CommandDeps: []string{},
|
|
Description: "Something quotable",
|
|
})
|
|
|
|
outputFile := android.PathForOutput(ctx, "picard", "picard.txt")
|
|
var deps android.Paths
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: picardRule,
|
|
Output: outputFile,
|
|
Inputs: deps,
|
|
})
|
|
}
|
|
|
|
EOF
|
|
|
|
run_soong
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Output Ninja file did not change"
|
|
fi
|
|
|
|
grep -q "Make it so" out/soong/build."${target_product}".ninja || fail "New action not present"
|
|
}
|
|
|
|
# Tests a glob in a build= statement in an Android.bp file, which is interpreted
|
|
# during bootstrapping.
|
|
function test_glob_during_bootstrapping() {
|
|
setup
|
|
|
|
mkdir -p build/soong/picard
|
|
cat > build/soong/picard/Android.bp <<'EOF'
|
|
build=["foo*.bp"]
|
|
EOF
|
|
cat > build/soong/picard/fooa.bp <<'EOF'
|
|
bootstrap_go_package {
|
|
name: "picard-soong-rules",
|
|
pkgPath: "android/soong/picard",
|
|
deps: [
|
|
"blueprint",
|
|
"soong",
|
|
"soong-android",
|
|
],
|
|
srcs: [
|
|
"picard.go",
|
|
],
|
|
pluginFor: ["soong_build"],
|
|
}
|
|
EOF
|
|
|
|
cat > build/soong/picard/picard.go <<'EOF'
|
|
package picard
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"github.com/google/blueprint"
|
|
)
|
|
|
|
var (
|
|
pctx = android.NewPackageContext("picard")
|
|
)
|
|
|
|
func init() {
|
|
android.RegisterSingletonType("picard", PicardSingleton)
|
|
}
|
|
|
|
func PicardSingleton() android.Singleton {
|
|
return &picardSingleton{}
|
|
}
|
|
|
|
type picardSingleton struct{}
|
|
|
|
var Message = "Make it so."
|
|
|
|
func (p *picardSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
picardRule := ctx.Rule(pctx, "picard",
|
|
blueprint.RuleParams{
|
|
Command: "echo " + Message + " > ${out}",
|
|
CommandDeps: []string{},
|
|
Description: "Something quotable",
|
|
})
|
|
|
|
outputFile := android.PathForOutput(ctx, "picard", "picard.txt")
|
|
var deps android.Paths
|
|
|
|
ctx.Build(pctx, android.BuildParams{
|
|
Rule: picardRule,
|
|
Output: outputFile,
|
|
Inputs: deps,
|
|
})
|
|
}
|
|
|
|
EOF
|
|
|
|
run_soong
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
grep -q "Make it so" out/soong/build."${target_product}".ninja || fail "Original action not present"
|
|
|
|
cat > build/soong/picard/foob.bp <<'EOF'
|
|
bootstrap_go_package {
|
|
name: "worf-soong-rules",
|
|
pkgPath: "android/soong/worf",
|
|
deps: [
|
|
"blueprint",
|
|
"soong",
|
|
"soong-android",
|
|
"picard-soong-rules",
|
|
],
|
|
srcs: [
|
|
"worf.go",
|
|
],
|
|
pluginFor: ["soong_build"],
|
|
}
|
|
EOF
|
|
|
|
cat > build/soong/picard/worf.go <<'EOF'
|
|
package worf
|
|
|
|
import "android/soong/picard"
|
|
|
|
func init() {
|
|
picard.Message = "Engage."
|
|
}
|
|
EOF
|
|
|
|
run_soong
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Output Ninja file did not change"
|
|
fi
|
|
|
|
grep -q "Engage" out/soong/build."${target_product}".ninja || fail "New action not present"
|
|
|
|
if grep -q "Make it so" out/soong/build."${target_product}".ninja; then
|
|
fail "Original action still present"
|
|
fi
|
|
}
|
|
|
|
function test_soong_docs_smoke() {
|
|
setup
|
|
|
|
run_soong soong_docs
|
|
|
|
[[ -e "out/soong/docs/soong_build.html" ]] || fail "Documentation for main page not created"
|
|
[[ -e "out/soong/docs/cc.html" ]] || fail "Documentation for C++ modules not created"
|
|
}
|
|
|
|
function test_null_build_after_soong_docs() {
|
|
setup
|
|
|
|
run_soong
|
|
local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
run_soong soong_docs
|
|
local -r docs_mtime1=$(stat -c "%y" out/soong/docs/soong_build.html)
|
|
|
|
run_soong soong_docs
|
|
local -r docs_mtime2=$(stat -c "%y" out/soong/docs/soong_build.html)
|
|
|
|
if [[ "$docs_mtime1" != "$docs_mtime2" ]]; then
|
|
fail "Output Ninja file changed on null build"
|
|
fi
|
|
|
|
run_soong
|
|
local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
|
|
fail "Output Ninja file changed on null build"
|
|
fi
|
|
}
|
|
|
|
function test_write_to_source_tree {
|
|
setup
|
|
mkdir -p a
|
|
cat > a/Android.bp <<EOF
|
|
genrule {
|
|
name: "write_to_source_tree",
|
|
out: ["write_to_source_tree"],
|
|
cmd: "touch file_in_source_tree && touch \$(out)",
|
|
}
|
|
EOF
|
|
readonly EXPECTED_OUT=out/soong/.intermediates/a/write_to_source_tree/gen/write_to_source_tree
|
|
readonly ERROR_LOG=${MOCK_TOP}/out/error.log
|
|
readonly ERROR_MSG="Read-only file system"
|
|
readonly ERROR_HINT_PATTERN="BUILD_BROKEN_SRC_DIR"
|
|
# Test in ReadOnly source tree
|
|
run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=false ${EXPECTED_OUT} &> /dev/null && \
|
|
fail "Write to source tree should not work in a ReadOnly source tree"
|
|
|
|
if grep -q "${ERROR_MSG}" "${ERROR_LOG}" && grep -q "${ERROR_HINT_PATTERN}" "${ERROR_LOG}" ; then
|
|
echo Error message and error hint found in logs >/dev/null
|
|
else
|
|
fail "Did not find Read-only error AND error hint in error.log"
|
|
fi
|
|
|
|
# Test in ReadWrite source tree
|
|
run_ninja BUILD_BROKEN_SRC_DIR_IS_WRITABLE=true ${EXPECTED_OUT} &> /dev/null || \
|
|
fail "Write to source tree did not succeed in a ReadWrite source tree"
|
|
|
|
if grep -q "${ERROR_MSG}\|${ERROR_HINT_PATTERN}" "${ERROR_LOG}" ; then
|
|
fail "Found read-only error OR error hint in error.log"
|
|
fi
|
|
}
|
|
|
|
function test_dump_json_module_graph() {
|
|
setup
|
|
run_soong json-module-graph
|
|
if [[ ! -r "out/soong/module-graph.json" ]]; then
|
|
fail "JSON file was not created"
|
|
fi
|
|
}
|
|
|
|
function test_json_module_graph_back_and_forth_null_build() {
|
|
setup
|
|
|
|
run_soong
|
|
local -r ninja_mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
run_soong json-module-graph
|
|
local -r json_mtime1=$(stat -c "%y" out/soong/module-graph.json)
|
|
|
|
run_soong
|
|
local -r ninja_mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
|
|
fail "Output Ninja file changed after writing JSON module graph"
|
|
fi
|
|
|
|
run_soong json-module-graph
|
|
local -r json_mtime2=$(stat -c "%y" out/soong/module-graph.json)
|
|
if [[ "$json_mtime1" != "$json_mtime2" ]]; then
|
|
fail "JSON module graph file changed after writing Ninja file"
|
|
fi
|
|
|
|
}
|
|
|
|
function test_queryview_null_build() {
|
|
setup
|
|
|
|
run_soong queryview
|
|
local -r output_mtime1=$(stat -c "%y" out/soong/queryview.marker)
|
|
|
|
run_soong queryview
|
|
local -r output_mtime2=$(stat -c "%y" out/soong/queryview.marker)
|
|
|
|
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
|
|
fail "Queryview marker file changed on null build"
|
|
fi
|
|
}
|
|
|
|
# This test verifies that adding a new glob to a blueprint file only
|
|
# causes build."${target_product}".ninja to be regenerated on the *next* build, and *not*
|
|
# the build after. (This is a regression test for a bug where globs
|
|
# resulted in two successive regenerations.)
|
|
function test_new_glob_incrementality {
|
|
setup
|
|
|
|
run_soong nothing
|
|
local -r mtime1=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
mkdir -p globdefpkg/
|
|
cat > globdefpkg/Android.bp <<'EOF'
|
|
filegroup {
|
|
name: "fg_with_glob",
|
|
srcs: ["*.txt"],
|
|
}
|
|
EOF
|
|
|
|
run_soong nothing
|
|
local -r mtime2=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
if [[ "$mtime1" == "$mtime2" ]]; then
|
|
fail "Ninja file was not regenerated, despite a new bp file"
|
|
fi
|
|
|
|
run_soong nothing
|
|
local -r mtime3=$(stat -c "%y" out/soong/build."${target_product}".ninja)
|
|
|
|
if [[ "$mtime2" != "$mtime3" ]]; then
|
|
fail "Ninja file was regenerated despite no previous bp changes"
|
|
fi
|
|
}
|
|
|
|
scan_and_run_tests
|