bp2build: convert paths/module refs to Bazel label
This currently expands all globs, still need to support converting glob
syntax.
Test: go build_conversion_test
Test: GENERATE_BAZEL_FILES=true m nothing
Test: m nothing
Bug: 165114590
Change-Id: If7b26e8e663d17566fad9614ca87a8da1f095284
diff --git a/android/arch.go b/android/arch.go
index baee9be..90e0485 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -436,7 +436,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
base := module.base()
@@ -576,7 +576,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
base := module.base()
diff --git a/android/filegroup.go b/android/filegroup.go
index 3d1bbc5..7a6cc4f 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -29,7 +29,7 @@
// https://docs.bazel.build/versions/master/be/general.html#filegroup
type bazelFilegroupAttributes struct {
Name *string
- Srcs []string
+ Srcs bazel.LabelList
}
type bazelFilegroup struct {
@@ -52,15 +52,18 @@
// TODO: Create helper functions to avoid this boilerplate.
func FilegroupBp2Build(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(*fileGroup); ok {
- name := "__bp2build__" + m.base().BaseModuleName()
- ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
- Name: proptools.StringPtr(name),
- Srcs: m.properties.Srcs,
- }, &bazel.BazelTargetModuleProperties{
- Rule_class: "filegroup",
- })
+ fg, ok := ctx.Module().(*fileGroup)
+ if !ok {
+ return
}
+
+ name := "__bp2build__" + fg.base().BaseModuleName()
+ ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
+ Name: proptools.StringPtr(name),
+ Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "filegroup",
+ })
}
type fileGroupProperties struct {
diff --git a/android/module.go b/android/module.go
index dcc2b84..1409d44 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2220,10 +2220,17 @@
}
var deps []dep
b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if aModule, _ := module.(Module); aModule != nil {
+ if aModule.base().BaseModuleName() == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, dep{aModule, returnedTag})
+ }
+ }
+ } else if b.bp.OtherModuleName(module) == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(module)
if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
+ deps = append(deps, dep{module, returnedTag})
}
}
})
diff --git a/android/mutator.go b/android/mutator.go
index 6b19dc5..15be65f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -45,14 +45,30 @@
}
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, bp2buildMutators []RegisterMutatorFunc) {
- mctx := ®isterMutatorsContext{}
-
- sharedMutators := []RegisterMutatorFunc{
- RegisterDefaultsPreArchMutators,
+func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+ mctx := ®isterMutatorsContext{
+ bazelConversionMode: true,
}
- for _, f := range sharedMutators {
+ bp2buildPreArchMutators = append([]RegisterMutatorFunc{
+ RegisterNamespaceMutator,
+ RegisterDefaultsPreArchMutators,
+ // TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
+ // evaluate the impact on conversion.
+ RegisterPrebuiltsPreArchMutators,
+ },
+ preArchMutators...)
+
+ for _, f := range bp2buildPreArchMutators {
+ f(mctx)
+ }
+
+ bp2buildDepsMutators = append([]RegisterMutatorFunc{
+ registerDepsMutatorBp2Build,
+ registerPathDepsMutator,
+ }, depsMutators...)
+
+ for _, f := range bp2buildDepsMutators {
f(mctx)
}
@@ -77,7 +93,7 @@
register(preDeps)
- mctx.BottomUp("deps", depsMutator).Parallel()
+ register([]RegisterMutatorFunc{registerDepsMutator})
register(postDeps)
@@ -88,8 +104,9 @@
}
type registerMutatorsContext struct {
- mutators []*mutator
- finalPhase bool
+ mutators []*mutator
+ finalPhase bool
+ bazelConversionMode bool
}
type RegisterMutatorsContext interface {
@@ -211,6 +228,8 @@
finalDeps = append(finalDeps, f)
}
+var bp2buildPreArchMutators = []RegisterMutatorFunc{}
+var bp2buildDepsMutators = []RegisterMutatorFunc{}
var bp2buildMutators = []RegisterMutatorFunc{}
// RegisterBp2BuildMutator registers specially crafted mutators for
@@ -219,13 +238,24 @@
//
// TODO(b/178068862): bring this into TestContext.
func RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- mutatorName := moduleType + "_bp2build"
f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(mutatorName, m)
+ ctx.TopDown(moduleType, m)
}
bp2buildMutators = append(bp2buildMutators, f)
}
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+ bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func DepsBp2BuildMutators(f RegisterMutatorFunc) {
+ bp2buildDepsMutators = append(bp2buildDepsMutators, f)
+}
+
type BaseMutatorContext interface {
BaseModuleContext
@@ -370,32 +400,38 @@
// variant of the current module. The value should not be modified after being passed to
// SetVariationProvider.
SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
+
+ // BazelConversionMode returns whether this mutator is being run as part of Bazel Conversion.
+ BazelConversionMode() bool
}
type bottomUpMutatorContext struct {
bp blueprint.BottomUpMutatorContext
baseModuleContext
- finalPhase bool
+ finalPhase bool
+ bazelConversionMode bool
}
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
- finalPhase bool) BottomUpMutatorContext {
+ finalPhase, bazelConversionMode bool) BottomUpMutatorContext {
return &bottomUpMutatorContext{
- bp: ctx,
- baseModuleContext: a.base().baseModuleContextFactory(ctx),
- finalPhase: finalPhase,
+ bp: ctx,
+ baseModuleContext: a.base().baseModuleContextFactory(ctx),
+ finalPhase: finalPhase,
+ bazelConversionMode: bazelConversionMode,
}
}
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
+ bazelConversionMode := x.bazelConversionMode
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
- m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
+ m(bottomUpMutatorContextFactory(ctx, a, finalPhase, bazelConversionMode))
}
}
- mutator := &mutator{name: name, bottomUpMutator: f}
+ mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
@@ -406,6 +442,13 @@
return mutator
}
+func (x *registerMutatorsContext) mutatorName(name string) string {
+ if x.bazelConversionMode {
+ return name + "_bp2build"
+ }
+ return name
+}
+
func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) MutatorHandle {
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
@@ -416,7 +459,7 @@
m(actx)
}
}
- mutator := &mutator{name: name, topDownMutator: f}
+ mutator := &mutator{name: x.mutatorName(name), topDownMutator: f}
x.mutators = append(x.mutators, mutator)
return mutator
}
@@ -449,6 +492,16 @@
}
}
+func registerDepsMutator(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
+func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) {
+ // TODO(b/179313531): Consider a separate mutator that only runs depsMutator for modules that are
+ // being converted to build targets.
+ ctx.BottomUp("deps", depsMutator).Parallel()
+}
+
func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
for _, p := range props {
err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
@@ -576,12 +629,28 @@
func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
names ...string) []blueprint.Module {
+ if b.bazelConversionMode {
+ _, noSelfDeps := RemoveFromList(b.ModuleName(), names)
+ if len(noSelfDeps) == 0 {
+ return []blueprint.Module(nil)
+ }
+ // In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+ // dependency, the variations would not exist and the dependency could not be added, by
+ // specifying no variations, we will allow adding the dependency to succeed.
+ return b.bp.AddFarVariationDependencies(nil, tag, noSelfDeps...)
+ }
return b.bp.AddVariationDependencies(variations, tag, names...)
}
func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
tag blueprint.DependencyTag, names ...string) []blueprint.Module {
+ if b.bazelConversionMode {
+ // In Bazel conversion mode, mutators should not have created any variants. So, when adding a
+ // dependency, the variations would not exist and the dependency could not be added, by
+ // specifying no variations, we will allow adding the dependency to succeed.
+ return b.bp.AddFarVariationDependencies(nil, tag, names...)
+ }
return b.bp.AddFarVariationDependencies(variations, tag, names...)
}
@@ -609,3 +678,7 @@
func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
b.bp.SetVariationProvider(module, provider, value)
}
+
+func (b *bottomUpMutatorContext) BazelConversionMode() bool {
+ return b.bazelConversionMode
+}
diff --git a/android/paths.go b/android/paths.go
index 8106958..44221be 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -15,6 +15,7 @@
package android
import (
+ "android/soong/bazel"
"fmt"
"io/ioutil"
"os"
@@ -331,6 +332,115 @@
return ret
}
+// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
+// order to form a Bazel-compatible label for conversion.
+type BazelConversionPathContext interface {
+ EarlyModulePathContext
+
+ GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+ OtherModuleName(m blueprint.Module) string
+ OtherModuleDir(m blueprint.Module) string
+}
+
+// BazelLabelForModuleDeps returns a Bazel-compatible label for the requested modules which
+// correspond to dependencies on the module within the given ctx.
+func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
+ var labels bazel.LabelList
+ for _, module := range modules {
+ bpText := module
+ if m := SrcIsModule(module); m == "" {
+ module = ":" + module
+ }
+ if m, t := SrcIsModuleWithTag(module); m != "" {
+ l := getOtherModuleLabel(ctx, m, t)
+ l.Bp_text = bpText
+ labels.Includes = append(labels.Includes, l)
+ } else {
+ ctx.ModuleErrorf("%q, is not a module reference", module)
+ }
+ }
+ return labels
+}
+
+// BazelLabelForModuleSrc returns bazel.LabelList with paths rooted from the module's local source
+// directory. It expands globs, and resolves references to modules using the ":name" syntax to
+// bazel-compatible labels. Properties passed as the paths or excludes argument must have been
+// annotated with struct tag `android:"path"` so that dependencies on other modules will have
+// already been handled by the path_properties mutator.
+func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
+ return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
+}
+
+// BazelLabelForModuleSrcExcludes returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels. Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
+ excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
+ excluded := make([]string, 0, len(excludeLabels.Includes))
+ for _, e := range excludeLabels.Includes {
+ excluded = append(excluded, e.Label)
+ }
+ labels := expandSrcsForBazel(ctx, paths, excluded)
+ labels.Excludes = excludeLabels.Includes
+ return labels
+}
+
+// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local
+// source directory, excluding labels included in the excludes argument. It expands globs, and
+// resolves references to modules using the ":name" syntax to bazel-compatible labels. Properties
+// passed as the paths or excludes argument must have been annotated with struct tag
+// `android:"path"` so that dependencies on other modules will have already been handled by the
+// path_properties mutator.
+func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
+ labels := bazel.LabelList{
+ Includes: []bazel.Label{},
+ }
+ for _, p := range paths {
+ if m, tag := SrcIsModuleWithTag(p); m != "" {
+ l := getOtherModuleLabel(ctx, m, tag)
+ if !InList(l.Label, expandedExcludes) {
+ l.Bp_text = fmt.Sprintf(":%s", m)
+ labels.Includes = append(labels.Includes, l)
+ }
+ } else {
+ var expandedPaths []bazel.Label
+ if pathtools.IsGlob(p) {
+ globbedPaths := GlobFiles(ctx, pathForModuleSrc(ctx, p).String(), expandedExcludes)
+ globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
+ for _, path := range globbedPaths {
+ s := path.Rel()
+ expandedPaths = append(expandedPaths, bazel.Label{Label: s})
+ }
+ } else {
+ if !InList(p, expandedExcludes) {
+ expandedPaths = append(expandedPaths, bazel.Label{Label: p})
+ }
+ }
+ labels.Includes = append(labels.Includes, expandedPaths...)
+ }
+ }
+ return labels
+}
+
+// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
+// module. The label will be relative to the current directory if appropriate. The dependency must
+// already be resolved by either deps mutator or path deps mutator.
+func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
+ m, _ := ctx.GetDirectDep(dep)
+ // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
+ otherModuleName := ctx.OtherModuleName(m)
+ var label bazel.Label
+ if otherDir, dir := ctx.OtherModuleDir(m), ctx.ModuleDir(); otherDir != dir {
+ label.Label = fmt.Sprintf("//%s:%s", otherDir, otherModuleName)
+ } else {
+ label.Label = fmt.Sprintf(":%s", otherModuleName)
+ }
+ return label
+}
+
// OutputPaths is a slice of OutputPath objects, with helpers to operate on the collection.
type OutputPaths []OutputPath
diff --git a/android/register.go b/android/register.go
index 02fc97e..18c743f 100644
--- a/android/register.go
+++ b/android/register.go
@@ -115,7 +115,7 @@
ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
}
- RegisterMutatorsForBazelConversion(ctx.Context, bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
}
// Register the pipeline of singletons, module types, and mutators for
diff --git a/android/testing.go b/android/testing.go
index 5640c29..de338bf 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -56,9 +56,9 @@
type TestContext struct {
*Context
- preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
- bp2buildMutators []RegisterMutatorFunc
- NameResolver *NameResolver
+ preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
+ bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
+ NameResolver *NameResolver
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -85,13 +85,24 @@
// RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
// type to the equivalent Bazel target.
func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- mutatorName := moduleType + "_bp2build"
f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(mutatorName, m)
+ ctx.TopDown(moduleType, m)
}
ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
}
+// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
+// into Bazel BUILD targets that should run prior to deps and conversion.
+func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
+ ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
+}
+
+// DepsBp2BuildMutators adds mutators to be register for converting Android Blueprint modules into
+// Bazel BUILD targets that should run prior to conversion to resolve dependencies.
+func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
+ ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
+}
+
func (ctx *TestContext) Register() {
registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
@@ -100,7 +111,7 @@
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {