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

Commit 8bbc3d5a authored by Colin Cross's avatar Colin Cross
Browse files

Convert arch and os mutators to TransitionMutators

Replace archMutator and osMutator with TransitionMutators.

Bug: 319288033
Flag: EXEMPT refactor
Test: all soong tests pass
Test: no change to out/soong/*.ninja
Change-Id: I92a4d7c895dd79f1dd8064d0ca90e7010b563525
parent 16723003
Loading
Loading
Loading
Loading
+190 −71
Original line number Diff line number Diff line
@@ -396,20 +396,21 @@ func (target Target) Variations() []blueprint.Variation {
// device_supported and host_supported properties to determine which OsTypes are enabled for this
// module, then searches through the Targets to determine which have enabled Targets for this
// module.
func osMutator(mctx BottomUpMutatorContext) {
	module := mctx.Module()
	base := module.base()
type osTransitionMutator struct{}

	// Nothing to do for modules that are not architecture specific (e.g. a genrule).
	if !base.ArchSpecific() {
		return
type allOsInfo struct {
	Os         map[string]OsType
	Variations []string
}

	// Collect a list of OSTypes supported by this module based on the HostOrDevice value
	// passed to InitAndroidArchModule and the device_supported and host_supported properties.
var allOsProvider = blueprint.NewMutatorProvider[*allOsInfo]("os_propagate")

// moduleOSList collects a list of OSTypes supported by this module based on the HostOrDevice
// value passed to InitAndroidArchModule and the device_supported and host_supported properties.
func moduleOSList(ctx ConfigContext, base *ModuleBase) []OsType {
	var moduleOSList []OsType
	for _, os := range osTypeList {
		for _, t := range mctx.Config().Targets[os] {
		for _, t := range ctx.Config().Targets[os] {
			if base.supportsTarget(t) {
				moduleOSList = append(moduleOSList, os)
				break
@@ -417,53 +418,91 @@ func osMutator(mctx BottomUpMutatorContext) {
		}
	}

	createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
	if base.commonProperties.CreateCommonOSVariant {
		// A CommonOS variant was requested so add it to the list of OS variants to
		// create. It needs to be added to the end because it needs to depend on the
		// the other variants and inter variant dependencies can only be created from a
		// later variant in that list to an earlier one. That is because variants are
		// always processed in the order in which they are created.
		moduleOSList = append(moduleOSList, CommonOS)
	}

	return moduleOSList
}

func (o *osTransitionMutator) Split(ctx BaseModuleContext) []string {
	module := ctx.Module()
	base := module.base()

	// Nothing to do for modules that are not architecture specific (e.g. a genrule).
	if !base.ArchSpecific() {
		return []string{""}
	}

	moduleOSList := moduleOSList(ctx, base)

	// If there are no supported OSes then disable the module.
	if len(moduleOSList) == 0 && !createCommonOSVariant {
	if len(moduleOSList) == 0 {
		base.Disable()
		return
		return []string{""}
	}

	// Convert the list of supported OsTypes to the variation names.
	osNames := make([]string, len(moduleOSList))
	osMapping := make(map[string]OsType, len(moduleOSList))
	for i, os := range moduleOSList {
		osNames[i] = os.String()
		osMapping[osNames[i]] = os
	}

	if createCommonOSVariant {
		// A CommonOS variant was requested so add it to the list of OS variants to
		// create. It needs to be added to the end because it needs to depend on the
		// the other variants in the list returned by CreateVariations(...) and inter
		// variant dependencies can only be created from a later variant in that list to
		// an earlier one. That is because variants are always processed in the order in
		// which they are returned from CreateVariations(...).
		osNames = append(osNames, CommonOS.Name)
		moduleOSList = append(moduleOSList, CommonOS)
	SetProvider(ctx, allOsProvider, &allOsInfo{
		Os:         osMapping,
		Variations: osNames,
	})

	return osNames
}

	// Create the variations, annotate each one with which OS it was created for, and
	// squash the appropriate OS-specific properties into the top level properties.
	modules := mctx.CreateVariations(osNames...)
	for i, m := range modules {
		m.base().commonProperties.CompileOS = moduleOSList[i]
		m.base().setOSProperties(mctx)
func (o *osTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
	return sourceVariation
}

	if createCommonOSVariant {
func (o *osTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
	module := ctx.Module()
	base := module.base()

	if !base.ArchSpecific() {
		return ""
	}

	return incomingVariation
}

func (o *osTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
	module := ctx.Module()
	base := module.base()

	if variation == "" {
		return
	}

	allOsInfo, ok := ModuleProvider(ctx, allOsProvider)
	if !ok {
		panic(fmt.Errorf("missing allOsProvider"))
	}

	// Annotate this variant with which OS it was created for, and
	// squash the appropriate OS-specific properties into the top level properties.
	base.commonProperties.CompileOS = allOsInfo.Os[variation]
	base.setOSProperties(ctx)

	if variation == CommonOS.String() {
		// A CommonOS variant was requested so add dependencies from it (the last one in
		// the list) to the OS type specific variants.
		last := len(modules) - 1
		commonOSVariant := modules[last]
		commonOSVariant.base().commonProperties.CommonOSVariant = true
		for _, module := range modules[0:last] {
			// Ignore modules that are enabled. Note, this will only avoid adding
			// dependencies on OsType variants that are explicitly disabled in their
			// properties. The CommonOS variant will still depend on disabled variants
			// if they are disabled afterwards, e.g. in archMutator if
			if module.Enabled(mctx) {
				mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
			}
		osList := allOsInfo.Variations[:len(allOsInfo.Variations)-1]
		for _, os := range osList {
			variation := []blueprint.Variation{{"os", os}}
			ctx.AddVariationDependencies(variation, commonOsToOsSpecificVariantTag, ctx.ModuleName())
		}
	}
}
@@ -496,7 +535,7 @@ func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {

var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}

// archMutator splits a module into a variant for each Target requested by the module.  Target selection
// archTransitionMutator splits a module into a variant for each Target requested by the module.  Target selection
// for a module is in three levels, OsClass, multilib, and then Target.
// OsClass selection is determined by:
//   - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
@@ -527,25 +566,32 @@ var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}
//
// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
func archMutator(mctx BottomUpMutatorContext) {
	module := mctx.Module()
type archTransitionMutator struct{}

type allArchInfo struct {
	Targets      map[string]Target
	MultiTargets []Target
	Primary      string
	Multilib     string
}

var allArchProvider = blueprint.NewMutatorProvider[*allArchInfo]("arch_propagate")

func (a *archTransitionMutator) Split(ctx BaseModuleContext) []string {
	module := ctx.Module()
	base := module.base()

	if !base.ArchSpecific() {
		return
		return []string{""}
	}

	os := base.commonProperties.CompileOS
	if os == CommonOS {
		// Make sure that the target related properties are initialized for the
		// CommonOS variant.
		addTargetProperties(module, commonTargetMap[os.Name], nil, true)

		// Do not create arch specific variants for the CommonOS variant.
		return
		return []string{""}
	}

	osTargets := mctx.Config().Targets[os]
	osTargets := ctx.Config().Targets[os]

	image := base.commonProperties.ImageVariation
	// Filter NativeBridge targets unless they are explicitly supported.
@@ -572,19 +618,18 @@ func archMutator(mctx BottomUpMutatorContext) {
	prefer32 := os == Windows

	// Determine the multilib selection for this module.
	ignorePrefer32OnDevice := mctx.Config().IgnorePrefer32OnDevice()
	multilib, extraMultilib := decodeMultilib(base, os, ignorePrefer32OnDevice)
	multilib, extraMultilib := decodeMultilib(ctx, base)

	// Convert the multilib selection into a list of Targets.
	targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
	if err != nil {
		mctx.ModuleErrorf("%s", err.Error())
		ctx.ModuleErrorf("%s", err.Error())
	}

	// If there are no supported targets disable the module.
	if len(targets) == 0 {
		base.Disable()
		return
		return []string{""}
	}

	// If the module is using extraMultilib, decode the extraMultilib selection into
@@ -593,7 +638,7 @@ func archMutator(mctx BottomUpMutatorContext) {
	if extraMultilib != "" {
		multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
		if err != nil {
			mctx.ModuleErrorf("%s", err.Error())
			ctx.ModuleErrorf("%s", err.Error())
		}
		multiTargets = filterHostCross(multiTargets, targets[0].HostCross)
	}
@@ -601,7 +646,7 @@ func archMutator(mctx BottomUpMutatorContext) {
	// Recovery is always the primary architecture, filter out any other architectures.
	// Common arch is also allowed
	if image == RecoveryVariation {
		primaryArch := mctx.Config().DevicePrimaryArchType()
		primaryArch := ctx.Config().DevicePrimaryArchType()
		targets = filterToArch(targets, primaryArch, Common)
		multiTargets = filterToArch(multiTargets, primaryArch, Common)
	}
@@ -609,37 +654,109 @@ func archMutator(mctx BottomUpMutatorContext) {
	// If there are no supported targets disable the module.
	if len(targets) == 0 {
		base.Disable()
		return
		return []string{""}
	}

	// Convert the targets into a list of arch variation names.
	targetNames := make([]string, len(targets))
	targetMapping := make(map[string]Target, len(targets))
	for i, target := range targets {
		targetNames[i] = target.ArchVariation()
		targetMapping[targetNames[i]] = targets[i]
	}

	SetProvider(ctx, allArchProvider, &allArchInfo{
		Targets:      targetMapping,
		MultiTargets: multiTargets,
		Primary:      targetNames[0],
		Multilib:     multilib,
	})
	return targetNames
}

func (a *archTransitionMutator) OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string {
	return sourceVariation
}

func (a *archTransitionMutator) IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string {
	module := ctx.Module()
	base := module.base()

	if !base.ArchSpecific() {
		return ""
	}

	// Create the variations, annotate each one with which Target it was created for, and
	os := base.commonProperties.CompileOS
	if os == CommonOS {
		// Do not create arch specific variants for the CommonOS variant.
		return ""
	}

	if incomingVariation == "" {
		multilib, _ := decodeMultilib(ctx, base)
		if multilib == "common" {
			return "common"
		}
	}
	return incomingVariation
}

func (a *archTransitionMutator) Mutate(ctx BottomUpMutatorContext, variation string) {
	module := ctx.Module()
	base := module.base()
	os := base.commonProperties.CompileOS

	if os == CommonOS {
		// Make sure that the target related properties are initialized for the
		// CommonOS variant.
		addTargetProperties(module, commonTargetMap[os.Name], nil, true)
		return
	}

	if variation == "" {
		return
	}

	if !base.ArchSpecific() {
		panic(fmt.Errorf("found variation %q for non arch specifc module", variation))
	}

	allArchInfo, ok := ModuleProvider(ctx, allArchProvider)
	if !ok {
		return
	}

	target, ok := allArchInfo.Targets[variation]
	if !ok {
		panic(fmt.Errorf("missing Target for %q", variation))
	}
	primary := variation == allArchInfo.Primary
	multiTargets := allArchInfo.MultiTargets

	// Annotate the new variant with which Target it was created for, and
	// squash the appropriate arch-specific properties into the top level properties.
	modules := mctx.CreateVariations(targetNames...)
	for i, m := range modules {
		addTargetProperties(m, targets[i], multiTargets, i == 0)
		m.base().setArchProperties(mctx)
	addTargetProperties(ctx.Module(), target, multiTargets, primary)
	base.setArchProperties(ctx)

	// Install support doesn't understand Darwin+Arm64
		if os == Darwin && targets[i].HostCross {
			m.base().commonProperties.SkipInstall = true
		}
	if os == Darwin && target.HostCross {
		base.commonProperties.SkipInstall = true
	}

	// Create a dependency for Darwin Universal binaries from the primary to secondary
	// architecture. The module itself will be responsible for calling lipo to merge the outputs.
	if os == Darwin {
		if multilib == "darwin_universal" && len(modules) == 2 {
			mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[1], modules[0])
		} else if multilib == "darwin_universal_common_first" && len(modules) == 3 {
			mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[2], modules[1])
		isUniversalBinary := (allArchInfo.Multilib == "darwin_universal" && len(allArchInfo.Targets) == 2) ||
			allArchInfo.Multilib == "darwin_universal_common_first" && len(allArchInfo.Targets) == 3
		isPrimary := variation == ctx.Config().BuildArch.String()
		hasSecondaryConfigured := len(ctx.Config().Targets[Darwin]) > 1
		if isUniversalBinary && isPrimary && hasSecondaryConfigured {
			secondaryArch := ctx.Config().Targets[Darwin][1].Arch.String()
			variation := []blueprint.Variation{{"arch", secondaryArch}}
			ctx.AddVariationDependencies(variation, DarwinUniversalVariantTag, ctx.ModuleName())
		}
	}

}

// addTargetProperties annotates a variant with the Target is is being compiled for, the list
@@ -656,7 +773,9 @@ func addTargetProperties(m Module, target Target, multiTargets []Target, primary
// multilib from the factory's call to InitAndroidArchModule if none was set.  For modules that
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
// the actual multilib in extraMultilib.
func decodeMultilib(base *ModuleBase, os OsType, ignorePrefer32OnDevice bool) (multilib, extraMultilib string) {
func decodeMultilib(ctx ConfigContext, base *ModuleBase) (multilib, extraMultilib string) {
	os := base.commonProperties.CompileOS
	ignorePrefer32OnDevice := ctx.Config().IgnorePrefer32OnDevice()
	// First check the "android.compile_multilib" or "host.compile_multilib" properties.
	switch os.Class {
	case Device:
+1 −1
Original line number Diff line number Diff line
@@ -451,7 +451,7 @@ func TestArchMutator(t *testing.T) {

	for _, tt := range testCases {
		t.Run(tt.name, func(t *testing.T) {
			if tt.goOS != runtime.GOOS {
			if tt.goOS != "" && tt.goOS != runtime.GOOS {
				t.Skipf("requries runtime.GOOS %s", tt.goOS)
			}

+5 −7
Original line number Diff line number Diff line
@@ -443,12 +443,6 @@ type commonProperties struct {
	// Set at module initialization time by calling InitCommonOSAndroidMultiTargetsArchModule
	CreateCommonOSVariant bool `blueprint:"mutated"`

	// If set to true then this variant is the CommonOS variant that has dependencies on its
	// OsType specific variants.
	//
	// Set by osMutator.
	CommonOSVariant bool `blueprint:"mutated"`

	// When set to true, this module is not installed to the full install path (ex: under
	// out/target/product/<name>/<partition>). It can be installed only to the packaging
	// modules like android_filesystem.
@@ -1221,7 +1215,7 @@ func (m *ModuleBase) ArchSpecific() bool {

// True if the current variant is a CommonOS variant, false otherwise.
func (m *ModuleBase) IsCommonOSVariant() bool {
	return m.commonProperties.CommonOSVariant
	return m.commonProperties.CompileOS == CommonOS
}

// supportsTarget returns true if the given Target is supported by the current module.
@@ -2204,6 +2198,10 @@ func (m *ModuleBase) IsNativeBridgeSupported() bool {
	return proptools.Bool(m.commonProperties.Native_bridge_supported)
}

type ConfigContext interface {
	Config() Config
}

type ConfigurableEvaluatorContext interface {
	Config() Config
	OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{})
+2 −2
Original line number Diff line number Diff line
@@ -148,9 +148,9 @@ var preArch = []RegisterMutatorFunc{
}

func registerArchMutator(ctx RegisterMutatorsContext) {
	ctx.BottomUp("os", osMutator).Parallel()
	ctx.Transition("os", &osTransitionMutator{})
	ctx.Transition("image", &imageTransitionMutator{})
	ctx.BottomUp("arch", archMutator).Parallel()
	ctx.Transition("arch", &archTransitionMutator{})
}

var preDeps = []RegisterMutatorFunc{