Merge "Make FirstTarget treat HostCross separately from Host"
diff --git a/android/arch.go b/android/arch.go
index a0895ed..1952b17 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -619,6 +619,12 @@
 		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
@@ -627,6 +633,7 @@
 		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.
@@ -763,6 +770,18 @@
 	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
@@ -1795,20 +1814,23 @@
 }
 
 // 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 ad2076d..6814f8a 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -259,6 +259,27 @@
 	}
 }
 
+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 @@
 	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 @@
 			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 @@
 				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 @@
 		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 @@
 			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 f36e8ba..0f88d51 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -118,6 +118,11 @@
 	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 {