Merge "Skip initHiddenAPI check of prebuilt's boot dex jar for APEX modules"
diff --git a/android/bazel.go b/android/bazel.go
index 1f7f7e6..6e87d57 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -126,6 +126,42 @@
)
var (
+ // Do not write BUILD files for these directories
+ // NOTE: this is not recursive
+ bp2buildDoNotWriteBuildFileList = []string{
+ // Don't generate these BUILD files - because external BUILD files already exist
+ "external/boringssl",
+ "external/brotli",
+ "external/dagger2",
+ "external/flatbuffers",
+ "external/gflags",
+ "external/google-fruit",
+ "external/grpc-grpc",
+ "external/grpc-grpc/test/core/util",
+ "external/grpc-grpc/test/cpp/common",
+ "external/grpc-grpc/third_party/address_sorting",
+ "external/nanopb-c",
+ "external/nos/host/generic",
+ "external/nos/host/generic/libnos",
+ "external/nos/host/generic/libnos/generator",
+ "external/nos/host/generic/libnos_datagram",
+ "external/nos/host/generic/libnos_transport",
+ "external/nos/host/generic/nugget/proto",
+ "external/perfetto",
+ "external/protobuf",
+ "external/rust/cxx",
+ "external/rust/cxx/demo",
+ "external/ruy",
+ "external/tensorflow",
+ "external/tensorflow/tensorflow/lite",
+ "external/tensorflow/tensorflow/lite/java",
+ "external/tensorflow/tensorflow/lite/kernels",
+ "external/tflite-support",
+ "external/tinyalsa_new",
+ "external/wycheproof",
+ "external/libyuv",
+ }
+
// Configure modules in these directories to enable bp2build_available: true or false by default.
bp2buildDefaultConfig = Bp2BuildConfig{
"bionic": Bp2BuildDefaultTrueRecursively,
@@ -190,11 +226,16 @@
}
// Used for quicker lookups
- bp2buildModuleDoNotConvert = map[string]bool{}
- mixedBuildsDisabled = map[string]bool{}
+ bp2buildDoNotWriteBuildFile = map[string]bool{}
+ bp2buildModuleDoNotConvert = map[string]bool{}
+ mixedBuildsDisabled = map[string]bool{}
)
func init() {
+ for _, moduleName := range bp2buildDoNotWriteBuildFileList {
+ bp2buildDoNotWriteBuildFile[moduleName] = true
+ }
+
for _, moduleName := range bp2buildModuleDoNotConvertList {
bp2buildModuleDoNotConvert[moduleName] = true
}
@@ -204,6 +245,14 @@
}
}
+func ShouldWriteBuildFileForDir(dir string) bool {
+ if _, ok := bp2buildDoNotWriteBuildFile[dir]; ok {
+ return false
+ } else {
+ return true
+ }
+}
+
// MixedBuildsEnabled checks that a module is ready to be replaced by a
// converted or handcrafted Bazel target.
func (b *BazelModuleBase) MixedBuildsEnabled(ctx BazelConversionPathContext) bool {
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 85f701f..cb25fee 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -11,7 +11,7 @@
label := "//foo:bar"
arch := Arm64
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "cquery", expression: "kind(rule, deps(//:buildroot))"}: `@sourceroot//foo:bar|arm64>>out/foo/bar.txt`,
+ bazelCommand{command: "cquery", expression: "kind(rule, deps(@soong_injection//:buildroot))"}: `//foo:bar|arm64>>out/foo/bar.txt`,
})
g, ok := bazelContext.GetOutputFiles(label, arch)
if ok {
@@ -35,19 +35,19 @@
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
- if _, err := os.Stat(filepath.Join(baseDir, "bazel", "main.bzl")); os.IsNotExist(err) {
+ if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "main.bzl")); os.IsNotExist(err) {
t.Errorf("Expected main.bzl to exist, but it does not")
} else if err != nil {
t.Errorf("Unexpected error stating main.bzl %s", err)
}
- if _, err := os.Stat(filepath.Join(baseDir, "bazel", "BUILD.bazel")); os.IsNotExist(err) {
+ if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "BUILD.bazel")); os.IsNotExist(err) {
t.Errorf("Expected BUILD.bazel to exist, but it does not")
} else if err != nil {
t.Errorf("Unexpected error stating BUILD.bazel %s", err)
}
- if _, err := os.Stat(filepath.Join(baseDir, "bazel", "WORKSPACE.bazel")); os.IsNotExist(err) {
+ if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
} else if err != nil {
t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
@@ -56,7 +56,7 @@
func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "aquery", expression: "deps(//:buildroot)"}: `
+ bazelCommand{command: "aquery", expression: "deps(@soong_injection//:buildroot)"}: `
{
"artifacts": [{
"id": 1,
@@ -105,7 +105,7 @@
outputBase: "outputbase",
workspaceDir: "workspace_dir",
}
- aqueryCommand := bazelCommand{command: "aquery", expression: "deps(//:buildroot)"}
+ aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//:buildroot)"}
if _, exists := bazelCommandResults[aqueryCommand]; !exists {
bazelCommandResults[aqueryCommand] = "{}\n"
}
diff --git a/android/fixture.go b/android/fixture.go
index 5fc668a..fd051a7 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -339,6 +339,15 @@
})
}
+// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
+// state before running the test.
+//
+// This must only be added temporarily to a test for local debugging and must be removed from the
+// test before submitting.
+var PrepareForDebug_DO_NOT_SUBMIT = newSimpleFixturePreparer(func(fixture *fixture) {
+ fixture.debug = true
+})
+
// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
// the supplied FixturePreparer instances in order.
//
@@ -708,6 +717,9 @@
// The error handler used to check the errors, if any, that are reported.
errorHandler FixtureErrorHandler
+
+ // Debug mode status
+ debug bool
}
func (f *fixture) Config() Config {
@@ -725,6 +737,11 @@
func (f *fixture) RunTest() *TestResult {
f.t.Helper()
+ // If in debug mode output the state of the fixture before running the test.
+ if f.debug {
+ f.outputDebugState()
+ }
+
ctx := f.ctx
// Do not use the fixture's mockFS to initialize the config's mock file system if it has been
@@ -769,6 +786,39 @@
return result
}
+func (f *fixture) outputDebugState() {
+ fmt.Printf("Begin Fixture State for %s\n", f.t.Name())
+ if len(f.config.env) == 0 {
+ fmt.Printf(" Fixture Env is empty\n")
+ } else {
+ fmt.Printf(" Begin Env\n")
+ for k, v := range f.config.env {
+ fmt.Printf(" - %s=%s\n", k, v)
+ }
+ fmt.Printf(" End Env\n")
+ }
+ if len(f.mockFS) == 0 {
+ fmt.Printf(" Mock FS is empty\n")
+ } else {
+ fmt.Printf(" Begin Mock FS Contents\n")
+ for p, c := range f.mockFS {
+ if c == nil {
+ fmt.Printf("\n - %s: nil\n", p)
+ } else {
+ contents := string(c)
+ separator := " ========================================================================"
+ fmt.Printf(" - %s\n%s\n", p, separator)
+ for i, line := range strings.Split(contents, "\n") {
+ fmt.Printf(" %6d: %s\n", i+1, line)
+ }
+ fmt.Printf("%s\n", separator)
+ }
+ }
+ fmt.Printf(" End Mock FS Contents\n")
+ }
+ fmt.Printf("End Fixture State for %s\n", f.t.Name())
+}
+
// NormalizePathForTesting removes the test invocation specific build directory from the supplied
// path.
//
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 007d6d8..f1bf648 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -28,7 +28,7 @@
outputDir := android.PathForOutput(ctx, "bp2build")
android.RemoveAllOutputDir(outputDir)
- buildToTargets, metrics := GenerateBazelTargets(ctx)
+ buildToTargets, metrics := GenerateBazelTargets(ctx, true)
filesToWrite := CreateBazelFiles(nil, buildToTargets, ctx.mode)
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index b7a2810..08790d1 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -176,7 +176,7 @@
return attributes
}
-func GenerateBazelTargets(ctx *CodegenContext) (map[string]BazelTargets, CodegenMetrics) {
+func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (map[string]BazelTargets, CodegenMetrics) {
buildFileToTargets := make(map[string]BazelTargets)
buildFileToAppend := make(map[string]bool)
@@ -185,9 +185,13 @@
RuleClassCount: make(map[string]int),
}
+ dirs := make(map[string]bool)
+
bpCtx := ctx.Context()
bpCtx.VisitAllModules(func(m blueprint.Module) {
dir := bpCtx.ModuleDir(m)
+ dirs[dir] = true
+
var t BazelTarget
switch ctx.Mode() {
@@ -230,6 +234,17 @@
buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
})
+ if generateFilegroups {
+ // Add a filegroup target that exposes all sources in the subtree of this package
+ // NOTE: This also means we generate a BUILD file for every Android.bp file (as long as it has at least one module)
+ for dir, _ := range dirs {
+ buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{
+ name: "bp2build_all_srcs",
+ content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`,
+ ruleClass: "filegroup",
+ })
+ }
+ }
return buildFileToTargets, metrics
}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6b47cd1..114b668 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -2,6 +2,7 @@
import (
"android/soong/android"
+ "fmt"
"reflect"
"sort"
"strings"
@@ -48,6 +49,10 @@
func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
files := make([]BazelFile, 0, len(buildToTargets))
for _, dir := range android.SortedStringKeys(buildToTargets) {
+ if !android.ShouldWriteBuildFileForDir(dir) {
+ fmt.Printf("[bp2build] Not writing generated BUILD file for dir: '%s'\n", dir)
+ continue
+ }
targets := buildToTargets[dir]
sort.Slice(targets, func(i, j int) bool {
// this will cover all bp2build generated targets
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index db7bef8..15a6335 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -94,7 +94,7 @@
// contain every file in buildFilesDir and srcDir excluding the files in
// exclude. Collects every directory encountered during the traversal of srcDir
// into acc.
-func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string) {
+func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string, okay *bool) {
if exclude != nil && exclude.excluded {
// This directory is not needed, bail out
return
@@ -149,7 +149,7 @@
if buildFilesChildEntry.IsDir() && excludeChild != nil {
// Not in the source tree, but we have to exclude something from under
// this subtree, so descend
- plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc)
+ plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
} else {
// Not in the source tree, symlink BUILD file
symlinkIntoForest(topdir, forestChild, buildFilesChild)
@@ -158,20 +158,26 @@
if srcChildEntry.IsDir() && excludeChild != nil {
// Not in the build file tree, but we have to exclude something from
// under this subtree, so descend
- plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc)
+ plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
} else {
// Not in the build file tree, symlink source tree, carry on
symlinkIntoForest(topdir, forestChild, srcChild)
}
} else if srcChildEntry.IsDir() && buildFilesChildEntry.IsDir() {
// Both are directories. Descend.
- plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc)
+ plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ } else if !srcChildEntry.IsDir() && !buildFilesChildEntry.IsDir() {
+ // Neither is a directory. Prioritize BUILD files generated by bp2build
+ // over any BUILD file imported into external/.
+ fmt.Fprintf(os.Stderr, "Both '%s' and '%s' exist, symlinking the former to '%s'\n",
+ buildFilesChild, srcChild, forestChild)
+ symlinkIntoForest(topdir, forestChild, buildFilesChild)
} else {
// Both exist and one is a file. This is an error.
fmt.Fprintf(os.Stderr,
- "Conflict in workspace symlink tree creation: both '%s' and '%s' exist and at least one of them is a file\n",
+ "Conflict in workspace symlink tree creation: both '%s' and '%s' exist and exactly one is a directory\n",
srcChild, buildFilesChild)
- os.Exit(1)
+ *okay = false
}
}
}
@@ -184,6 +190,10 @@
deps := make([]string, 0)
os.RemoveAll(shared.JoinPath(topdir, forest))
excludeTree := treeFromExcludePathList(exclude)
- plantSymlinkForestRecursive(topdir, forest, buildFiles, srcDir, excludeTree, &deps)
+ okay := true
+ plantSymlinkForestRecursive(topdir, forest, buildFiles, srcDir, excludeTree, &deps, &okay)
+ if !okay {
+ os.Exit(1)
+ }
return deps
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index ef3a78f..c4661ea 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -183,6 +183,7 @@
// Helper method for tests to easily access the targets in a dir.
func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets {
- buildFileToTargets, _ := GenerateBazelTargets(codegenCtx)
+ // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
+ buildFileToTargets, _ := GenerateBazelTargets(codegenCtx, false)
return buildFileToTargets[dir]
}
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index edc8a42..e2ce772 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -27,7 +27,7 @@
// Ignore metrics reporting for queryview, since queryview is already a full-repo
// conversion and can use data from bazel query directly.
- buildToTargets, _ := bp2build.GenerateBazelTargets(ctx)
+ buildToTargets, _ := bp2build.GenerateBazelTargets(ctx, true)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
for _, f := range filesToWrite {
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index e5dba33..ebf541d 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -64,7 +64,7 @@
func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
info := hiddenAPIFlagFileInfo{categoryToPaths: map[*hiddenAPIFlagFileCategory]android.Paths{}}
for _, category := range hiddenAPIFlagFileCategories {
- paths := android.PathsForModuleSrc(ctx, category.propertyAccessor(p))
+ paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
info.categoryToPaths[category] = paths
}
return info
@@ -74,9 +74,9 @@
// propertyName is the name of the property for this category.
propertyName string
- // propertyAccessor retrieves the value of the property for this category from the set of
+ // propertyValueReader retrieves the value of the property for this category from the set of
// properties.
- propertyAccessor func(properties *HiddenAPIFlagFileProperties) []string
+ propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
// commandMutator adds the appropriate command line options for this category to the supplied
// command
@@ -87,7 +87,7 @@
// See HiddenAPIFlagFileProperties.Unsupported
{
propertyName: "unsupported",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -97,7 +97,7 @@
// See HiddenAPIFlagFileProperties.Removed
{
propertyName: "removed",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Removed
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -107,7 +107,7 @@
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
{
propertyName: "max_target_r_low_priority",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_r_low_priority
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -117,7 +117,7 @@
// See HiddenAPIFlagFileProperties.Max_target_q
{
propertyName: "max_target_q",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_q
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -127,7 +127,7 @@
// See HiddenAPIFlagFileProperties.Max_target_p
{
propertyName: "max_target_p",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_p
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -137,7 +137,7 @@
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
{
propertyName: "max_target_o_low_priority",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Max_target_o_low_priority
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -147,7 +147,7 @@
// See HiddenAPIFlagFileProperties.Blocked
{
propertyName: "blocked",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Blocked
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
@@ -157,7 +157,7 @@
// See HiddenAPIFlagFileProperties.Unsupported_packages
{
propertyName: "unsupported_packages",
- propertyAccessor: func(properties *HiddenAPIFlagFileProperties) []string {
+ propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
return properties.Unsupported_packages
},
commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 8edb7c9..ba0ab93 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -79,7 +79,7 @@
// binary must expect arguments in a similar fashion to bindgen, e.g.
//
// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
- Custom_bindgen string `android:"path"`
+ Custom_bindgen string
}
type bindgenDecorator struct {
diff --git a/rust/compiler.go b/rust/compiler.go
index bfc23b2..a3f02c0 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -77,10 +77,10 @@
Lints *string
// flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties.
- Flags []string `android:"path,arch_variant"`
+ Flags []string `android:"arch_variant"`
// flags to pass to the linker
- Ld_flags []string `android:"path,arch_variant"`
+ Ld_flags []string `android:"arch_variant"`
// list of rust rlib crate dependencies
Rlibs []string `android:"arch_variant"`
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 1a39464..3f51114 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -1,5 +1,7 @@
#!/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.
@@ -609,11 +611,62 @@
[[ -L out/soong/workspace/a/a2.txt ]] || fail "a/a2.txt not symlinked"
}
+function test_bp2build_build_file_precedence {
+ setup
+
+ mkdir -p a
+ touch a/a.txt
+ touch a/BUILD
+ cat > a/Android.bp <<EOF
+filegroup {
+ name: "a",
+ srcs: ["a.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ GENERATE_BAZEL_FILES=1 run_soong
+ [[ -L out/soong/workspace/a/BUILD ]] || fail "BUILD file not symlinked"
+ [[ "$(readlink -f out/soong/workspace/a/BUILD)" =~ bp2build/a/BUILD$ ]] \
+ || fail "BUILD files symlinked to the wrong place"
+}
+
+function test_bp2build_reports_multiple_errors {
+ setup
+
+ mkdir -p a/BUILD
+ touch a/a.txt
+ cat > a/Android.bp <<EOF
+filegroup {
+ name: "a",
+ srcs: ["a.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ mkdir -p b/BUILD
+ touch b/b.txt
+ cat > b/Android.bp <<EOF
+filegroup {
+ name: "b",
+ srcs: ["b.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ if GENERATE_BAZEL_FILES=1 run_soong >& "$MOCK_TOP/errors"; then
+ fail "Build should have failed"
+ fi
+
+ grep -q "a/BUILD' exist" "$MOCK_TOP/errors" || fail "Error for a/BUILD not found"
+ grep -q "b/BUILD' exist" "$MOCK_TOP/errors" || fail "Error for b/BUILD not found"
+}
+
test_smoke
test_null_build
test_null_build_after_docs
test_soong_build_rebuilt_if_blueprint_changes
-# test_glob_noop_incremental # Currently failing
+test_glob_noop_incremental
test_add_file_to_glob
test_add_android_bp
test_change_android_bp
@@ -628,3 +681,5 @@
test_bp2build_add_to_glob
test_bp2build_bazel_workspace_structure
test_bp2build_bazel_workspace_add_file
+test_bp2build_build_file_precedence
+test_bp2build_reports_multiple_errors
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
new file mode 100755
index 0000000..082cd06
--- /dev/null
+++ b/tests/bp2build_bazel_test.sh
@@ -0,0 +1,75 @@
+#!/bin/bash -eu
+
+set -o pipefail
+
+# Test that bp2build and Bazel can play nicely together
+
+source "$(dirname "$0")/lib.sh"
+
+function test_bp2build_generates_all_buildfiles {
+ setup
+ create_mock_bazel
+
+ mkdir -p foo/convertible_soong_module
+ cat > foo/convertible_soong_module/Android.bp <<'EOF'
+genrule {
+ name: "the_answer",
+ cmd: "echo '42' > $(out)",
+ out: [
+ "the_answer.txt",
+ ],
+ bazel_module: {
+ bp2build_available: true,
+ },
+ }
+EOF
+
+ mkdir -p foo/unconvertible_soong_module
+ cat > foo/unconvertible_soong_module/Android.bp <<'EOF'
+genrule {
+ name: "not_the_answer",
+ cmd: "echo '43' > $(out)",
+ out: [
+ "not_the_answer.txt",
+ ],
+ bazel_module: {
+ bp2build_available: false,
+ },
+ }
+EOF
+
+ run_bp2build
+
+ if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/BUILD" ]]; then
+ fail "./out/soong/workspace/foo/convertible_soong_module/BUILD was not generated"
+ fi
+
+ if [[ ! -f "./out/soong/workspace/foo/unconvertible_soong_module/BUILD" ]]; then
+ fail "./out/soong/workspace/foo/unconvertible_soong_module/BUILD was not generated"
+ fi
+
+ if ! grep "the_answer" "./out/soong/workspace/foo/convertible_soong_module/BUILD"; then
+ fail "missing BUILD target the_answer in convertible_soong_module/BUILD"
+ fi
+
+ if grep "not_the_answer" "./out/soong/workspace/foo/unconvertible_soong_module/BUILD"; then
+ fail "found unexpected BUILD target not_the_answer in unconvertible_soong_module/BUILD"
+ fi
+
+ if ! grep "filegroup" "./out/soong/workspace/foo/unconvertible_soong_module/BUILD"; then
+ fail "missing filegroup in unconvertible_soong_module/BUILD"
+ fi
+
+ # NOTE: We don't actually use the extra BUILD file for anything here
+ run_bazel build --package_path=out/soong/workspace //foo/...
+
+ local the_answer_file="bazel-out/k8-fastbuild/bin/foo/convertible_soong_module/the_answer.txt"
+ if [[ ! -f "${the_answer_file}" ]]; then
+ fail "Expected '${the_answer_file}' to be generated, but was missing"
+ fi
+ if ! grep 42 "${the_answer_file}"; then
+ fail "Expected to find 42 in '${the_answer_file}'"
+ fi
+}
+
+test_bp2build_generates_all_buildfiles
diff --git a/tests/lib.sh b/tests/lib.sh
index 3795dfc..e561a3d 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -1,5 +1,7 @@
#!/bin/bash -eu
+set -o pipefail
+
HARDWIRED_MOCK_TOP=
# Uncomment this to be able to view the source tree after a test is run
# HARDWIRED_MOCK_TOP=/tmp/td
@@ -102,7 +104,25 @@
}
function run_soong() {
- build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests
+ build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests "$@"
+}
+
+function create_mock_bazel() {
+ copy_directory build/bazel
+
+ symlink_directory prebuilts/bazel
+ symlink_directory prebuilts/jdk
+
+ symlink_file WORKSPACE
+ symlink_file tools/bazel
+}
+
+run_bazel() {
+ tools/bazel "$@"
+}
+
+run_bp2build() {
+ GENERATE_BAZEL_FILES=true build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests nothing
}
info "Starting Soong integration test suite $(basename $0)"
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index 7dbafea..80774bf 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -1,5 +1,7 @@
#!/bin/bash -eu
+set -o pipefail
+
# This test exercises mixed builds where Soong and Bazel cooperate in building
# Android.
#
@@ -8,21 +10,11 @@
source "$(dirname "$0")/lib.sh"
-function create_mock_bazel() {
- copy_directory build/bazel
-
- symlink_directory prebuilts/bazel
- symlink_directory prebuilts/jdk
-
- symlink_file WORKSPACE
- symlink_file tools/bazel
-}
-
function test_bazel_smoke {
setup
create_mock_bazel
- tools/bazel info
+ run_bazel info
}
test_bazel_smoke
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 76b324b..8399573 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -1,6 +1,8 @@
#!/bin/bash -eu
+set -o pipefail
+
TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/bootstrap_test.sh"
"$TOP/build/soong/tests/mixed_mode_test.sh"
-
+"$TOP/build/soong/tests/bp2build_bazel_test.sh"