diff --git a/android/api_domain.go b/android/api_domain.go index 0603c7016..38f48e3d4 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 @@ const ( 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 5df12f02e..e307b18d2 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -625,7 +625,18 @@ func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) { 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 @@ func bp2buildConversionMutator(ctx BottomUpMutatorContext) { 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 @@ func bp2buildConversionMutator(ctx BottomUpMutatorContext) { } } +// 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 09580a762..a554775fb 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -102,8 +102,8 @@ type BazelConversionPathContext interface { // BazelLabelForModuleDeps expects a list of reference to other modules, ("" // or ":") 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 @@ -112,15 +112,16 @@ func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) b // 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, ("" // or ":") 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 { @@ -134,7 +135,7 @@ func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []str 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) @@ -151,27 +152,27 @@ func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []str // to other modules, ("" or ":"). 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] } @@ -184,7 +185,7 @@ func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) b // 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)) } @@ -194,13 +195,13 @@ func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) baze // (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 @@ -361,6 +362,12 @@ func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []ba 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 @@ -383,7 +390,7 @@ func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []ba // 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{} } @@ -400,7 +407,7 @@ func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes 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 @@ -432,8 +439,9 @@ func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes // 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 @@ -444,6 +452,13 @@ func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string, 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 7cff81e7d..622a672ca 100644 --- a/android/config.go +++ b/android/config.go @@ -297,6 +297,10 @@ type config struct { // 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 57ff1e092..3d596554d 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -35,6 +35,9 @@ import ( // 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 @@ type Bp2buildMutatorContext interface { 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 @@ type BottomUpMutatorContext interface { 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 afbfffacc..dc56a17b0 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -2101,3 +2101,219 @@ func TestCreateBazelTargetInDifferentDir(t *testing.T) { }) } + +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 402d4b013..645298f15 100644 --- a/bp2build/bzl_conversion_test.go +++ b/bp2build/bzl_conversion_test.go @@ -95,6 +95,7 @@ custom = rule( "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 @@ custom_defaults = rule( "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 @@ custom_test_ = rule( "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 d26b346dd..690748756 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -124,25 +124,37 @@ type Bp2buildTestCase struct { // 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 @@ type customProps struct { // 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) dir() *string { } 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 7738487db..45fbf278a 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -99,7 +99,7 @@ type tidyAttributes struct { 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 @@ type depsPartition struct { 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 @@ func maybePartitionExportedAndImplementationsDeps(ctx android.BazelConversionPat } } -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 @@ type prebuiltAttributes struct { 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 @@ func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.L } // 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 Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, m } } -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 bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, mo } } -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 @@ func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []stri 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 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i } // 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 @@ var ( // 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) convertStripProps(ctx android.BazelConversionPathCon }) } -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 @@ func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionP // 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 @@ func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionP 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 @@ func xsdConfigCppTarget(xsd android.XsdConfigBp2buildTargets) string { 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 e66ce08e6..90d91ca0e 100644 --- a/cc/library.go +++ b/cc/library.go @@ -547,54 +547,6 @@ func (includes *apiIncludes) addDep(name string) { 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 56c57b94c..3a8417461 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -580,15 +580,6 @@ type bazelCcApiContributionAttributes struct { 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 8c63dc614..f128187d2 100644 --- a/cc/test.go +++ b/cc/test.go @@ -799,7 +799,7 @@ func testBinaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { // 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)