Merge "Add health to vndk vendor variant list"
diff --git a/Android.bp b/Android.bp
index d6260b4..b5ddaa4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,6 +62,7 @@
         },
     },
     notice: ":mingw-libwinpthread-notice",
+    licenses: ["winpthreads_license"],
 }
 
 kernel_headers {
diff --git a/android/androidmk.go b/android/androidmk.go
index 967c550..f48c06b 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -29,6 +29,7 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"runtime"
 	"sort"
 	"strings"
 
@@ -836,6 +837,7 @@
 		case "*aidl.aidlApi": // writes non-custom before adding .phony
 		case "*aidl.aidlMapping": // writes non-custom before adding .phony
 		case "*android.customModule": // appears in tests only
+		case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
 		case "*apex.apexBundle": // license properties written
 		case "*bpf.bpf": // license properties written (both for module and objs)
 		case "*genrule.Module": // writes non-custom before adding .phony
@@ -901,6 +903,13 @@
 		return true
 	}
 
+	// On Mac, only expose host darwin modules to Make, as that's all we claim to support.
+	// In reality, some of them depend on device-built (Java) modules, so we can't disable all
+	// device modules in Soong, but we can hide them from Make (and thus the build user interface)
+	if runtime.GOOS == "darwin" && module.Os() != Darwin {
+		return true
+	}
+
 	return !module.Enabled() ||
 		module.commonProperties.HideFromMake ||
 		// Make does not understand LinuxBionic
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 8eda9b2..ecfb008 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"io"
 	"reflect"
+	"runtime"
 	"strings"
 	"testing"
 
@@ -155,6 +156,11 @@
 }
 
 func TestAndroidMkSingleton_PassesUpdatedAndroidMkDataToCustomCallback(t *testing.T) {
+	if runtime.GOOS == "darwin" {
+		// Device modules are not exported on Mac, so this test doesn't work.
+		t.SkipNow()
+	}
+
 	bp := `
 	custom {
 		name: "foo",
diff --git a/android/arch.go b/android/arch.go
index 54242e5..5e3e920 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1587,10 +1587,12 @@
 	return PrefixInList(arch.Abi, "arm")
 }
 
-// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
+// hasArmAndroidArch returns true if targets has at least
+// one arm Android arch (possibly native bridged)
 func hasArmAndroidArch(targets []Target) bool {
 	for _, target := range targets {
-		if target.Os == Android && target.Arch.ArchType == Arm {
+		if target.Os == Android &&
+			(target.Arch.ArchType == Arm || target.Arch.ArchType == Arm64) {
 			return true
 		}
 	}
@@ -2006,17 +2008,10 @@
 	osToProp := ArchVariantProperties{}
 	archOsToProp := ArchVariantProperties{}
 
-	var linuxStructs, bionicStructs []reflect.Value
-	var ok bool
-
-	linuxStructs, ok = getTargetStructs(ctx, archProperties, "Linux")
-	if !ok {
-		linuxStructs = make([]reflect.Value, 0)
-	}
-	bionicStructs, ok = getTargetStructs(ctx, archProperties, "Bionic")
-	if !ok {
-		bionicStructs = make([]reflect.Value, 0)
-	}
+	linuxStructs := getTargetStructs(ctx, archProperties, "Linux")
+	bionicStructs := getTargetStructs(ctx, archProperties, "Bionic")
+	hostStructs := getTargetStructs(ctx, archProperties, "Host")
+	hostNotWindowsStructs := getTargetStructs(ctx, archProperties, "Not_windows")
 
 	// For android, linux, ...
 	for _, os := range osTypeList {
@@ -2025,9 +2020,10 @@
 			continue
 		}
 		osStructs := make([]reflect.Value, 0)
-		osSpecificStructs, ok := getTargetStructs(ctx, archProperties, os.Field)
-		if ok {
-			osStructs = append(osStructs, osSpecificStructs...)
+
+		osSpecificStructs := getTargetStructs(ctx, archProperties, os.Field)
+		if os.Class == Host {
+			osStructs = append(osStructs, hostStructs...)
 		}
 		if os.Linux() {
 			osStructs = append(osStructs, linuxStructs...)
@@ -2035,37 +2031,44 @@
 		if os.Bionic() {
 			osStructs = append(osStructs, bionicStructs...)
 		}
+
+		if os == LinuxMusl {
+			osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Musl")...)
+		}
+		if os == Linux {
+			osStructs = append(osStructs, getTargetStructs(ctx, archProperties, "Glibc")...)
+		}
+
+		osStructs = append(osStructs, osSpecificStructs...)
+
+		if os.Class == Host && os != Windows {
+			osStructs = append(osStructs, hostNotWindowsStructs...)
+		}
 		osToProp[os.Name] = mergeStructs(ctx, osStructs, propertySet)
 
 		// For arm, x86, ...
 		for _, arch := range osArchTypeMap[os] {
 			osArchStructs := make([]reflect.Value, 0)
 
-			targetField := GetCompoundTargetField(os, arch)
-			targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
-			targetStructs, ok := getTargetStructs(ctx, archProperties, targetField)
-			if ok {
-				osArchStructs = append(osArchStructs, targetStructs...)
-			}
-
 			// Auto-combine with Linux_ and Bionic_ targets. This potentially results in
 			// repetition and select() bloat, but use of Linux_* and Bionic_* targets is rare.
 			// TODO(b/201423152): Look into cleanup.
 			if os.Linux() {
 				targetField := "Linux_" + arch.Name
-				targetStructs, ok := getTargetStructs(ctx, archProperties, targetField)
-				if ok {
-					osArchStructs = append(osArchStructs, targetStructs...)
-				}
+				targetStructs := getTargetStructs(ctx, archProperties, targetField)
+				osArchStructs = append(osArchStructs, targetStructs...)
 			}
 			if os.Bionic() {
 				targetField := "Bionic_" + arch.Name
-				targetStructs, ok := getTargetStructs(ctx, archProperties, targetField)
-				if ok {
-					osArchStructs = append(osArchStructs, targetStructs...)
-				}
+				targetStructs := getTargetStructs(ctx, archProperties, targetField)
+				osArchStructs = append(osArchStructs, targetStructs...)
 			}
 
+			targetField := GetCompoundTargetField(os, arch)
+			targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
+			targetStructs := getTargetStructs(ctx, archProperties, targetField)
+			osArchStructs = append(osArchStructs, targetStructs...)
+
 			archOsToProp[targetName] = mergeStructs(ctx, osArchStructs, propertySet)
 		}
 	}
@@ -2089,8 +2092,8 @@
 //      }
 //    }
 // This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"]
-func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) ([]reflect.Value, bool) {
-	propertyStructs := make([]reflect.Value, 0)
+func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value {
+	var propertyStructs []reflect.Value
 	for _, archProperty := range archProperties {
 		archPropValues := reflect.ValueOf(archProperty).Elem()
 		targetProp := archPropValues.FieldByName("Target").Elem()
@@ -2098,11 +2101,11 @@
 		if ok {
 			propertyStructs = append(propertyStructs, targetStruct)
 		} else {
-			return propertyStructs, false
+			return []reflect.Value{}
 		}
 	}
 
-	return propertyStructs, true
+	return propertyStructs
 }
 
 func mergeStructs(ctx ArchVariantContext, propertyStructs []reflect.Value, propertySet interface{}) interface{} {
diff --git a/android/bazel.go b/android/bazel.go
index 6aba759..5dda655 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -182,8 +182,8 @@
 		"external/boringssl":                                 Bp2BuildDefaultTrueRecursively,
 		"external/brotli":                                    Bp2BuildDefaultTrue,
 		"external/fmtlib":                                    Bp2BuildDefaultTrueRecursively,
-		"external/googletest/googletest":                     Bp2BuildDefaultTrueRecursively,
 		"external/google-benchmark":                          Bp2BuildDefaultTrueRecursively,
+		"external/googletest/googletest":                     Bp2BuildDefaultTrueRecursively,
 		"external/gwp_asan":                                  Bp2BuildDefaultTrueRecursively,
 		"external/jemalloc_new":                              Bp2BuildDefaultTrueRecursively,
 		"external/jsoncpp":                                   Bp2BuildDefaultTrueRecursively,
@@ -191,10 +191,15 @@
 		"external/libcxx":                                    Bp2BuildDefaultTrueRecursively,
 		"external/libcxxabi":                                 Bp2BuildDefaultTrueRecursively,
 		"external/lz4/lib":                                   Bp2BuildDefaultTrue,
+		"external/mdnsresponder":                             Bp2BuildDefaultTrueRecursively,
+		"external/minijail":                                  Bp2BuildDefaultTrueRecursively,
+		"external/pcre":                                      Bp2BuildDefaultTrueRecursively,
 		"external/protobuf":                                  Bp2BuildDefaultTrueRecursively,
 		"external/python/six":                                Bp2BuildDefaultTrueRecursively,
 		"external/scudo":                                     Bp2BuildDefaultTrueRecursively,
+		"external/selinux/libselinux":                        Bp2BuildDefaultTrueRecursively,
 		"external/zlib":                                      Bp2BuildDefaultTrueRecursively,
+		"external/zstd":                                      Bp2BuildDefaultTrueRecursively,
 		"frameworks/native/libs/adbd_auth":                   Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb":                               Bp2BuildDefaultTrue,
 		"packages/modules/adb/crypto":                        Bp2BuildDefaultTrueRecursively,
@@ -208,6 +213,7 @@
 		"system/core/libasyncio":                             Bp2BuildDefaultTrue,
 		"system/core/libcrypto_utils":                        Bp2BuildDefaultTrueRecursively,
 		"system/core/libcutils":                              Bp2BuildDefaultTrueRecursively,
+		"system/core/libpackagelistparser":                   Bp2BuildDefaultTrueRecursively,
 		"system/core/libprocessgroup":                        Bp2BuildDefaultTrue,
 		"system/core/libprocessgroup/cgrouprc":               Bp2BuildDefaultTrue,
 		"system/core/libprocessgroup/cgrouprc_format":        Bp2BuildDefaultTrue,
@@ -237,10 +243,21 @@
 
 		"brotli-fuzzer-corpus", // b/202015218: outputs are in location incompatible with bazel genrule handling.
 
+		// b/203369847: multiple genrules in the same package creating the same file
+		// //development/sdk/...
+		"platform_tools_properties",
+		"build_tools_source_properties",
+
 		// //external/libcap/...
 		"libcap",      // http://b/198595332, depends on _makenames, a cc_binary
 		"cap_names.h", // http://b/198596102, depends on _makenames, a cc_binary
 
+		"libminijail", // depends on unconverted modules: libcap
+		"getcap",      // depends on unconverted modules: libcap
+		"setcap",      // depends on unconverted modules: libcap
+		"minijail0",   // depends on unconverted modules: libcap, libminijail
+		"drop_privs",  // depends on unconverted modules: libminijail
+
 		// Tests. Handle later.
 		"libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found
 		"libjemalloc5_integrationtest",
@@ -266,6 +283,20 @@
 
 		"libgtest_ndk_c++",      // b/201816222: Requires sdk_version support.
 		"libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support.
+
+		"abb",                     // depends on unconverted modules: libadbd_core, libadbd_services, libcmd, libbinder, libutils, libselinux
+		"adb",                     // depends on unconverted modules: bin2c_fastdeployagent, libadb_crypto, libadb_host, libadb_pairing_connection, libadb_protos, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libmdnssd, libopenscreen-discovery, libopenscreen-platform-impl, libusb, libutils, libziparchive, libzstd, AdbWinApi
+		"adbd",                    // depends on unconverted modules: libadb_crypto, libadb_pairing_connection, libadb_protos, libadbd, libadbd_core, libapp_processes_protos_lite, libmdnssd, libzstd, libadbd_services, libcap, libminijail, libselinux
+		"bionic_tests_zipalign",   // depends on unconverted modules: libziparchive, libutils
+		"linker",                  // depends on unconverted modules: liblinker_debuggerd_stub, libdebuggerd_handler_fallback, libziparchive, liblinker_main, liblinker_malloc
+		"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
+		"sefcontext_compile",      // depends on unconverted modules: libsepol
+		"versioner",               // depends on unconverted modules: libclang_cxx_host, libLLVM_host
+
+		"linkerconfig", // http://b/202876379 has arch-variant static_executable
+		"mdnsd",        // http://b/202876379 has arch-variant static_executable
+
+		"acvp_modulewrapper", // disabled for android x86/x86_64
 	}
 
 	// Per-module denylist of cc_library modules to only generate the static
@@ -282,7 +313,7 @@
 		"libseccomp_policy_app_zygote_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
 		"libseccomp_policy_app_sources",        // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
 		"libseccomp_policy_system_sources",     // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
-
+		"minijail_constants_json",              // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
 	}
 
 	// Used for quicker lookups
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 06712a1..3c6212e 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -48,11 +48,17 @@
 	StarlarkFunctionBody() string
 }
 
+// Portion of cquery map key to describe target configuration.
+type configKey struct {
+	archType ArchType
+	osType   OsType
+}
+
 // Map key to describe bazel cquery requests.
 type cqueryKey struct {
 	label       string
 	requestType cqueryRequest
-	archType    ArchType
+	configKey   configKey
 }
 
 // bazelHandler is the interface for a helper object related to deferring to Bazel for
@@ -72,14 +78,14 @@
 	// has been queued to be run later.
 
 	// Returns result files built by building the given bazel target label.
-	GetOutputFiles(label string, archType ArchType) ([]string, bool)
+	GetOutputFiles(label string, cfgKey configKey) ([]string, bool)
 
 	// TODO(cparsons): Other cquery-related methods should be added here.
 	// Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
-	GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error)
+	GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error)
 
 	// Returns the executable binary resultant from building together the python sources
-	GetPythonBinary(label string, archType ArchType) (string, bool)
+	GetPythonBinary(label string, cfgKey configKey) (string, bool)
 
 	// ** End cquery methods
 
@@ -140,17 +146,17 @@
 	LabelToPythonBinary map[string]string
 }
 
-func (m MockBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
+func (m MockBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) {
 	result, ok := m.LabelToOutputFiles[label]
 	return result, ok
 }
 
-func (m MockBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
+func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) {
 	result, ok := m.LabelToCcInfo[label]
 	return result, ok, nil
 }
 
-func (m MockBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
+func (m MockBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) {
 	result, ok := m.LabelToPythonBinary[label]
 	return result, ok
 }
@@ -171,8 +177,8 @@
 
 var _ BazelContext = MockBazelContext{}
 
-func (bazelCtx *bazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
-	rawString, ok := bazelCtx.cquery(label, cquery.GetOutputFiles, archType)
+func (bazelCtx *bazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) {
+	rawString, ok := bazelCtx.cquery(label, cquery.GetOutputFiles, cfgKey)
 	var ret []string
 	if ok {
 		bazelOutput := strings.TrimSpace(rawString)
@@ -181,8 +187,8 @@
 	return ret, ok
 }
 
-func (bazelCtx *bazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
-	result, ok := bazelCtx.cquery(label, cquery.GetCcInfo, archType)
+func (bazelCtx *bazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) {
+	result, ok := bazelCtx.cquery(label, cquery.GetCcInfo, cfgKey)
 	if !ok {
 		return cquery.CcInfo{}, ok, nil
 	}
@@ -192,8 +198,8 @@
 	return ret, ok, err
 }
 
-func (bazelCtx *bazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
-	rawString, ok := bazelCtx.cquery(label, cquery.GetPythonBinary, archType)
+func (bazelCtx *bazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) {
+	rawString, ok := bazelCtx.cquery(label, cquery.GetPythonBinary, cfgKey)
 	var ret string
 	if ok {
 		bazelOutput := strings.TrimSpace(rawString)
@@ -202,19 +208,15 @@
 	return ret, ok
 }
 
-func (n noopBazelContext) GetOutputFiles(label string, archType ArchType) ([]string, bool) {
+func (n noopBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, bool) {
 	panic("unimplemented")
 }
 
-func (n noopBazelContext) GetCcInfo(label string, archType ArchType) (cquery.CcInfo, bool, error) {
+func (n noopBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, bool, error) {
 	panic("unimplemented")
 }
 
-func (n noopBazelContext) GetPythonBinary(label string, archType ArchType) (string, bool) {
-	panic("unimplemented")
-}
-
-func (n noopBazelContext) GetPrebuiltCcStaticLibraryFiles(label string, archType ArchType) ([]string, bool) {
+func (n noopBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, bool) {
 	panic("unimplemented")
 }
 
@@ -303,8 +305,8 @@
 // returns (result, true). If the request is queued but no results are available,
 // then returns ("", false).
 func (context *bazelContext) cquery(label string, requestType cqueryRequest,
-	archType ArchType) (string, bool) {
-	key := cqueryKey{label, requestType, archType}
+	cfgKey configKey) (string, bool) {
+	key := cqueryKey{label, requestType, cfgKey}
 	if result, ok := context.results[key]; ok {
 		return result, true
 	} else {
@@ -419,7 +421,7 @@
 
 def _config_node_transition_impl(settings, attr):
     return {
-        "//command_line_option:platforms": "@//build/bazel/platforms:android_%s" % attr.arch,
+        "//command_line_option:platforms": "@//build/bazel/platforms:%s_%s" % (attr.os, attr.arch),
     }
 
 _config_node_transition = transition(
@@ -437,7 +439,8 @@
     implementation = _passthrough_rule_impl,
     attrs = {
         "arch" : attr.string(mandatory = True),
-        "deps" : attr.label_list(cfg = _config_node_transition),
+        "os"   : attr.string(mandatory = True),
+        "deps" : attr.label_list(cfg = _config_node_transition, allow_files = True),
         "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
     },
 )
@@ -488,38 +491,32 @@
 	configNodeFormatString := `
 config_node(name = "%s",
     arch = "%s",
+    os = "%s",
     deps = [%s],
 )
 `
 
-	commonArchFilegroupString := `
-filegroup(name = "common",
-    srcs = [%s],
-)
-`
-
 	configNodesSection := ""
 
-	labelsByArch := map[string][]string{}
+	labelsByConfig := map[string][]string{}
 	for val, _ := range context.requests {
 		labelString := fmt.Sprintf("\"@%s\"", val.label)
-		archString := getArchString(val)
-		labelsByArch[archString] = append(labelsByArch[archString], labelString)
+		configString := getConfigString(val)
+		labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
 	}
 
 	allLabels := []string{}
-	for archString, labels := range labelsByArch {
-		if archString == "common" {
-			// arch-less labels (e.g. filegroups) don't need a config_node
-			allLabels = append(allLabels, "\":common\"")
-			labelsString := strings.Join(labels, ",\n            ")
-			configNodesSection += fmt.Sprintf(commonArchFilegroupString, labelsString)
-		} else {
-			// Create a config_node, and add the config_node's label to allLabels
-			allLabels = append(allLabels, fmt.Sprintf("\":%s\"", archString))
-			labelsString := strings.Join(labels, ",\n            ")
-			configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
+	for configString, labels := range labelsByConfig {
+		configTokens := strings.Split(configString, "|")
+		if len(configTokens) != 2 {
+			panic(fmt.Errorf("Unexpected config string format: %s", configString))
 		}
+		archString := configTokens[0]
+		osString := configTokens[1]
+		targetString := fmt.Sprintf("%s_%s", osString, archString)
+		allLabels = append(allLabels, fmt.Sprintf("\":%s\"", targetString))
+		labelsString := strings.Join(labels, ",\n            ")
+		configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, labelsString)
 	}
 
 	return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n            ")))
@@ -587,11 +584,15 @@
 %s
 
 def get_arch(target):
+  # TODO(b/199363072): filegroups and file targets aren't associated with any
+  # specific platform architecture in mixed builds. This is consistent with how
+  # Soong treats filegroups, but it may not be the case with manually-written
+  # filegroup BUILD targets.
   buildoptions = build_options(target)
   if buildoptions == None:
     # File targets do not have buildoptions. File targets aren't associated with
-    #  any specific platform architecture in mixed builds.
-    return "common"
+    #  any specific platform architecture in mixed builds, so use the host.
+    return "x86_64|linux"
   platforms = build_options(target)["//command_line_option:platforms"]
   if len(platforms) != 1:
     # An individual configured target should have only one platform architecture.
@@ -601,10 +602,12 @@
   platform_name = build_options(target)["//command_line_option:platforms"][0].name
   if platform_name == "host":
     return "HOST"
+  elif platform_name.startswith("linux_glibc_"):
+    return platform_name[len("linux_glibc_"):] + "|" + platform_name[:len("linux_glibc_")-1]
   elif platform_name.startswith("android_"):
-    return platform_name[len("android_"):]
+    return platform_name[len("android_"):] + "|" + platform_name[:len("android_")-1]
   elif platform_name.startswith("linux_"):
-    return platform_name[len("linux_"):]
+    return platform_name[len("linux_"):] + "|" + platform_name[:len("linux_")-1]
   else:
     fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms))
     return "UNKNOWN"
@@ -852,14 +855,23 @@
 }
 
 func getCqueryId(key cqueryKey) string {
-	return key.label + "|" + getArchString(key)
+	return key.label + "|" + getConfigString(key)
 }
 
-func getArchString(key cqueryKey) string {
-	arch := key.archType.Name
-	if len(arch) > 0 {
-		return arch
-	} else {
-		return "x86_64"
+func getConfigString(key cqueryKey) string {
+	arch := key.configKey.archType.Name
+	if len(arch) == 0 || arch == "common" {
+		// Use host platform, which is currently hardcoded to be x86_64.
+		arch = "x86_64"
 	}
+	os := key.configKey.osType.Name
+	if len(os) == 0 || os == "common_os" {
+		// Use host OS, which is currently hardcoded to be linux.
+		os = "linux"
+	}
+	return arch + "|" + os
+}
+
+func GetConfigKey(ctx ModuleContext) configKey {
+	return configKey{archType: ctx.Arch().ArchType, osType: ctx.Os()}
 }
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index fe66a90..ad5b63b 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -9,11 +9,11 @@
 
 func TestRequestResultsAfterInvokeBazel(t *testing.T) {
 	label := "//foo:bar"
-	arch := Arm64
+	cfg := configKey{Arm64, Android}
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
-		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64>>out/foo/bar.txt`,
+		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64|android>>out/foo/bar.txt`,
 	})
-	g, ok := bazelContext.GetOutputFiles(label, arch)
+	g, ok := bazelContext.GetOutputFiles(label, cfg)
 	if ok {
 		t.Errorf("Did not expect cquery results prior to running InvokeBazel(), but got %s", g)
 	}
@@ -21,7 +21,7 @@
 	if err != nil {
 		t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
 	}
-	g, ok = bazelContext.GetOutputFiles(label, arch)
+	g, ok = bazelContext.GetOutputFiles(label, cfg)
 	if !ok {
 		t.Errorf("Expected cquery results after running InvokeBazel(), but got none")
 	} else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) {
diff --git a/android/config.go b/android/config.go
index c8d7cfd..6060bce 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1578,6 +1578,10 @@
 	return c.config.productVariables.SepolicyFreezeTestExtraPrebuiltDirs
 }
 
+func (c *deviceConfig) GenerateAidlNdkPlatformBackend() bool {
+	return c.config.productVariables.GenerateAidlNdkPlatformBackend
+}
+
 // The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
 // Such lists are used in the build system for things like bootclasspath jars or system server jars.
 // The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
diff --git a/android/filegroup.go b/android/filegroup.go
index f8f0955..a79374d 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -118,14 +118,16 @@
 	}
 
 	archVariant := ctx.Arch().ArchType
+	osVariant := ctx.Os()
 	if len(fg.Srcs()) == 1 && fg.Srcs()[0].Base() == fg.Name() {
 		// This will be a regular file target, not filegroup, in Bazel.
 		// See FilegroupBp2Build for more information.
 		archVariant = Common
+		osVariant = CommonOS
 	}
 
 	bazelCtx := ctx.Config().BazelContext
-	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), archVariant)
+	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{archVariant, osVariant})
 	if !ok {
 		return
 	}
diff --git a/android/module.go b/android/module.go
index 327e6ae..02706ec 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2818,11 +2818,13 @@
 }
 
 func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
+	licenseFiles := m.Module().EffectiveLicenseFiles()
 	spec := PackagingSpec{
-		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
-		srcPath:          srcPath,
-		symlinkTarget:    "",
-		executable:       executable,
+		relPathInPackage:      Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+		srcPath:               srcPath,
+		symlinkTarget:         "",
+		executable:            executable,
+		effectiveLicenseFiles: &licenseFiles,
 	}
 	m.packagingSpecs = append(m.packagingSpecs, spec)
 	return spec
diff --git a/android/neverallow.go b/android/neverallow.go
index b8517a9..9098a71 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -150,6 +150,7 @@
 
 func createJavaDeviceForHostRules() []Rule {
 	javaDeviceForHostProjectsAllowedList := []string{
+		"development/build",
 		"external/guava",
 		"external/robolectric-shadows",
 		"frameworks/layoutlib",
diff --git a/android/notices.go b/android/notices.go
index 07cf3e4..d8cfaf2 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -100,3 +100,56 @@
 		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
 	}
 }
+
+// BuildNotices merges the supplied NOTICE files into a single file that lists notices
+// for every key in noticeMap (which would normally be installed files).
+func BuildNotices(ctx ModuleContext, noticeMap map[string]Paths) NoticeOutputs {
+	// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
+	//
+	// generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
+	// about input NOTICE file paths.
+	// 1. Their relative paths to the src root become their NOTICE index titles. We want to use
+	// on-device paths as titles, and so output the merged NOTICE file the corresponding location.
+	// 2. They must end with .txt extension. Otherwise, they're ignored.
+
+	mergeTool := PathForSource(ctx, "build/soong/scripts/mergenotice.py")
+	generateNoticeTool := PathForSource(ctx, "build/soong/scripts/generate-notice-files.py")
+
+	outputDir := PathForModuleOut(ctx, "notices")
+	builder := NewRuleBuilder(pctx, ctx).
+		Sbox(outputDir, PathForModuleOut(ctx, "notices.sbox.textproto"))
+	for _, installPath := range SortedStringKeys(noticeMap) {
+		noticePath := outputDir.Join(ctx, installPath+".txt")
+		// It would be nice if sbox created directories for temporaries, but until then
+		// this is simple enough.
+		builder.Command().
+			Text("(cd").OutputDir().Text("&&").
+			Text("mkdir -p").Text(filepath.Dir(installPath)).Text(")")
+		builder.Temporary(noticePath)
+		builder.Command().
+			Tool(mergeTool).
+			Flag("--output").Output(noticePath).
+			Inputs(noticeMap[installPath])
+	}
+
+	// Transform the merged NOTICE file into a gzipped HTML file.
+	txtOutput := outputDir.Join(ctx, "NOTICE.txt")
+	htmlOutput := outputDir.Join(ctx, "NOTICE.html")
+	htmlGzOutput := outputDir.Join(ctx, "NOTICE.html.gz")
+	title := "\"Notices for " + ctx.ModuleName() + "\""
+	builder.Command().Tool(generateNoticeTool).
+		FlagWithOutput("--text-output ", txtOutput).
+		FlagWithOutput("--html-output ", htmlOutput).
+		FlagWithArg("-t ", title).
+		Flag("-s").OutputDir()
+	builder.Command().BuiltTool("minigzip").
+		FlagWithInput("-c ", htmlOutput).
+		FlagWithOutput("> ", htmlGzOutput)
+	builder.Build("build_notices", "generate notice output")
+
+	return NoticeOutputs{
+		TxtOutput:    OptionalPathForPath(txtOutput),
+		HtmlOutput:   OptionalPathForPath(htmlOutput),
+		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
+	}
+}
diff --git a/android/packaging.go b/android/packaging.go
index 9065826..e3a0b54 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -38,6 +38,8 @@
 
 	// Whether relPathInPackage should be marked as executable or not
 	executable bool
+
+	effectiveLicenseFiles *Paths
 }
 
 // Get file name of installed package
@@ -54,6 +56,17 @@
 	return p.relPathInPackage
 }
 
+func (p *PackagingSpec) SetRelPathInPackage(relPathInPackage string) {
+	p.relPathInPackage = relPathInPackage
+}
+
+func (p *PackagingSpec) EffectiveLicenseFiles() Paths {
+	if p.effectiveLicenseFiles == nil {
+		return Paths{}
+	}
+	return *p.effectiveLicenseFiles
+}
+
 type PackageModule interface {
 	Module
 	packagingBase() *PackagingBase
@@ -214,15 +227,9 @@
 	return m
 }
 
-// See PackageModule.CopyDepsToZip
-func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) {
-	m := p.GatherPackagingSpecs(ctx)
-	builder := NewRuleBuilder(pctx, ctx)
-
-	dir := PathForModuleOut(ctx, ".zip")
-	builder.Command().Text("rm").Flag("-rf").Text(dir.String())
-	builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
-
+// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
+// entries into the specified directory.
+func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, m map[string]PackagingSpec, dir ModuleOutPath) (entries []string) {
 	seenDir := make(map[string]bool)
 	for _, k := range SortedStringKeys(m) {
 		ps := m[k]
@@ -243,6 +250,19 @@
 		}
 	}
 
+	return entries
+}
+
+// See PackageModule.CopyDepsToZip
+func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut WritablePath) (entries []string) {
+	m := p.GatherPackagingSpecs(ctx)
+	builder := NewRuleBuilder(pctx, ctx)
+
+	dir := PathForModuleOut(ctx, ".zip")
+	builder.Command().Text("rm").Flag("-rf").Text(dir.String())
+	builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
+	entries = p.CopySpecsToDir(ctx, builder, m, dir)
+
 	builder.Command().
 		BuiltTool("soong_zip").
 		FlagWithOutput("-o ", zipOut).
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index b2f8eaa..0ec9bcb 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -60,7 +60,7 @@
 			module_type: "test",
 			config_namespace: "acme",
 			variables: ["board", "feature1", "FEATURE3", "unused_string_var"],
-			bool_variables: ["feature2", "unused_feature"],
+			bool_variables: ["feature2", "unused_feature", "always_true"],
 			value_variables: ["size", "unused_size"],
 			properties: ["cflags", "srcs", "defaults"],
 		}
@@ -148,6 +148,11 @@
 			cflags: ["DEFAULT_B"],
 		}
 
+		test_defaults {
+			name: "foo_defaults_always_true",
+			cflags: ["DEFAULT_ALWAYS_TRUE"],
+		}
+
 		acme_test {
 			name: "foo_with_defaults",
 			cflags: ["-DGENERIC"],
@@ -176,6 +181,15 @@
 				FEATURE3: {
 					cflags: ["-DFEATURE3"],
 				},
+				always_true: {
+					defaults: ["foo_defaults_always_true"],
+					conditions_default: {
+						// verify that conditions_default is skipped if the
+						// soong config variable is true by specifying a
+						// non-existent module in conditions_default
+						defaults: ["//nonexistent:defaults"],
+					}
+				},
 			},
 		}
     `
@@ -205,6 +219,7 @@
 						"unused_feature":    "true", // unused
 						"unused_size":       "1",    // unused
 						"unused_string_var": "a",    // unused
+						"always_true":       "true",
 					},
 				}),
 				fooExpectedFlags: []string{
@@ -217,6 +232,7 @@
 				},
 				fooDefaultsExpectedFlags: []string{
 					"DEFAULT_A",
+					"DEFAULT_ALWAYS_TRUE",
 					"DEFAULT",
 					"-DGENERIC",
 					"-DSIZE=42",
@@ -227,7 +243,10 @@
 			{
 				name: "empty_prop_for_string_var",
 				preparer: fixtureForVendorVars(map[string]map[string]string{
-					"acme": {"board": "soc_c"}}),
+					"acme": {
+						"board":       "soc_c",
+						"always_true": "true",
+					}}),
 				fooExpectedFlags: []string{
 					"DEFAULT",
 					"-DGENERIC",
@@ -236,6 +255,7 @@
 					"-DF1_CONDITIONS_DEFAULT",
 				},
 				fooDefaultsExpectedFlags: []string{
+					"DEFAULT_ALWAYS_TRUE",
 					"DEFAULT",
 					"-DGENERIC",
 				},
@@ -243,7 +263,10 @@
 			{
 				name: "unused_string_var",
 				preparer: fixtureForVendorVars(map[string]map[string]string{
-					"acme": {"board": "soc_d"}}),
+					"acme": {
+						"board":       "soc_d",
+						"always_true": "true",
+					}}),
 				fooExpectedFlags: []string{
 					"DEFAULT",
 					"-DGENERIC",
@@ -253,14 +276,18 @@
 					"-DF1_CONDITIONS_DEFAULT",
 				},
 				fooDefaultsExpectedFlags: []string{
+					"DEFAULT_ALWAYS_TRUE",
 					"DEFAULT",
 					"-DGENERIC",
 				},
 			},
 
 			{
-				name:     "conditions_default",
-				preparer: fixtureForVendorVars(map[string]map[string]string{}),
+				name: "conditions_default",
+				preparer: fixtureForVendorVars(map[string]map[string]string{
+					"acme": {
+						"always_true": "true",
+					}}),
 				fooExpectedFlags: []string{
 					"DEFAULT",
 					"-DGENERIC",
@@ -270,6 +297,7 @@
 					"-DF1_CONDITIONS_DEFAULT",
 				},
 				fooDefaultsExpectedFlags: []string{
+					"DEFAULT_ALWAYS_TRUE",
 					"DEFAULT",
 					"-DGENERIC",
 				},
diff --git a/android/variable.go b/android/variable.go
index 4a82f23..baa6dfa 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -40,6 +40,7 @@
 		Platform_sdk_version struct {
 			Asflags []string
 			Cflags  []string
+			Cmd     *string
 		}
 
 		Platform_sdk_version_or_codename struct {
@@ -50,6 +51,10 @@
 			Cmd *string
 		}
 
+		Platform_version_name struct {
+			Base_dir *string
+		}
+
 		// unbundled_build is a catch-all property to annotate modules that don't build in one or
 		// more unbundled branches, usually due to dependencies missing from the manifest.
 		Unbundled_build struct {
@@ -414,6 +419,8 @@
 
 	SepolicyFreezeTestExtraDirs         []string `json:",omitempty"`
 	SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
+
+	GenerateAidlNdkPlatformBackend bool `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/android_sdk/Android.bp b/android_sdk/Android.bp
new file mode 100644
index 0000000..e686d59
--- /dev/null
+++ b/android_sdk/Android.bp
@@ -0,0 +1,22 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-android-sdk",
+    pkgPath: "android/soong/android_sdk",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-cc-config",
+    ],
+    srcs: [
+        "sdk_repo_host.go",
+    ],
+    testSrcs: [
+        "sdk_repo_host_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
new file mode 100644
index 0000000..d64eb7a
--- /dev/null
+++ b/android_sdk/sdk_repo_host.go
@@ -0,0 +1,294 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android_sdk
+
+import (
+	"fmt"
+	"io"
+	"path/filepath"
+	"strings"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/pathtools"
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/cc/config"
+)
+
+var pctx = android.NewPackageContext("android/soong/android_sdk")
+
+func init() {
+	registerBuildComponents(android.InitRegistrationContext)
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("android_sdk_repo_host", SdkRepoHostFactory)
+}
+
+type sdkRepoHost struct {
+	android.ModuleBase
+	android.PackagingBase
+
+	properties sdkRepoHostProperties
+
+	outputBaseName string
+	outputFile     android.OptionalPath
+}
+
+type remapProperties struct {
+	From string
+	To   string
+}
+
+type sdkRepoHostProperties struct {
+	// The top level directory to use for the SDK repo.
+	Base_dir *string
+
+	// List of src:dst mappings to rename files from `deps`.
+	Deps_remap []remapProperties `android:"arch_variant"`
+
+	// List of zip files to merge into the SDK repo.
+	Merge_zips []string `android:"arch_variant,path"`
+
+	// List of sources to include into the SDK repo. These are usually raw files, filegroups,
+	// or genrules, as most built modules should be referenced via `deps`.
+	Srcs []string `android:"arch_variant,path"`
+
+	// List of files to strip. This should be a list of files, not modules. This happens after
+	// `deps_remap` and `merge_zips` are applied, but before the `base_dir` is added.
+	Strip_files []string `android:"arch_variant"`
+}
+
+// android_sdk_repo_host defines an Android SDK repo containing host tools.
+//
+// This implementation is trying to be a faithful reproduction of how these sdk-repos were produced
+// in the Make system, which may explain some of the oddities (like `strip_files` not being
+// automatic)
+func SdkRepoHostFactory() android.Module {
+	return newSdkRepoHostModule()
+}
+
+func newSdkRepoHostModule() *sdkRepoHost {
+	s := &sdkRepoHost{}
+	s.AddProperties(&s.properties)
+	android.InitPackageModule(s)
+	android.InitAndroidMultiTargetsArchModule(s, android.HostSupported, android.MultilibCommon)
+	return s
+}
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	android.PackagingItemAlwaysDepTag
+}
+
+// TODO(b/201696252): Evaluate whether licenses should be propagated through this dependency.
+func (d dependencyTag) PropagateLicenses() bool {
+	return false
+}
+
+var depTag = dependencyTag{}
+
+func (s *sdkRepoHost) DepsMutator(ctx android.BottomUpMutatorContext) {
+	s.AddDeps(ctx, depTag)
+}
+
+func (s *sdkRepoHost) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	dir := android.PathForModuleOut(ctx, "zip")
+	builder := android.NewRuleBuilder(pctx, ctx).
+		Sbox(dir, android.PathForModuleOut(ctx, "out.sbox.textproto")).
+		SandboxInputs()
+
+	// Get files from modules listed in `deps`
+	packageSpecs := s.GatherPackagingSpecs(ctx)
+
+	// Handle `deps_remap` renames
+	err := remapPackageSpecs(packageSpecs, s.properties.Deps_remap)
+	if err != nil {
+		ctx.PropertyErrorf("deps_remap", "%s", err.Error())
+	}
+
+	s.CopySpecsToDir(ctx, builder, packageSpecs, dir)
+
+	// Collect licenses to write into NOTICE.txt
+	noticeMap := map[string]android.Paths{}
+	for path, pkgSpec := range packageSpecs {
+		licenseFiles := pkgSpec.EffectiveLicenseFiles()
+		if len(licenseFiles) > 0 {
+			noticeMap[path] = pkgSpec.EffectiveLicenseFiles()
+		}
+	}
+	notices := android.BuildNotices(ctx, noticeMap)
+	builder.Command().Text("cp").
+		Input(notices.TxtOutput.Path()).
+		Text(filepath.Join(dir.String(), "NOTICE.txt"))
+
+	// Handle `merge_zips` by extracting their contents into our tmpdir
+	for _, zip := range android.PathsForModuleSrc(ctx, s.properties.Merge_zips) {
+		builder.Command().
+			Text("unzip").
+			Flag("-DD").
+			Flag("-q").
+			FlagWithArg("-d ", dir.String()).
+			Input(zip)
+	}
+
+	// Copy files from `srcs` into our tmpdir
+	for _, src := range android.PathsForModuleSrc(ctx, s.properties.Srcs) {
+		builder.Command().
+			Text("cp").Input(src).Flag(dir.Join(ctx, src.Rel()).String())
+	}
+
+	// Handle `strip_files` by calling the necessary strip commands
+	//
+	// Note: this stripping logic was copied over from the old Make implementation
+	// It's not using the same flags as the regular stripping support, nor does it
+	// support the array of per-module stripping options. It would be nice if we
+	// pulled the stripped versions from the CC modules, but that doesn't exist
+	// for host tools today. (And not all the things we strip are CC modules today)
+	if ctx.Darwin() {
+		macStrip := config.MacStripPath(ctx)
+		for _, strip := range s.properties.Strip_files {
+			builder.Command().
+				Text(macStrip).Flag("-x").
+				Flag(dir.Join(ctx, strip).String())
+		}
+	} else {
+		llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
+		llvmLib := config.ClangPath(ctx, "lib64/libc++.so.1")
+		for _, strip := range s.properties.Strip_files {
+			cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib)
+			if !ctx.Windows() {
+				cmd.Flag("-x")
+			}
+			cmd.Flag(dir.Join(ctx, strip).String())
+		}
+	}
+
+	// Fix up the line endings of all text files. This also removes executable permissions.
+	builder.Command().
+		Text("find").
+		Flag(dir.String()).
+		Flag("-name '*.aidl' -o -name '*.css' -o -name '*.html' -o -name '*.java'").
+		Flag("-o -name '*.js' -o -name '*.prop' -o -name '*.template'").
+		Flag("-o -name '*.txt' -o -name '*.windows' -o -name '*.xml' -print0").
+		// Using -n 500 for xargs to limit the max number of arguments per call to line_endings
+		// to 500. This avoids line_endings failing with "arguments too long".
+		Text("| xargs -0 -n 500 ").
+		BuiltTool("line_endings").
+		Flag("unix")
+
+	// Exclude some file types (roughly matching sdk.exclude.atree)
+	builder.Command().
+		Text("find").
+		Flag(dir.String()).
+		Flag("'('").
+		Flag("-name '.*' -o -name '*~' -o -name 'Makefile' -o -name 'Android.mk' -o").
+		Flag("-name '.*.swp' -o -name '.DS_Store' -o -name '*.pyc' -o -name 'OWNERS' -o").
+		Flag("-name 'MODULE_LICENSE_*' -o -name '*.ezt' -o -name 'Android.bp'").
+		Flag("')' -print0").
+		Text("| xargs -0 -r rm -rf")
+	builder.Command().
+		Text("find").
+		Flag(dir.String()).
+		Flag("-name '_*' ! -name '__*' -print0").
+		Text("| xargs -0 -r rm -rf")
+
+	if ctx.Windows() {
+		// Fix EOL chars to make window users happy
+		builder.Command().
+			Text("find").
+			Flag(dir.String()).
+			Flag("-maxdepth 2 -name '*.bat' -type f -print0").
+			Text("| xargs -0 -r unix2dos")
+	}
+
+	// Zip up our temporary directory as the sdk-repo
+	outputZipFile := dir.Join(ctx, "output.zip")
+	builder.Command().
+		BuiltTool("soong_zip").
+		FlagWithOutput("-o ", outputZipFile).
+		FlagWithArg("-P ", proptools.StringDefault(s.properties.Base_dir, ".")).
+		FlagWithArg("-C ", dir.String()).
+		FlagWithArg("-D ", dir.String())
+	builder.Command().Text("rm").Flag("-rf").Text(dir.String())
+
+	builder.Build("build_sdk_repo", "Creating sdk-repo-"+s.BaseModuleName())
+
+	osName := ctx.Os().String()
+	if osName == "linux_glibc" {
+		osName = "linux"
+	}
+	name := fmt.Sprintf("sdk-repo-%s-%s", osName, s.BaseModuleName())
+
+	s.outputBaseName = name
+	s.outputFile = android.OptionalPathForPath(outputZipFile)
+	ctx.InstallFile(android.PathForModuleInstall(ctx, "sdk-repo"), name+".zip", outputZipFile)
+}
+
+func (s *sdkRepoHost) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+			fmt.Fprintln(w, ".PHONY:", name, "sdk_repo", "sdk-repo-"+name)
+			fmt.Fprintln(w, "sdk_repo", "sdk-repo-"+name+":", strings.Join(s.FilesToInstall().Strings(), " "))
+
+			fmt.Fprintf(w, "$(call dist-for-goals,sdk_repo sdk-repo-%s,%s:%s-$(FILE_NAME_TAG).zip)\n\n", s.BaseModuleName(), s.outputFile.String(), s.outputBaseName)
+		},
+	}
+}
+
+func remapPackageSpecs(specs map[string]android.PackagingSpec, remaps []remapProperties) error {
+	for _, remap := range remaps {
+		for path, spec := range specs {
+			if match, err := pathtools.Match(remap.From, path); err != nil {
+				return fmt.Errorf("Error parsing %q: %v", remap.From, err)
+			} else if match {
+				newPath := remap.To
+				if pathtools.IsGlob(remap.From) {
+					rel, err := filepath.Rel(constantPartOfPattern(remap.From), path)
+					if err != nil {
+						return fmt.Errorf("Error handling %q", path)
+					}
+					newPath = filepath.Join(remap.To, rel)
+				}
+				delete(specs, path)
+				spec.SetRelPathInPackage(newPath)
+				specs[newPath] = spec
+			}
+		}
+	}
+	return nil
+}
+
+func constantPartOfPattern(pattern string) string {
+	ret := ""
+	for pattern != "" {
+		var first string
+		first, pattern = splitFirst(pattern)
+		if pathtools.IsGlob(first) {
+			return ret
+		}
+		ret = filepath.Join(ret, first)
+	}
+	return ret
+}
+
+func splitFirst(path string) (string, string) {
+	i := strings.IndexRune(path, filepath.Separator)
+	if i < 0 {
+		return path, ""
+	}
+	return path[:i], path[i+1:]
+}
diff --git a/android_sdk/sdk_repo_host_test.go b/android_sdk/sdk_repo_host_test.go
new file mode 100644
index 0000000..0688921
--- /dev/null
+++ b/android_sdk/sdk_repo_host_test.go
@@ -0,0 +1,124 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android_sdk
+
+import (
+	"fmt"
+	"runtime"
+	"sort"
+	"testing"
+
+	"android/soong/android"
+	"android/soong/cc"
+
+	"github.com/google/blueprint/pathtools"
+)
+
+var fixture = android.GroupFixturePreparers(
+	android.PrepareForIntegrationTestWithAndroid,
+	cc.PrepareForIntegrationTestWithCc,
+	android.FixtureRegisterWithContext(registerBuildComponents),
+)
+
+func TestSdkRepoHostDeps(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skipf("Skipping sdk_repo_host testing that is only supported on linux not %s", runtime.GOOS)
+	}
+
+	result := fixture.RunTestWithBp(t, `
+		android_sdk_repo_host {
+			name: "platform-tools",
+		}
+	`)
+
+	// produces "sdk-repo-{OS}-platform-tools.zip"
+	result.ModuleForTests("platform-tools", "linux_glibc_common").Output("sdk-repo-linux-platform-tools.zip")
+}
+
+func TestRemapPackageSpecs(t *testing.T) {
+	testcases := []struct {
+		name   string
+		input  []string
+		remaps []remapProperties
+		output []string
+		err    string
+	}{
+		{
+			name:  "basic remap",
+			input: []string{"a", "c"},
+			remaps: []remapProperties{
+				{From: "a", To: "b"},
+			},
+			output: []string{"b", "c"},
+		},
+		{
+			name:  "non-matching remap",
+			input: []string{"a"},
+			remaps: []remapProperties{
+				{From: "b", To: "c"},
+			},
+			output: []string{"a"},
+		},
+		{
+			name:  "glob",
+			input: []string{"bin/d", "liba.so", "libb.so", "lib/c.so"},
+			remaps: []remapProperties{
+				{From: "lib*.so", To: "lib/"},
+			},
+			output: []string{"bin/d", "lib/c.so", "lib/liba.so", "lib/libb.so"},
+		},
+		{
+			name:  "bad glob",
+			input: []string{"a"},
+			remaps: []remapProperties{
+				{From: "**", To: "./"},
+			},
+			err: fmt.Sprintf("Error parsing \"**\": %v", pathtools.GlobLastRecursiveErr.Error()),
+		},
+		{
+			name:  "globbed dirs",
+			input: []string{"a/b/c"},
+			remaps: []remapProperties{
+				{From: "a/*/c", To: "./"},
+			},
+			output: []string{"b/c"},
+		},
+	}
+
+	for _, test := range testcases {
+		t.Run(test.name, func(t *testing.T) {
+			specs := map[string]android.PackagingSpec{}
+			for _, input := range test.input {
+				spec := android.PackagingSpec{}
+				spec.SetRelPathInPackage(input)
+				specs[input] = spec
+			}
+
+			err := remapPackageSpecs(specs, test.remaps)
+
+			if test.err != "" {
+				android.AssertErrorMessageEquals(t, "", test.err, err)
+			} else {
+				outputs := []string{}
+				for path, spec := range specs {
+					android.AssertStringEquals(t, "path does not match rel path", path, spec.RelPathInPackage())
+					outputs = append(outputs, path)
+				}
+				sort.Strings(outputs)
+				android.AssertArrayString(t, "outputs mismatch", test.output, outputs)
+			}
+		})
+	}
+}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 963e905..f3ad152 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -639,6 +639,12 @@
 	if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" {
 		fixed = val.Strings[1]
 		varname = val.Variables[0].Name.Strings[0]
+		// TARGET_OUT_OPTIONAL_EXECUTABLES puts the artifact in xbin, which is
+		// deprecated. TARGET_OUT_DATA_APPS install location will be handled
+		// automatically by Soong
+		if varname == "TARGET_OUT_OPTIONAL_EXECUTABLES" || varname == "TARGET_OUT_DATA_APPS" {
+			return nil
+		}
 	} else if len(val.Variables) == 2 && varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && varLiteralName(val.Variables[1]) == "TARGET_COPY_OUT_VENDOR" &&
 		len(val.Strings) == 3 && val.Strings[0] == "" && val.Strings[1] == "/" {
 		fixed = val.Strings[2]
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 9fd4ff9..775a9a8 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1516,7 +1516,23 @@
     ],
 }
 `,
-	},
+	}, {
+		desc: "Obsolete LOCAL_MODULE_PATH",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_CTS_TEST_PACKAGE := bar
+LOCAL_USE_AAPT2 := blah
+include $(BUILD_PACKAGE)
+`,
+		expected: `
+android_app {
+  name: "foo",
+
+}
+`},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/apex/apex.go b/apex/apex.go
index 7ac3bc8..1f06187 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -158,8 +158,8 @@
 	// is 'image'.
 	Payload_type *string
 
-	// The type of filesystem to use when the payload_type is 'image'. Either 'ext4' or 'f2fs'.
-	// Default 'ext4'.
+	// The type of filesystem to use when the payload_type is 'image'. Either 'ext4', 'f2fs'
+	// or 'erofs'. Default 'ext4'.
 	Payload_fs_type *string
 
 	// For telling the APEX to ignore special handling for system libraries such as bionic.
@@ -348,7 +348,6 @@
 	// Flags for special variants of APEX
 	testApex bool
 	vndkApex bool
-	artApex  bool
 
 	// Tells whether this variant of the APEX bundle is the primary one or not. Only the primary
 	// one gets installed to the device.
@@ -754,13 +753,6 @@
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
 	ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
 
-	if a.artApex {
-		// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
-		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-			ctx.AddFarVariationDependencies(commonVariation, javaLibTag, "jacocoagent")
-		}
-	}
-
 	// Marks that this APEX (in fact all the modules in it) has to be built with the given SDKs.
 	// This field currently isn't used.
 	// TODO(jiyong): consider dropping this feature
@@ -1151,8 +1143,9 @@
 	zipApexType       = "zip"
 	flattenedApexType = "flattened"
 
-	ext4FsType = "ext4"
-	f2fsFsType = "f2fs"
+	ext4FsType  = "ext4"
+	f2fsFsType  = "f2fs"
+	erofsFsType = "erofs"
 )
 
 // The suffix for the output "file", not the module
@@ -1625,6 +1618,7 @@
 const (
 	ext4 fsType = iota
 	f2fs
+	erofs
 )
 
 func (f fsType) string() string {
@@ -1633,6 +1627,8 @@
 		return ext4FsType
 	case f2fs:
 		return f2fsFsType
+	case erofs:
+		return erofsFsType
 	default:
 		panic(fmt.Errorf("unknown APEX payload type %d", f))
 	}
@@ -1679,6 +1675,9 @@
 		if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
 			return false
 		}
+		if mod, ok := child.(android.Module); ok && !mod.Enabled() {
+			return false
+		}
 		depName := ctx.OtherModuleName(child)
 		if _, isDirectDep := parent.(*apexBundle); isDirectDep {
 			switch depTag {
@@ -2056,8 +2055,10 @@
 		a.payloadFsType = ext4
 	case f2fsFsType:
 		a.payloadFsType = f2fs
+	case erofsFsType:
+		a.payloadFsType = erofs
 	default:
-		ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs]", *a.properties.Payload_fs_type)
+		ctx.PropertyErrorf("payload_fs_type", "%q is not a valid filesystem for apex [ext4, f2fs, erofs]", *a.properties.Payload_fs_type)
 	}
 
 	// Optimization. If we are building bundled APEX, for the files that are gathered due to the
@@ -2194,10 +2195,9 @@
 	return module
 }
 
-func ApexBundleFactory(testApex bool, artApex bool) android.Module {
+func ApexBundleFactory(testApex bool) android.Module {
 	bundle := newApexBundle()
 	bundle.testApex = testApex
-	bundle.artApex = artApex
 	return bundle
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5d7a1be..78a6bb8 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3183,7 +3183,6 @@
 				"myapex",
 				"otherapex",
 			],
-			use_apex_name_macro: true,
 			recovery_available: true,
 			min_sdk_version: "29",
 		}
@@ -3198,13 +3197,11 @@
 	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=10000")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
 
 	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=29")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
 
 	// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
 	// each variant defines additional macros to distinguish which apex variant it is built for
@@ -3213,42 +3210,15 @@
 	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 
-	// APEX variant has __ANDROID_APEX__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
-
-	// APEX variant has __ANDROID_APEX__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
-
 	// recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
 	mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
 
-	// When a dependency of a cc_library sets use_apex_name_macro: true each apex gets a unique
-	// variant.
-
 	// non-APEX variant does not have __ANDROID_APEX__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 
-	// APEX variant has __ANDROID_APEX__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
-
-	// APEX variant has __ANDROID_APEX__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
-	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
-
 	// recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
 	mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
@@ -8289,6 +8259,75 @@
 	`)
 }
 
+func TestAndroidMk_DexpreoptBuiltInstalledForApex(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			updatable: false,
+			java_libs: ["foo"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_library {
+			name: "foo",
+			srcs: ["foo.java"],
+			apex_available: ["myapex"],
+			installable: true,
+		}
+	`,
+		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+	)
+
+	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
+	var builder strings.Builder
+	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
+	androidMk := builder.String()
+	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex")
+}
+
+func TestAndroidMk_DexpreoptBuiltInstalledForApex_Prebuilt(t *testing.T) {
+	ctx := testApex(t, `
+		prebuilt_apex {
+			name: "myapex",
+			arch: {
+				arm64: {
+					src: "myapex-arm64.apex",
+				},
+				arm: {
+					src: "myapex-arm.apex",
+				},
+			},
+			exported_java_libs: ["foo"],
+		}
+
+		java_import {
+			name: "foo",
+			jars: ["foo.jar"],
+			installable: true,
+		}
+	`,
+		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+	)
+
+	prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
+	entriesList := android.AndroidMkEntriesForTest(t, ctx, prebuilt)
+	mainModuleEntries := entriesList[0]
+	android.AssertArrayString(t,
+		"LOCAL_REQUIRED_MODULES",
+		mainModuleEntries.EntryMap["LOCAL_REQUIRED_MODULES"],
+		[]string{
+			"foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex",
+			"foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex",
+		})
+}
+
 func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 }
diff --git a/apex/builder.go b/apex/builder.go
index c05c20c..772f789 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -65,6 +65,7 @@
 	pctx.HostBinToolVariable("extract_apks", "extract_apks")
 	pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
 	pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
+	pctx.HostBinToolVariable("make_erofs", "make_erofs")
 	pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
 	pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
 }
@@ -120,7 +121,7 @@
 			`--payload_type image ` +
 			`--key ${key} ${opt_flags} ${image_dir} ${out} `,
 		CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
-			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}",
+			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}", "${make_erofs}",
 			"${soong_zip}", "${zipalign}", "${aapt2}", "prebuilts/sdk/current/public/android.jar"},
 		Rspfile:        "${out}.copy_commands",
 		RspfileContent: "${copy_commands}",
@@ -715,12 +716,10 @@
 			}
 		}
 		apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
-		ndkLibraryList := android.PathForSource(ctx, "system/core/rootdir/etc/public.libraries.android.txt")
 		rule := android.NewRuleBuilder(pctx, ctx)
 		rule.Command().
 			Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
 			Output(apisBackedbyOutputFile).
-			Input(ndkLibraryList).
 			Flags(libNames)
 		rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
 		a.apisBackedByModuleFile = apisBackedbyOutputFile
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 53ef4d7..61e7a0b 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -264,17 +264,6 @@
 				// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
 				// we will have foo.jar.jar
 				entries.SetString("LOCAL_MODULE_STEM", strings.TrimSuffix(fi.stem(), ".jar"))
-				var classesJar android.Path
-				var headerJar android.Path
-				if javaModule, ok := fi.module.(java.ApexDependency); ok {
-					classesJar = javaModule.ImplementationAndResourcesJars()[0]
-					headerJar = javaModule.HeaderJars()[0]
-				} else {
-					classesJar = fi.builtFile
-					headerJar = fi.builtFile
-				}
-				entries.SetString("LOCAL_SOONG_CLASSES_JAR", classesJar.String())
-				entries.SetString("LOCAL_SOONG_HEADER_JAR", headerJar.String())
 				entries.SetString("LOCAL_SOONG_DEX_JAR", fi.builtFile.String())
 				entries.SetString("LOCAL_DEX_PREOPT", "false")
 			},
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 8741afb..0dedcf4 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -246,7 +246,8 @@
 			outDir := proptools.ShellEscapeIncludingSpaces(filepath.Dir(out))
 			out = proptools.ShellEscapeIncludingSpaces(out)
 			in := proptools.ShellEscapeIncludingSpaces(inputPaths[0])
-			buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -rsf %[3]s %[2]s", outDir, out, in)
+			// Use hard links, because some soong actions expect real files (for example, `cp -d`).
+			buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -f %[3]s %[2]s", outDir, out, in)
 			buildStatement.SymlinkPaths = outputPaths[:]
 		} else if len(actionEntry.Arguments) < 1 {
 			return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 43e4155..88066c8 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -859,7 +859,7 @@
 		BuildStatement{
 			Command: "mkdir -p one/symlink_subdir && " +
 				"rm -f one/symlink_subdir/symlink && " +
-				"ln -rsf one/file_subdir/file one/symlink_subdir/symlink",
+				"ln -f one/file_subdir/file one/symlink_subdir/symlink",
 			InputPaths:   []string{"one/file_subdir/file"},
 			OutputPaths:  []string{"one/symlink_subdir/symlink"},
 			SymlinkPaths: []string{"one/symlink_subdir/symlink"},
@@ -923,7 +923,7 @@
 		BuildStatement{
 			Command: "mkdir -p 'one/symlink subdir' && " +
 				"rm -f 'one/symlink subdir/symlink' && " +
-				"ln -rsf 'one/file subdir/file' 'one/symlink subdir/symlink'",
+				"ln -f 'one/file subdir/file' 'one/symlink subdir/symlink'",
 			InputPaths:   []string{"one/file subdir/file"},
 			OutputPaths:  []string{"one/symlink subdir/symlink"},
 			SymlinkPaths: []string{"one/symlink subdir/symlink"},
diff --git a/bazel/properties.go b/bazel/properties.go
index ee32e73..6a06c1b 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -164,48 +164,36 @@
 // Subtract needle from haystack
 func SubtractStrings(haystack []string, needle []string) []string {
 	// This is really a set
-	remainder := make(map[string]bool)
-
-	for _, s := range haystack {
-		remainder[s] = true
-	}
+	needleMap := make(map[string]bool)
 	for _, s := range needle {
-		delete(remainder, s)
+		needleMap[s] = true
 	}
 
 	var strings []string
-	for s, _ := range remainder {
-		strings = append(strings, s)
+	for _, s := range haystack {
+		if exclude := needleMap[s]; !exclude {
+			strings = append(strings, s)
+		}
 	}
 
-	sort.SliceStable(strings, func(i, j int) bool {
-		return strings[i] < strings[j]
-	})
-
 	return strings
 }
 
 // Subtract needle from haystack
 func SubtractBazelLabels(haystack []Label, needle []Label) []Label {
 	// This is really a set
-	remainder := make(map[Label]bool)
-
-	for _, label := range haystack {
-		remainder[label] = true
-	}
-	for _, label := range needle {
-		delete(remainder, label)
+	needleMap := make(map[Label]bool)
+	for _, s := range needle {
+		needleMap[s] = true
 	}
 
 	var labels []Label
-	for label, _ := range remainder {
-		labels = append(labels, label)
+	for _, label := range haystack {
+		if exclude := needleMap[label]; !exclude {
+			labels = append(labels, label)
+		}
 	}
 
-	sort.SliceStable(labels, func(i, j int) bool {
-		return labels[i].Label < labels[j].Label
-	})
-
 	return labels
 }
 
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 45a3cb6..b0c3899 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -15,11 +15,12 @@
 package bp2build
 
 import (
-	"android/soong/android"
-	"android/soong/bazel"
 	"fmt"
 	"os"
 	"strings"
+
+	"android/soong/android"
+	"android/soong/bazel"
 )
 
 // Codegen is the backend of bp2build. The code generator is responsible for
@@ -43,7 +44,7 @@
 	writeFiles(ctx, bp2buildDir, bp2buildFiles)
 
 	soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
-	writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(res.metrics))
+	writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics))
 
 	return res.metrics
 }
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index f14574c..ee1d862 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -223,6 +223,7 @@
 func TestGenerateBazelTargetModules(t *testing.T) {
 	testCases := []bp2buildTestCase{
 		{
+			description: "string props",
 			blueprint: `custom {
 	name: "foo",
     string_list_prop: ["a", "b"],
@@ -240,6 +241,7 @@
 			},
 		},
 		{
+			description: "control characters",
 			blueprint: `custom {
 	name: "control_characters",
     string_list_prop: ["\t", "\n"],
@@ -257,6 +259,7 @@
 			},
 		},
 		{
+			description: "handles dep",
 			blueprint: `custom {
   name: "has_dep",
   arch_paths: [":dep"],
@@ -279,25 +282,98 @@
 			},
 		},
 		{
+			description: "arch-variant srcs",
 			blueprint: `custom {
     name: "arch_paths",
     arch: {
-      x86: {
-        arch_paths: ["abc"],
-      },
+      x86: { arch_paths: ["x86.txt"] },
+      x86_64:  { arch_paths: ["x86_64.txt"] },
+      arm:  { arch_paths: ["arm.txt"] },
+      arm64:  { arch_paths: ["arm64.txt"] },
+    },
+    target: {
+      linux: { arch_paths: ["linux.txt"] },
+      bionic: { arch_paths: ["bionic.txt"] },
+      host: { arch_paths: ["host.txt"] },
+      not_windows: { arch_paths: ["not_windows.txt"] },
+      android: { arch_paths: ["android.txt"] },
+      linux_musl: { arch_paths: ["linux_musl.txt"] },
+      musl: { arch_paths: ["musl.txt"] },
+      linux_glibc: { arch_paths: ["linux_glibc.txt"] },
+      glibc: { arch_paths: ["glibc.txt"] },
+      linux_bionic: { arch_paths: ["linux_bionic.txt"] },
+      darwin: { arch_paths: ["darwin.txt"] },
+      windows: { arch_paths: ["windows.txt"] },
+    },
+    multilib: {
+        lib32: { arch_paths: ["lib32.txt"] },
+        lib64: { arch_paths: ["lib64.txt"] },
     },
     bazel_module: { bp2build_available: true },
 }`,
 			expectedBazelTargets: []string{`custom(
     name = "arch_paths",
     arch_paths = select({
-        "//build/bazel/platforms/arch:x86": ["abc"],
+        "//build/bazel/platforms/arch:arm": [
+            "arm.txt",
+            "lib32.txt",
+        ],
+        "//build/bazel/platforms/arch:arm64": [
+            "arm64.txt",
+            "lib64.txt",
+        ],
+        "//build/bazel/platforms/arch:x86": [
+            "x86.txt",
+            "lib32.txt",
+        ],
+        "//build/bazel/platforms/arch:x86_64": [
+            "x86_64.txt",
+            "lib64.txt",
+        ],
+        "//conditions:default": [],
+    }) + select({
+        "//build/bazel/platforms/os:android": [
+            "linux.txt",
+            "bionic.txt",
+            "android.txt",
+        ],
+        "//build/bazel/platforms/os:darwin": [
+            "host.txt",
+            "darwin.txt",
+            "not_windows.txt",
+        ],
+        "//build/bazel/platforms/os:linux": [
+            "host.txt",
+            "linux.txt",
+            "glibc.txt",
+            "linux_glibc.txt",
+            "not_windows.txt",
+        ],
+        "//build/bazel/platforms/os:linux_bionic": [
+            "host.txt",
+            "linux.txt",
+            "bionic.txt",
+            "linux_bionic.txt",
+            "not_windows.txt",
+        ],
+        "//build/bazel/platforms/os:linux_musl": [
+            "host.txt",
+            "linux.txt",
+            "musl.txt",
+            "linux_musl.txt",
+            "not_windows.txt",
+        ],
+        "//build/bazel/platforms/os:windows": [
+            "host.txt",
+            "windows.txt",
+        ],
         "//conditions:default": [],
     }),
 )`,
 			},
 		},
 		{
+			description: "arch-variant deps",
 			blueprint: `custom {
   name: "has_dep",
   arch: {
@@ -327,6 +403,7 @@
 			},
 		},
 		{
+			description: "embedded props",
 			blueprint: `custom {
     name: "embedded_props",
     embedded_prop: "abc",
@@ -339,6 +416,7 @@
 			},
 		},
 		{
+			description: "ptr to embedded props",
 			blueprint: `custom {
     name: "ptr_to_embedded_props",
     other_embedded_prop: "abc",
@@ -354,38 +432,40 @@
 
 	dir := "."
 	for _, testCase := range testCases {
-		config := android.TestConfig(buildDir, nil, testCase.blueprint, nil)
-		ctx := android.NewTestContext(config)
+		t.Run(testCase.description, func(t *testing.T) {
+			config := android.TestConfig(buildDir, nil, testCase.blueprint, nil)
+			ctx := android.NewTestContext(config)
 
-		registerCustomModuleForBp2buildConversion(ctx)
+			registerCustomModuleForBp2buildConversion(ctx)
 
-		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		if errored(t, testCase, errs) {
-			continue
-		}
-		_, errs = ctx.ResolveDependencies(config)
-		if errored(t, testCase, errs) {
-			continue
-		}
+			_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+			if errored(t, testCase, errs) {
+				return
+			}
+			_, errs = ctx.ResolveDependencies(config)
+			if errored(t, testCase, errs) {
+				return
+			}
 
-		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
-		android.FailIfErrored(t, err)
+			codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+			bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
+			android.FailIfErrored(t, err)
 
-		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
-			t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
-		} else {
-			for i, expectedBazelTarget := range testCase.expectedBazelTargets {
-				actualBazelTarget := bazelTargets[i]
-				if actualBazelTarget.content != expectedBazelTarget {
-					t.Errorf(
-						"Expected generated Bazel target to be '%s', got '%s'",
-						expectedBazelTarget,
-						actualBazelTarget.content,
-					)
+			if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+				t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
+			} else {
+				for i, expectedBazelTarget := range testCase.expectedBazelTargets {
+					actualBazelTarget := bazelTargets[i]
+					if actualBazelTarget.content != expectedBazelTarget {
+						t.Errorf(
+							"Expected generated Bazel target to be '%s', got '%s'",
+							expectedBazelTarget,
+							actualBazelTarget.content,
+						)
+					}
 				}
 			}
-		}
+		})
 	}
 }
 
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
new file mode 100644
index 0000000..3a07128
--- /dev/null
+++ b/bp2build/cc_binary_conversion_test.go
@@ -0,0 +1,415 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/cc"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+const (
+	ccBinaryTypePlaceHolder   = "{rule_name}"
+	compatibleWithPlaceHolder = "{target_compatible_with}"
+)
+
+func registerCcBinaryModuleTypes(ctx android.RegistrationContext) {
+	cc.RegisterCCBuildComponents(ctx)
+	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
+	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
+}
+
+var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary", compatibleWithPlaceHolder, "")
+var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host", compatibleWithPlaceHolder, `
+    target_compatible_with = select({
+        "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),`)
+
+func runCcBinaryTests(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	runCcBinaryTestCase(t, tc)
+	runCcHostBinaryTestCase(t, tc)
+}
+
+func runCcBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	testCase := tc
+	testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
+	testCase.moduleTypeUnderTest = "cc_binary"
+	testCase.moduleTypeUnderTestFactory = cc.BinaryFactory
+	testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryBp2build
+	testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
+	testCase.blueprint = binaryReplacer.Replace(testCase.blueprint)
+	for i, et := range testCase.expectedBazelTargets {
+		testCase.expectedBazelTargets[i] = binaryReplacer.Replace(et)
+	}
+	t.Run(testCase.description, func(t *testing.T) {
+		runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
+	})
+}
+
+func runCcHostBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	testCase := tc
+	testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
+	testCase.moduleTypeUnderTest = "cc_binary_host"
+	testCase.moduleTypeUnderTestFactory = cc.BinaryHostFactory
+	testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryHostBp2build
+	testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
+	testCase.blueprint = hostBinaryReplacer.Replace(testCase.blueprint)
+	for i, et := range testCase.expectedBazelTargets {
+		testCase.expectedBazelTargets[i] = hostBinaryReplacer.Replace(et)
+	}
+	t.Run(testCase.description, func(t *testing.T) {
+		runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
+	})
+}
+
+func TestBasicCcBinary(t *testing.T) {
+	runCcBinaryTests(t, bp2buildTestCase{
+		description: "basic -- properties -> attrs with little/no transformation",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    srcs: ["a.cc"],
+    local_include_dirs: ["dir"],
+    include_dirs: ["absolute_dir"],
+    cflags: ["-Dcopt"],
+    cppflags: ["-Dcppflag"],
+    conlyflags: ["-Dconlyflag"],
+    asflags: ["-Dasflag"],
+    ldflags: ["ld-flag"],
+    rtti: true,
+    strip: {
+        all: true,
+        keep_symbols: true,
+        keep_symbols_and_debug_frame: true,
+        keep_symbols_list: ["symbol"],
+        none: true,
+    },
+}
+`,
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    absolute_includes = ["absolute_dir"],
+    asflags = ["-Dasflag"],
+    conlyflags = ["-Dconlyflag"],
+    copts = ["-Dcopt"],
+    cppflags = ["-Dcppflag"],
+    linkopts = ["ld-flag"],
+    local_includes = [
+        "dir",
+        ".",
+    ],
+    rtti = True,
+    srcs = ["a.cc"],
+    strip = {
+        "all": True,
+        "keep_symbols": True,
+        "keep_symbols_and_debug_frame": True,
+        "keep_symbols_list": ["symbol"],
+        "none": True,
+    },{target_compatible_with}
+)`},
+	})
+}
+
+func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) {
+	runCcBinaryTests(t, bp2buildTestCase{
+		description: `ldflag "-shared" disables static_flag feature`,
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    ldflags: ["-shared"],
+    include_build_directory: false,
+}
+`,
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    features = ["-static_flag"],
+    linkopts = ["-shared"],{target_compatible_with}
+)`},
+	})
+}
+
+func TestCcBinaryWithLinkStatic(t *testing.T) {
+	runCcBinaryTests(t, bp2buildTestCase{
+		description: "link static",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    static_executable: true,
+    include_build_directory: false,
+}
+`,
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    linkshared = False,{target_compatible_with}
+)`},
+	})
+}
+
+func TestCcBinaryVersionScript(t *testing.T) {
+	runCcBinaryTests(t, bp2buildTestCase{
+		description: `version script`,
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    include_build_directory: false,
+    version_script: "vs",
+}
+`,
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    additional_linker_inputs = ["vs"],
+    linkopts = ["-Wl,--version-script,$(location vs)"],{target_compatible_with}
+)`},
+	})
+}
+
+func TestCcBinarySplitSrcsByLang(t *testing.T) {
+	runCcHostBinaryTestCase(t, bp2buildTestCase{
+		description: "split srcs by lang",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    srcs: [
+        "asonly.S",
+        "conly.c",
+        "cpponly.cpp",
+        ":fg_foo",
+    ],
+    include_build_directory: false,
+}
+` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"),
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    srcs = [
+        "cpponly.cpp",
+        ":fg_foo_cpp_srcs",
+    ],
+    srcs_as = [
+        "asonly.S",
+        ":fg_foo_as_srcs",
+    ],
+    srcs_c = [
+        "conly.c",
+        ":fg_foo_c_srcs",
+    ],{target_compatible_with}
+)`},
+	})
+}
+
+func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) {
+	runCcBinaryTestCase(t, bp2buildTestCase{
+		description: "no implementation deps",
+		blueprint: `
+{rule_name} {
+    name: "foo",
+    shared_libs: ["implementation_shared_dep", "shared_dep"],
+    export_shared_lib_headers: ["shared_dep"],
+    static_libs: ["implementation_static_dep", "static_dep"],
+    export_static_lib_headers: ["static_dep", "whole_static_dep"],
+    whole_static_libs: ["not_explicitly_exported_whole_static_dep", "whole_static_dep"],
+    include_build_directory: false,
+}
+` +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") +
+			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") +
+			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"),
+		expectedBazelTargets: []string{`cc_binary(
+    name = "foo",
+    deps = [
+        ":implementation_static_dep",
+        ":static_dep",
+    ],
+    dynamic_deps = [
+        ":implementation_shared_dep",
+        ":shared_dep",
+    ],{target_compatible_with}
+    whole_archive_deps = [
+        ":not_explicitly_exported_whole_static_dep",
+        ":whole_static_dep",
+    ],
+)`},
+	})
+}
+
+func TestCcBinaryNocrtTests(t *testing.T) {
+	baseTestCases := []struct {
+		description   string
+		soongProperty string
+		bazelAttr     string
+	}{
+		{
+			description:   "nocrt: true",
+			soongProperty: `nocrt: true,`,
+			bazelAttr:     `    link_crt = False,`,
+		},
+		{
+			description:   "nocrt: false",
+			soongProperty: `nocrt: false,`,
+		},
+		{
+			description: "nocrt: not set",
+		},
+	}
+
+	baseBlueprint := `{rule_name} {
+    name: "foo",%s
+    include_build_directory: false,
+}
+`
+
+	baseBazelTarget := `cc_binary(
+    name = "foo",%s{target_compatible_with}
+)`
+
+	for _, btc := range baseTestCases {
+		prop := btc.soongProperty
+		if len(prop) > 0 {
+			prop = "\n" + prop
+		}
+		attr := btc.bazelAttr
+		if len(attr) > 0 {
+			attr = "\n" + attr
+		}
+		runCcBinaryTests(t, bp2buildTestCase{
+			description: btc.description,
+			blueprint:   fmt.Sprintf(baseBlueprint, prop),
+			expectedBazelTargets: []string{
+				fmt.Sprintf(baseBazelTarget, attr),
+			},
+		})
+	}
+}
+
+func TestCcBinaryNo_libcrtTests(t *testing.T) {
+	baseTestCases := []struct {
+		description   string
+		soongProperty string
+		bazelAttr     string
+	}{
+		{
+			description:   "no_libcrt: true",
+			soongProperty: `no_libcrt: true,`,
+			bazelAttr:     `    use_libcrt = False,`,
+		},
+		{
+			description:   "no_libcrt: false",
+			soongProperty: `no_libcrt: false,`,
+			bazelAttr:     `    use_libcrt = True,`,
+		},
+		{
+			description: "no_libcrt: not set",
+		},
+	}
+
+	baseBlueprint := `{rule_name} {
+    name: "foo",%s
+    include_build_directory: false,
+}
+`
+
+	baseBazelTarget := `cc_binary(
+    name = "foo",{target_compatible_with}%s
+)`
+
+	for _, btc := range baseTestCases {
+		prop := btc.soongProperty
+		if len(prop) > 0 {
+			prop = "\n" + prop
+		}
+		attr := btc.bazelAttr
+		if len(attr) > 0 {
+			attr = "\n" + attr
+		}
+		runCcBinaryTests(t, bp2buildTestCase{
+			description: btc.description,
+			blueprint:   fmt.Sprintf(baseBlueprint, prop),
+			expectedBazelTargets: []string{
+				fmt.Sprintf(baseBazelTarget, attr),
+			},
+		})
+	}
+}
+
+func TestCcBinaryPropertiesToFeatures(t *testing.T) {
+	baseTestCases := []struct {
+		description   string
+		soongProperty string
+		bazelAttr     string
+	}{
+		{
+			description:   "pack_relocation: true",
+			soongProperty: `pack_relocations: true,`,
+		},
+		{
+			description:   "pack_relocations: false",
+			soongProperty: `pack_relocations: false,`,
+			bazelAttr:     `    features = ["disable_pack_relocations"],`,
+		},
+		{
+			description: "pack_relocations: not set",
+		},
+		{
+			description:   "pack_relocation: true",
+			soongProperty: `allow_undefined_symbols: true,`,
+			bazelAttr:     `    features = ["-no_undefined_symbols"],`,
+		},
+		{
+			description:   "allow_undefined_symbols: false",
+			soongProperty: `allow_undefined_symbols: false,`,
+		},
+		{
+			description: "allow_undefined_symbols: not set",
+		},
+	}
+
+	baseBlueprint := `{rule_name} {
+    name: "foo",%s
+    include_build_directory: false,
+}
+`
+
+	baseBazelTarget := `cc_binary(
+    name = "foo",%s{target_compatible_with}
+)`
+
+	for _, btc := range baseTestCases {
+		prop := btc.soongProperty
+		if len(prop) > 0 {
+			prop = "\n" + prop
+		}
+		attr := btc.bazelAttr
+		if len(attr) > 0 {
+			attr = "\n" + attr
+		}
+		runCcBinaryTests(t, bp2buildTestCase{
+			description: btc.description,
+			blueprint:   fmt.Sprintf(baseBlueprint, prop),
+			expectedBazelTargets: []string{
+				fmt.Sprintf(baseBazelTarget, attr),
+			},
+		})
+	}
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 76f83e7..cbdc167 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -133,8 +133,8 @@
         "//conditions:default": [],
     }) + select({
         "//build/bazel/platforms/os:android": [
-            "android.cpp",
             "bionic.cpp",
+            "android.cpp",
         ],
         "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
         "//build/bazel/platforms/os:linux": ["linux.cpp"],
@@ -803,8 +803,9 @@
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
+    additional_linker_inputs = ["v.map"],
+    linkopts = ["-Wl,--version-script,$(location v.map)"],
     srcs = ["a.cpp"],
-    version_script = "v.map",
 )`},
 	})
 }
@@ -838,12 +839,17 @@
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    srcs = ["a.cpp"],
-    version_script = select({
-        "//build/bazel/platforms/arch:arm": "arm.map",
-        "//build/bazel/platforms/arch:arm64": "arm64.map",
-        "//conditions:default": None,
+    additional_linker_inputs = select({
+        "//build/bazel/platforms/arch:arm": ["arm.map"],
+        "//build/bazel/platforms/arch:arm64": ["arm64.map"],
+        "//conditions:default": [],
     }),
+    linkopts = select({
+        "//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"],
+        "//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"],
+        "//conditions:default": [],
+    }),
+    srcs = ["a.cpp"],
 )`},
 	})
 }
@@ -1010,39 +1016,6 @@
 	})
 }
 
-func TestCcLibraryLabelAttributeGetTargetProperties(t *testing.T) {
-	runCcLibraryTestCase(t, bp2buildTestCase{
-		description:                        "cc_library GetTargetProperties on a LabelAttribute",
-		moduleTypeUnderTest:                "cc_library",
-		moduleTypeUnderTestFactory:         cc.LibraryFactory,
-		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		blueprint: soongCcLibraryPreamble + `
-cc_library {
-   name: "a",
-   srcs: ["a.cpp"],
-   target: {
-     android_arm: {
-       version_script: "android_arm.map",
-     },
-     linux_bionic_arm64: {
-       version_script: "linux_bionic_arm64.map",
-     },
-   },
-    include_build_directory: false,
-}
-    `,
-		expectedBazelTargets: []string{`cc_library(
-    name = "a",
-    srcs = ["a.cpp"],
-    version_script = select({
-        "//build/bazel/platforms/os_arch:android_arm": "android_arm.map",
-        "//build/bazel/platforms/os_arch:linux_bionic_arm64": "linux_bionic_arm64.map",
-        "//conditions:default": None,
-    }),
-)`},
-	})
-}
-
 func TestCcLibraryExcludeLibs(t *testing.T) {
 	runCcLibraryTestCase(t, bp2buildTestCase{
 		moduleTypeUnderTest:                "cc_library",
@@ -1668,9 +1641,9 @@
     name = "foo-lib",
     srcs = ["base.cpp"] + select({
         "//build/bazel/platforms/os:android": [
-            "android.cpp",
-            "bionic.cpp",
             "linux.cpp",
+            "bionic.cpp",
+            "android.cpp",
         ],
         "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
         "//build/bazel/platforms/os:linux": [
@@ -1678,8 +1651,8 @@
             "linux_glibc.cpp",
         ],
         "//build/bazel/platforms/os:linux_bionic": [
-            "bionic.cpp",
             "linux.cpp",
+            "bionic.cpp",
         ],
         "//build/bazel/platforms/os:linux_musl": [
             "linux.cpp",
@@ -1692,7 +1665,7 @@
 
 }
 
-func TestCcLibraryCppStdWithGnuExtensions_ConvertstoCopt(t *testing.T) {
+func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) {
 	type testCase struct {
 		cpp_std        string
 		gnu_extensions string
@@ -1751,7 +1724,7 @@
 		}
 		bazelCppStdAttr := ""
 		if tc.bazel_cpp_std != "" {
-			bazelCppStdAttr = fmt.Sprintf("\n    copts = [\"-std=%s\"],", tc.bazel_cpp_std)
+			bazelCppStdAttr = fmt.Sprintf("\n    cpp_std = \"%s\",", tc.bazel_cpp_std)
 		}
 
 		runCcLibraryTestCase(t, bp2buildTestCase{
@@ -1772,5 +1745,43 @@
     name = "a",%s
 )`, bazelCppStdAttr)},
 		})
+
+		runCcLibraryStaticTestCase(t, bp2buildTestCase{
+			description: fmt.Sprintf(
+				"cc_library_static with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
+cc_library_static {
+	name: "a",
+%s // cpp_std: *string
+%s // gnu_extensions: *bool
+	include_build_directory: false,
+}
+`, cppStdAttr, gnuExtensionsAttr),
+			expectedBazelTargets: []string{fmt.Sprintf(`cc_library_static(
+    name = "a",%s
+)`, bazelCppStdAttr)},
+		})
+
+		runCcLibrarySharedTestCase(t, bp2buildTestCase{
+			description: fmt.Sprintf(
+				"cc_library_shared with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
+			moduleTypeUnderTest:                "cc_library_shared",
+			moduleTypeUnderTestFactory:         cc.LibrarySharedFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+			blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
+cc_library_shared {
+	name: "a",
+%s // cpp_std: *string
+%s // gnu_extensions: *bool
+	include_build_directory: false,
+}
+`, cppStdAttr, gnuExtensionsAttr),
+			expectedBazelTargets: []string{fmt.Sprintf(`cc_library_shared(
+    name = "a",%s
+)`, bazelCppStdAttr)},
+		})
 	}
 }
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index b272067..bb15776 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -361,7 +361,8 @@
 }`,
 		expectedBazelTargets: []string{`cc_library_shared(
     name = "foo_shared",
-    version_script = "version_script",
+    additional_linker_inputs = ["version_script"],
+    linkopts = ["-Wl,--version-script,$(location version_script)"],
 )`},
 	})
 }
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index f02ce4d..ef2ec32 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -641,12 +641,12 @@
     name = "foo_static",
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
-            "for-arm.c",
             "not-for-x86.c",
+            "for-arm.c",
         ],
         "//build/bazel/platforms/arch:x86": [
-            "for-x86.c",
             "not-for-arm.c",
+            "for-x86.c",
         ],
         "//conditions:default": [
             "not-for-arm.c",
@@ -691,28 +691,28 @@
     name = "foo_static",
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
-            "for-arm.c",
             "not-for-arm64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
+            "for-arm.c",
         ],
         "//build/bazel/platforms/arch:arm64": [
-            "for-arm64.c",
             "not-for-arm.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
+            "for-arm64.c",
         ],
         "//build/bazel/platforms/arch:x86": [
-            "for-x86.c",
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-x86_64.c",
+            "for-x86.c",
         ],
         "//build/bazel/platforms/arch:x86_64": [
-            "for-x86_64.c",
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-x86.c",
+            "for-x86_64.c",
         ],
         "//conditions:default": [
             "not-for-arm.c",
@@ -875,20 +875,20 @@
     name = "foo_static2",
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
-            "for-lib32.c",
             "not-for-lib64.c",
+            "for-lib32.c",
         ],
         "//build/bazel/platforms/arch:arm64": [
-            "for-lib64.c",
             "not-for-lib32.c",
+            "for-lib64.c",
         ],
         "//build/bazel/platforms/arch:x86": [
-            "for-lib32.c",
             "not-for-lib64.c",
+            "for-lib32.c",
         ],
         "//build/bazel/platforms/arch:x86_64": [
-            "for-lib64.c",
             "not-for-lib32.c",
+            "for-lib64.c",
         ],
         "//conditions:default": [
             "not-for-lib32.c",
@@ -942,36 +942,36 @@
     name = "foo_static3",
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
+            "not-for-arm64.c",
+            "not-for-lib64.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
             "for-arm.c",
             "for-lib32.c",
-            "not-for-arm64.c",
-            "not-for-lib64.c",
-            "not-for-x86.c",
-            "not-for-x86_64.c",
         ],
         "//build/bazel/platforms/arch:arm64": [
-            "for-arm64.c",
-            "for-lib64.c",
             "not-for-arm.c",
             "not-for-lib32.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
+            "for-arm64.c",
+            "for-lib64.c",
         ],
         "//build/bazel/platforms/arch:x86": [
-            "for-lib32.c",
-            "for-x86.c",
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib64.c",
             "not-for-x86_64.c",
+            "for-x86.c",
+            "for-lib32.c",
         ],
         "//build/bazel/platforms/arch:x86_64": [
-            "for-lib64.c",
-            "for-x86_64.c",
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib32.c",
             "not-for-x86.c",
+            "for-x86_64.c",
+            "for-lib64.c",
         ],
         "//conditions:default": [
             "not-for-arm.c",
@@ -986,6 +986,41 @@
 	})
 }
 
+func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) {
+	runCcLibraryStaticTestCase(t, bp2buildTestCase{
+		moduleTypeUnderTest:                "cc_library_static",
+		moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+		blueprint: soongCcLibraryStaticPreamble + `
+genrule {
+    name: "generated_hdr",
+    cmd: "nothing to see here",
+}
+
+cc_library_static {
+    name: "foo_static",
+    srcs: ["cpp_src.cpp", "as_src.S", "c_src.c"],
+    generated_headers: ["generated_hdr"],
+    include_build_directory: false,
+}`,
+		expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    srcs = [
+        "cpp_src.cpp",
+        ":generated_hdr",
+    ],
+    srcs_as = [
+        "as_src.S",
+        ":generated_hdr",
+    ],
+    srcs_c = [
+        "c_src.c",
+        ":generated_hdr",
+    ],
+)`},
+	})
+}
+
 func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
 	runCcLibraryStaticTestCase(t, bp2buildTestCase{
 		description:                        "cc_library_static arch srcs/exclude_srcs with generated files",
@@ -1000,73 +1035,92 @@
 			"dep/Android.bp": `
 genrule {
   name: "generated_src_other_pkg",
-  out: ["generated_src_other_pkg.cpp"],
   cmd: "nothing to see here",
 }
 
 genrule {
   name: "generated_hdr_other_pkg",
-  out: ["generated_hdr_other_pkg.cpp"],
   cmd: "nothing to see here",
 }
 
 genrule {
   name: "generated_hdr_other_pkg_x86",
-  out: ["generated_hdr_other_pkg_x86.cpp"],
+  cmd: "nothing to see here",
+}
+
+genrule {
+  name: "generated_hdr_other_pkg_android",
   cmd: "nothing to see here",
 }`,
 		},
 		blueprint: soongCcLibraryStaticPreamble + `
 genrule {
     name: "generated_src",
-    out: ["generated_src.cpp"],
     cmd: "nothing to see here",
 }
 
 genrule {
-    name: "generated_src_x86",
-    out: ["generated_src_x86.cpp"],
+    name: "generated_src_not_x86",
+    cmd: "nothing to see here",
+}
+
+genrule {
+    name: "generated_src_android",
     cmd: "nothing to see here",
 }
 
 genrule {
     name: "generated_hdr",
-    out: ["generated_hdr.h"],
     cmd: "nothing to see here",
 }
 
 cc_library_static {
-   name: "foo_static3",
-   srcs: ["common.cpp", "not-for-*.cpp"],
-   exclude_srcs: ["not-for-everything.cpp"],
-   generated_sources: ["generated_src", "generated_src_other_pkg"],
-   generated_headers: ["generated_hdr", "generated_hdr_other_pkg"],
-   arch: {
-       x86: {
-           srcs: ["for-x86.cpp"],
-           exclude_srcs: ["not-for-x86.cpp"],
-           generated_sources: ["generated_src_x86"],
-           generated_headers: ["generated_hdr_other_pkg_x86"],
-       },
-   },
+    name: "foo_static3",
+    srcs: ["common.cpp", "not-for-*.cpp"],
+    exclude_srcs: ["not-for-everything.cpp"],
+    generated_sources: ["generated_src", "generated_src_other_pkg", "generated_src_not_x86"],
+    generated_headers: ["generated_hdr", "generated_hdr_other_pkg"],
+    arch: {
+        x86: {
+          srcs: ["for-x86.cpp"],
+          exclude_srcs: ["not-for-x86.cpp"],
+          generated_headers: ["generated_hdr_other_pkg_x86"],
+          exclude_generated_sources: ["generated_src_not_x86"],
+        },
+    },
+    target: {
+        android: {
+            generated_sources: ["generated_src_android"],
+            generated_headers: ["generated_hdr_other_pkg_android"],
+        },
+    },
+
     include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static3",
     srcs = [
-        "//dep:generated_hdr_other_pkg",
+        "common.cpp",
+        ":generated_src",
         "//dep:generated_src_other_pkg",
         ":generated_hdr",
-        ":generated_src",
-        "common.cpp",
+        "//dep:generated_hdr_other_pkg",
     ] + select({
         "//build/bazel/platforms/arch:x86": [
-            "//dep:generated_hdr_other_pkg_x86",
-            ":generated_src_x86",
             "for-x86.cpp",
+            "//dep:generated_hdr_other_pkg_x86",
         ],
-        "//conditions:default": ["not-for-x86.cpp"],
+        "//conditions:default": [
+            "not-for-x86.cpp",
+            ":generated_src_not_x86",
+        ],
+    }) + select({
+        "//build/bazel/platforms/os:android": [
+            ":generated_src_android",
+            "//dep:generated_hdr_other_pkg_android",
+        ],
+        "//conditions:default": [],
     }),
 )`},
 	})
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 63a0b8a..c4b276a 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -439,13 +439,13 @@
     copts = ["-fno-addrsig"],
     srcs = ["base.cpp"] + select({
         "//build/bazel/platforms/os_arch:android_arm64": [
-            "bionic_arm64.cpp",
             "linux_arm64.cpp",
+            "bionic_arm64.cpp",
         ],
         "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"],
         "//build/bazel/platforms/os_arch:linux_bionic_arm64": [
-            "bionic_arm64.cpp",
             "linux_arm64.cpp",
+            "bionic_arm64.cpp",
         ],
         "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"],
         "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"],
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index d34a4ba..944cb83 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -17,11 +17,11 @@
 	Contents string
 }
 
-func CreateSoongInjectionFiles(metrics CodegenMetrics) []BazelFile {
+func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []BazelFile {
 	var files []BazelFile
 
 	files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
-	files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars()))
+	files = append(files, newFile("cc_toolchain", "constants.bzl", config.BazelCcToolchainVars(cfg)))
 
 	files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
 
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index dfa1a9e..d09238a 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -17,6 +17,8 @@
 import (
 	"sort"
 	"testing"
+
+	"android/soong/android"
 )
 
 type bazelFilepath struct {
@@ -80,7 +82,7 @@
 }
 
 func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
-	files := CreateSoongInjectionFiles(CodegenMetrics{})
+	files := CreateSoongInjectionFiles(android.Config{}, CodegenMetrics{})
 
 	expectedFilePaths := []bazelFilepath{
 		{
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 6c322ee..7c2f43a 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -283,7 +283,7 @@
 			return
 		}
 
-		paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.props.Arch_paths, m.props.Arch_paths_exclude))
+		paths := bazel.LabelListAttribute{}
 
 		for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
 			for config, props := range configToProps {
diff --git a/cc/binary.go b/cc/binary.go
index b423c50..4d1301b 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -20,6 +20,7 @@
 	"github.com/google/blueprint"
 
 	"android/soong/android"
+	"android/soong/bazel"
 )
 
 type BinaryLinkerProperties struct {
@@ -62,7 +63,7 @@
 
 func RegisterBinaryBuildComponents(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("cc_binary", BinaryFactory)
-	ctx.RegisterModuleType("cc_binary_host", binaryHostFactory)
+	ctx.RegisterModuleType("cc_binary_host", BinaryHostFactory)
 }
 
 // cc_binary produces a binary that is runnable on a device.
@@ -72,7 +73,7 @@
 }
 
 // cc_binary_host produces a binary that is runnable on a host.
-func binaryHostFactory() android.Module {
+func BinaryHostFactory() android.Module {
 	module, _ := NewBinary(android.HostSupported)
 	return module.Init()
 }
@@ -541,3 +542,125 @@
 		},
 	})
 }
+
+func init() {
+	android.RegisterBp2BuildMutator("cc_binary", BinaryBp2build)
+	android.RegisterBp2BuildMutator("cc_binary_host", BinaryHostBp2build)
+}
+
+func BinaryBp2build(ctx android.TopDownMutatorContext) {
+	binaryBp2build(ctx, "cc_binary")
+}
+
+func BinaryHostBp2build(ctx android.TopDownMutatorContext) {
+	binaryBp2build(ctx, "cc_binary_host")
+}
+
+func binaryBp2build(ctx android.TopDownMutatorContext, typ string) {
+	m, ok := ctx.Module().(*Module)
+	if !ok {
+		// Not a cc module
+		return
+	}
+	if !m.ConvertWithBp2build(ctx) {
+		return
+	}
+
+	if ctx.ModuleType() != typ {
+		return
+	}
+
+	var compatibleWith bazel.StringListAttribute
+	if typ == "cc_binary_host" {
+		//incompatible with android OS
+		compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, android.Android.Name, []string{"@platforms//:incompatible"})
+		compatibleWith.SetSelectValue(bazel.OsConfigurationAxis, bazel.ConditionsDefaultConfigKey, []string{})
+	}
+
+	compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
+	linkerAttrs := bp2BuildParseLinkerProps(ctx, m)
+
+	attrs := &binaryAttributes{
+		binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m),
+
+		Srcs:    compilerAttrs.srcs,
+		Srcs_c:  compilerAttrs.cSrcs,
+		Srcs_as: compilerAttrs.asSrcs,
+
+		Copts:      compilerAttrs.copts,
+		Cppflags:   compilerAttrs.cppFlags,
+		Conlyflags: compilerAttrs.conlyFlags,
+		Asflags:    compilerAttrs.asFlags,
+
+		Deps:               linkerAttrs.implementationDeps,
+		Dynamic_deps:       linkerAttrs.implementationDynamicDeps,
+		Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+		System_deps:        linkerAttrs.systemDynamicDeps,
+
+		Local_includes:    compilerAttrs.localIncludes,
+		Absolute_includes: compilerAttrs.absoluteIncludes,
+		Linkopts:          linkerAttrs.linkopts,
+		Link_crt:          linkerAttrs.linkCrt,
+		Use_libcrt:        linkerAttrs.useLibcrt,
+		Rtti:              compilerAttrs.rtti,
+		Stl:               compilerAttrs.stl,
+		Cpp_std:           compilerAttrs.cppStd,
+
+		Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
+
+		Strip: stripAttributes{
+			Keep_symbols:                 linkerAttrs.stripKeepSymbols,
+			Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
+			Keep_symbols_list:            linkerAttrs.stripKeepSymbolsList,
+			All:                          linkerAttrs.stripAll,
+			None:                         linkerAttrs.stripNone,
+		},
+
+		Target_compatible_with: compatibleWith,
+		Features:               linkerAttrs.features,
+	}
+
+	ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
+		Rule_class:        "cc_binary",
+		Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
+	},
+		android.CommonAttributes{Name: m.Name()},
+		attrs)
+}
+
+// binaryAttributes contains Bazel attributes corresponding to a cc binary
+type binaryAttributes struct {
+	binaryLinkerAttrs
+	Srcs    bazel.LabelListAttribute
+	Srcs_c  bazel.LabelListAttribute
+	Srcs_as bazel.LabelListAttribute
+
+	Copts      bazel.StringListAttribute
+	Cppflags   bazel.StringListAttribute
+	Conlyflags bazel.StringListAttribute
+	Asflags    bazel.StringListAttribute
+
+	Deps               bazel.LabelListAttribute
+	Dynamic_deps       bazel.LabelListAttribute
+	Whole_archive_deps bazel.LabelListAttribute
+	System_deps        bazel.LabelListAttribute
+
+	Local_includes    bazel.StringListAttribute
+	Absolute_includes bazel.StringListAttribute
+
+	Linkopts                 bazel.StringListAttribute
+	Additional_linker_inputs bazel.LabelListAttribute
+
+	Link_crt   bazel.BoolAttribute
+	Use_libcrt bazel.BoolAttribute
+
+	Rtti    bazel.BoolAttribute
+	Stl     *string
+	Cpp_std *string
+
+	Strip stripAttributes
+
+	Features bazel.StringListAttribute
+
+	Target_compatible_with bazel.StringListAttribute
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 0b2c133..3c238b5 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -14,6 +14,7 @@
 package cc
 
 import (
+	"fmt"
 	"path/filepath"
 	"strings"
 
@@ -25,6 +26,12 @@
 	"github.com/google/blueprint/proptools"
 )
 
+const (
+	cSrcPartition   = "c"
+	asSrcPartition  = "as"
+	cppSrcPartition = "cpp"
+)
+
 // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
 // properties which apply to either the shared or static version of a cc_library module.
 type staticOrSharedAttributes struct {
@@ -42,7 +49,7 @@
 	System_dynamic_deps bazel.LabelListAttribute
 }
 
-func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) {
+func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
 	// Check that a module is a filegroup type named <label>.
 	isFilegroupNamed := func(m android.Module, fullLabel string) bool {
 		if ctx.OtherModuleType(m) != "filegroup" {
@@ -74,17 +81,14 @@
 
 	// TODO(b/190006308): Handle language detection of sources in a Bazel rule.
 	partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
-		"c":  bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
-		"as": bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
+		cSrcPartition:  bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
+		asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
 		// C++ is the "catch-all" group, and comprises generated sources because we don't
 		// know the language of these sources until the genrule is executed.
-		"cpp": bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+		cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
 	})
 
-	cSrcs = partitioned["c"]
-	asSrcs = partitioned["as"]
-	cppSrcs = partitioned["cpp"]
-	return
+	return partitioned
 }
 
 // bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
@@ -113,7 +117,13 @@
 
 type bazelLabelForDepsFn func(android.TopDownMutatorContext, []string) bazel.LabelList
 
-func partitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
+func maybePartitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
+	if !exportsDeps {
+		return depsPartition{
+			implementation: fn(ctx, allDeps),
+		}
+	}
+
 	implementation, export := android.FilterList(allDeps, exportedDeps)
 
 	return depsPartition{
@@ -124,7 +134,12 @@
 
 type bazelLabelForDepsExcludesFn func(android.TopDownMutatorContext, []string, []string) bazel.LabelList
 
-func partitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
+func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
+	if !exportsDeps {
+		return depsPartition{
+			implementation: fn(ctx, allDeps, excludes),
+		}
+	}
 	implementation, export := android.FilterList(allDeps, exportedDeps)
 
 	return depsPartition{
@@ -141,11 +156,11 @@
 		attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
 		attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
 
-		staticDeps := partitionExportedAndImplementationsDeps(ctx, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps)
+		staticDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps)
 		attrs.Deps.SetSelectValue(axis, config, staticDeps.export)
 		attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation)
 
-		sharedDeps := partitionExportedAndImplementationsDeps(ctx, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps)
+		sharedDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps)
 		attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export)
 		attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
 
@@ -174,10 +189,10 @@
 		}
 	}
 
-	cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.Srcs)
-	attrs.Srcs = cppSrcs
-	attrs.Srcs_c = cSrcs
-	attrs.Srcs_as = asSrcs
+	partitionedSrcs := groupSrcsByExtension(ctx, attrs.Srcs)
+	attrs.Srcs = partitionedSrcs[cppSrcPartition]
+	attrs.Srcs_c = partitionedSrcs[cSrcPartition]
+	attrs.Srcs_as = partitionedSrcs[asSrcPartition]
 
 	return attrs
 }
@@ -226,7 +241,10 @@
 	srcs     bazel.LabelListAttribute
 
 	rtti bazel.BoolAttribute
-	stl  *string
+
+	// Not affected by arch variants
+	stl    *string
+	cppStd *string
 
 	localIncludes    bazel.StringListAttribute
 	absoluteIncludes bazel.StringListAttribute
@@ -235,6 +253,7 @@
 // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
 func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Module) compilerAttributes {
 	var srcs bazel.LabelListAttribute
+	var implementationHdrs bazel.LabelListAttribute
 	var copts bazel.StringListAttribute
 	var asFlags bazel.StringListAttribute
 	var conlyFlags bazel.StringListAttribute
@@ -242,6 +261,8 @@
 	var rtti bazel.BoolAttribute
 	var localIncludes bazel.StringListAttribute
 	var absoluteIncludes bazel.StringListAttribute
+	var stl *string = nil
+	var cppStd *string = nil
 
 	parseCommandLineFlags := func(soongFlags []string) []string {
 		var result []string
@@ -255,15 +276,20 @@
 	}
 
 	// Parse srcs from an arch or OS's props value.
-	parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
+	parseSrcs := func(props *BaseCompilerProperties) (bazel.LabelList, bool) {
+		anySrcs := false
 		// Add srcs-like dependencies such as generated files.
 		// First create a LabelList containing these dependencies, then merge the values with srcs.
-		generatedHdrsAndSrcs := baseCompilerProps.Generated_headers
-		generatedHdrsAndSrcs = append(generatedHdrsAndSrcs, baseCompilerProps.Generated_sources...)
-		generatedHdrsAndSrcsLabelList := android.BazelLabelForModuleDeps(ctx, generatedHdrsAndSrcs)
+		generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, props.Generated_sources, props.Exclude_generated_sources)
+		if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 {
+			anySrcs = true
+		}
 
-		allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs)
-		return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedHdrsAndSrcsLabelList)
+		allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
+		if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 {
+			anySrcs = true
+		}
+		return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
 	}
 
 	archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
@@ -272,12 +298,13 @@
 			if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
 				// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
 				// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
-				if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
-					srcsList := parseSrcs(baseCompilerProps)
+				if srcsList, ok := parseSrcs(baseCompilerProps); ok {
 					srcs.SetSelectValue(axis, config, srcsList)
 				}
+				if len(baseCompilerProps.Generated_headers) > 0 {
+					implementationHdrs.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Generated_headers))
+				}
 
-				var archVariantCopts []string
 				if axis == bazel.NoConfigAxis {
 					// If cpp_std is not specified, don't generate it in the
 					// BUILD file. For readability purposes, cpp_std and gnu_extensions are
@@ -289,11 +316,14 @@
 						// These transformations are shared with compiler.go.
 						cppStdVal := parseCppStd(baseCompilerProps.Cpp_std)
 						_, cppStdVal = maybeReplaceGnuToC(baseCompilerProps.Gnu_extensions, "", cppStdVal)
-						archVariantCopts = append(archVariantCopts, "-std="+cppStdVal)
+						cppStd = &cppStdVal
 					} else if baseCompilerProps.Gnu_extensions != nil && !*baseCompilerProps.Gnu_extensions {
-						archVariantCopts = append(archVariantCopts, "-std=c++17")
+						cppStdVal := "c++17"
+						cppStd = &cppStdVal
 					}
 				}
+
+				var archVariantCopts []string
 				archVariantCopts = append(archVariantCopts, parseCommandLineFlags(baseCompilerProps.Cflags)...)
 				archVariantAsflags := parseCommandLineFlags(baseCompilerProps.Asflags)
 
@@ -315,6 +345,21 @@
 	}
 
 	srcs.ResolveExcludes()
+	partitionedSrcs := groupSrcsByExtension(ctx, srcs)
+
+	for p, lla := range partitionedSrcs {
+		// if there are no sources, there is no need for headers
+		if lla.IsEmpty() {
+			continue
+		}
+		lla.Append(implementationHdrs)
+		partitionedSrcs[p] = lla
+	}
+
+	srcs = partitionedSrcs[cppSrcPartition]
+	cSrcs := partitionedSrcs[cSrcPartition]
+	asSrcs := partitionedSrcs[asSrcPartition]
+
 	absoluteIncludes.DeduplicateAxesFromBase()
 	localIncludes.DeduplicateAxesFromBase()
 
@@ -337,9 +382,6 @@
 		}
 	}
 
-	srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs)
-
-	var stl *string = nil
 	stlPropsByArch := module.GetArchVariantProperties(ctx, &StlProperties{})
 	for _, configToProps := range stlPropsByArch {
 		for _, props := range configToProps {
@@ -367,6 +409,7 @@
 		cppFlags:         cppFlags,
 		rtti:             rtti,
 		stl:              stl,
+		cppStd:           cppStd,
 		localIncludes:    localIncludes,
 		absoluteIncludes: absoluteIncludes,
 	}
@@ -384,7 +427,7 @@
 	linkCrt                       bazel.BoolAttribute
 	useLibcrt                     bazel.BoolAttribute
 	linkopts                      bazel.StringListAttribute
-	versionScript                 bazel.LabelAttribute
+	additionalLinkerInputs        bazel.LabelListAttribute
 	stripKeepSymbols              bazel.BoolAttribute
 	stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
 	stripKeepSymbolsList          bazel.StringListAttribute
@@ -407,8 +450,8 @@
 	systemSharedDeps := bazel.LabelListAttribute{ForceSpecifyEmptyList: true}
 
 	var linkopts bazel.StringListAttribute
-	var versionScript bazel.LabelAttribute
 	var linkCrt bazel.BoolAttribute
+	var additionalLinkerInputs bazel.LabelListAttribute
 	var useLibcrt bazel.BoolAttribute
 
 	var stripKeepSymbols bazel.BoolAttribute
@@ -433,6 +476,7 @@
 
 	// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
 	var disallowedArchVariantCrt bool
+	isBinary := module.Binary()
 
 	for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
 		for config, props := range configToProps {
@@ -442,7 +486,7 @@
 				// Excludes to parallel Soong:
 				// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
 				staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
-				staticDeps := partitionExportedAndImplementationsDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
+				staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
 				deps.SetSelectValue(axis, config, staticDeps.export)
 				implementationDeps.SetSelectValue(axis, config, staticDeps.implementation)
 
@@ -459,17 +503,16 @@
 				systemSharedDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
 
 				sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
-				sharedDeps := partitionExportedAndImplementationsDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
+				sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
 				dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
 				implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
 
 				headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
-				hDeps := partitionExportedAndImplementationsDeps(ctx, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps)
+				hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps)
 
 				headerDeps.SetSelectValue(axis, config, hDeps.export)
 				implementationHeaderDeps.SetSelectValue(axis, config, hDeps.implementation)
 
-				linkopts.SetSelectValue(axis, config, baseLinkerProps.Ldflags)
 				if !BoolDefault(baseLinkerProps.Pack_relocations, packRelocationsDefault) {
 					axisFeatures = append(axisFeatures, "disable_pack_relocations")
 				}
@@ -478,9 +521,20 @@
 					axisFeatures = append(axisFeatures, "-no_undefined_symbols")
 				}
 
-				if baseLinkerProps.Version_script != nil {
-					versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
+				var linkerFlags []string
+				if len(baseLinkerProps.Ldflags) > 0 {
+					linkerFlags = append(linkerFlags, baseLinkerProps.Ldflags...)
+					// binaries remove static flag if -shared is in the linker flags
+					if module.Binary() && android.InList("-shared", linkerFlags) {
+						axisFeatures = append(axisFeatures, "-static_flag")
+					}
 				}
+				if baseLinkerProps.Version_script != nil {
+					label := android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)
+					additionalLinkerInputs.SetSelectValue(axis, config, bazel.LabelList{Includes: []bazel.Label{label}})
+					linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label))
+				}
+				linkopts.SetSelectValue(axis, config, linkerFlags)
 				useLibcrt.SetSelectValue(axis, config, baseLinkerProps.libCrt())
 
 				// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
@@ -572,10 +626,10 @@
 		wholeArchiveDeps:          wholeArchiveDeps,
 		systemDynamicDeps:         systemSharedDeps,
 
-		linkCrt:       linkCrt,
-		linkopts:      linkopts,
-		useLibcrt:     useLibcrt,
-		versionScript: versionScript,
+		linkCrt:                linkCrt,
+		linkopts:               linkopts,
+		useLibcrt:              useLibcrt,
+		additionalLinkerInputs: additionalLinkerInputs,
 
 		// Strip properties
 		stripKeepSymbols:              stripKeepSymbols,
@@ -708,3 +762,29 @@
 func bazelLabelForSharedDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
 	return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
 }
+
+type binaryLinkerAttrs struct {
+	Linkshared *bool
+}
+
+func bp2buildBinaryLinkerProps(ctx android.TopDownMutatorContext, m *Module) binaryLinkerAttrs {
+	attrs := binaryLinkerAttrs{}
+	archVariantProps := m.GetArchVariantProperties(ctx, &BinaryLinkerProperties{})
+	for axis, configToProps := range archVariantProps {
+		for _, p := range configToProps {
+			props := p.(*BinaryLinkerProperties)
+			staticExecutable := props.Static_executable
+			if axis == bazel.NoConfigAxis {
+				if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared {
+					attrs.Linkshared = &linkBinaryShared
+				}
+			} else if staticExecutable != nil {
+				// TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a
+				// nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling
+				ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values")
+			}
+		}
+	}
+
+	return attrs
+}
diff --git a/cc/builder.go b/cc/builder.go
index b494f7b..082a70c 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -238,14 +238,6 @@
 		},
 		"asFlags")
 
-	// Rule to invoke windres, for interaction with Windows resources.
-	windres = pctx.AndroidStaticRule("windres",
-		blueprint.RuleParams{
-			Command:     "$windresCmd $flags -I$$(dirname $in) -i $in -o $out --preprocessor \"${config.ClangBin}/clang -E -xc-header -DRC_INVOKED\"",
-			CommandDeps: []string{"$windresCmd"},
-		},
-		"windresCmd", "flags")
-
 	_ = pctx.SourcePathVariable("sAbiDumper", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/header-abi-dumper")
 
 	// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
@@ -577,20 +569,6 @@
 				},
 			})
 			continue
-		case ".rc":
-			ctx.Build(pctx, android.BuildParams{
-				Rule:        windres,
-				Description: "windres " + srcFile.Rel(),
-				Output:      objFile,
-				Input:       srcFile,
-				Implicits:   cFlagsDeps,
-				OrderOnly:   pathDeps,
-				Args: map[string]string{
-					"windresCmd": mingwCmd(flags.toolchain, "windres"),
-					"flags":      shareFlags("flags", flags.toolchain.WindresFlags()),
-				},
-			})
-			continue
 		case ".o":
 			objFiles[i] = srcFile
 			continue
diff --git a/cc/cc.go b/cc/cc.go
index 87de1c8..1c65549 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3249,16 +3249,6 @@
 	return c.Properties.Test_for
 }
 
-func (c *Module) UniqueApexVariations() bool {
-	if u, ok := c.compiler.(interface {
-		uniqueApexVariations() bool
-	}); ok {
-		return u.uniqueApexVariations()
-	} else {
-		return false
-	}
-}
-
 func (c *Module) EverInstallable() bool {
 	return c.installer != nil &&
 		// Check to see whether the module is actually ever installable.
diff --git a/cc/compiler.go b/cc/compiler.go
index 4f96712..00df669 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -209,15 +209,6 @@
 
 	// Build and link with OpenMP
 	Openmp *bool `android:"arch_variant"`
-
-	// Deprecated.
-	// Adds __ANDROID_APEX_<APEX_MODULE_NAME>__ macro defined for apex variants in addition to __ANDROID_APEX__
-	Use_apex_name_macro *bool
-
-	// Adds two macros for apex variants in addition to __ANDROID_APEX__
-	// * __ANDROID_APEX_COM_ANDROID_FOO__
-	// * __ANDROID_APEX_NAME__="com.android.foo"
-	UseApexNameMacro bool `blueprint:"mutated"`
 }
 
 func NewBaseCompiler() *baseCompiler {
@@ -291,10 +282,6 @@
 	return deps
 }
 
-func (compiler *baseCompiler) useApexNameMacro() bool {
-	return Bool(compiler.Properties.Use_apex_name_macro) || compiler.Properties.UseApexNameMacro
-}
-
 // Return true if the module is in the WarningAllowedProjects.
 func warningsAreAllowed(subdir string) bool {
 	subdir += "/"
@@ -405,10 +392,6 @@
 
 	if ctx.apexVariationName() != "" {
 		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__")
-		if compiler.useApexNameMacro() {
-			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexVariationName())+"__")
-			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_NAME__='\""+ctx.apexVariationName()+"\"'")
-		}
 		if ctx.Device() {
 			flags.Global.CommonFlags = append(flags.Global.CommonFlags,
 				fmt.Sprintf("-D__ANDROID_APEX_MIN_SDK_VERSION__=%d",
@@ -554,11 +537,6 @@
 			"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
 	}
 
-	if compiler.hasSrcExt(".mc") {
-		flags.Local.CommonFlags = append(flags.Local.CommonFlags,
-			"-I"+android.PathForModuleGen(ctx, "windmc", ctx.ModuleDir()).String())
-	}
-
 	if compiler.hasSrcExt(".aidl") {
 		flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
 		if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
@@ -634,10 +612,6 @@
 	return false
 }
 
-func (compiler *baseCompiler) uniqueApexVariations() bool {
-	return compiler.useApexNameMacro()
-}
-
 var invalidDefineCharRegex = regexp.MustCompile("[^a-zA-Z0-9_]")
 
 // makeDefineString transforms a name of an APEX module into a value to be used as value for C define
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index d19f5ac..4797acc 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -16,9 +16,13 @@
 
 import (
 	"fmt"
+	"reflect"
 	"regexp"
 	"sort"
 	"strings"
+
+	"android/soong/android"
+	"github.com/google/blueprint"
 )
 
 const (
@@ -26,18 +30,27 @@
 )
 
 type bazelVarExporter interface {
-	asBazel(exportedStringVariables, exportedStringListVariables) []bazelConstant
+	asBazel(android.Config, exportedStringVariables, exportedStringListVariables, exportedConfigDependingVariables) []bazelConstant
 }
 
 // Helpers for exporting cc configuration information to Bazel.
 var (
-	// Map containing toolchain variables that are independent of the
+	// Maps containing toolchain variables that are independent of the
 	// environment variables of the build.
 	exportedStringListVars     = exportedStringListVariables{}
 	exportedStringVars         = exportedStringVariables{}
 	exportedStringListDictVars = exportedStringListDictVariables{}
+
+	/// Maps containing variables that are dependent on the build config.
+	exportedConfigDependingVars = exportedConfigDependingVariables{}
 )
 
+type exportedConfigDependingVariables map[string]interface{}
+
+func (m exportedConfigDependingVariables) Set(k string, v interface{}) {
+	m[k] = v
+}
+
 // Ensure that string s has no invalid characters to be generated into the bzl file.
 func validateCharacters(s string) string {
 	for _, c := range []string{`\n`, `"`, `\`} {
@@ -74,10 +87,14 @@
 	return strings.Join(list, "\n")
 }
 
-func (m exportedStringVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
+func (m exportedStringVariables) asBazel(config android.Config,
+	stringVars exportedStringVariables, stringListVars exportedStringListVariables, cfgDepVars exportedConfigDependingVariables) []bazelConstant {
 	ret := make([]bazelConstant, 0, len(m))
 	for k, variableValue := range m {
-		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
+		expandedVar, err := expandVar(config, variableValue, stringVars, stringListVars, cfgDepVars)
+		if err != nil {
+			panic(fmt.Errorf("error expanding config variable %s: %s", k, err))
+		}
 		if len(expandedVar) > 1 {
 			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
 		}
@@ -101,7 +118,9 @@
 	m[k] = v
 }
 
-func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
+func (m exportedStringListVariables) asBazel(config android.Config,
+	stringScope exportedStringVariables, stringListScope exportedStringListVariables,
+	exportedVars exportedConfigDependingVariables) []bazelConstant {
 	ret := make([]bazelConstant, 0, len(m))
 	// For each exported variable, recursively expand elements in the variableValue
 	// list to ensure that interpolated variables are expanded according to their values
@@ -109,7 +128,11 @@
 	for k, variableValue := range m {
 		var expandedVars []string
 		for _, v := range variableValue {
-			expandedVars = append(expandedVars, expandVar(v, stringScope, stringListScope)...)
+			expandedVar, err := expandVar(config, v, stringScope, stringListScope, exportedVars)
+			if err != nil {
+				panic(fmt.Errorf("Error expanding config variable %s=%s: %s", k, v, err))
+			}
+			expandedVars = append(expandedVars, expandedVar...)
 		}
 		// Assign the list as a bzl-private variable; this variable will be exported
 		// out through a constants struct later.
@@ -121,6 +144,18 @@
 	return ret
 }
 
+// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain.
+func exportVariableConfigMethod(name string, method interface{}) blueprint.Variable {
+	exportedConfigDependingVars.Set(name, method)
+	return pctx.VariableConfigMethod(name, method)
+}
+
+// Convenience function to declare a static "source path" variable and export it to Bazel's cc_toolchain.
+func exportSourcePathVariable(name string, value string) {
+	pctx.SourcePathVariable(name, value)
+	exportedStringVars.Set(name, value)
+}
+
 // Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
 func exportStringListStaticVariable(name string, value []string) {
 	pctx.StaticVariable(name, strings.Join(value, " "))
@@ -145,7 +180,8 @@
 }
 
 // Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
-func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ exportedStringListVariables) []bazelConstant {
+func (m exportedStringListDictVariables) asBazel(_ android.Config, _ exportedStringVariables,
+	_ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant {
 	ret := make([]bazelConstant, 0, len(m))
 	for k, dict := range m {
 		ret = append(ret, bazelConstant{
@@ -158,19 +194,20 @@
 
 // BazelCcToolchainVars generates bzl file content containing variables for
 // Bazel's cc_toolchain configuration.
-func BazelCcToolchainVars() string {
+func BazelCcToolchainVars(config android.Config) string {
 	return bazelToolchainVars(
+		config,
 		exportedStringListDictVars,
 		exportedStringListVars,
 		exportedStringVars)
 }
 
-func bazelToolchainVars(vars ...bazelVarExporter) string {
+func bazelToolchainVars(config android.Config, vars ...bazelVarExporter) string {
 	ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"
 
 	results := []bazelConstant{}
 	for _, v := range vars {
-		results = append(results, v.asBazel(exportedStringVars, exportedStringListVars)...)
+		results = append(results, v.asBazel(config, exportedStringVars, exportedStringListVars, exportedConfigDependingVars)...)
 	}
 
 	sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName })
@@ -201,34 +238,35 @@
 // string slice than to handle a pass-by-referenced map, which would make it
 // quite complex to track depth-first interpolations. It's also unlikely the
 // interpolation stacks are deep (n > 1).
-func expandVar(toExpand string, stringScope exportedStringVariables, stringListScope exportedStringListVariables) []string {
+func expandVar(config android.Config, toExpand string, stringScope exportedStringVariables,
+	stringListScope exportedStringListVariables, exportedVars exportedConfigDependingVariables) ([]string, error) {
 	// e.g. "${ExternalCflags}"
 	r := regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`)
 
 	// Internal recursive function.
-	var expandVarInternal func(string, map[string]bool) []string
-	expandVarInternal = func(toExpand string, seenVars map[string]bool) []string {
-		var ret []string
-		for _, v := range strings.Split(toExpand, " ") {
-			matches := r.FindStringSubmatch(v)
+	var expandVarInternal func(string, map[string]bool) (string, error)
+	expandVarInternal = func(toExpand string, seenVars map[string]bool) (string, error) {
+		var ret string
+		remainingString := toExpand
+		for len(remainingString) > 0 {
+			matches := r.FindStringSubmatch(remainingString)
 			if len(matches) == 0 {
-				return []string{v}
+				return ret + remainingString, nil
 			}
-
 			if len(matches) != 2 {
-				panic(fmt.Errorf(
-					"Expected to only match 1 subexpression in %s, got %d",
-					v,
-					len(matches)-1))
+				panic(fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", remainingString, len(matches)-1))
 			}
+			matchIndex := strings.Index(remainingString, matches[0])
+			ret += remainingString[:matchIndex]
+			remainingString = remainingString[matchIndex+len(matches[0]):]
 
 			// Index 1 of FindStringSubmatch contains the subexpression match
 			// (variable name) of the capture group.
 			variable := matches[1]
 			// toExpand contains a variable.
 			if _, ok := seenVars[variable]; ok {
-				panic(fmt.Errorf(
-					"Unbounded recursive interpolation of variable: %s", variable))
+				return ret, fmt.Errorf(
+					"Unbounded recursive interpolation of variable: %s", variable)
 			}
 			// A map is passed-by-reference. Create a new map for
 			// this scope to prevent variables seen in one depth-first expansion
@@ -239,15 +277,65 @@
 			}
 			newSeenVars[variable] = true
 			if unexpandedVars, ok := stringListScope[variable]; ok {
+				expandedVars := []string{}
 				for _, unexpandedVar := range unexpandedVars {
-					ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...)
+					expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
+					if err != nil {
+						return ret, err
+					}
+					expandedVars = append(expandedVars, expandedVar)
 				}
+				ret += strings.Join(expandedVars, " ")
 			} else if unexpandedVar, ok := stringScope[variable]; ok {
-				ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...)
+				expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
+				if err != nil {
+					return ret, err
+				}
+				ret += expandedVar
+			} else if unevaluatedVar, ok := exportedVars[variable]; ok {
+				evalFunc := reflect.ValueOf(unevaluatedVar)
+				validateVariableMethod(variable, evalFunc)
+				evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
+				evaluatedValue := evaluatedResult[0].Interface().(string)
+				expandedVar, err := expandVarInternal(evaluatedValue, newSeenVars)
+				if err != nil {
+					return ret, err
+				}
+				ret += expandedVar
+			} else {
+				return "", fmt.Errorf("Unbound config variable %s", variable)
 			}
 		}
-		return ret
+		return ret, nil
+	}
+	var ret []string
+	for _, v := range strings.Split(toExpand, " ") {
+		val, err := expandVarInternal(v, map[string]bool{})
+		if err != nil {
+			return ret, err
+		}
+		ret = append(ret, val)
 	}
 
-	return expandVarInternal(toExpand, map[string]bool{})
+	return ret, nil
+}
+
+func validateVariableMethod(name string, methodValue reflect.Value) {
+	methodType := methodValue.Type()
+	if methodType.Kind() != reflect.Func {
+		panic(fmt.Errorf("method given for variable %s is not a function",
+			name))
+	}
+	if n := methodType.NumIn(); n != 1 {
+		panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)",
+			name, n))
+	}
+	if n := methodType.NumOut(); n != 1 {
+		panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)",
+			name, n))
+	}
+	if kind := methodType.Out(0).Kind(); kind != reflect.String {
+		panic(fmt.Errorf("method for variable %s does not return a string",
+			name))
+	}
 }
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index 883597a..3118df1 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -16,13 +16,21 @@
 
 import (
 	"testing"
+
+	"android/soong/android"
 )
 
 func TestExpandVars(t *testing.T) {
+	android_arm64_config := android.TestConfig("out", nil, "", nil)
+	android_arm64_config.BuildOS = android.Android
+	android_arm64_config.BuildArch = android.Arm64
+
 	testCases := []struct {
 		description     string
+		config          android.Config
 		stringScope     exportedStringVariables
 		stringListScope exportedStringListVariables
+		configVars      exportedConfigDependingVariables
 		toExpand        string
 		expectedValues  []string
 	}{
@@ -57,7 +65,7 @@
 				"bar": []string{"baz", "${qux}"},
 			},
 			toExpand:       "${foo}",
-			expectedValues: []string{"baz", "hello"},
+			expectedValues: []string{"baz hello"},
 		},
 		{
 			description: "double level expansion",
@@ -75,7 +83,7 @@
 				"b": []string{"d"},
 			},
 			toExpand:       "${a}",
-			expectedValues: []string{"d", "c"},
+			expectedValues: []string{"d c"},
 		},
 		{
 			description: "double level expansion, with two variables in a string",
@@ -85,7 +93,7 @@
 				"c": []string{"e"},
 			},
 			toExpand:       "${a}",
-			expectedValues: []string{"d", "e"},
+			expectedValues: []string{"d e"},
 		},
 		{
 			description: "triple level expansion with two variables in a string",
@@ -96,13 +104,38 @@
 				"d": []string{"foo"},
 			},
 			toExpand:       "${a}",
-			expectedValues: []string{"foo", "foo", "foo"},
+			expectedValues: []string{"foo foo foo"},
+		},
+		{
+			description: "expansion with config depending vars",
+			configVars: exportedConfigDependingVariables{
+				"a": func(c android.Config) string { return c.BuildOS.String() },
+				"b": func(c android.Config) string { return c.BuildArch.String() },
+			},
+			config:         android_arm64_config,
+			toExpand:       "${a}-${b}",
+			expectedValues: []string{"android-arm64"},
+		},
+		{
+			description: "double level multi type expansion",
+			stringListScope: exportedStringListVariables{
+				"platform": []string{"${os}-${arch}"},
+				"const":    []string{"const"},
+			},
+			configVars: exportedConfigDependingVariables{
+				"os":   func(c android.Config) string { return c.BuildOS.String() },
+				"arch": func(c android.Config) string { return c.BuildArch.String() },
+				"foo":  func(c android.Config) string { return "foo" },
+			},
+			config:         android_arm64_config,
+			toExpand:       "${const}/${platform}/${foo}",
+			expectedValues: []string{"const/android-arm64/foo"},
 		},
 	}
 
 	for _, testCase := range testCases {
 		t.Run(testCase.description, func(t *testing.T) {
-			output := expandVar(testCase.toExpand, testCase.stringScope, testCase.stringListScope)
+			output, _ := expandVar(testCase.config, testCase.toExpand, testCase.stringScope, testCase.stringListScope, testCase.configVars)
 			if len(output) != len(testCase.expectedValues) {
 				t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output))
 			}
@@ -119,6 +152,7 @@
 func TestBazelToolchainVars(t *testing.T) {
 	testCases := []struct {
 		name        string
+		config      android.Config
 		vars        []bazelVarExporter
 		expectedOut string
 	}{
@@ -248,7 +282,7 @@
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			out := bazelToolchainVars(tc.vars...)
+			out := bazelToolchainVars(tc.config, tc.vars...)
 			if out != tc.expectedOut {
 				t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
 			}
diff --git a/cc/config/global.go b/cc/config/global.go
index 5f41f9e..7abd2fc 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -77,10 +77,6 @@
 		// TODO: can we remove this now?
 		"-Wno-reserved-id-macro",
 
-		// Workaround for ccache with clang.
-		// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
-		"-Wno-unused-command-line-argument",
-
 		// Force clang to always output color diagnostics. Ninja will strip the ANSI
 		// color codes if it is not running in a terminal.
 		"-fcolor-diagnostics",
@@ -274,8 +270,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r433403"
-	ClangDefaultShortVersion = "13.0.2"
+	ClangDefaultVersion      = "clang-r433403b"
+	ClangDefaultShortVersion = "13.0.3"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
@@ -329,6 +325,12 @@
 			// Default to zero initialization.
 			flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang")
 		}
+
+		// Workaround for ccache with clang.
+		// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
+		if ctx.Config().IsEnvTrue("USE_CCACHE") {
+			flags = append(flags, "-Wno-unused-command-line-argument")
+		}
 		return strings.Join(flags, " ")
 	})
 
@@ -364,28 +366,12 @@
 	exportStringStaticVariable("CLANG_DEFAULT_VERSION", ClangDefaultVersion)
 	exportStringStaticVariable("CLANG_DEFAULT_SHORT_VERSION", ClangDefaultShortVersion)
 
-	pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase)
-	pctx.VariableFunc("ClangBase", func(ctx android.PackageVarContext) string {
-		if override := ctx.Config().Getenv("LLVM_PREBUILTS_BASE"); override != "" {
-			return override
-		}
-		return "${ClangDefaultBase}"
-	})
-	pctx.VariableFunc("ClangVersion", func(ctx android.PackageVarContext) string {
-		if override := ctx.Config().Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
-			return override
-		}
-		return ClangDefaultVersion
-	})
+	pctx.StaticVariableWithEnvOverride("ClangBase", "LLVM_PREBUILTS_BASE", ClangDefaultBase)
+	pctx.StaticVariableWithEnvOverride("ClangVersion", "LLVM_PREBUILTS_VERSION", ClangDefaultVersion)
 	pctx.StaticVariable("ClangPath", "${ClangBase}/${HostPrebuiltTag}/${ClangVersion}")
 	pctx.StaticVariable("ClangBin", "${ClangPath}/bin")
 
-	pctx.VariableFunc("ClangShortVersion", func(ctx android.PackageVarContext) string {
-		if override := ctx.Config().Getenv("LLVM_RELEASE_VERSION"); override != "" {
-			return override
-		}
-		return ClangDefaultShortVersion
-	})
+	pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion)
 	pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib64/clang/${ClangShortVersion}/lib/linux")
 
 	// These are tied to the version of LLVM directly in external/llvm, so they might trail the host prebuilts
@@ -418,4 +404,30 @@
 	pctx.StaticVariableWithEnvOverride("REAbiLinkerExecStrategy", "RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
 }
 
-var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+var HostPrebuiltTag = exportVariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+
+func ClangPath(ctx android.PathContext, file string) android.SourcePath {
+	type clangToolKey string
+
+	key := android.NewCustomOnceKey(clangToolKey(file))
+
+	return ctx.Config().OnceSourcePath(key, func() android.SourcePath {
+		return clangPath(ctx).Join(ctx, file)
+	})
+}
+
+var clangPathKey = android.NewOnceKey("clangPath")
+
+func clangPath(ctx android.PathContext) android.SourcePath {
+	return ctx.Config().OnceSourcePath(clangPathKey, func() android.SourcePath {
+		clangBase := ClangDefaultBase
+		if override := ctx.Config().Getenv("LLVM_PREBUILTS_BASE"); override != "" {
+			clangBase = override
+		}
+		clangVersion := ClangDefaultVersion
+		if override := ctx.Config().Getenv("LLVM_PREBUILTS_VERSION"); override != "" {
+			clangVersion = override
+		}
+		return android.PathForSource(ctx, clangBase, ctx.Config().PrebuiltOS(), clangVersion)
+	})
+}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 20384a8..6320dbb 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -95,8 +95,6 @@
 
 	YasmFlags() string
 
-	WindresFlags() string
-
 	Is64Bit() bool
 
 	ShlibSuffix() string
@@ -169,10 +167,6 @@
 	return ""
 }
 
-func (toolchainBase) WindresFlags() string {
-	return ""
-}
-
 func (toolchainBase) LibclangRuntimeLibraryArch() string {
 	return ""
 }
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 3f30191..9577a8c 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -103,6 +103,7 @@
 	"android.system.keystore2-V1-ndk",
 	"android.hardware.wifi.hostapd-V1-ndk",
 	"android.hardware.wifi.hostapd-V1-ndk_platform",
+	"android.hardware.wifi.supplicant-V1-ndk",
 	"android.system.keystore2-V1-ndk_platform",
 	"android.system.keystore2-ndk_platform",
 	"android.system.keystore2-unstable-ndk_platform",
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 0bb1a81..ad82b94 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -56,9 +56,7 @@
 		"10.13",
 		"10.14",
 		"10.15",
-		"11.0",
-		"11.1",
-		"11.3",
+		"11",
 	}
 
 	darwinAvailableLibraries = append(
@@ -113,6 +111,10 @@
 	pctx.StaticVariable("DarwinYasmFlags", "-f macho -m amd64")
 }
 
+func MacStripPath(ctx android.PathContext) string {
+	return getMacTools(ctx).stripPath
+}
+
 type macPlatformTools struct {
 	once sync.Once
 	err  error
@@ -125,7 +127,7 @@
 
 var macTools = &macPlatformTools{}
 
-func getMacTools(ctx android.PackageVarContext) *macPlatformTools {
+func getMacTools(ctx android.PathContext) *macPlatformTools {
 	macTools.once.Do(func() {
 		xcrunTool := "/usr/bin/xcrun"
 
@@ -134,7 +136,7 @@
 				return ""
 			}
 
-			bytes, err := exec.Command(xcrunTool, args...).Output()
+			bytes, err := exec.Command(xcrunTool, append([]string{"--sdk", "macosx"}, args...)...).Output()
 			if err != nil {
 				macTools.err = fmt.Errorf("xcrun %q failed with: %q", args, err)
 				return ""
@@ -143,34 +145,26 @@
 			return strings.TrimSpace(string(bytes))
 		}
 
-		xcrunSdk := func(arg string) string {
-			if selected := ctx.Config().Getenv("MAC_SDK_VERSION"); selected != "" {
-				if !inList(selected, darwinSupportedSdkVersions) {
-					macTools.err = fmt.Errorf("MAC_SDK_VERSION %s isn't supported: %q", selected, darwinSupportedSdkVersions)
-					return ""
-				}
-
-				return xcrun("--sdk", "macosx"+selected, arg)
+		sdkVersion := xcrun("--show-sdk-version")
+		sdkVersionSupported := false
+		for _, version := range darwinSupportedSdkVersions {
+			if version == sdkVersion || strings.HasPrefix(sdkVersion, version+".") {
+				sdkVersionSupported = true
 			}
-
-			for _, sdk := range darwinSupportedSdkVersions {
-				bytes, err := exec.Command(xcrunTool, "--sdk", "macosx"+sdk, arg).Output()
-				if err == nil {
-					return strings.TrimSpace(string(bytes))
-				}
-			}
-			macTools.err = fmt.Errorf("Could not find a supported mac sdk: %q", darwinSupportedSdkVersions)
-			return ""
+		}
+		if !sdkVersionSupported {
+			macTools.err = fmt.Errorf("Unsupported macOS SDK version %q not in %v", sdkVersion, darwinSupportedSdkVersions)
+			return
 		}
 
-		macTools.sdkRoot = xcrunSdk("--show-sdk-path")
+		macTools.sdkRoot = xcrun("--show-sdk-path")
 
 		macTools.arPath = xcrun("--find", "ar")
 		macTools.stripPath = xcrun("--find", "strip")
 		macTools.toolPath = filepath.Dir(xcrun("--find", "ld"))
 	})
 	if macTools.err != nil {
-		ctx.Errorf("%q", macTools.err)
+		android.ReportPathErrorf(ctx, "%q", macTools.err)
 	}
 	return macTools
 }
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index ac5d5f7..43333fa 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -120,40 +120,40 @@
 )
 
 func init() {
-	pctx.StaticVariable("LinuxGccVersion", linuxGccVersion)
-	pctx.StaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
+	exportStringStaticVariable("LinuxGccVersion", linuxGccVersion)
+	exportStringStaticVariable("LinuxGlibcVersion", linuxGlibcVersion)
+
 	// Most places use the full GCC version. A few only use up to the first two numbers.
 	if p := strings.Split(linuxGccVersion, "."); len(p) > 2 {
-		pctx.StaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
+		exportStringStaticVariable("ShortLinuxGccVersion", strings.Join(p[:2], "."))
 	} else {
-		pctx.StaticVariable("ShortLinuxGccVersion", linuxGccVersion)
+		exportStringStaticVariable("ShortLinuxGccVersion", linuxGccVersion)
 	}
 
-	pctx.SourcePathVariable("LinuxGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}")
+	exportSourcePathVariable("LinuxGccRoot",
+		"prebuilts/gcc/linux-x86/host/x86_64-linux-glibc${LinuxGlibcVersion}-${ShortLinuxGccVersion}")
 
-	pctx.StaticVariable("LinuxGccTriple", "x86_64-linux")
+	exportStringListStaticVariable("LinuxGccTriple", []string{"x86_64-linux"})
 
-	pctx.StaticVariable("LinuxCflags", strings.Join(linuxCflags, " "))
-	pctx.StaticVariable("LinuxLdflags", strings.Join(linuxLdflags, " "))
-	pctx.StaticVariable("LinuxLldflags", strings.Join(linuxLdflags, " "))
+	exportStringListStaticVariable("LinuxCflags", linuxCflags)
+	exportStringListStaticVariable("LinuxLdflags", linuxLdflags)
+	exportStringListStaticVariable("LinuxLldflags", linuxLdflags)
+	exportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags)
+	exportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags)
+	exportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags)
+	exportStringListStaticVariable("LinuxMuslCflags", linuxMuslCflags)
+	exportStringListStaticVariable("LinuxMuslLdflags", linuxMuslLdflags)
+	exportStringListStaticVariable("LinuxMuslLldflags", linuxMuslLdflags)
 
-	pctx.StaticVariable("LinuxX86Cflags", strings.Join(linuxX86Cflags, " "))
-	pctx.StaticVariable("LinuxX8664Cflags", strings.Join(linuxX8664Cflags, " "))
-	pctx.StaticVariable("LinuxX86Ldflags", strings.Join(linuxX86Ldflags, " "))
-	pctx.StaticVariable("LinuxX86Lldflags", strings.Join(linuxX86Ldflags, " "))
-	pctx.StaticVariable("LinuxX8664Ldflags", strings.Join(linuxX8664Ldflags, " "))
-	pctx.StaticVariable("LinuxX8664Lldflags", strings.Join(linuxX8664Ldflags, " "))
+	exportStringListStaticVariable("LinuxX86Cflags", linuxX86Cflags)
+	exportStringListStaticVariable("LinuxX8664Cflags", linuxX8664Cflags)
+	exportStringListStaticVariable("LinuxX86Ldflags", linuxX86Ldflags)
+	exportStringListStaticVariable("LinuxX86Lldflags", linuxX86Ldflags)
+	exportStringListStaticVariable("LinuxX8664Ldflags", linuxX8664Ldflags)
+	exportStringListStaticVariable("LinuxX8664Lldflags", linuxX8664Ldflags)
 	// Yasm flags
-	pctx.StaticVariable("LinuxX86YasmFlags", "-f elf32 -m x86")
-	pctx.StaticVariable("LinuxX8664YasmFlags", "-f elf64 -m amd64")
-
-	pctx.StaticVariable("LinuxGlibcCflags", strings.Join(linuxGlibcCflags, " "))
-	pctx.StaticVariable("LinuxGlibcLdflags", strings.Join(linuxGlibcLdflags, " "))
-	pctx.StaticVariable("LinuxGlibcLldflags", strings.Join(linuxGlibcLdflags, " "))
-	pctx.StaticVariable("LinuxMuslCflags", strings.Join(linuxMuslCflags, " "))
-	pctx.StaticVariable("LinuxMuslLdflags", strings.Join(linuxMuslLdflags, " "))
-	pctx.StaticVariable("LinuxMuslLldflags", strings.Join(linuxMuslLdflags, " "))
+	exportStringListStaticVariable("LinuxX86YasmFlags", []string{"-f elf32 -m x86"})
+	exportStringListStaticVariable("LinuxX8664YasmFlags", []string{"-f elf64 -m amd64"})
 }
 
 type toolchainLinux struct {
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index d9a7537..9daf40f 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -188,14 +188,6 @@
 	return "${config.WindowsIncludeFlags}"
 }
 
-func (t *toolchainWindowsX86) WindresFlags() string {
-	return "-F pe-i386"
-}
-
-func (t *toolchainWindowsX8664) WindresFlags() string {
-	return "-F pe-x86-64"
-}
-
 func (t *toolchainWindowsX86) ClangTriple() string {
 	return "i686-windows-gnu"
 }
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 83f0037..40f16f3 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -79,54 +79,21 @@
 	return flags
 }
 
-// This function performs a breadth-first search over the provided module's
-// dependencies using `visitDirectDeps` to enumerate all shared library
-// dependencies. We require breadth-first expansion, as otherwise we may
-// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
-// from a dependency. This may cause issues when dependencies have explicit
-// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
-func collectAllSharedDependencies(ctx android.SingletonContext, module android.Module) android.Paths {
-	var fringe []android.Module
-
-	seen := make(map[string]bool)
-
-	// Enumerate the first level of dependencies, as we discard all non-library
-	// modules in the BFS loop below.
-	ctx.VisitDirectDeps(module, func(dep android.Module) {
-		if isValidSharedDependency(dep) {
-			fringe = append(fringe, dep)
-		}
-	})
-
-	var sharedLibraries android.Paths
-
-	for i := 0; i < len(fringe); i++ {
-		module := fringe[i]
-		if seen[module.Name()] {
-			continue
-		}
-		seen[module.Name()] = true
-
-		ccModule := module.(*Module)
-		sharedLibraries = append(sharedLibraries, ccModule.UnstrippedOutputFile())
-		ctx.VisitDirectDeps(module, func(dep android.Module) {
-			if isValidSharedDependency(dep) && !seen[dep.Name()] {
-				fringe = append(fringe, dep)
-			}
-		})
+func UnstrippedOutputFile(module android.Module) android.Path {
+	if mod, ok := module.(LinkableInterface); ok {
+		return mod.UnstrippedOutputFile()
 	}
-
-	return sharedLibraries
+	panic("UnstrippedOutputFile called on non-LinkableInterface module: " + module.Name())
 }
 
-// This function takes a module and determines if it is a unique shared library
+// IsValidSharedDependency takes a module and determines if it is a unique shared library
 // that should be installed in the fuzz target output directories. This function
 // returns true, unless:
 //  - The module is not an installable shared library, or
 //  - The module is a header or stub, or
 //  - The module is a prebuilt and its source is available, or
 //  - The module is a versioned member of an SDK snapshot.
-func isValidSharedDependency(dependency android.Module) bool {
+func IsValidSharedDependency(dependency android.Module) bool {
 	// TODO(b/144090547): We should be parsing these modules using
 	// ModuleDependencyTag instead of the current brute-force checking.
 
@@ -246,7 +213,7 @@
 		}
 		seen[child.Name()] = true
 
-		if isValidSharedDependency(child) {
+		if IsValidSharedDependency(child) {
 			sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
 			return true
 		}
@@ -304,7 +271,6 @@
 // their architecture & target/host specific zip file.
 type ccFuzzPackager struct {
 	fuzz.FuzzPackager
-	sharedLibInstallStrings []string
 }
 
 func fuzzPackagingFactory() android.Singleton {
@@ -317,14 +283,14 @@
 	// archive}).
 	archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
 
-	// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
-	// multiple fuzzers that depend on the same shared library.
-	sharedLibraryInstalled := make(map[string]bool)
-
 	// List of individual fuzz targets, so that 'make fuzz' also installs the targets
 	// to the correct output directories as well.
 	s.FuzzTargets = make(map[string]bool)
 
+	// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
+	// multiple fuzzers that depend on the same shared library.
+	sharedLibraryInstalled := make(map[string]bool)
+
 	ctx.VisitAllModules(func(module android.Module) {
 		ccModule, ok := module.(*Module)
 		if !ok || ccModule.Properties.PreventInstall {
@@ -351,7 +317,7 @@
 		archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
 
 		// Grab the list of required shared libraries.
-		sharedLibraries := collectAllSharedDependencies(ctx, module)
+		sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, UnstrippedOutputFile, IsValidSharedDependency)
 
 		var files []fuzz.FileToZip
 		builder := android.NewRuleBuilder(pctx, ctx)
@@ -359,39 +325,8 @@
 		// Package the corpus, data, dict and config into a zipfile.
 		files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
 
-		// Find and mark all the transiently-dependent shared libraries for
-		// packaging.
-		for _, library := range sharedLibraries {
-			files = append(files, fuzz.FileToZip{library, "lib"})
-
-			// For each architecture-specific shared library dependency, we need to
-			// install it to the output directory. Setup the install destination here,
-			// which will be used by $(copy-many-files) in the Make backend.
-			installDestination := sharedLibraryInstallLocation(
-				library, ccModule.Host(), archString)
-			if sharedLibraryInstalled[installDestination] {
-				continue
-			}
-			sharedLibraryInstalled[installDestination] = true
-
-			// Escape all the variables, as the install destination here will be called
-			// via. $(eval) in Make.
-			installDestination = strings.ReplaceAll(
-				installDestination, "$", "$$")
-			s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
-				library.String()+":"+installDestination)
-
-			// Ensure that on device, the library is also reinstalled to the /symbols/
-			// dir. Symbolized DSO's are always installed to the device when fuzzing, but
-			// we want symbolization tools (like `stack`) to be able to find the symbols
-			// in $ANDROID_PRODUCT_OUT/symbols automagically.
-			if !ccModule.Host() {
-				symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
-				symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
-				s.sharedLibInstallStrings = append(s.sharedLibInstallStrings,
-					library.String()+":"+symbolsInstallDestination)
-			}
-		}
+		// Package shared libraries
+		files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
 
 		// The executable.
 		files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""})
@@ -409,15 +344,54 @@
 func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
 	packages := s.Packages.Strings()
 	sort.Strings(packages)
-	sort.Strings(s.sharedLibInstallStrings)
+	sort.Strings(s.FuzzPackager.SharedLibInstallStrings)
 	// TODO(mitchp): Migrate this to use MakeVarsContext::DistForGoal() when it's
 	// ready to handle phony targets created in Soong. In the meantime, this
 	// exports the phony 'fuzz' target and dependencies on packages to
 	// core/main.mk so that we can use dist-for-goals.
 	ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
 	ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
-		strings.Join(s.sharedLibInstallStrings, " "))
+		strings.Join(s.FuzzPackager.SharedLibInstallStrings, " "))
 
 	// Preallocate the slice of fuzz targets to minimise memory allocations.
 	s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS")
 }
+
+// GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for
+// packaging.
+func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
+	var files []fuzz.FileToZip
+
+	for _, library := range sharedLibraries {
+		files = append(files, fuzz.FileToZip{library, "lib"})
+
+		// For each architecture-specific shared library dependency, we need to
+		// install it to the output directory. Setup the install destination here,
+		// which will be used by $(copy-many-files) in the Make backend.
+		installDestination := sharedLibraryInstallLocation(
+			library, module.Host(), archString)
+		if (*sharedLibraryInstalled)[installDestination] {
+			continue
+		}
+		(*sharedLibraryInstalled)[installDestination] = true
+
+		// Escape all the variables, as the install destination here will be called
+		// via. $(eval) in Make.
+		installDestination = strings.ReplaceAll(
+			installDestination, "$", "$$")
+		s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
+			library.String()+":"+installDestination)
+
+		// Ensure that on device, the library is also reinstalled to the /symbols/
+		// dir. Symbolized DSO's are always installed to the device when fuzzing, but
+		// we want symbolization tools (like `stack`) to be able to find the symbols
+		// in $ANDROID_PRODUCT_OUT/symbols automagically.
+		if !module.Host() {
+			symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
+			symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
+			s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
+				library.String()+":"+symbolsInstallDestination)
+		}
+	}
+	return files
+}
diff --git a/cc/gen.go b/cc/gen.go
index 3a1a0e2..8f62363 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -45,13 +45,6 @@
 			CommandDeps: []string{"$syspropCmd"},
 		},
 		"headerOutDir", "publicOutDir", "srcOutDir", "includeName")
-
-	windmc = pctx.AndroidStaticRule("windmc",
-		blueprint.RuleParams{
-			Command:     "$windmcCmd -r$$(dirname $out) -h$$(dirname $out) $in",
-			CommandDeps: []string{"$windmcCmd"},
-		},
-		"windmcCmd")
 )
 
 type YaccProperties struct {
@@ -200,26 +193,6 @@
 	return cppFile, headers.Paths()
 }
 
-func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFlags) (android.Path, android.Path) {
-	headerFile := android.GenPathWithExt(ctx, "windmc", srcFile, "h")
-	rcFile := android.GenPathWithExt(ctx, "windmc", srcFile, "rc")
-
-	windmcCmd := mingwCmd(flags.toolchain, "windmc")
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:           windmc,
-		Description:    "windmc " + srcFile.Rel(),
-		Output:         rcFile,
-		ImplicitOutput: headerFile,
-		Input:          srcFile,
-		Args: map[string]string{
-			"windmcCmd": windmcCmd,
-		},
-	})
-
-	return rcFile, headerFile
-}
-
 // Used to communicate information from the genSources method back to the library code that uses
 // it.
 type generatedSourceInfo struct {
@@ -305,10 +278,6 @@
 			cppFile := rsGeneratedCppFile(ctx, srcFile)
 			rsFiles = append(rsFiles, srcFiles[i])
 			srcFiles[i] = cppFile
-		case ".mc":
-			rcFile, headerFile := genWinMsg(ctx, srcFile, buildFlags)
-			srcFiles[i] = rcFile
-			deps = append(deps, headerFile)
 		case ".sysprop":
 			cppFile, headerFiles := genSysprop(ctx, srcFile)
 			srcFiles[i] = cppFile
diff --git a/cc/installer.go b/cc/installer.go
index f95b493..2522610 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -29,6 +29,9 @@
 	// Install output directly in {partition}/, not in any subdir.  This is only intended for use by
 	// init_first_stage.
 	Install_in_root *bool `android:"arch_variant"`
+
+	// Install output directly in {partition}/xbin
+	Install_in_xbin *bool `android:"arch_vvariant"`
 }
 
 type installLocation int
@@ -73,6 +76,8 @@
 
 	if installer.installInRoot() {
 		dir = ""
+	} else if installer.installInXbin() {
+		dir = "xbin"
 	}
 
 	if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
@@ -123,3 +128,7 @@
 func (installer *baseInstaller) installInRoot() bool {
 	return Bool(installer.Properties.Install_in_root)
 }
+
+func (installer *baseInstaller) installInXbin() bool {
+	return Bool(installer.Properties.Install_in_xbin)
+}
diff --git a/cc/library.go b/cc/library.go
index 0cffd56..d63acfb 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -248,11 +248,13 @@
 	Linkopts               bazel.StringListAttribute
 	Use_libcrt             bazel.BoolAttribute
 	Rtti                   bazel.BoolAttribute
-	Stl                    *string
+
+	Stl     *string
+	Cpp_std *string
 
 	// This is shared only.
-	Version_script bazel.LabelAttribute
-	Link_crt       bazel.BoolAttribute
+	Link_crt                 bazel.BoolAttribute
+	Additional_linker_inputs bazel.LabelListAttribute
 
 	// Common properties shared between both shared and static variants.
 	Shared staticOrSharedAttributes
@@ -328,8 +330,9 @@
 		Use_libcrt:                  linkerAttrs.useLibcrt,
 		Rtti:                        compilerAttrs.rtti,
 		Stl:                         compilerAttrs.stl,
+		Cpp_std:                     compilerAttrs.cppStd,
 
-		Version_script: linkerAttrs.versionScript,
+		Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
 
 		Strip: stripAttributes{
 			Keep_symbols:                 linkerAttrs.stripKeepSymbols,
@@ -636,7 +639,7 @@
 
 func (handler *ccLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
 	bazelCtx := ctx.Config().BazelContext
-	ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
+	ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
 	if err != nil {
 		ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
 		return false
@@ -2399,10 +2402,10 @@
 		attrs = &bazelCcLibraryStaticAttributes{
 			staticOrSharedAttributes: commonAttrs,
 
-			Linkopts:               linkerAttrs.linkopts,
 			Use_libcrt:             linkerAttrs.useLibcrt,
 			Rtti:                   compilerAttrs.rtti,
 			Stl:                    compilerAttrs.stl,
+			Cpp_std:                compilerAttrs.cppStd,
 			Export_includes:        exportedIncludes.Includes,
 			Export_system_includes: exportedIncludes.SystemIncludes,
 			Local_includes:         compilerAttrs.localIncludes,
@@ -2427,12 +2430,13 @@
 			Use_libcrt: linkerAttrs.useLibcrt,
 			Rtti:       compilerAttrs.rtti,
 			Stl:        compilerAttrs.stl,
+			Cpp_std:    compilerAttrs.cppStd,
 
-			Export_includes:        exportedIncludes.Includes,
-			Export_system_includes: exportedIncludes.SystemIncludes,
-			Local_includes:         compilerAttrs.localIncludes,
-			Absolute_includes:      compilerAttrs.absoluteIncludes,
-			Version_script:         linkerAttrs.versionScript,
+			Export_includes:          exportedIncludes.Includes,
+			Export_system_includes:   exportedIncludes.SystemIncludes,
+			Local_includes:           compilerAttrs.localIncludes,
+			Absolute_includes:        compilerAttrs.absoluteIncludes,
+			Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
 
 			Strip: stripAttributes{
 				Keep_symbols:                 linkerAttrs.stripKeepSymbols,
@@ -2458,10 +2462,10 @@
 type bazelCcLibraryStaticAttributes struct {
 	staticOrSharedAttributes
 
-	Linkopts   bazel.StringListAttribute
 	Use_libcrt bazel.BoolAttribute
 	Rtti       bazel.BoolAttribute
 	Stl        *string
+	Cpp_std    *string
 
 	Export_includes        bazel.StringListAttribute
 	Export_system_includes bazel.StringListAttribute
@@ -2489,6 +2493,7 @@
 	Use_libcrt bazel.BoolAttribute
 	Rtti       bazel.BoolAttribute
 	Stl        *string
+	Cpp_std    *string
 
 	Export_includes        bazel.StringListAttribute
 	Export_system_includes bazel.StringListAttribute
@@ -2496,8 +2501,8 @@
 	Absolute_includes      bazel.StringListAttribute
 	Hdrs                   bazel.LabelListAttribute
 
-	Strip          stripAttributes
-	Version_script bazel.LabelAttribute
+	Strip                    stripAttributes
+	Additional_linker_inputs bazel.LabelListAttribute
 
 	Cppflags   bazel.StringListAttribute
 	Conlyflags bazel.StringListAttribute
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 51c1eb8..b2b3dbc 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -57,7 +57,7 @@
 
 func (h *libraryHeaderBazelHander) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
 	bazelCtx := ctx.Config().BazelContext
-	ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
+	ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
 	if err != nil {
 		ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
 		return false
diff --git a/cc/linkable.go b/cc/linkable.go
index b510508..560c9de 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -110,6 +110,7 @@
 	BaseModuleName() string
 
 	OutputFile() android.OptionalPath
+	UnstrippedOutputFile() android.Path
 	CoverageFiles() android.Paths
 
 	NonCcVariants() bool
diff --git a/cc/lto.go b/cc/lto.go
index d9a0118..99598a9 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -49,8 +49,9 @@
 
 	// Dep properties indicate that this module needs to be built with LTO
 	// since it is an object dependency of an LTO module.
-	FullDep bool `blueprint:"mutated"`
-	ThinDep bool `blueprint:"mutated"`
+	FullDep  bool `blueprint:"mutated"`
+	ThinDep  bool `blueprint:"mutated"`
+	NoLtoDep bool `blueprint:"mutated"`
 
 	// Use clang lld instead of gnu ld.
 	Use_clang_lld *bool
@@ -70,15 +71,6 @@
 func (lto *lto) begin(ctx BaseModuleContext) {
 	if ctx.Config().IsEnvTrue("DISABLE_LTO") {
 		lto.Properties.Lto.Never = proptools.BoolPtr(true)
-	} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
-		staticLib := ctx.static() && !ctx.staticBinary()
-		hostBin := ctx.Host()
-		vndk := ctx.isVndk() // b/169217596
-		if !staticLib && !hostBin && !vndk {
-			if !lto.Never() && !lto.FullLTO() {
-				lto.Properties.Lto.Thin = proptools.BoolPtr(true)
-			}
-		}
 	}
 }
 
@@ -96,22 +88,27 @@
 		return flags
 	}
 
-	if lto.LTO() {
-		var ltoFlag string
+	if lto.LTO(ctx) {
+		var ltoCFlag string
+		var ltoLdFlag string
 		if lto.ThinLTO() {
-			ltoFlag = "-flto=thin -fsplit-lto-unit"
+			ltoCFlag = "-flto=thin -fsplit-lto-unit"
+		} else if lto.FullLTO() {
+			ltoCFlag = "-flto"
 		} else {
-			ltoFlag = "-flto"
+			ltoCFlag = "-flto=thin -fsplit-lto-unit"
+			ltoLdFlag = "-Wl,--lto-O0"
 		}
 
-		flags.Local.CFlags = append(flags.Local.CFlags, ltoFlag)
-		flags.Local.LdFlags = append(flags.Local.LdFlags, ltoFlag)
+		flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlag)
+		flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlag)
+		flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlag)
 
 		if Bool(lto.Properties.Whole_program_vtables) {
 			flags.Local.CFlags = append(flags.Local.CFlags, "-fwhole-program-vtables")
 		}
 
-		if lto.ThinLTO() && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
+		if (lto.DefaultThinLTO(ctx) || lto.ThinLTO()) && ctx.Config().IsEnvTrue("USE_THINLTO_CACHE") && lto.useClangLld(ctx) {
 			// Set appropriate ThinLTO cache policy
 			cacheDirFormat := "-Wl,--thinlto-cache-dir="
 			cacheDir := android.PathForOutput(ctx, "thinlto-cache").String()
@@ -134,33 +131,41 @@
 	return flags
 }
 
-// Can be called with a null receiver
-func (lto *lto) LTO() bool {
-	if lto == nil || lto.Never() {
-		return false
-	}
+func (lto *lto) LTO(ctx BaseModuleContext) bool {
+	return lto.ThinLTO() || lto.FullLTO() || lto.DefaultThinLTO(ctx)
+}
 
-	return lto.FullLTO() || lto.ThinLTO()
+func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
+	host := ctx.Host()
+	test := ctx.testBinary()
+	vndk := ctx.isVndk() // b/169217596
+	return GlobalThinLTO(ctx) && !lto.Never() && !host && !test && !vndk
 }
 
 func (lto *lto) FullLTO() bool {
-	return Bool(lto.Properties.Lto.Full)
+	return lto != nil && Bool(lto.Properties.Lto.Full)
 }
 
 func (lto *lto) ThinLTO() bool {
-	return Bool(lto.Properties.Lto.Thin)
+	return lto != nil && Bool(lto.Properties.Lto.Thin)
 }
 
-// Is lto.never explicitly set to true?
 func (lto *lto) Never() bool {
-	return Bool(lto.Properties.Lto.Never)
+	return lto != nil && Bool(lto.Properties.Lto.Never)
+}
+
+func GlobalThinLTO(ctx android.BaseModuleContext) bool {
+	return ctx.Config().IsEnvTrue("GLOBAL_THINLTO")
 }
 
 // Propagate lto requirements down from binaries
 func ltoDepsMutator(mctx android.TopDownMutatorContext) {
-	if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
+	globalThinLTO := GlobalThinLTO(mctx)
+
+	if m, ok := mctx.Module().(*Module); ok {
 		full := m.lto.FullLTO()
 		thin := m.lto.ThinLTO()
+		never := m.lto.Never()
 		if full && thin {
 			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
 		}
@@ -180,14 +185,16 @@
 				}
 			}
 
-			if dep, ok := dep.(*Module); ok && dep.lto != nil &&
-				!dep.lto.Never() {
+			if dep, ok := dep.(*Module); ok {
 				if full && !dep.lto.FullLTO() {
 					dep.lto.Properties.FullDep = true
 				}
-				if thin && !dep.lto.ThinLTO() {
+				if !globalThinLTO && thin && !dep.lto.ThinLTO() {
 					dep.lto.Properties.ThinDep = true
 				}
+				if globalThinLTO && never && !dep.lto.Never() {
+					dep.lto.Properties.NoLtoDep = true
+				}
 			}
 
 			// Recursively walk static dependencies
@@ -198,6 +205,8 @@
 
 // Create lto variants for modules that need them
 func ltoMutator(mctx android.BottomUpMutatorContext) {
+	globalThinLTO := GlobalThinLTO(mctx)
+
 	if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
 		// Create variations for LTO types required as static
 		// dependencies
@@ -205,18 +214,25 @@
 		if m.lto.Properties.FullDep && !m.lto.FullLTO() {
 			variationNames = append(variationNames, "lto-full")
 		}
-		if m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
+		if !globalThinLTO && m.lto.Properties.ThinDep && !m.lto.ThinLTO() {
 			variationNames = append(variationNames, "lto-thin")
 		}
+		if globalThinLTO && m.lto.Properties.NoLtoDep && !m.lto.Never() {
+			variationNames = append(variationNames, "lto-none")
+		}
 
 		// Use correct dependencies if LTO property is explicitly set
 		// (mutually exclusive)
 		if m.lto.FullLTO() {
 			mctx.SetDependencyVariation("lto-full")
 		}
-		if m.lto.ThinLTO() {
+		if !globalThinLTO && m.lto.ThinLTO() {
 			mctx.SetDependencyVariation("lto-thin")
 		}
+		// Never must be the last, it overrides Thin or Full.
+		if globalThinLTO && m.lto.Never() {
+			mctx.SetDependencyVariation("lto-none")
+		}
 
 		if len(variationNames) > 1 {
 			modules := mctx.CreateVariations(variationNames...)
@@ -232,16 +248,18 @@
 				// LTO properties for dependencies
 				if name == "lto-full" {
 					variation.lto.Properties.Lto.Full = proptools.BoolPtr(true)
-					variation.lto.Properties.Lto.Thin = proptools.BoolPtr(false)
 				}
 				if name == "lto-thin" {
-					variation.lto.Properties.Lto.Full = proptools.BoolPtr(false)
 					variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true)
 				}
+				if name == "lto-none" {
+					variation.lto.Properties.Lto.Never = proptools.BoolPtr(true)
+				}
 				variation.Properties.PreventInstall = true
 				variation.Properties.HideFromMake = true
 				variation.lto.Properties.FullDep = false
 				variation.lto.Properties.ThinDep = false
+				variation.lto.Properties.NoLtoDep = false
 			}
 		}
 	}
diff --git a/cc/object.go b/cc/object.go
index d8bb08f..43abb3a 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -54,7 +54,7 @@
 
 func (handler *objectBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
 	bazelCtx := ctx.Config().BazelContext
-	objPaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType)
+	objPaths, ok := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
 	if ok {
 		if len(objPaths) != 1 {
 			ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index d324241..4a2c451 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,7 +16,6 @@
 
 import (
 	"path/filepath"
-	"strings"
 
 	"android/soong/android"
 )
@@ -232,7 +231,7 @@
 
 // Implements versionedInterface
 func (p *prebuiltLibraryLinker) implementationModuleName(name string) string {
-	return strings.TrimPrefix(name, "prebuilt_")
+	return android.RemoveOptionalPrebuiltPrefix(name)
 }
 
 func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
@@ -330,7 +329,7 @@
 
 func (h *prebuiltStaticLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
 	bazelCtx := ctx.Config().BazelContext
-	ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
+	ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
 	if err != nil {
 		ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
 	}
diff --git a/cmd/multiproduct_kati/Android.bp b/cmd/multiproduct_kati/Android.bp
index e5be6c0..20ca2a3 100644
--- a/cmd/multiproduct_kati/Android.bp
+++ b/cmd/multiproduct_kati/Android.bp
@@ -31,4 +31,14 @@
     testSrcs: [
         "main_test.go",
     ],
+    linux: {
+        srcs: [
+            "main_linux.go",
+        ],
+    },
+    darwin: {
+        srcs: [
+            "main_darwin.go",
+        ],
+    },
 }
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 3c9cac1..0577c86 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -166,15 +166,6 @@
 	MainLogsDir string
 }
 
-func detectTotalRAM() uint64 {
-	var info syscall.Sysinfo_t
-	err := syscall.Sysinfo(&info)
-	if err != nil {
-		panic(err)
-	}
-	return info.Totalram * uint64(info.Unit)
-}
-
 func findNamedProducts(soongUi string, log logger.Logger) []string {
 	cmd := exec.Command(soongUi, "--dumpvars-mode", "--vars=all_named_products")
 	output, err := cmd.Output()
@@ -301,7 +292,7 @@
 		jobs = runtime.NumCPU() / 4
 
 		ramGb := int(detectTotalRAM() / (1024 * 1024 * 1024))
-		if ramJobs := ramGb / 25; ramGb > 0 && jobs > ramJobs {
+		if ramJobs := ramGb / 30; ramGb > 0 && jobs > ramJobs {
 			jobs = ramJobs
 		}
 
diff --git a/cmd/multiproduct_kati/main_darwin.go b/cmd/multiproduct_kati/main_darwin.go
new file mode 100644
index 0000000..3d1b12a
--- /dev/null
+++ b/cmd/multiproduct_kati/main_darwin.go
@@ -0,0 +1,20 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+func detectTotalRAM() uint64 {
+	// unimplemented stub on darwin
+	return 0
+}
diff --git a/cmd/multiproduct_kati/main_linux.go b/cmd/multiproduct_kati/main_linux.go
new file mode 100644
index 0000000..db74496
--- /dev/null
+++ b/cmd/multiproduct_kati/main_linux.go
@@ -0,0 +1,28 @@
+// Copyright 2017 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"syscall"
+)
+
+func detectTotalRAM() uint64 {
+	var info syscall.Sysinfo_t
+	err := syscall.Sysinfo(&info)
+	if err != nil {
+		panic(err)
+	}
+	return info.Totalram * uint64(info.Unit)
+}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index c5e8896..e9eabd3 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -217,15 +217,6 @@
 	generateModuleGraphFile := moduleGraphFile != ""
 	generateDocFile := docFile != ""
 
-	blueprintArgs := cmdlineArgs
-
-	var stopBefore bootstrap.StopBefore
-	if !generateModuleGraphFile && !generateQueryView && !generateDocFile {
-		stopBefore = bootstrap.DoEverything
-	} else {
-		stopBefore = bootstrap.StopBeforePrepareBuildActions
-	}
-
 	if generateBazelWorkspace {
 		// Run the alternate pipeline of bp2build mutators and singleton to convert
 		// Blueprint to BUILD files before everything else.
@@ -233,6 +224,19 @@
 		return bp2buildMarker
 	}
 
+	blueprintArgs := cmdlineArgs
+
+	var stopBefore bootstrap.StopBefore
+	if generateModuleGraphFile {
+		stopBefore = bootstrap.StopBeforeWriteNinja
+	} else if generateQueryView {
+		stopBefore = bootstrap.StopBeforePrepareBuildActions
+	} else if generateDocFile {
+		stopBefore = bootstrap.StopBeforePrepareBuildActions
+	} else {
+		stopBefore = bootstrap.DoEverything
+	}
+
 	ctx := newContext(configuration)
 	if mixedModeBuild {
 		runMixedModeBuild(configuration, ctx, extraNinjaDeps)
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index a1ce8dc..2865ffa 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -439,6 +439,7 @@
 	InitPrebuiltEtcModule(module, "etc")
 	// This module is host-only
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -449,6 +450,7 @@
 	InitPrebuiltRootModule(module)
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -459,6 +461,7 @@
 	InitPrebuiltEtcModule(module, "usr/share")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -469,6 +472,7 @@
 	InitPrebuiltEtcModule(module, "usr/share")
 	// This module is host-only
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -478,6 +482,7 @@
 	InitPrebuiltEtcModule(module, "fonts")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -491,6 +496,7 @@
 	InitPrebuiltEtcModule(module, "etc/firmware")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -503,6 +509,7 @@
 	InitPrebuiltEtcModule(module, "etc/dsp")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
@@ -516,6 +523,7 @@
 	InitPrebuiltEtcModule(module, "lib/rfsa")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
 	return module
 }
 
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index ccadc0f..8861d1b 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -42,8 +42,9 @@
 }
 
 type FuzzPackager struct {
-	Packages    android.Paths
-	FuzzTargets map[string]bool
+	Packages                android.Paths
+	FuzzTargets             map[string]bool
+	SharedLibInstallStrings []string
 }
 
 type FileToZip struct {
@@ -251,3 +252,42 @@
 	sort.Strings(fuzzTargets)
 	ctx.Strict(targets, strings.Join(fuzzTargets, " "))
 }
+
+// CollectAllSharedDependencies performs a breadth-first search over the provided module's
+// dependencies using `visitDirectDeps` to enumerate all shared library
+// dependencies. We require breadth-first expansion, as otherwise we may
+// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
+// from a dependency. This may cause issues when dependencies have explicit
+// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
+func CollectAllSharedDependencies(ctx android.SingletonContext, module android.Module, unstrippedOutputFile func(module android.Module) android.Path, isValidSharedDependency func(dependency android.Module) bool) android.Paths {
+	var fringe []android.Module
+
+	seen := make(map[string]bool)
+
+	// Enumerate the first level of dependencies, as we discard all non-library
+	// modules in the BFS loop below.
+	ctx.VisitDirectDeps(module, func(dep android.Module) {
+		if isValidSharedDependency(dep) {
+			fringe = append(fringe, dep)
+		}
+	})
+
+	var sharedLibraries android.Paths
+
+	for i := 0; i < len(fringe); i++ {
+		module := fringe[i]
+		if seen[module.Name()] {
+			continue
+		}
+		seen[module.Name()] = true
+
+		sharedLibraries = append(sharedLibraries, unstrippedOutputFile(module))
+		ctx.VisitDirectDeps(module, func(dep android.Module) {
+			if isValidSharedDependency(dep) && !seen[dep.Name()] {
+				fringe = append(fringe, dep)
+			}
+		})
+	}
+
+	return sharedLibraries
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 4dd2135..b9c2b10 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -248,7 +248,7 @@
 // Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
 func (c *Module) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
 	bazelCtx := ctx.Config().BazelContext
-	filePaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType)
+	filePaths, ok := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
 	if ok {
 		var bazelOutputFiles android.Paths
 		exportIncludeDirs := map[string]bool{}
diff --git a/java/androidmk.go b/java/androidmk.go
index 537159e..eca5caa 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -60,6 +60,11 @@
 func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
 	var entriesList []android.AndroidMkEntries
 
+	if library.Os() == android.Windows {
+		// Make does not support Windows Java modules
+		return nil
+	}
+
 	if library.hideApexVariantFromMake {
 		// For a java library built for an APEX, we don't need a Make module for itself. Otherwise, it
 		// will conflict with the platform variant because they have the same module name in the
@@ -250,6 +255,10 @@
 }
 
 func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
+	if binary.Os() == android.Windows {
+		// Make does not support Windows Java modules
+		return nil
+	}
 
 	if !binary.isWrapperVariant {
 		return []android.AndroidMkEntries{android.AndroidMkEntries{
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 39fb04a..4abdcc6 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -118,7 +118,7 @@
 		TransformJarsToJar(ctx, outputFile, "combine", d.implementationAndResourceJars,
 			android.OptionalPath{}, false, nil, nil)
 		d.combinedImplementationJar = outputFile
-	} else {
+	} else if len(d.implementationAndResourceJars) == 1 {
 		d.combinedImplementationJar = d.implementationAndResourceJars[0]
 	}
 
@@ -127,7 +127,7 @@
 		TransformJarsToJar(ctx, outputFile, "turbine combine", d.headerJars,
 			android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"})
 		d.combinedHeaderJar = outputFile
-	} else {
+	} else if len(d.headerJars) == 1 {
 		d.combinedHeaderJar = d.headerJars[0]
 	}
 
@@ -174,7 +174,9 @@
 	return android.AndroidMkData{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(d.combinedImplementationJar),
-		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+		// Make does not support Windows Java modules
+		Disabled: d.Os() == android.Windows,
+		Include:  "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
 		Extra: []android.AndroidMkExtraFunc{
 			func(w io.Writer, outputFile android.Path) {
 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
diff --git a/java/genrule.go b/java/genrule.go
index e0a9c8f..16743b3 100644
--- a/java/genrule.go
+++ b/java/genrule.go
@@ -64,6 +64,7 @@
 	module := genrule.NewGenRule()
 
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 
 	return module
 }
@@ -76,6 +77,7 @@
 	module := genrule.NewGenRule()
 
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
+	android.InitDefaultableModule(module)
 
 	return module
 }
diff --git a/java/java.go b/java/java.go
index 287bcfa..854097b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -532,6 +532,14 @@
 	return false
 }
 
+// Sets `dexer.dexProperties.Uncompress_dex` to the proper value.
+func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) {
+	if dexer.dexProperties.Uncompress_dex == nil {
+		// If the value was not force-set by the user, use reasonable default based on the module.
+		dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, dexpreopter))
+	}
+}
+
 func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	j.sdkVersion = j.SdkVersion(ctx)
 	j.minSdkVersion = j.MinSdkVersion(ctx)
@@ -545,10 +553,7 @@
 	j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
 		ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
 	j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
-	if j.dexProperties.Uncompress_dex == nil {
-		// If the value was not force-set by the user, use reasonable default based on the module.
-		j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
-	}
+	setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
 	j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
 	j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
 	j.compile(ctx, nil)
@@ -565,10 +570,6 @@
 		j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
 			j.Stem()+".jar", j.outputFile, extraInstallDeps...)
 	}
-
-	if ctx.Windows() {
-		j.HideFromMake()
-	}
 }
 
 func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1135,10 +1136,6 @@
 		j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
 			ctx.ModuleName()+ext, j.wrapperFile)
 	}
-
-	if ctx.Windows() {
-		j.HideFromMake()
-	}
 }
 
 func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1401,16 +1398,13 @@
 				installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
 				j.dexJarInstallFile = installPath
 
-				// Initialize the hiddenapi structure.
-				j.initHiddenAPI(ctx, dexJarFile, outputFile, nil)
-
 				j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
-				if j.dexProperties.Uncompress_dex == nil {
-					// If the value was not force-set by the user, use reasonable default based on the module.
-					j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
-				}
+				setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
 				j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
 				j.dexpreopt(ctx, dexOutputPath)
+
+				// Initialize the hiddenapi structure.
+				j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
 			} else {
 				// This should never happen as a variant for a prebuilt_apex is only created if the
 				// prebuilt_apex has been configured to export the java library dex file.
@@ -1430,10 +1424,7 @@
 
 			j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
 				ctx, android.PathForModuleInstall(ctx, "framework", jarName))
-			if j.dexProperties.Uncompress_dex == nil {
-				// If the value was not force-set by the user, use reasonable default based on the module.
-				j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
-			}
+			setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
 			j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
 
 			var dexOutputFile android.OutputPath
@@ -1549,9 +1540,6 @@
 var _ android.IDECustomizedModuleName = (*Import)(nil)
 
 // Collect information for opening IDE project files in java/jdeps.go.
-const (
-	removedPrefix = "prebuilt_"
-)
 
 func (j *Import) IDEInfo(dpInfo *android.IdeInfo) {
 	dpInfo.Jars = append(dpInfo.Jars, j.PrebuiltSrcs()...)
diff --git a/java/proto.go b/java/proto.go
index 8731822..2fa22b6 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -24,7 +24,7 @@
 func genProto(ctx android.ModuleContext, protoFiles android.Paths, flags android.ProtoFlags) android.Paths {
 	// Shard proto files into groups of 100 to avoid having to recompile all of them if one changes and to avoid
 	// hitting command line length limits.
-	shards := android.ShardPaths(protoFiles, 100)
+	shards := android.ShardPaths(protoFiles, 50)
 
 	srcJarFiles := make(android.Paths, 0, len(shards))
 
diff --git a/java/sdk.go b/java/sdk.go
index d1b899e..80f2d6a 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -370,7 +370,7 @@
 			"frameworks-base-api-current.txt",
 			"frameworks-base-api-system-current.txt",
 			"frameworks-base-api-module-lib-current.txt",
-			"services-system-server-current.txt",
+			"frameworks-base-api-system-server-current.txt",
 		}
 		count := 0
 		ctx.VisitAllModules(func(module android.Module) {
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 3ae8ab9..b377fd8 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1162,17 +1162,21 @@
 		}
 		// Either pattern or text should be const, and the
 		// non-const one should be varRefExpr
-		if xInList, ok = xPattern.(*stringLiteralExpr); ok {
+		if xInList, ok = xPattern.(*stringLiteralExpr); ok && !strings.ContainsRune(xInList.literal, '%') && xText.typ() == starlarkTypeList {
 			expr = xText
 		} else if xInList, ok = xText.(*stringLiteralExpr); ok {
 			expr = xPattern
 		} else {
-			return &callExpr{
+			expr = &callExpr{
 				object:     nil,
 				name:       filterFuncCall.name,
 				args:       filterFuncCall.args,
 				returnType: starlarkTypeBool,
 			}
+			if negate {
+				expr = &notExpr{expr: expr}
+			}
+			return expr
 		}
 	case *variableRefExpr:
 		if v, ok := xPattern.(*variableRefExpr); ok {
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 434500b..fe1fa08 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -360,20 +360,27 @@
 endif
 ifneq (,$(filter true, $(v1)$(v2)))
 endif
+ifeq (,$(filter barbet coral%,$(TARGET_PRODUCT)))
+else ifneq (,$(filter barbet%,$(TARGET_PRODUCT)))
+endif
 `,
 		expected: `load("//build/make/core:product_config.rbc", "rblf")
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]:
+  if not rblf.filter("userdebug eng", g["TARGET_BUILD_VARIANT"]):
     pass
-  if g["TARGET_BUILD_VARIANT"] == "userdebug":
+  if rblf.filter("userdebug", g["TARGET_BUILD_VARIANT"]):
     pass
   if "plaf" in g.get("PLATFORM_LIST", []):
     pass
   if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]:
     pass
-  if "%s%s" % (_v1, _v2) == "true":
+  if rblf.filter("true", "%s%s" % (_v1, _v2)):
+    pass
+  if not rblf.filter("barbet coral%", g["TARGET_PRODUCT"]):
+    pass
+  elif rblf.filter("barbet%", g["TARGET_PRODUCT"]):
     pass
 `,
 	},
diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go
index 27e8198..64645d7 100644
--- a/mk2rbc/version_defaults.go
+++ b/mk2rbc/version_defaults.go
@@ -15,7 +15,6 @@
 package mk2rbc
 
 import (
-	mkparser "android/soong/androidmk/parser"
 	"bytes"
 	"fmt"
 	"io/ioutil"
@@ -23,6 +22,8 @@
 	"sort"
 	"strconv"
 	"strings"
+
+	mkparser "android/soong/androidmk/parser"
 )
 
 const codenamePrefix = "PLATFORM_VERSION_CODENAME."
@@ -97,7 +98,10 @@
 				strings.ToLower(name), genericValue(value)))
 		}
 	}
+
 	sort.Strings(lines)
+	sort.Strings(codenames)
+
 	sink.WriteString("version_defaults = struct(\n")
 	for _, l := range lines {
 		sink.WriteString(l)
diff --git a/rust/builder.go b/rust/builder.go
index 426a569..f79cf9b 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -95,7 +95,7 @@
 
 func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
 	outputFile android.WritablePath) buildOutput {
-	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
 
 	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin")
 }
@@ -112,13 +112,13 @@
 
 func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
 	outputFile android.WritablePath) buildOutput {
-	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
 	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib")
 }
 
 func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
 	outputFile android.WritablePath) buildOutput {
-	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto")
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, "-C lto=thin")
 	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib")
 }
 
diff --git a/rust/compiler.go b/rust/compiler.go
index 1ce71f6..cada985 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -449,6 +449,10 @@
 
 // Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
 func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) {
+	if len(srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "srcs must not be empty")
+	}
+
 	// The srcs can contain strings with prefix ":".
 	// They are dependent modules of this module, with android.SourceDepTag.
 	// They are not the main source file compiled by rustc.
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index f589b69..ec6829a 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -98,6 +98,41 @@
 		}`)
 }
 
+// Test that we reject _no_ source files.
+func TestEnforceMissingSourceFiles(t *testing.T) {
+
+	singleSrcError := "srcs must not be empty"
+
+	// Test libraries
+	testRustError(t, singleSrcError, `
+		rust_library_host {
+			name: "foo-bar-library",
+			crate_name: "foo",
+		}`)
+
+	// Test binaries
+	testRustError(t, singleSrcError, `
+		rust_binary_host {
+			name: "foo-bar-binary",
+			crate_name: "foo",
+		}`)
+
+	// Test proc_macros
+	testRustError(t, singleSrcError, `
+		rust_proc_macro {
+			name: "foo-bar-proc-macro",
+			crate_name: "foo",
+		}`)
+
+	// Test prebuilts
+	testRustError(t, singleSrcError, `
+		rust_prebuilt_dylib {
+			name: "foo-bar-prebuilt",
+			crate_name: "foo",
+		  host_supported: true,
+		}`)
+}
+
 // Test environment vars for Cargo compat are set.
 func TestCargoCompat(t *testing.T) {
 	ctx := testRust(t, `
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 47ca3a7..b113573 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -32,6 +32,7 @@
 		"system/security",
 		"system/tools/aidl",
 		"tools/security/fuzzing/example_rust_fuzzer",
+		"tools/security/fuzzing/orphans",
 		"vendor/",
 	}
 
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 5fb56ff..a628b61 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -111,6 +111,10 @@
 	// List of individual fuzz targets.
 	s.FuzzTargets = make(map[string]bool)
 
+	// Map tracking whether each shared library has an install rule to avoid duplicate install rules from
+	// multiple fuzzers that depend on the same shared library.
+	sharedLibraryInstalled := make(map[string]bool)
+
 	ctx.VisitAllModules(func(module android.Module) {
 		// Discard non-fuzz targets.
 		rustModule, ok := module.(*Module)
@@ -145,6 +149,12 @@
 		// The executable.
 		files = append(files, fuzz.FileToZip{rustModule.unstrippedOutputFile.Path(), ""})
 
+		// Grab the list of required shared libraries.
+		sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency)
+
+		// Package shared libraries
+		files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
+
 		archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
 		if !ok {
 			return
diff --git a/rust/rust.go b/rust/rust.go
index b9afc7f..13169f1 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -130,9 +130,10 @@
 	// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
 	Min_sdk_version *string
 
-	PreventInstall bool
-	HideFromMake   bool
-	Installable    *bool
+	HideFromMake   bool `blueprint:"mutated"`
+	PreventInstall bool `blueprint:"mutated"`
+
+	Installable *bool
 }
 
 type Module struct {
@@ -177,8 +178,8 @@
 	mod.Properties.HideFromMake = true
 }
 
-func (c *Module) HiddenFromMake() bool {
-	return c.Properties.HideFromMake
+func (mod *Module) HiddenFromMake() bool {
+	return mod.Properties.HideFromMake
 }
 
 func (mod *Module) SanitizePropDefined() bool {
@@ -526,10 +527,6 @@
 	return mod.Properties.PreventInstall
 }
 
-func (mod *Module) HideFromMake() {
-	mod.Properties.HideFromMake = true
-}
-
 func (mod *Module) MarkAsCoverageVariant(coverage bool) {
 	mod.coverage.Properties.IsCoverageVariant = coverage
 }
@@ -597,6 +594,13 @@
 	return false
 }
 
+func (mod *Module) UnstrippedOutputFile() android.Path {
+	if mod.unstrippedOutputFile.Valid() {
+		return mod.unstrippedOutputFile.Path()
+	}
+	return nil
+}
+
 func (mod *Module) IncludeDirs() android.Paths {
 	if mod.compiler != nil {
 		if library, ok := mod.compiler.(*libraryDecorator); ok {
@@ -898,8 +902,24 @@
 		}
 
 		apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
-		if mod.installable(apexInfo) {
+		if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) {
+			// If the module has been specifically configure to not be installed then
+			// hide from make as otherwise it will break when running inside make as the
+			// output path to install will not be specified. Not all uninstallable
+			// modules can be hidden from make as some are needed for resolving make
+			// side dependencies.
+			mod.HideFromMake()
+		} else if !mod.installable(apexInfo) {
+			mod.SkipInstall()
+		}
+
+		// Still call install though, the installs will be stored as PackageSpecs to allow
+		// using the outputs in a genrule.
+		if mod.OutputFile().Valid() {
 			mod.compiler.install(ctx)
+			if ctx.Failed() {
+				return
+			}
 		}
 
 		ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index b05861b..281cb82 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -17,6 +17,7 @@
 MODULES_SDK_AND_EXPORTS=(
   art-module-sdk
   art-module-test-exports
+  compos-module-sdk
   conscrypt-module-host-exports
   conscrypt-module-sdk
   conscrypt-module-test-exports
diff --git a/scripts/gen_ndk_backedby_apex.sh b/scripts/gen_ndk_backedby_apex.sh
index 4abaaba..212362e 100755
--- a/scripts/gen_ndk_backedby_apex.sh
+++ b/scripts/gen_ndk_backedby_apex.sh
@@ -21,52 +21,29 @@
 # After the parse function below "dlopen" would be write to the output file.
 printHelp() {
     echo "**************************** Usage Instructions ****************************"
-    echo "This script is used to generate the Mainline modules backed-by NDK symbols."
+    echo "This script is used to generate the native libraries backed by Mainline modules."
     echo ""
-    echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$NDK_LIB_NAME_LIST \$MODULE_LIB1 \$MODULE_LIB2..."
+    echo "To run this script use: ./gen_ndk_backed_by_apex.sh \$OUTPUT_FILE_PATH \$MODULE_LIB1 \$MODULE_LIB2..."
     echo "For example: If output write to /backedby.txt then the command would be:"
-    echo "./gen_ndk_backed_by_apex.sh /backedby.txt /ndkLibList.txt lib1.so lib2.so"
+    echo "./gen_ndk_backed_by_apex.sh /backedby.txt lib1.so lib2.so"
     echo "If the module1 is backing lib1 then the backedby.txt would contains: "
-    echo "lib1"
+    echo "lib1.so lib2.so"
 }
 
-contains() {
-  val="$1"
-  shift
-  for x in "$@"; do
-    if [ "$x" = "$val" ]; then
-      return 0
-    fi
-  done
-  return 1
-}
-
-
-genBackedByList() {
+genAllBackedByList() {
   out="$1"
   shift
-  ndk_list="$1"
-  shift
   rm -f "$out"
   touch "$out"
-  while IFS= read -r line
-  do
-    soFileName=$(echo "$line" | sed 's/\(.*so\).*/\1/')
-    if [[ ! -z "$soFileName" && "$soFileName" != *"#"* ]]
-    then
-      if contains "$soFileName" "$@"; then
-        echo "$soFileName" >> "$out"
-      fi
-    fi
-  done < "$ndk_list"
+  echo "$@" >> "$out"
 }
 
 if [[ "$1" == "help" ]]
 then
   printHelp
-elif [[ "$#" -lt 2 ]]
+elif [[ "$#" -lt 1 ]]
 then
-  echo "Wrong argument length. Expecting at least 2 argument representing output path, path to ndk library list, followed by a list of libraries in the Mainline module."
+  echo "Wrong argument length. Expecting at least 1 argument representing output path, followed by a list of libraries in the Mainline module."
 else
-  genBackedByList "$@"
+  genAllBackedByList "$@"
 fi
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
index 64d922a..691c45d 100755
--- a/scripts/get_clang_version.py
+++ b/scripts/get_clang_version.py
@@ -34,7 +34,7 @@
   with open(global_go) as infile:
     contents = infile.read()
 
-  regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-r\d+[a-z]?\d?)"'
+  regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-.*)"'
   match_rev = re.search(regex_rev, contents)
   if match_rev is None:
     raise RuntimeError('Parsing clang info failed')
diff --git a/ui/build/config.go b/ui/build/config.go
index 5cd5c65..7837cc4 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -83,6 +83,8 @@
 
 	// Set by multiproduct_kati
 	emptyNinjaFile bool
+
+	metricsUploader string
 }
 
 const srcDirFileCheck = "build/soong/root.bp"
@@ -237,7 +239,8 @@
 	// Precondition: the current directory is the top of the source tree
 	checkTopDir(ctx)
 
-	if srcDir := absPath(ctx, "."); strings.ContainsRune(srcDir, ' ') {
+	srcDir := absPath(ctx, ".")
+	if strings.ContainsRune(srcDir, ' ') {
 		ctx.Println("You are building in a directory whose absolute path contains a space character:")
 		ctx.Println()
 		ctx.Printf("%q\n", srcDir)
@@ -245,6 +248,8 @@
 		ctx.Fatalln("Directory names containing spaces are not supported")
 	}
 
+	ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
+
 	if outDir := ret.OutDir(); strings.ContainsRune(outDir, ' ') {
 		ctx.Println("The absolute path of your output directory ($OUT_DIR) contains a space character:")
 		ctx.Println()
@@ -1246,10 +1251,7 @@
 }
 
 func (c *configImpl) MetricsUploaderApp() string {
-	if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok {
-		return p
-	}
-	return ""
+	return c.metricsUploader
 }
 
 // LogsDir returns the logs directory where build log and metrics
@@ -1277,3 +1279,14 @@
 func (c *configImpl) EmptyNinjaFile() bool {
 	return c.emptyNinjaFile
 }
+
+func GetMetricsUploader(topDir string, env *Environment) string {
+	if p, ok := env.Get("METRICS_UPLOADER"); ok {
+		metricsUploader := filepath.Join(topDir, p)
+		if _, err := os.Stat(metricsUploader); err == nil {
+			return metricsUploader
+		}
+	}
+
+	return ""
+}
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 03d304e..e293275 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -1122,3 +1122,65 @@
 		})
 	}
 }
+
+func TestGetMetricsUploaderApp(t *testing.T) {
+
+	metricsUploaderDir := "metrics_uploader_dir"
+	metricsUploaderBinary := "metrics_uploader_binary"
+	metricsUploaderPath := filepath.Join(metricsUploaderDir, metricsUploaderBinary)
+	tests := []struct {
+		description string
+		environ     Environment
+		createFiles bool
+		expected    string
+	}{{
+		description: "Uploader binary exist",
+		environ:     Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
+		createFiles: true,
+		expected:    metricsUploaderPath,
+	}, {
+		description: "Uploader binary not exist",
+		environ:     Environment{"METRICS_UPLOADER=" + metricsUploaderPath},
+		createFiles: false,
+		expected:    "",
+	}, {
+		description: "Uploader binary variable not set",
+		createFiles: true,
+		expected:    "",
+	}}
+
+	for _, tt := range tests {
+		t.Run(tt.description, func(t *testing.T) {
+			defer logger.Recover(func(err error) {
+				t.Fatalf("got unexpected error: %v", err)
+			})
+
+			// Create the root source tree.
+			topDir, err := ioutil.TempDir("", "")
+			if err != nil {
+				t.Fatalf("failed to create temp dir: %v", err)
+			}
+			defer os.RemoveAll(topDir)
+
+			expected := tt.expected
+			if len(expected) > 0 {
+				expected = filepath.Join(topDir, expected)
+			}
+
+			if tt.createFiles {
+				if err := os.MkdirAll(filepath.Join(topDir, metricsUploaderDir), 0755); err != nil {
+					t.Errorf("failed to create %s directory: %v", metricsUploaderDir, err)
+				}
+				if err := ioutil.WriteFile(filepath.Join(topDir, metricsUploaderPath), []byte{}, 0644); err != nil {
+					t.Errorf("failed to create file %s: %v", expected, err)
+				}
+			}
+
+			actual := GetMetricsUploader(topDir, &tt.environ)
+
+			if actual != expected {
+				t.Errorf("expecting: %s, actual: %s", expected, actual)
+			}
+		})
+	}
+}
diff --git a/ui/build/context.go b/ui/build/context.go
index f5e987e..4a4352c 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -71,9 +71,9 @@
 		realTime := end - begin
 		c.Metrics.SetTimeMetrics(
 			soong_metrics_proto.PerfInfo{
-				Desc:      &desc,
-				Name:      &name,
-				StartTime: &begin,
-				RealTime:  &realTime})
+				Description: &desc,
+				Name:        &name,
+				StartTime:   &begin,
+				RealTime:    &realTime})
 	}
 }
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 55ada33..687f519 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -70,12 +70,11 @@
 	return metricsFiles
 }
 
