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

Commit 906856c7 authored by Colin Cross's avatar Colin Cross Committed by Automerger Merge Worker
Browse files

Merge "Convert arch and os mutators to TransitionMutators" into main am: 1531a12d

parents 0eff90b3 1531a12d
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.
@@ -2212,6 +2206,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{