Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f1b3c7a authored by Chris Parsons's avatar Chris Parsons
Browse files

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
parent dec9ce66
Loading
Loading
Loading
Loading
+0 −16
Original line number Diff line number Diff line
@@ -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)
}
+36 −0
Original line number Diff line number Diff line
@@ -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.
+34 −19
Original line number Diff line number Diff line
@@ -101,8 +101,8 @@ type BazelConversionPathContext interface {
// 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 @@ 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, ("<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 @@ 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)
@@ -150,27 +151,27 @@ func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []str
// 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 @@ 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))
}

@@ -193,13 +194,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
@@ -352,6 +353,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
@@ -374,7 +381,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{}
	}
@@ -391,7 +398,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
@@ -423,8 +430,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
@@ -435,6 +443,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)
	}
+4 −0
Original line number Diff line number Diff line
@@ -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
+12 −9
Original line number Diff line number Diff line
@@ -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
Loading