123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- #!/bin/bash -eu
- # 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.
- HARDWIRED_MOCK_TOP=
- # Uncomment this to be able to view the source tree after a test is run
- # HARDWIRED_MOCK_TOP=/tmp/td
- REAL_TOP="$(readlink -f "$(dirname "$0")"/../..)"
- function fail {
- echo ERROR: $1
- exit 1
- }
- function copy_directory() {
- local dir="$1"
- local parent="$(dirname "$dir")"
- mkdir -p "$MOCK_TOP/$parent"
- cp -R "$REAL_TOP/$dir" "$MOCK_TOP/$parent"
- }
- function symlink_file() {
- local file="$1"
- mkdir -p "$MOCK_TOP/$(dirname "$file")"
- ln -s "$REAL_TOP/$file" "$MOCK_TOP/$file"
- }
- function symlink_directory() {
- local dir="$1"
- mkdir -p "$MOCK_TOP/$dir"
- # We need to symlink the contents of the directory individually instead of
- # using one symlink for the whole directory because finder.go doesn't follow
- # symlinks when looking for Android.bp files
- for i in $(ls "$REAL_TOP/$dir"); do
- local target="$MOCK_TOP/$dir/$i"
- local source="$REAL_TOP/$dir/$i"
- if [[ -e "$target" ]]; then
- if [[ ! -d "$source" || ! -d "$target" ]]; then
- fail "Trying to symlink $dir twice"
- fi
- else
- ln -s "$REAL_TOP/$dir/$i" "$MOCK_TOP/$dir/$i";
- fi
- done
- }
- function setup_bazel() {
- copy_directory build/bazel
- symlink_directory prebuilts/bazel
- symlink_directory prebuilts/jdk
- symlink_file WORKSPACE
- symlink_file tools/bazel
- }
- function setup() {
- if [[ ! -z "$HARDWIRED_MOCK_TOP" ]]; then
- MOCK_TOP="$HARDWIRED_MOCK_TOP"
- rm -fr "$MOCK_TOP"
- mkdir -p "$MOCK_TOP"
- else
- MOCK_TOP=$(mktemp -t -d st.XXXXX)
- trap 'echo cd / && echo rm -fr "$MOCK_TOP"' EXIT
- fi
- echo "Test case: ${FUNCNAME[1]}, mock top path: $MOCK_TOP"
- cd "$MOCK_TOP"
- copy_directory build/blueprint
- copy_directory build/soong
- symlink_directory prebuilts/go
- symlink_directory prebuilts/build-tools
- symlink_directory external/golang-protobuf
- touch "$MOCK_TOP/Android.bp"
- export ALLOW_MISSING_DEPENDENCIES=true
- mkdir -p out/soong
- }
- function run_soong() {
- build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests
- }
- function test_smoke {
- setup
- run_soong
- }
- function test_bazel_smoke {
- setup
- setup_bazel
- tools/bazel info
- }
- function test_null_build() {
- setup
- run_soong
- local bootstrap_mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
- local output_mtime1=$(stat -c "%y" out/soong/build.ninja)
- run_soong
- local bootstrap_mtime2=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
- local output_mtime2=$(stat -c "%y" out/soong/build.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 mtime1=$(stat -c "%y" out/soong/.bootstrap/build.ninja)
- sed -i 's/pluginGenSrcCmd/pluginGenSrcCmd2/g' build/blueprint/bootstrap/bootstrap.go
- run_soong
- local mtime2=$(stat -c "%y" out/soong/.bootstrap/build.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.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.ninja && fail "old module found"
- grep -q "^# Module:.*my_great_binary_host" out/soong/build.ninja || fail "new module not found"
- }
- function test_add_android_bp() {
- setup
- run_soong
- local mtime1=$(stat -c "%y" out/soong/build.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 mtime2=$(stat -c "%y" out/soong/build.ninja)
- if [[ "$mtime1" == "$mtime2" ]]; then
- fail "Output Ninja file did not change"
- fi
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build.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.ninja || fail "Module not in output"
- rm a/Android.bp
- run_soong
- grep -q "^# Module:.*my_little_binary_host$" out/soong/build.ninja && fail "Old module in output"
- }
- 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 mtime1=$(stat -c "%y" out/soong/build.ninja)
- touch a/my_little_library.py
- run_soong
- local mtime2=$(stat -c "%y" out/soong/build.ninja)
- if [[ "$mtime1" == "$mtime2" ]]; then
- fail "Output Ninja file did not change"
- fi
- grep -q my_little_library.py out/soong/build.ninja || fail "new file is not in output"
- }
- function test_add_file_to_soong_build() {
- setup
- run_soong
- local mtime1=$(stat -c "%y" out/soong/build.ninja)
- mkdir -p a
- cat > a/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 > a/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 mtime2=$(stat -c "%y" out/soong/build.ninja)
- if [[ "$mtime1" == "$mtime2" ]]; then
- fail "Output Ninja file did not change"
- fi
- grep -q "Make it so" out/soong/build.ninja || fail "New action not present"
- }
- test_bazel_smoke
- test_smoke
- test_null_build
- test_soong_build_rebuilt_if_blueprint_changes
- test_add_file_to_glob
- test_add_android_bp
- test_change_android_bp
- test_delete_android_bp
- test_add_file_to_soong_build
|