create, but dont register, bp2build_deps mutator
This is the bulk of the "allowlist v2" feature. It will disable bp2build
generation for modules which have transitive dependencies without a
bazel build definition.
This CL includes this mutator, but doesn't register it as a bp2build
mutator (outside of a few unit tests). This allows us to easily iterate
on completion of this feature and ensure there are no launch blockers
before we finalize the change in AOSP.
Bug: 285631638
Test: Unit tests
Change-Id: Ifb0a079c409ca19b02cafa3fab2efa0d3deebc50
diff --git a/android/api_domain.go b/android/api_domain.go
index 0603c70..38f48e3 100644
--- a/android/api_domain.go
+++ b/android/api_domain.go
@@ -14,12 +14,6 @@
package android
-import (
- "github.com/google/blueprint"
-
- "android/soong/bazel"
-)
-
func init() {
RegisterApiDomainBuildComponents(InitRegistrationContext)
}
@@ -97,13 +91,3 @@
func ApiContributionTargetName(moduleName string) string {
return moduleName + apiContributionSuffix
}
-
-// For each contributing cc_library, format the name to its corresponding contribution bazel target in the bp2build workspace
-func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []string) bazel.LabelListAttribute {
- addSuffix := func(ctx BazelConversionPathContext, module blueprint.Module) string {
- baseLabel := BazelModuleLabel(ctx, module)
- return ApiContributionTargetName(baseLabel)
- }
- bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix)
- return bazel.MakeLabelListAttribute(bazelLabels)
-}
diff --git a/android/bazel.go b/android/bazel.go
index 5df12f0..e307b18 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -625,7 +625,18 @@
ctx.BottomUp("bp2build_conversion", bp2buildConversionMutator).Parallel()
}
+func registerBp2buildDepsMutator(ctx RegisterMutatorsContext) {
+ ctx.BottomUp("bp2build_deps", bp2buildDepsMutator).Parallel()
+}
+
func bp2buildConversionMutator(ctx BottomUpMutatorContext) {
+ // If an existing BUILD file in the module directory has a target defined
+ // with this same name as this module, assume that this is an existing
+ // definition for this target.
+ if ctx.Config().HasBazelBuildTargetInSource(ctx.ModuleDir(), ctx.ModuleName()) {
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, ctx.ModuleName())
+ return
+ }
bModule, ok := ctx.Module().(Bazelable)
if !ok {
ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
@@ -659,6 +670,10 @@
panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
}
+ // If an existing BUILD file in the module directory has a target defined
+ // with the same name as any target generated by this module, assume that this
+ // is an existing definition for this target. (These generated target names
+ // may be different than the module name, as checked at the beginning of this function!)
for _, targetInfo := range ctx.Module().base().Bp2buildTargets() {
if ctx.Config().HasBazelBuildTargetInSource(targetInfo.TargetPackage(), targetInfo.TargetName()) {
// Defer to the BUILD target. Generating an additional target would
@@ -669,6 +684,27 @@
}
}
+// TODO: b/285631638 - Add this as a new mutator to the bp2build conversion mutators.
+// Currently, this only exists to prepare test coverage for the launch of this feature.
+func bp2buildDepsMutator(ctx BottomUpMutatorContext) {
+ if ctx.Module().base().GetUnconvertedReason() != nil {
+ return
+ }
+
+ if len(ctx.Module().GetMissingBp2buildDeps()) > 0 {
+ exampleDep := ctx.Module().GetMissingBp2buildDeps()[0]
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, exampleDep)
+ }
+
+ ctx.VisitDirectDeps(func(dep Module) {
+ if dep.base().GetUnconvertedReason() != nil &&
+ dep.base().GetUnconvertedReason().ReasonType != int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE) &&
+ ctx.OtherModuleDependencyTag(dep) == Bp2buildDepTag {
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNCONVERTED_DEP, dep.Name())
+ }
+ })
+}
+
// GetMainClassInManifest scans the manifest file specified in filepath and returns
// the value of attribute Main-Class in the manifest file if it exists, or returns error.
// WARNING: this is for bp2build converters of java_* modules only.
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index d8effaa..d85ce4b 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -101,8 +101,8 @@
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
// module within the given ctx.
-func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
- return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel)
+func BazelLabelForModuleDeps(ctx Bp2buildMutatorContext, modules []string) bazel.LabelList {
+ return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel, true)
}
// BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
@@ -111,15 +111,16 @@
// list which corresponds to dependencies on the module within the given ctx, and the excluded
// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
// whole static libraries.
-func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+func BazelLabelForModuleDepsExcludes(ctx Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
return BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, BazelModuleLabel)
}
// BazelLabelForModuleDepsWithFn expects a list of reference to other modules, ("<module>"
// or ":<module>") and applies moduleToLabelFn to determine and return a Bazel-compatible label
// which corresponds to dependencies on the module within the given ctx.
-func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []string,
- moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
+func BazelLabelForModuleDepsWithFn(ctx Bp2buildMutatorContext, modules []string,
+ moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string,
+ markAsDeps bool) bazel.LabelList {
var labels bazel.LabelList
// In some cases, a nil string list is different than an explicitly empty list.
if len(modules) == 0 && modules != nil {
@@ -133,7 +134,7 @@
module = ":" + module
}
if m, t := SrcIsModuleWithTag(module); m != "" {
- l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn)
+ l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn, markAsDeps)
if l != nil {
l.OriginalModuleName = bpText
labels.Includes = append(labels.Includes, *l)
@@ -150,27 +151,27 @@
// to other modules, ("<module>" or ":<module>"). It applies moduleToLabelFn to determine and return a
// Bazel-compatible label list which corresponds to dependencies on the module within the given ctx, and
// the excluded dependencies.
-func BazelLabelForModuleDepsExcludesWithFn(ctx BazelConversionPathContext, modules, excludes []string,
+func BazelLabelForModuleDepsExcludesWithFn(ctx Bp2buildMutatorContext, modules, excludes []string,
moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
- moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn)
+ moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn, true)
if len(excludes) == 0 {
return moduleLabels
}
- excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn)
+ excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn, false)
return bazel.LabelList{
Includes: moduleLabels.Includes,
Excludes: excludeLabels.Includes,
}
}
-func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
+func BazelLabelForModuleSrcSingle(ctx Bp2buildMutatorContext, path string) bazel.Label {
if srcs := BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
return srcs[0]
}
return bazel.Label{}
}
-func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) bazel.Label {
+func BazelLabelForModuleDepSingle(ctx Bp2buildMutatorContext, path string) bazel.Label {
if srcs := BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
return srcs[0]
}
@@ -183,7 +184,7 @@
// relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
+func BazelLabelForModuleSrc(ctx Bp2buildMutatorContext, paths []string) bazel.LabelList {
return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
}
@@ -193,13 +194,13 @@
// (absolute if in a different package or relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
- excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
+func BazelLabelForModuleSrcExcludes(ctx Bp2buildMutatorContext, paths, excludes []string) bazel.LabelList {
+ excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil), false)
excluded := make([]string, 0, len(excludeLabels.Includes))
for _, e := range excludeLabels.Includes {
excluded = append(excluded, e.Label)
}
- labels := expandSrcsForBazel(ctx, paths, excluded)
+ labels := expandSrcsForBazel(ctx, paths, excluded, true)
labels.Excludes = excludeLabels.Includes
labels = TransformSubpackagePaths(ctx.Config(), ctx.ModuleDir(), labels)
return labels
@@ -352,6 +353,12 @@
return newPaths
}
+var Bp2buildDepTag bp2buildDepTag
+
+type bp2buildDepTag struct {
+ blueprint.BaseDependencyTag
+}
+
// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local source
// directory and Bazel target labels, excluding those included in the excludes argument (which
// should already be expanded to resolve references to Soong-modules). Valid elements of paths
@@ -374,7 +381,7 @@
// 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
// pathdeps mutator.
-func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
+func expandSrcsForBazel(ctx Bp2buildMutatorContext, paths, expandedExcludes []string, markAsDeps bool) bazel.LabelList {
if paths == nil {
return bazel.LabelList{}
}
@@ -391,7 +398,7 @@
for _, p := range paths {
if m, tag := SrcIsModuleWithTag(p); m != "" {
- l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel)
+ l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel, markAsDeps)
if l != nil && !InList(l.Label, expandedExcludes) {
if strings.HasPrefix(m, "//") {
// this is a module in a soong namespace
@@ -423,8 +430,9 @@
// 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,
- labelFromModule func(BazelConversionPathContext, blueprint.Module) string) *bazel.Label {
+func getOtherModuleLabel(ctx Bp2buildMutatorContext, dep, tag string,
+ labelFromModule func(BazelConversionPathContext, blueprint.Module) string,
+ markAsDep bool) *bazel.Label {
m, _ := ctx.ModuleFromName(dep)
// The module was not found in an Android.bp file, this is often due to:
// * a limited manifest
@@ -435,6 +443,13 @@
Label: ":" + dep + "__BP2BUILD__MISSING__DEP",
}
}
+ if markAsDep {
+ // Don't count dependencies of "libc". This is a hack to circumvent the
+ // fact that, in a variantless build graph, "libc" has a dependency on itself.
+ if ctx.ModuleName() != "libc" {
+ ctx.AddDependency(ctx.Module(), Bp2buildDepTag, dep)
+ }
+ }
if !convertedToBazel(ctx, m) {
ctx.AddUnconvertedBp2buildDep(dep)
}
diff --git a/android/config.go b/android/config.go
index b3ff86b..e5db9b1 100644
--- a/android/config.go
+++ b/android/config.go
@@ -297,6 +297,10 @@
// in tests when a path doesn't exist.
TestAllowNonExistentPaths bool
+ // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
+ // in tests when a path doesn't exist.
+ Bp2buildDepsMutator bool
+
// The list of files that when changed, must invalidate soong_build to
// regenerate build.ninja.
ninjaFileDepsSet sync.Map
diff --git a/android/mutator.go b/android/mutator.go
index 57ff1e0..3d59655 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -35,6 +35,9 @@
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
+ if ctx.config.Bp2buildDepsMutator {
+ bp2buildMutators = append(bp2buildMutators, registerBp2buildDepsMutator)
+ }
registerMutatorsForBazelConversion(ctx, bp2buildMutators)
}
@@ -226,6 +229,15 @@
BazelConversionPathContext
BaseMutatorContext
+ // AddDependency adds a dependency to the given module. It returns a slice of modules for each
+ // dependency (some entries may be nil).
+ //
+ // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
+ // new dependencies have had the current mutator called on them. If the mutator is not
+ // parallel this method does not affect the ordering of the current mutator pass, but will
+ // be ordered correctly for all future mutator passes.
+ AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
+
// CreateBazelTargetModule creates a BazelTargetModule by calling the
// factory method, just like in CreateModule, but also requires
// BazelTargetModuleProperties containing additional metadata for the
@@ -294,15 +306,6 @@
BaseMutatorContext
Bp2buildMutatorContext
- // AddDependency adds a dependency to the given module. It returns a slice of modules for each
- // dependency (some entries may be nil).
- //
- // If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
- // new dependencies have had the current mutator called on them. If the mutator is not
- // parallel this method does not affect the ordering of the current mutator pass, but will
- // be ordered correctly for all future mutator passes.
- AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
-
// AddReverseDependency adds a dependency from the destination to the given module.
// Does not affect the ordering of the current mutator pass, but will be ordered
// correctly for all future mutator passes. All reverse dependencies for a destination module are
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index afbfffa..dc56a17 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -2101,3 +2101,219 @@
})
}
+
+func TestBp2buildDepsMutator_missingTransitiveDep(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ }
+
+ custom {
+ name: "has_deps",
+ arch_paths: [":has_missing_dep", ":foo"],
+ }
+
+ custom {
+ name: "has_missing_dep",
+ arch_paths: [":missing"],
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "custom",
+ "foo",
+ AttrNameToString{},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Skipping conversion of a target with missing transitive dep",
+ DepsMutator: true,
+ })
+}
+
+func TestBp2buildDepsMutator_missingDirectDep(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ arch_paths: [":exists"],
+ }
+ custom {
+ name: "exists",
+ }
+
+ custom {
+ name: "has_missing_dep",
+ arch_paths: [":missing"],
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "custom",
+ "foo",
+ AttrNameToString{"arch_paths": `[":exists"]`},
+ ),
+ MakeBazelTarget(
+ "custom",
+ "exists",
+ AttrNameToString{},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Skipping conversion of a target with missing direct dep",
+ DepsMutator: true,
+ })
+}
+
+func TestBp2buildDepsMutator_unconvertedDirectDep(t *testing.T) {
+ bp := `
+ custom {
+ name: "has_unconverted_dep",
+ arch_paths: [":unconvertible"],
+ }
+
+ custom {
+ name: "unconvertible",
+ does_not_convert_to_bazel: true
+ }
+ `
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{},
+ Description: "Skipping conversion of a target with unconverted direct dep",
+ DepsMutator: true,
+ })
+}
+
+func TestBp2buildDepsMutator_unconvertedTransitiveDep(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ arch_paths: [":has_unconverted_dep", ":bar"],
+ }
+
+ custom {
+ name: "bar",
+ }
+
+ custom {
+ name: "has_unconverted_dep",
+ arch_paths: [":unconvertible"],
+ }
+
+ custom {
+ name: "unconvertible",
+ does_not_convert_to_bazel: true
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "custom",
+ "bar",
+ AttrNameToString{},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Skipping conversion of a target with unconverted transitive dep",
+ DepsMutator: true,
+ })
+}
+
+func TestBp2buildDepsMutator_alreadyExistsBuildDeps(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ arch_paths: [":bar"],
+ }
+ custom {
+ name: "bar",
+ arch_paths: [":checked_in"],
+ }
+ custom {
+ name: "checked_in",
+ arch_paths: [":checked_in"],
+ does_not_convert_to_bazel: true
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "custom",
+ "foo",
+ AttrNameToString{"arch_paths": `[":bar"]`},
+ ),
+ MakeBazelTarget(
+ "custom",
+ "bar",
+ AttrNameToString{"arch_paths": `[":checked_in"]`},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ StubbedBuildDefinitions: []string{"checked_in"},
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Convert target with already-existing build dep",
+ DepsMutator: true,
+ })
+}
+
+// Tests that deps of libc are always considered valid for libc. This circumvents
+// an issue that, in a variantless graph (such as bp2build's), libc has the
+// unique predicament that it depends on itself.
+func TestBp2buildDepsMutator_depOnLibc(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ arch_paths: [":libc"],
+ }
+ custom {
+ name: "libc",
+ arch_paths: [":libc_dep"],
+ }
+ custom {
+ name: "libc_dep",
+ does_not_convert_to_bazel: true
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "custom",
+ "foo",
+ AttrNameToString{"arch_paths": `[":libc"]`},
+ ),
+ MakeBazelTarget(
+ "custom",
+ "libc",
+ AttrNameToString{"arch_paths": `[":libc_dep"]`},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ StubbedBuildDefinitions: []string{"checked_in"},
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Convert target with dep on libc",
+ DepsMutator: true,
+ })
+}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 402d4b0..645298f 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -95,6 +95,7 @@
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
"dir": attr.string(),
+ "does_not_convert_to_bazel": attr.bool(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
@@ -128,6 +129,7 @@
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
"dir": attr.string(),
+ "does_not_convert_to_bazel": attr.bool(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
@@ -161,6 +163,7 @@
"bool_prop": attr.bool(),
"bool_ptr_prop": attr.bool(),
"dir": attr.string(),
+ "does_not_convert_to_bazel": attr.bool(),
"embedded_prop": attr.string(),
"int64_ptr_prop": attr.int(),
# nested_props start
diff --git a/bp2build/testing.go b/bp2build/testing.go
index d26b346..6907487 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -124,25 +124,37 @@
// be merged with the generated BUILD file. This allows custom BUILD targets
// to be used in tests, or use BUILD files to draw package boundaries.
KeepBuildFileForDirs []string
+
+ // If true, the bp2build_deps mutator is used for this test. This is an
+ // experimental mutator that will disable modules which have transitive
+ // dependencies with no bazel definition.
+ // TODO: b/285631638 - Enable this feature by default.
+ DepsMutator bool
}
func RunBp2BuildTestCaseExtraContext(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), modifyContext func(ctx *android.TestContext), tc Bp2buildTestCase) {
t.Helper()
- bp2buildSetup := android.GroupFixturePreparers(
+ preparers := []android.FixturePreparer{
android.FixtureRegisterWithContext(registerModuleTypes),
- android.FixtureModifyContext(modifyContext),
- SetBp2BuildTestRunner,
+ }
+ if modifyContext != nil {
+ preparers = append(preparers, android.FixtureModifyContext(modifyContext))
+ }
+ if tc.DepsMutator {
+ preparers = append(preparers, android.FixtureModifyConfig(func(cfg android.Config) {
+ cfg.Bp2buildDepsMutator = true
+ }))
+ }
+ preparers = append(preparers, SetBp2BuildTestRunner)
+ bp2buildSetup := android.GroupFixturePreparers(
+ preparers...,
)
runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
}
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
t.Helper()
- bp2buildSetup := android.GroupFixturePreparers(
- android.FixtureRegisterWithContext(registerModuleTypes),
- SetBp2BuildTestRunner,
- )
- runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
+ RunBp2BuildTestCaseExtraContext(t, registerModuleTypes, nil, tc)
}
func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
@@ -400,6 +412,10 @@
// Prop used to indicate this conversion should be 1 module -> multiple targets
One_to_many_prop *bool
+ // Prop used to simulate an unsupported property in bp2build conversion. If this
+ // is true, this module should be treated as "unconvertible" via bp2build.
+ Does_not_convert_to_bazel *bool
+
Api *string // File describing the APIs of this module
Test_config_setting *bool // Used to test generation of config_setting targets
@@ -535,6 +551,10 @@
}
func (m *customModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
+ if p := m.props.Does_not_convert_to_bazel; p != nil && *p {
+ ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "")
+ return
+ }
if p := m.props.One_to_many_prop; p != nil && *p {
customBp2buildOneToMany(ctx, m)
return
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 7738487..45fbf27 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -99,7 +99,7 @@
Tidy_timeout_srcs bazel.LabelListAttribute
}
-func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) {
+func (m *Module) convertTidyAttributes(ctx android.Bp2buildMutatorContext, moduleAttrs *tidyAttributes) {
for _, f := range m.features {
if tidy, ok := f.(*tidyFeature); ok {
var tidyAttr *string
@@ -246,9 +246,9 @@
implementation bazel.LabelList
}
-type bazelLabelForDepsFn func(android.BazelConversionPathContext, []string) bazel.LabelList
+type bazelLabelForDepsFn func(android.Bp2buildMutatorContext, []string) bazel.LabelList
-func maybePartitionExportedAndImplementationsDeps(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
+func maybePartitionExportedAndImplementationsDeps(ctx android.Bp2buildMutatorContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
if !exportsDeps {
return depsPartition{
implementation: fn(ctx, allDeps),
@@ -263,9 +263,9 @@
}
}
-type bazelLabelForDepsExcludesFn func(android.BazelConversionPathContext, []string, []string) bazel.LabelList
+type bazelLabelForDepsExcludesFn func(android.Bp2buildMutatorContext, []string, []string) bazel.LabelList
-func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
+func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.Bp2buildMutatorContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
if !exportsDeps {
return depsPartition{
implementation: fn(ctx, allDeps, excludes),
@@ -352,7 +352,7 @@
Enabled bazel.BoolAttribute
}
-func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) {
+func parseSrc(ctx android.Bp2buildMutatorContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) {
srcFileError := func() {
ctx.ModuleErrorf("parseSrc: Expected at most one source file for %s %s\n", axis, config)
}
@@ -370,7 +370,7 @@
}
// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
-func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) prebuiltAttributes {
+func Bp2BuildParsePrebuiltLibraryProps(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) prebuiltAttributes {
var srcLabelAttribute bazel.LabelAttribute
bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
@@ -407,7 +407,7 @@
}
}
-func bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+func bp2BuildParsePrebuiltBinaryProps(ctx android.Bp2buildMutatorContext, module *Module) prebuiltAttributes {
var srcLabelAttribute bazel.LabelAttribute
bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if props, ok := props.(*prebuiltLinkerProperties); ok {
@@ -420,7 +420,7 @@
}
}
-func bp2BuildParsePrebuiltObjectProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+func bp2BuildParsePrebuiltObjectProps(ctx android.Bp2buildMutatorContext, module *Module) prebuiltAttributes {
var srcLabelAttribute bazel.LabelAttribute
bp2BuildPropParseHelper(ctx, module, &prebuiltObjectProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if props, ok := props.(*prebuiltObjectProperties); ok {
@@ -555,7 +555,7 @@
return result
}
-func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
+func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.Bp2buildMutatorContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
srcsList, ok := parseSrcs(ctx, props)
@@ -680,7 +680,7 @@
}
// Parse srcs from an arch or OS's props value.
-func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
+func parseSrcs(ctx android.Bp2buildMutatorContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
anySrcs := false
// Add srcs-like dependencies such as generated files.
// First create a LabelList containing these dependencies, then merge the values with srcs.
@@ -1265,7 +1265,7 @@
// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant
// since all libs are already excluded by default
-func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, props *BaseLinkerProperties) {
+func (la *linkerAttributes) resolveTargetApexProp(ctx android.Bp2buildMutatorContext, props *BaseLinkerProperties) {
excludeSharedLibs := bazelLabelForSharedDeps(ctx, props.Target.Apex.Exclude_shared_libs)
sharedExcludes := bazel.LabelList{Excludes: excludeSharedLibs.Includes}
sharedExcludesLabelList := bazel.LabelListAttribute{}
@@ -1696,7 +1696,7 @@
})
}
-func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
+func (la *linkerAttributes) convertProductVariables(ctx android.Bp2buildMutatorContext, productVariableProps android.ProductConfigProperties) {
type productVarDep struct {
// the name of the corresponding excludes field, if one exists
@@ -1704,7 +1704,7 @@
// reference to the bazel attribute that should be set for the given product variable config
attribute *bazel.LabelListAttribute
- depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
+ depResolutionFunc func(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList
}
// an intermediate attribute that holds Header_libs info, and will be appended to
@@ -1762,7 +1762,7 @@
la.implementationDeps.Append(headerDeps)
}
-func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
+func (la *linkerAttributes) finalize(ctx android.Bp2buildMutatorContext) {
// if system dynamic deps have the default value, any use of a system dynamic library used will
// result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries
// from bionic OSes and the no config case as these libraries only build for bionic OSes.
@@ -1903,39 +1903,39 @@
return xsd.CppBp2buildTargetName()
}
-func bazelLabelForWholeDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps)
+func bazelLabelForWholeDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps, true)
}
-func bazelLabelForWholeDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForWholeDepsExcludes(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps)
}
-func bazelLabelForStaticDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForStaticDepsExcludes(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule)
}
-func bazelLabelForStaticDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule)
+func bazelLabelForStaticDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule, true)
}
-func bazelLabelForSharedDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule)
+func bazelLabelForSharedDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule, true)
}
-func bazelLabelForHeaderDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
+func bazelLabelForHeaderDeps(ctx android.Bp2buildMutatorContext, modules []string) bazel.LabelList {
// This is not elegant, but bp2build's shared library targets only propagate
// their header information as part of the normal C++ provider.
return bazelLabelForSharedDeps(ctx, modules)
}
-func bazelLabelForHeaderDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForHeaderDepsExcludes(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
// This is only used when product_variable header_libs is processed, to follow
// the pattern of depResolutionFunc
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
}
-func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+func bazelLabelForSharedDepsExcludes(ctx android.Bp2buildMutatorContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
}
diff --git a/cc/library.go b/cc/library.go
index e66ce08..90d91ca 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -547,54 +547,6 @@
includes.attrs.Deps.Append(lla)
}
-// includes provided to the module-lib API surface. This API surface is used by apexes.
-func getModuleLibApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
- flagProps := c.library.(*libraryDecorator).flagExporter.Properties
- linkProps := c.library.(*libraryDecorator).baseLinker.Properties
- includes := android.FirstUniqueStrings(flagProps.Export_include_dirs)
- systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs)
- headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers)
- attrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(includes),
- Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
- Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)),
- }
-
- return apiIncludes{
- name: c.Name() + ".module-libapi.headers",
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: attrs,
- },
- }
-}
-
-func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
- baseProps := c.library.(*libraryDecorator).flagExporter.Properties
- llndkProps := c.library.(*libraryDecorator).Properties.Llndk
- includes := baseProps.Export_include_dirs
- systemIncludes := baseProps.Export_system_include_dirs
- // LLNDK can override the base includes
- if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil {
- includes = llndkIncludes
- }
- if proptools.Bool(llndkProps.Export_headers_as_system) {
- systemIncludes = append(systemIncludes, includes...)
- includes = nil
- }
-
- attrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(includes),
- Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
- Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)),
- }
- return apiIncludes{
- name: c.Name() + ".vendorapi.headers",
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: attrs,
- },
- }
-}
-
// cc_library creates both static and/or shared libraries for a device and/or
// host. By default, a cc_library has a single variant that targets the device.
// Specifying `host_supported: true` also creates a library that targets the
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 56c57b9..3a84174 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -580,15 +580,6 @@
Library_name string
}
-// Names of the cc_api_header targets in the bp2build workspace
-func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList {
- addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string {
- label := android.BazelModuleLabel(ctx, module)
- return android.ApiContributionTargetName(label)
- }
- return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
-}
-
func ndkLibraryBp2build(ctx android.Bp2buildMutatorContext, c *Module) {
ndk, _ := c.linker.(*stubDecorator)
props := bazel.BazelTargetModuleProperties{
diff --git a/cc/test.go b/cc/test.go
index 8c63dc6..f128187 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -799,7 +799,7 @@
// cc_test that builds using gtest needs some additional deps
// addImplicitGtestDeps makes these deps explicit in the generated BUILD files
-func addImplicitGtestDeps(ctx android.BazelConversionPathContext, attrs *testBinaryAttributes, gtest, gtestIsolated bool) {
+func addImplicitGtestDeps(ctx android.Bp2buildMutatorContext, attrs *testBinaryAttributes, gtest, gtestIsolated bool) {
addDepsAndDedupe := func(lla *bazel.LabelListAttribute, modules []string) {
moduleLabels := android.BazelLabelForModuleDeps(ctx, modules)
lla.Value.Append(moduleLabels)