android: Add host_cross_supported prop

Some modules are only intended to be build for the build host,
e.g. rust_library modules only used in rust_proc_macro or
code generators.

These should not be expected to be built for or supported on non-build
host platforms. Thus, add a host_cross_supported property to disable
the HostCross target.

Test: m blueprint_tests
Test: Modules with host_cross_supported: false don't build for HostCross
Change-Id: Ia15f55776e04d86aee19bb0dd0d27e1b985b2b75
diff --git a/android/arch.go b/android/arch.go
index e0c6908..251990b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -587,6 +587,7 @@
 	}
 
 	osTargets := mctx.Config().Targets[os]
+
 	image := base.commonProperties.ImageVariation
 	// Filter NativeBridge targets unless they are explicitly supported.
 	// Skip creating native bridge variants for non-core modules.
@@ -602,6 +603,17 @@
 		osTargets = targets
 	}
 
+	// Filter HostCross targets if disabled.
+	if base.HostSupported() && !base.HostCrossSupported() {
+		var targets []Target
+		for _, t := range osTargets {
+			if !t.HostCross {
+				targets = append(targets, t)
+			}
+		}
+		osTargets = targets
+	}
+
 	// only the primary arch in the ramdisk / vendor_ramdisk / recovery partition
 	if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) {
 		osTargets = []Target{osTargets[0]}
diff --git a/android/arch_test.go b/android/arch_test.go
index f0a58a9..6134a06 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -332,6 +332,12 @@
 		}
 
 		module {
+			name: "nohostcross",
+			host_supported: true,
+			host_cross_supported: false,
+		}
+
+		module {
 			name: "baz",
 			device_supported: false,
 		}
@@ -355,13 +361,14 @@
 	`
 
 	testCases := []struct {
-		name          string
-		preparer      FixturePreparer
-		fooVariants   []string
-		barVariants   []string
-		bazVariants   []string
-		quxVariants   []string
-		firstVariants []string
+		name                string
+		preparer            FixturePreparer
+		fooVariants         []string
+		barVariants         []string
+		noHostCrossVariants []string
+		bazVariants         []string
+		quxVariants         []string
+		firstVariants       []string
 
 		multiTargetVariants    []string
 		multiTargetVariantsMap map[string][]string
@@ -373,6 +380,7 @@
 			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"),
+			noHostCrossVariants: 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"),
@@ -390,6 +398,7 @@
 			}),
 			fooVariants:         nil,
 			barVariants:         buildOSVariants,
+			noHostCrossVariants: buildOSVariants,
 			bazVariants:         nil,
 			quxVariants:         buildOS32Variants,
 			firstVariants:       buildOS64Variants,
@@ -406,6 +415,7 @@
 			}),
 			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"},
+			noHostCrossVariants: []string{"linux_musl_x86_64", "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"},
@@ -461,6 +471,10 @@
 				t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
 			}
 
+			if g, w := enabledVariants(ctx, "nohostcross"), tt.noHostCrossVariants; !reflect.DeepEqual(w, g) {
+				t.Errorf("want nohostcross variants:\n%q\ngot:\n%q\n", w, g)
+			}
+
 			if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
 				t.Errorf("want baz variants:\n%q\ngot:\n%q\n", w, g)
 			}
diff --git a/android/module.go b/android/module.go
index 9f7cb37..f1cc870 100644
--- a/android/module.go
+++ b/android/module.go
@@ -603,6 +603,11 @@
 	Device_supported *bool
 }
 
+type hostCrossProperties struct {
+	// If set to true, build a variant of the module for the host cross.  Defaults to true.
+	Host_cross_supported *bool
+}
+
 type Multilib string
 
 const (
@@ -718,6 +723,10 @@
 		m.AddProperties(&base.hostAndDeviceProperties)
 	}
 
+	if hod&hostCrossSupported != 0 {
+		m.AddProperties(&base.hostCrossProperties)
+	}
+
 	initArchModule(m)
 }
 
@@ -803,6 +812,7 @@
 	distProperties          distProperties
 	variableProperties      interface{}
 	hostAndDeviceProperties hostAndDeviceProperties
+	hostCrossProperties     hostCrossProperties
 
 	// Arch specific versions of structs in GetProperties() prior to
 	// initialization in InitAndroidArchModule, lets call it `generalProperties`.
@@ -1321,7 +1331,11 @@
 	// hostEnabled is true if the host_supported property is true or the HostOrDeviceSupported
 	// value has the hostDefault bit set.
 	hostEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Host_supported, hod&hostDefault != 0)
-	return hod&hostCrossSupported != 0 && hostEnabled
+
+	// Default true for the Host_cross_supported property
+	hostCrossEnabled := proptools.BoolDefault(m.hostCrossProperties.Host_cross_supported, true)
+
+	return hod&hostCrossSupported != 0 && hostEnabled && hostCrossEnabled
 }
 
 func (m *ModuleBase) Platform() bool {