-// UploadMetrics uploads a set of metrics files to a server for analysis. An
-// uploader full path is specified in ANDROID_ENABLE_METRICS_UPLOAD environment
-// variable in order to upload the set of metrics files. The metrics files are
-// first copied to a temporary directory and the uploader is then executed in
-// the background to allow the user/system to continue working. Soong communicates
-// to the uploader through the upload_proto raw protobuf file.
+// UploadMetrics uploads a set of metrics files to a server for analysis.
+// The metrics files are first copied to a temporary directory
+// and the uploader is then executed in the background to allow the user/system
+// to continue working. Soong communicates to the uploader through the
+// upload_proto raw protobuf file.
 func UploadMetrics(ctx Context, config Config, simpleOutput bool, buildStarted time.Time, paths ...string) {
 	ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
 	defer ctx.EndTrace()
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
index b740c11..764a1e1 100644
--- a/ui/build/upload_test.go
+++ b/ui/build/upload_test.go
@@ -80,13 +80,10 @@
 		createFiles bool
 		files       []string
 	}{{
-		description: "ANDROID_ENABLE_METRICS_UPLOAD not set",
-	}, {
-		description: "no metrics files to upload",
-		uploader:    "fake",
+		description: "no metrics uploader",
 	}, {
 		description: "non-existent metrics files no upload",
-		uploader:    "fake",
+		uploader:    "echo",
 		files:       []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"},
 	}, {
 		description: "trigger upload",
@@ -137,9 +134,9 @@
 			config := Config{&configImpl{
 				environ: &Environment{
 					"OUT_DIR=" + outDir,
-					"ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader,
 				},
-				buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
+				buildDateTime:   strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
+				metricsUploader: tt.uploader,
 			}}
 
 			UploadMetrics(ctx, config, false, time.Now(), metricsFiles...)
@@ -192,9 +189,10 @@
 
 			config := Config{&configImpl{
 				environ: &Environment{
-					"ANDROID_ENABLE_METRICS_UPLOAD=fake",
 					"OUT_DIR=/bad",
-				}}}
+				},
+				metricsUploader: "echo",
+			}}
 
 			UploadMetrics(ctx, config, true, time.Now(), metricsFile)
 			t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index c3367e3..ebe664f 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -69,7 +69,7 @@
 func (e event) perfInfo() soong_metrics_proto.PerfInfo {
 	realTime := uint64(_now().Sub(e.start).Nanoseconds())
 	return soong_metrics_proto.PerfInfo{
-		Desc:                  proto.String(e.desc),
+		Description:           proto.String(e.desc),
 		Name:                  proto.String(e.name),
 		StartTime:             proto.Uint64(uint64(e.start.UnixNano())),
 		RealTime:              proto.Uint64(realTime),
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index ccf9bd8..f1bb862 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -25,16 +25,11 @@
 // that captures the metrics and is them added as a perfInfo into the set
 // of the collected metrics. Finally, when soong_ui has finished the build,
 // the defer Dump function is invoked to store the collected metrics to the
-// raw protobuf file in the $OUT directory.
-//
-// There is one additional step that occurs after the raw protobuf file is written.
-// If the configuration environment variable ANDROID_ENABLE_METRICS_UPLOAD is
-// set with the path, the raw protobuf file is uploaded to the destination. See
-// ui/build/upload.go for more details. The filename of the raw protobuf file
-// and the list of files to be uploaded is defined in cmd/soong_ui/main.go.
-//
-// See ui/metrics/event.go for the explanation of what an event is and how
-// the metrics system is a stack based system.
+// raw protobuf file in the $OUT directory and this raw protobuf file will be
+// uploaded to the destination. See ui/build/upload.go for more details. The
+// filename of the raw protobuf file and the list of files to be uploaded is
+// defined in cmd/soong_ui/main.go. See ui/metrics/event.go for the explanation
+// of what an event is and how the metrics system is a stack based system.
 
 import (
 	"io/ioutil"
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 80f80bc..2e530b0 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -660,7 +660,7 @@
 	unknownFields protoimpl.UnknownFields
 
 	// The description for the phase/action/part while the tool running.
-	Desc *string `protobuf:"bytes,1,opt,name=desc" json:"desc,omitempty"`
+	Description *string `protobuf:"bytes,1,opt,name=description" json:"description,omitempty"`
 	// The name for the running phase/action/part.
 	Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
 	// The absolute start time.
@@ -709,9 +709,9 @@
 	return file_metrics_proto_rawDescGZIP(), []int{3}
 }
 
-func (x *PerfInfo) GetDesc() string {
-	if x != nil && x.Desc != nil {
-		return *x.Desc
+func (x *PerfInfo) GetDescription() string {
+	if x != nil && x.Description != nil {
+		return *x.Description
 	}
 	return ""
 }
@@ -1268,93 +1268,93 @@
 	0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12,
 	0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75,
 	0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-	0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0xf3, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49,
-	0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
-	0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
-	0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65,
-	0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72,
-	0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
-	0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52,
-	0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72,
-	0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f,
-	0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
-	0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73,
-	0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xb9, 0x03, 0x0a,
-	0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
-	0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72,
-	0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72,
-	0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d,
-	0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10,
-	0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
-	0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a,
-	0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75,
-	0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
-	0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61,
-	0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18,
-	0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65,
-	0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70,
-	0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49,
-	0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74,
-	0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f,
-	0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75,
-	0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77,
-	0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f,
+	0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0x81, 0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49,
+	0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
+	0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61,
+	0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73,
+	0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x6c,
+	0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x61,
+	0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f,
+	0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x6d,
+	0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63,
+	0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
+	0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
+	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
+	0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
+	0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65,
+	0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50,
+	0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74,
+	0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
+	0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
+	0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f,
+	0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79,
+	0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c,
+	0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11,
+	0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74,
+	0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61,
+	0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f,
+	0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61,
+	0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
+	0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70,
+	0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75,
+	0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75,
+	0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
+	0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74,
+	0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75,
+	0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74,
+	0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
+	0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74,
+	0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f,
 	0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77,
-	0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75,
-	0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77,
-	0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e,
-	0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
-	0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64,
-	0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62,
-	0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
-	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79,
-	0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74,
-	0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69,
-	0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75,
-	0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d,
-	0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d,
-	0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22,
-	0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b,
-	0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53,
-	0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02,
-	0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72,
-	0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
-	0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62,
-	0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
-	0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a,
-	0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f,
-	0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
-	0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75,
-	0x6a, 0x73, 0x22, 0xc3, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c,
-	0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75,
-	0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
-	0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a,
-	0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f,
-	0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
-	0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f,
-	0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04,
-	0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-	0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70,
-	0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78,
-	0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72,
-	0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74,
-	0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f,
-	0x74, 0x6f,
+	0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+	0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69,
+	0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+	0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65,
+	0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
+	0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64,
+	0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64,
+	0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f,
+	0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
+	0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a,
+	0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07,
+	0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f,
+	0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c,
+	0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
+	0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42,
+	0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b,
+	0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72,
+	0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63,
+	0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
+	0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
+	0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72,
+	0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73,
+	0x22, 0xc3, 0x01, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+	0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+	0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11,
+	0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+	0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
+	0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61,
+	0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69,
+	0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73,
+	0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65,
+	0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+	0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+	0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 }
 
 var (
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index ec8f36b..db0a14a 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -139,7 +139,7 @@
 
 message PerfInfo {
   // The description for the phase/action/part while the tool running.
-  optional string desc = 1;
+  optional string description = 1;
 
   // The name for the running phase/action/part.
   optional string name = 2;