Merge "Read BUILD files in bp2build" am: 01f8784246

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2617569

Change-Id: I890438dbb170523db0b6379e2c2f27e9b83e7f4c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Treehugger Robot
2023-06-09 23:26:54 +00:00
committed by Automerger Merge Worker
5 changed files with 126 additions and 3 deletions

View File

@@ -461,6 +461,9 @@ var (
// TODO(b/266459895): remove this and the placeholder BUILD file after re-enabling libunwindstack
"external/rust/crates/rustc-demangle-capi":/* recursive = */ false,
// Used for testing purposes only. Should not actually exist in the real source tree.
"testpkg/keep_build_file":/* recursive = */ false,
}
Bp2buildModuleAlwaysConvertList = []string{
@@ -845,9 +848,6 @@ var (
"libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
"bouncycastle", // TODO(b/274474005): Need support for custom system_modules.
// python protos
"libprotobuf-python", // Has a handcrafted alternative
// genrule incompatibilities
"brotli-fuzzer-corpus", // TODO(b/202015218): outputs are in location incompatible with bazel genrule handling.
"platform_tools_properties", "build_tools_source_properties", // TODO(b/203369847): multiple genrules in the same package creating the same file

View File

@@ -537,6 +537,12 @@ func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
}
func convertWithBp2build(ctx TopDownMutatorContext) {
if ctx.Config().HasBazelBuildTargetInSource(ctx) {
// Defer to the BUILD target. Generating an additional target would
// cause a BUILD file conflict.
return
}
bModule, ok := ctx.Module().(Bazelable)
if !ok || !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
return

View File

@@ -291,6 +291,10 @@ type config struct {
// "--bazel-force-enabled-modules"
bazelForceEnabledModules map[string]struct{}
// Names of Bazel targets as defined by BUILD files in the source tree,
// keyed by the directory in which they are defined.
bazelTargetsByDir map[string][]string
// If true, for any requests to Bazel, communicate with a Bazel proxy using
// unix sockets, instead of spawning Bazel as a subprocess.
UseBazelProxy bool
@@ -2002,6 +2006,20 @@ func (c *config) LogMixedBuild(ctx BaseModuleContext, useBazel bool) {
}
}
func (c *config) HasBazelBuildTargetInSource(ctx BaseModuleContext) bool {
moduleName := ctx.Module().Name()
for _, buildTarget := range c.bazelTargetsByDir[ctx.ModuleDir()] {
if moduleName == buildTarget {
return true
}
}
return false
}
func (c *config) SetBazelBuildFileTargets(bazelTargetsByDir map[string][]string) {
c.bazelTargetsByDir = bazelTargetsByDir
}
// ApiSurfaces directory returns the source path inside the api_surfaces repo
// (relative to workspace root).
func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"time"
@@ -762,6 +763,43 @@ func excludedFromSymlinkForest(ctx *android.Context, verbose bool) []string {
return excluded
}
// buildTargetsByPackage parses Bazel BUILD.bazel and BUILD files under
// the workspace, and returns a map containing names of Bazel targets defined in
// these BUILD files.
// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist.
func buildTargetsByPackage(ctx *android.Context) map[string][]string {
existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
maybeQuit(err, "Error determining existing Bazel-related files")
result := map[string][]string{}
// Search for instances of `name = "$NAME"` (with arbitrary spacing).
targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`)
for _, path := range existingBazelFiles {
if !ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
continue
}
fullPath := shared.JoinPath(topDir, path)
sourceDir := filepath.Dir(path)
fileInfo, err := os.Stat(fullPath)
maybeQuit(err, "Error accessing Bazel file '%s'", fullPath)
if !fileInfo.IsDir() &&
(fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") {
// Process this BUILD file.
buildFileContent, err := os.ReadFile(fullPath)
maybeQuit(err, "Error reading Bazel file '%s'", fullPath)
matches := targetNameRegex.FindAllStringSubmatch(string(buildFileContent), -1)
for _, match := range matches {
result[sourceDir] = append(result[sourceDir], match[1])
}
}
}
return result
}
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
@@ -769,6 +807,10 @@ func runBp2Build(ctx *android.Context, extraNinjaDeps []string, metricsDir strin
var codegenMetrics *bp2build.CodegenMetrics
ctx.EventHandler.Do("bp2build", func() {
ctx.EventHandler.Do("read_build", func() {
ctx.Config().SetBazelBuildFileTargets(buildTargetsByPackage(ctx))
})
// Propagate "allow misssing dependencies" bit. This is normally set in
// newContext(), but we create ctx without calling that method.
ctx.SetAllowMissingDependencies(ctx.Config().AllowMissingDependencies())

View File

@@ -232,6 +232,63 @@ function test_bp2build_generates_all_buildfiles {
eval "${_save_trap}"
}
function test_build_files_take_precedence {
_save_trap=$(trap -p EXIT)
trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
_build_files_take_precedence
eval "${_save_trap}"
}
function _build_files_take_precedence {
setup
# This specific directory is hardcoded in bp2build as being one
# where the BUILD file should be intentionally kept.
mkdir -p testpkg/keep_build_file
cat > testpkg/keep_build_file/Android.bp <<'EOF'
genrule {
name: "print_origin",
cmd: "echo 'from_soong' > $(out)",
out: [
"origin.txt",
],
bazel_module: {
bp2build_available: true,
},
}
EOF
run_soong bp2build
run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
local -r output_file="$(find -L bazel-out -name origin.txt)"
if [[ ! -f "${output_file}" ]]; then
fail "Expected origin.txt to be generated, but was missing"
fi
if ! grep from_soong "${output_file}"; then
fail "Expected to find 'from_soong' in '${output_file}'"
fi
cat > testpkg/keep_build_file/BUILD.bazel <<'EOF'
genrule(
name = "print_origin",
outs = ["origin.txt"],
cmd = "echo 'from_bazel' > $@",
)
EOF
# Clean the workspace. There is a test infrastructure bug where run_bazel
# will symlink Android.bp files in the source directory again and thus
# pollute the workspace.
# TODO: b/286059878 - Remove this clean after the underlying bug is fixed.
run_soong clean
run_soong bp2build
run_bazel build --config=android --config=bp2build --config=ci //testpkg/keep_build_file:print_origin
if ! grep from_bazel "${output_file}"; then
fail "Expected to find 'from_bazel' in '${output_file}'"
fi
}
function test_bp2build_symlinks_files {
setup
mkdir -p foo