Extend multilib

Allow multilib to be set to "prefer32", which will compile as 32-bit if
available, otherwise as 64-bit.

Add target.device.compile_multilib and target.host.compile_multilib.  If
set, they override the top-level compile_multlib property.

Change-Id: If658a035b5f441547bc74526feb1d34f773776ff
diff --git a/android/androidmk.go b/android/androidmk.go
index 0afa1bd..a408933 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -197,7 +197,6 @@
 	fmt.Fprintln(w, "LOCAL_PATH :=", filepath.Dir(ctx.BlueprintFile(mod)))
 	fmt.Fprintln(w, "LOCAL_MODULE :=", name)
 	fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", data.Class)
-	fmt.Fprintln(w, "LOCAL_MULTILIB :=", amod.commonProperties.Compile_multilib)
 	fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", data.OutputFile.String())
 
 	if len(amod.commonProperties.Required) > 0 {
diff --git a/android/arch.go b/android/arch.go
index 62acb09..4f7ffb4 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -420,7 +420,19 @@
 		if len(targets) == 0 {
 			continue
 		}
-		multilib := module.base().commonProperties.Compile_multilib
+		var multilib string
+		switch class {
+		case Device:
+			multilib = module.base().commonProperties.Target.Android.Compile_multilib
+		case Host, HostCross:
+			multilib = module.base().commonProperties.Target.Host.Compile_multilib
+		}
+		if multilib == "" {
+			multilib = module.base().commonProperties.Compile_multilib
+		}
+		if multilib == "" {
+			multilib = module.base().commonProperties.Default_multilib
+		}
 		targets, err := decodeMultilib(multilib, targets)
 		if err != nil {
 			mctx.ModuleErrorf("%s", err.Error())
@@ -903,6 +915,16 @@
 	return a, nil
 }
 
+func filterMultilibTargets(targets []Target, multilib string) []Target {
+	var ret []Target
+	for _, t := range targets {
+		if t.Arch.ArchType.Multilib == multilib {
+			ret = append(ret, t)
+		}
+	}
+	return ret
+}
+
 // Use the module multilib setting to select one or more targets from a target list
 func decodeMultilib(multilib string, targets []Target) ([]Target, error) {
 	buildTargets := []Target{}
@@ -914,19 +936,16 @@
 	case "first":
 		buildTargets = append(buildTargets, targets[0])
 	case "32":
-		for _, t := range targets {
-			if t.Arch.ArchType.Multilib == "lib32" {
-				buildTargets = append(buildTargets, t)
-			}
-		}
+		buildTargets = filterMultilibTargets(targets, "lib32")
 	case "64":
-		for _, t := range targets {
-			if t.Arch.ArchType.Multilib == "lib64" {
-				buildTargets = append(buildTargets, t)
-			}
+		buildTargets = filterMultilibTargets(targets, "lib64")
+	case "prefer32":
+		buildTargets = filterMultilibTargets(targets, "lib32")
+		if len(buildTargets) == 0 {
+			buildTargets = filterMultilibTargets(targets, "lib64")
 		}
 	default:
-		return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", or "64", found %q`,
+		return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", or "prefer32" found %q`,
 			multilib)
 	}
 
diff --git a/android/module.go b/android/module.go
index 45afec1..aaaa2fb 100644
--- a/android/module.go
+++ b/android/module.go
@@ -118,7 +118,18 @@
 	// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
 	// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
 	// platform
-	Compile_multilib string
+	Compile_multilib string `android:"arch_variant"`
+
+	Target struct {
+		Host struct {
+			Compile_multilib string
+		}
+		Android struct {
+			Compile_multilib string
+		}
+	}
+
+	Default_multilib string `blueprint:"mutated"`
 
 	// whether this is a proprietary vendor module, and should be installed into /vendor
 	Proprietary bool
@@ -182,7 +193,7 @@
 
 	base := m.base()
 	base.commonProperties.HostOrDeviceSupported = hod
-	base.commonProperties.Compile_multilib = string(defaultMultilib)
+	base.commonProperties.Default_multilib = string(defaultMultilib)
 
 	switch hod {
 	case HostAndDeviceSupported: