diff --git a/android/arch.go b/android/arch.go index b5bd2f080..809b2c60d 100644 --- a/android/arch.go +++ b/android/arch.go @@ -616,6 +616,12 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { mctx.ModuleErrorf("%s", err.Error()) } + // If there are no supported targets disable the module. + if len(targets) == 0 { + base.Disable() + return + } + // If the module is using extraMultilib, decode the extraMultilib selection into // a separate list of Targets. var multiTargets []Target @@ -624,6 +630,7 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { if err != nil { mctx.ModuleErrorf("%s", err.Error()) } + multiTargets = filterHostCross(multiTargets, targets[0].HostCross) } // Recovery is always the primary architecture, filter out any other architectures. @@ -760,6 +767,18 @@ func filterToArch(targets []Target, archs ...ArchType) []Target { return targets } +// filterHostCross takes a list of Targets and a hostCross value, and returns a modified list +// that contains only Targets that have the specified HostCross. +func filterHostCross(targets []Target, hostCross bool) []Target { + for i := 0; i < len(targets); i++ { + if targets[i].HostCross != hostCross { + targets = append(targets[:i], targets[i+1:]...) + i-- + } + } + return targets +} + // archPropRoot is a struct type used as the top level of the arch-specific properties. It // contains the "arch", "multilib", and "target" property structs. It is used to split up the // property structs to limit how much is allocated when a single arch-specific property group is @@ -1789,20 +1808,23 @@ func getCommonTargets(targets []Target) []Target { } // FirstTarget takes a list of Targets and a list of multilib values and returns a list of Targets -// that contains zero or one Target for each OsType, selecting the one that matches the earliest -// filter. +// that contains zero or one Target for each OsType and HostCross, selecting the one that matches +// the earliest filter. func FirstTarget(targets []Target, filters ...string) []Target { // find the first target from each OS var ret []Target - hasHost := false - set := make(map[OsType]bool) + type osHostCross struct { + os OsType + hostCross bool + } + set := make(map[osHostCross]bool) for _, filter := range filters { buildTargets := filterMultilibTargets(targets, filter) for _, t := range buildTargets { - if _, found := set[t.Os]; !found { - hasHost = hasHost || (t.Os.Class == Host) - set[t.Os] = true + key := osHostCross{t.Os, t.HostCross} + if _, found := set[key]; !found { + set[key] = true ret = append(ret, t) } } diff --git a/android/arch_test.go b/android/arch_test.go index ad2076d4d..6814f8a7d 100644 --- a/android/arch_test.go +++ b/android/arch_test.go @@ -259,6 +259,27 @@ type archTestModule struct { } } +func (m *archTestMultiTargetsModule) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +func (m *archTestMultiTargetsModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), nil, m.props.Deps...) +} + +func archTestMultiTargetsModuleFactory() Module { + m := &archTestMultiTargetsModule{} + m.AddProperties(&m.props) + InitAndroidMultiTargetsArchModule(m, HostAndDeviceSupported, MultilibCommon) + return m +} + +type archTestMultiTargetsModule struct { + ModuleBase + props struct { + Deps []string + } +} + func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { } @@ -277,19 +298,27 @@ var prepareForArchTest = GroupFixturePreparers( PrepareForTestWithArchMutator, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("module", archTestModuleFactory) + ctx.RegisterModuleType("multi_targets_module", archTestMultiTargetsModuleFactory) }), ) func TestArchMutator(t *testing.T) { var buildOSVariants []string + var buildOS64Variants []string var buildOS32Variants []string + var buildOSCommonVariant string + switch runtime.GOOS { case "linux": buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"} + buildOS64Variants = []string{"linux_glibc_x86_64"} buildOS32Variants = []string{"linux_glibc_x86"} + buildOSCommonVariant = "linux_glibc_common" case "darwin": buildOSVariants = []string{"darwin_x86_64"} + buildOS64Variants = []string{"darwin_x86_64"} buildOS32Variants = nil + buildOSCommonVariant = "darwin_common" } bp := ` @@ -312,24 +341,46 @@ func TestArchMutator(t *testing.T) { host_supported: true, compile_multilib: "32", } + + module { + name: "first", + host_supported: true, + compile_multilib: "first", + } + + multi_targets_module { + name: "multi_targets", + host_supported: true, + } ` testCases := []struct { - name string - preparer FixturePreparer - fooVariants []string - barVariants []string - bazVariants []string - quxVariants []string + name string + preparer FixturePreparer + fooVariants []string + barVariants []string + bazVariants []string + quxVariants []string + firstVariants []string + + multiTargetVariants []string + multiTargetVariantsMap map[string][]string + + goOS string }{ { - name: "normal", - preparer: nil, - fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, - barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"), - bazVariants: nil, - quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"), - }, + name: "normal", + preparer: nil, + fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"), + bazVariants: nil, + quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"), + firstVariants: append(buildOS64Variants, "android_arm64_armv8-a"), + multiTargetVariants: []string{buildOSCommonVariant, "android_common"}, + multiTargetVariantsMap: map[string][]string{ + buildOSCommonVariant: buildOS64Variants, + "android_common": {"android_arm64_armv8-a"}, + }}, { name: "host-only", preparer: FixtureModifyConfig(func(config Config) { @@ -337,10 +388,33 @@ func TestArchMutator(t *testing.T) { config.BuildOSCommonTarget = Target{} config.Targets[Android] = nil }), - fooVariants: nil, - barVariants: buildOSVariants, - bazVariants: nil, - quxVariants: buildOS32Variants, + fooVariants: nil, + barVariants: buildOSVariants, + bazVariants: nil, + quxVariants: buildOS32Variants, + firstVariants: buildOS64Variants, + multiTargetVariants: []string{buildOSCommonVariant}, + multiTargetVariantsMap: map[string][]string{ + buildOSCommonVariant: buildOS64Variants, + }, + }, + { + name: "same arch host and host cross", + preparer: FixtureModifyConfig(func(config Config) { + modifyTestConfigForMusl(config) + modifyTestConfigForMuslArm64HostCross(config) + }), + fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + barVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "linux_musl_x86", "android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + bazVariants: nil, + quxVariants: []string{"linux_musl_x86", "android_arm_armv7-a-neon"}, + firstVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "android_arm64_armv8-a"}, + multiTargetVariants: []string{"linux_musl_common", "android_common"}, + multiTargetVariantsMap: map[string][]string{ + "linux_musl_common": {"linux_musl_x86_64"}, + "android_common": {"android_arm64_armv8-a"}, + }, + goOS: "linux", }, } @@ -356,8 +430,21 @@ func TestArchMutator(t *testing.T) { return ret } + moduleMultiTargets := func(ctx *TestContext, name string, variant string) []string { + var ret []string + targets := ctx.ModuleForTests(name, variant).Module().MultiTargets() + for _, t := range targets { + ret = append(ret, t.String()) + } + return ret + } + for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + if tt.goOS != runtime.GOOS { + t.Skipf("requries runtime.GOOS %s", tt.goOS) + } + result := GroupFixturePreparers( prepareForArchTest, // Test specific preparer @@ -381,6 +468,20 @@ func TestArchMutator(t *testing.T) { if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) { t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g) } + if g, w := enabledVariants(ctx, "first"), tt.firstVariants; !reflect.DeepEqual(w, g) { + t.Errorf("want first variants:\n%q\ngot:\n%q\n", w, g) + } + + if g, w := enabledVariants(ctx, "multi_targets"), tt.multiTargetVariants; !reflect.DeepEqual(w, g) { + t.Fatalf("want multi_target variants:\n%q\ngot:\n%q\n", w, g) + } + + for _, variant := range tt.multiTargetVariants { + targets := moduleMultiTargets(ctx, "multi_targets", variant) + if g, w := targets, tt.multiTargetVariantsMap[variant]; !reflect.DeepEqual(w, g) { + t.Errorf("want ctx.MultiTarget() for %q:\n%q\ngot:\n%q\n", variant, w, g) + } + } }) } } diff --git a/android/test_config.go b/android/test_config.go index f36e8ba6a..0f88d5164 100644 --- a/android/test_config.go +++ b/android/test_config.go @@ -118,6 +118,11 @@ func modifyTestConfigForMusl(config Config) { config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] } +func modifyTestConfigForMuslArm64HostCross(config Config) { + config.Targets[LinuxMusl] = append(config.Targets[LinuxMusl], + Target{config.BuildOS, Arch{ArchType: Arm64}, NativeBridgeDisabled, "", "", true}) +} + // TestArchConfig returns a Config object suitable for using for tests that // need to run the arch mutator. func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {