d1e3f1ff08
This requires linking Blueprint into soong_ui. It lets us avoid the complicated dance of Ninja files and shell scripts: now the information as to how soong_build is built is passed directly to Blueprint using a struct that contains all the information the command line arguments used to contain. The ability to run Blueprint from the command line is kept (for now). Some variables in bootstrap/command.go needed public accessor functions because soong_build reads them. This will be disentangled by moving the flag parsing to soong_build. The presence of the flag definitions in Blueprint means that soong_ui now also accepts them. This is not a problem in practice because they are ignored and because soong_ui itself is hidden behind a few layers of shell scripts. Test: Presubmits + the new bootstrap_test.sh . Change-Id: I6dca478f356f56a8aee1e457d71439272351390b
376 lines
8.6 KiB
Bash
Executable file
376 lines
8.6 KiB
Bash
Executable file
#!/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 for 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
|
|
# This is necessary because the empty soong.variables file written to satisfy
|
|
# Ninja would contain "BootJars: {}" instead of "BootJars: []" which cannot
|
|
# be parsed back
|
|
# TODO(b/182965747): Fix this.
|
|
cat > out/soong/soong.variables <<'EOF'
|
|
{
|
|
"BuildNumberFile": "build_number.txt",
|
|
"Platform_version_name": "S",
|
|
"Platform_sdk_version": 30,
|
|
"Platform_sdk_codename": "S",
|
|
"Platform_sdk_final": false,
|
|
"Platform_version_active_codenames": [
|
|
"S"
|
|
],
|
|
"Platform_vndk_version": "S",
|
|
"DeviceName": "generic_arm64",
|
|
"DeviceArch": "arm64",
|
|
"DeviceArchVariant": "armv8-a",
|
|
"DeviceCpuVariant": "generic",
|
|
"DeviceAbi": [
|
|
"arm64-v8a"
|
|
],
|
|
"DeviceSecondaryArch": "arm",
|
|
"DeviceSecondaryArchVariant": "armv8-a",
|
|
"DeviceSecondaryCpuVariant": "generic",
|
|
"DeviceSecondaryAbi": [
|
|
"armeabi-v7a",
|
|
"armeabi"
|
|
],
|
|
"HostArch": "x86_64",
|
|
"HostSecondaryArch": "x86",
|
|
"CrossHost": "windows",
|
|
"CrossHostArch": "x86",
|
|
"CrossHostSecondaryArch": "x86_64",
|
|
"AAPTCharacteristics": "nosdcard",
|
|
"AAPTConfig": [
|
|
"normal",
|
|
"large",
|
|
"xlarge",
|
|
"hdpi",
|
|
"xhdpi",
|
|
"xxhdpi"
|
|
],
|
|
"AAPTPreferredConfig": "xhdpi",
|
|
"AAPTPrebuiltDPI": [
|
|
"xhdpi",
|
|
"xxhdpi"
|
|
],
|
|
"Malloc_not_svelte": true,
|
|
"Malloc_zero_contents": true,
|
|
"Malloc_pattern_fill_contents": false,
|
|
"Safestack": false,
|
|
"BootJars": [],
|
|
"UpdatableBootJars": [],
|
|
"Native_coverage": null
|
|
}
|
|
EOF
|
|
}
|
|
|
|
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
|