Merge "Remove member signature and inner classes from signature-patterns.csv"
diff --git a/android/bazel.go b/android/bazel.go
index e3d017f..6942d57 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -137,6 +137,7 @@
 		// build/bazel explicitly.
 		"build/bazel":/* recursive = */ false,
 		"build/bazel/examples/android_app":/* recursive = */ true,
+		"build/bazel/examples/java":/* recursive = */ true,
 		"build/bazel/bazel_skylib":/* recursive = */ true,
 		"build/bazel/rules":/* recursive = */ true,
 		"build/bazel/rules_cc":/* recursive = */ true,
@@ -149,6 +150,7 @@
 		// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
 		"external/bazelbuild-rules_android":/* recursive = */ true,
 
+		"prebuilts/jdk":/* recursive = */ true,
 		"prebuilts/sdk":/* recursive = */ false,
 		"prebuilts/sdk/tools":/* recursive = */ false,
 		"prebuilts/r8":/* recursive = */ false,
@@ -166,9 +168,10 @@
 		"system/logging/liblog":           Bp2BuildDefaultTrueRecursively,
 		"system/timezone/apex":            Bp2BuildDefaultTrueRecursively,
 		"system/timezone/output_data":     Bp2BuildDefaultTrueRecursively,
-		"external/jemalloc_new":           Bp2BuildDefaultTrueRecursively,
-		"external/fmtlib":                 Bp2BuildDefaultTrueRecursively,
 		"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+		"external/fmtlib":                 Bp2BuildDefaultTrueRecursively,
+		"external/jemalloc_new":           Bp2BuildDefaultTrueRecursively,
+		"external/libcxxabi":              Bp2BuildDefaultTrueRecursively,
 		"external/scudo":                  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/clang/host/linux-x86":  Bp2BuildDefaultTrueRecursively,
 	}
@@ -231,7 +234,10 @@
 
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
-	mixedBuildsDisabledList = []string{}
+	mixedBuildsDisabledList = []string{
+		"libc++abi",      // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+		"libc++demangle", // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+	}
 
 	// Used for quicker lookups
 	bp2buildModuleDoNotConvert  = map[string]bool{}
diff --git a/apex/builder.go b/apex/builder.go
index 148f42f..5baa5c0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -75,7 +75,7 @@
 	// by default set to (uid/gid/mode) = (1000/1000/0644)
 	// TODO(b/113082813) make this configurable using config.fs syntax
 	generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
-		Command: `( echo '/ 1000 1000 0755' ` +
+		Command: `( set -e; echo '/ 1000 1000 0755' ` +
 			`&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
 			`&& for i in  ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
 			`&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 7a57477..1706d72 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -240,6 +240,8 @@
 	// C++ options and sources
 	cppFlags bazel.StringListAttribute
 	srcs     bazel.LabelListAttribute
+
+	rtti bazel.BoolAttribute
 }
 
 // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
@@ -249,6 +251,7 @@
 	var asFlags bazel.StringListAttribute
 	var conlyFlags bazel.StringListAttribute
 	var cppFlags bazel.StringListAttribute
+	var rtti bazel.BoolAttribute
 
 	// Creates the -I flags for a directory, while making the directory relative
 	// to the exec root for Bazel to work.
@@ -302,6 +305,7 @@
 			asFlags.Value = parseCommandLineFlags(baseCompilerProps.Asflags)
 			conlyFlags.Value = parseCommandLineFlags(baseCompilerProps.Conlyflags)
 			cppFlags.Value = parseCommandLineFlags(baseCompilerProps.Cppflags)
+			rtti.Value = baseCompilerProps.Rtti
 
 			for _, dir := range parseLocalIncludeDirs(baseCompilerProps) {
 				copts.Value = append(copts.Value, includeFlags(dir)...)
@@ -345,6 +349,7 @@
 				asFlags.SetSelectValue(axis, config, archVariantAsflags)
 				conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Conlyflags))
 				cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Cppflags))
+				rtti.SetSelectValue(axis, config, baseCompilerProps.Rtti)
 			}
 		}
 	}
@@ -380,6 +385,7 @@
 		cSrcs:      cSrcs,
 		conlyFlags: conlyFlags,
 		cppFlags:   cppFlags,
+		rtti:       rtti,
 	}
 }
 
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 812a245..2d6bcb8 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -96,31 +96,25 @@
 	pctx.SourcePathVariable("Arm64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
 
-	pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
-	pctx.StaticVariable("Arm64Lldflags", strings.Join(arm64Lldflags, " "))
+	exportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
+	exportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
 
-	pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
-	pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
+	exportStringListStaticVariable("Arm64Cflags", arm64Cflags)
+	exportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
+
+	exportedStringListDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflags)
+	exportedStringListDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflags)
 
 	pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
 	pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
 	pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
 	pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))
 
-	pctx.StaticVariable("Arm64CortexA53Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
-
-	pctx.StaticVariable("Arm64CortexA55Cflags",
-		strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
-
-	pctx.StaticVariable("Arm64KryoCflags",
-		strings.Join(arm64CpuVariantCflags["kryo"], " "))
-
-	pctx.StaticVariable("Arm64ExynosM1Cflags",
-		strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
-
-	pctx.StaticVariable("Arm64ExynosM2Cflags",
-		strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
+	pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
+	pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
+	pctx.StaticVariable("Arm64KryoCflags", strings.Join(arm64CpuVariantCflags["kryo"], " "))
+	pctx.StaticVariable("Arm64ExynosM1Cflags", strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
+	pctx.StaticVariable("Arm64ExynosM2Cflags", strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
 }
 
 var (
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index b5afe40..0fe5e68 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -188,6 +188,9 @@
 	exportStringListStaticVariable("ArmArmCflags", armArmCflags)
 	exportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
 
+	exportedStringListDictVars.Set("ArmArchVariantCflags", armArchVariantCflags)
+	exportedStringListDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflags)
+
 	// Clang arch variant cflags
 	exportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
 	exportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index e7e94a8..d19f5ac 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -15,98 +15,182 @@
 package config
 
 import (
-	"android/soong/android"
 	"fmt"
 	"regexp"
+	"sort"
 	"strings"
 )
 
+const (
+	bazelIndent = 4
+)
+
+type bazelVarExporter interface {
+	asBazel(exportedStringVariables, exportedStringListVariables) []bazelConstant
+}
+
 // Helpers for exporting cc configuration information to Bazel.
 var (
 	// Map containing toolchain variables that are independent of the
 	// environment variables of the build.
-	exportedStringListVars = exportedStringListVariables{}
-	exportedStringVars     = exportedStringVariables{}
+	exportedStringListVars     = exportedStringListVariables{}
+	exportedStringVars         = exportedStringVariables{}
+	exportedStringListDictVars = exportedStringListDictVariables{}
 )
 
+// 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`, `"`, `\`} {
+		if strings.Contains(s, c) {
+			panic(fmt.Errorf("%s contains illegal character %s", s, c))
+		}
+	}
+	return s
+}
+
+type bazelConstant struct {
+	variableName       string
+	internalDefinition string
+}
+
 type exportedStringVariables map[string]string
-type exportedStringListVariables map[string][]string
 
 func (m exportedStringVariables) Set(k string, v string) {
 	m[k] = v
 }
 
+func bazelIndention(level int) string {
+	return strings.Repeat(" ", level*bazelIndent)
+}
+
+func printBazelList(items []string, indentLevel int) string {
+	list := make([]string, 0, len(items)+2)
+	list = append(list, "[")
+	innerIndent := bazelIndention(indentLevel + 1)
+	for _, item := range items {
+		list = append(list, fmt.Sprintf(`%s"%s",`, innerIndent, item))
+	}
+	list = append(list, bazelIndention(indentLevel)+"]")
+	return strings.Join(list, "\n")
+}
+
+func (m exportedStringVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
+	ret := make([]bazelConstant, 0, len(m))
+	for k, variableValue := range m {
+		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
+		if len(expandedVar) > 1 {
+			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
+		}
+		ret = append(ret, bazelConstant{
+			variableName:       k,
+			internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
+		})
+	}
+	return ret
+}
+
 // Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
 func exportStringStaticVariable(name string, value string) {
 	pctx.StaticVariable(name, value)
 	exportedStringVars.Set(name, value)
 }
 
+type exportedStringListVariables map[string][]string
+
 func (m exportedStringListVariables) Set(k string, v []string) {
 	m[k] = v
 }
 
+func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []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
+	// in the variable scope.
+	for k, variableValue := range m {
+		var expandedVars []string
+		for _, v := range variableValue {
+			expandedVars = append(expandedVars, expandVar(v, stringScope, stringListScope)...)
+		}
+		// Assign the list as a bzl-private variable; this variable will be exported
+		// out through a constants struct later.
+		ret = append(ret, bazelConstant{
+			variableName:       k,
+			internalDefinition: printBazelList(expandedVars, 0),
+		})
+	}
+	return ret
+}
+
 // 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, " "))
 	exportedStringListVars.Set(name, value)
 }
 
+type exportedStringListDictVariables map[string]map[string][]string
+
+func (m exportedStringListDictVariables) Set(k string, v map[string][]string) {
+	m[k] = v
+}
+
+func printBazelStringListDict(dict map[string][]string) string {
+	bazelDict := make([]string, 0, len(dict)+2)
+	bazelDict = append(bazelDict, "{")
+	for k, v := range dict {
+		bazelDict = append(bazelDict,
+			fmt.Sprintf(`%s"%s": %s,`, bazelIndention(1), k, printBazelList(v, 1)))
+	}
+	bazelDict = append(bazelDict, "}")
+	return strings.Join(bazelDict, "\n")
+}
+
+// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
+func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ exportedStringListVariables) []bazelConstant {
+	ret := make([]bazelConstant, 0, len(m))
+	for k, dict := range m {
+		ret = append(ret, bazelConstant{
+			variableName:       k,
+			internalDefinition: printBazelStringListDict(dict),
+		})
+	}
+	return ret
+}
+
 // BazelCcToolchainVars generates bzl file content containing variables for
 // Bazel's cc_toolchain configuration.
 func BazelCcToolchainVars() string {
+	return bazelToolchainVars(
+		exportedStringListDictVars,
+		exportedStringListVars,
+		exportedStringVars)
+}
+
+func bazelToolchainVars(vars ...bazelVarExporter) string {
 	ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"
 
-	// Ensure that string s has no invalid characters to be generated into the bzl file.
-	validateCharacters := func(s string) string {
-		for _, c := range []string{`\n`, `"`, `\`} {
-			if strings.Contains(s, c) {
-				panic(fmt.Errorf("%s contains illegal character %s", s, c))
-			}
-		}
-		return s
+	results := []bazelConstant{}
+	for _, v := range vars {
+		results = append(results, v.asBazel(exportedStringVars, exportedStringListVars)...)
 	}
 
-	// For each exported variable, recursively expand elements in the variableValue
-	// list to ensure that interpolated variables are expanded according to their values
-	// in the variable scope.
-	for _, k := range android.SortedStringKeys(exportedStringListVars) {
-		variableValue := exportedStringListVars[k]
-		var expandedVars []string
-		for _, v := range variableValue {
-			expandedVars = append(expandedVars, expandVar(v, exportedStringVars, exportedStringListVars)...)
-		}
-		// Build the list for this variable.
-		list := "["
-		for _, flag := range expandedVars {
-			list += fmt.Sprintf("\n    \"%s\",", validateCharacters(flag))
-		}
-		list += "\n]"
-		// Assign the list as a bzl-private variable; this variable will be exported
-		// out through a constants struct later.
-		ret += fmt.Sprintf("_%s = %s\n", k, list)
-		ret += "\n"
-	}
+	sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName })
 
-	for _, k := range android.SortedStringKeys(exportedStringVars) {
-		variableValue := exportedStringVars[k]
-		expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
-		if len(expandedVar) > 1 {
-			panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
-		}
-		ret += fmt.Sprintf("_%s = \"%s\"\n", k, validateCharacters(expandedVar[0]))
-		ret += "\n"
+	definitions := make([]string, 0, len(results))
+	constants := make([]string, 0, len(results))
+	for _, b := range results {
+		definitions = append(definitions,
+			fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
+		constants = append(constants,
+			fmt.Sprintf("%[1]s%[2]s = _%[2]s,", bazelIndention(1), b.variableName))
 	}
 
 	// Build the exported constants struct.
+	ret += strings.Join(definitions, "\n\n")
+	ret += "\n\n"
 	ret += "constants = struct(\n"
-	for _, k := range android.SortedStringKeys(exportedStringVars) {
-		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
-	}
-	for _, k := range android.SortedStringKeys(exportedStringListVars) {
-		ret += fmt.Sprintf("    %s = _%s,\n", k, k)
-	}
-	ret += ")"
+	ret += strings.Join(constants, "\n")
+	ret += "\n)"
+
 	return ret
 }
 
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index a4745e6..883597a 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -115,3 +115,143 @@
 		})
 	}
 }
+
+func TestBazelToolchainVars(t *testing.T) {
+	testCases := []struct {
+		name        string
+		vars        []bazelVarExporter
+		expectedOut string
+	}{
+		{
+			name: "exports strings",
+			vars: []bazelVarExporter{
+				exportedStringVariables{
+					"a": "b",
+					"c": "d",
+				},
+			},
+			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = "b"
+
+_c = "d"
+
+constants = struct(
+    a = _a,
+    c = _c,
+)`,
+		},
+		{
+			name: "exports string lists",
+			vars: []bazelVarExporter{
+				exportedStringListVariables{
+					"a": []string{"b1", "b2"},
+					"c": []string{"d1", "d2"},
+				},
+			},
+			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = [
+    "b1",
+    "b2",
+]
+
+_c = [
+    "d1",
+    "d2",
+]
+
+constants = struct(
+    a = _a,
+    c = _c,
+)`,
+		},
+		{
+			name: "exports string lists dicts",
+			vars: []bazelVarExporter{
+				exportedStringListDictVariables{
+					"a": map[string][]string{"b1": []string{"b2"}},
+					"c": map[string][]string{"d1": []string{"d2"}},
+				},
+			},
+			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = {
+    "b1": [
+        "b2",
+    ],
+}
+
+_c = {
+    "d1": [
+        "d2",
+    ],
+}
+
+constants = struct(
+    a = _a,
+    c = _c,
+)`,
+		},
+		{
+			name: "sorts across types",
+			vars: []bazelVarExporter{
+				exportedStringVariables{
+					"b": "b-val",
+					"d": "d-val",
+				},
+				exportedStringListVariables{
+					"c": []string{"c-val"},
+					"e": []string{"e-val"},
+				},
+				exportedStringListDictVariables{
+					"a": map[string][]string{"a1": []string{"a2"}},
+					"f": map[string][]string{"f1": []string{"f2"}},
+				},
+			},
+			expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = {
+    "a1": [
+        "a2",
+    ],
+}
+
+_b = "b-val"
+
+_c = [
+    "c-val",
+]
+
+_d = "d-val"
+
+_e = [
+    "e-val",
+]
+
+_f = {
+    "f1": [
+        "f2",
+    ],
+}
+
+constants = struct(
+    a = _a,
+    b = _b,
+    c = _c,
+    d = _d,
+    e = _e,
+    f = _f,
+)`,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			out := bazelToolchainVars(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 3daee38..248822f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -228,6 +228,8 @@
 		"-Wno-non-c-typedef-for-linkage", // http://b/161304145
 		// New warnings to be fixed after clang-r407598
 		"-Wno-string-concatenation", // http://b/175068488
+		// New warnings to be fixed after clang-r428724
+		"-Wno-align-mismatch", // http://b/193679946
 	}
 
 	// Extra cflags for external third-party projects to disable warnings that
@@ -266,8 +268,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r416183b1"
-	ClangDefaultShortVersion = "12.0.7"
+	ClangDefaultVersion      = "clang-r428724"
+	ClangDefaultShortVersion = "13.0.1"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index c4f47a7..00f07ff 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -77,6 +77,14 @@
 		"popcnt": []string{"-mpopcnt"},
 		"aes_ni": []string{"-maes"},
 	}
+
+	x86_64DefaultArchVariantFeatures = []string{
+		"ssse3",
+		"sse4",
+		"sse4_1",
+		"sse4_2",
+		"popcnt",
+	}
 )
 
 const (
@@ -84,37 +92,38 @@
 )
 
 func init() {
-	android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64,
-		"ssse3",
-		"sse4",
-		"sse4_1",
-		"sse4_2",
-		"popcnt")
+	android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64, x86_64DefaultArchVariantFeatures...)
+	exportedStringListVars.Set("X86_64DefaultArchVariantFeatures", x86_64DefaultArchVariantFeatures)
 
 	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
 
 	pctx.SourcePathVariable("X86_64GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
 
-	pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
-	pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
+	exportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
+	exportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
 
-	pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
-	pctx.StaticVariable("X86_64Lldflags", strings.Join(x86_64Ldflags, " "))
+	exportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
+	exportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)
 
 	// Clang cflags
-	pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
-	pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
+	exportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
+	exportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
 
 	// Yasm flags
-	pctx.StaticVariable("X86_64YasmFlags", "-f elf64 -m amd64")
+	exportStringListStaticVariable("X86_64YasmFlags", []string{
+		"-f elf64",
+		"-m amd64",
+	})
 
 	// Extended cflags
 
+	exportedStringListDictVars.Set("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
+	exportedStringListDictVars.Set("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)
+
 	// Architecture variant cflags
 	for variant, cflags := range x86_64ArchVariantCflags {
-		pctx.StaticVariable("X86_64"+variant+"VariantCflags",
-			strings.Join(cflags, " "))
+		pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
 	}
 }
 
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 5e510a4..29f0593 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -97,25 +97,29 @@
 	pctx.SourcePathVariable("X86GccRoot",
 		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
 
-	pctx.StaticVariable("X86ToolchainCflags", "-m32")
-	pctx.StaticVariable("X86ToolchainLdflags", "-m32")
+	exportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
+	exportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
 
-	pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
-	pctx.StaticVariable("X86Lldflags", strings.Join(x86Ldflags, " "))
+	exportStringListStaticVariable("X86Ldflags", x86Ldflags)
+	exportStringListStaticVariable("X86Lldflags", x86Ldflags)
 
 	// Clang cflags
-	pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
-	pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
+	exportStringListStaticVariable("X86Cflags", x86Cflags)
+	exportStringListStaticVariable("X86Cppflags", x86Cppflags)
 
 	// Yasm flags
-	pctx.StaticVariable("X86YasmFlags", "-f elf32 -m x86")
+	exportStringListStaticVariable("X86YasmFlags", []string{
+		"-f elf32",
+		"-m x86",
+	})
 
 	// Extended cflags
+	exportedStringListDictVars.Set("X86ArchVariantCflags", x86ArchVariantCflags)
+	exportedStringListDictVars.Set("X86ArchFeatureCflags", x86ArchFeatureCflags)
 
 	// Architecture variant cflags
 	for variant, cflags := range x86ArchVariantCflags {
-		pctx.StaticVariable("X86"+variant+"VariantCflags",
-			strings.Join(cflags, " "))
+		pctx.StaticVariable("X86"+variant+"VariantCflags", strings.Join(cflags, " "))
 	}
 }
 
diff --git a/cc/library.go b/cc/library.go
index 1478a16..51cba20 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -236,6 +236,7 @@
 	Includes            bazel.StringListAttribute
 	Linkopts            bazel.StringListAttribute
 	Use_libcrt          bazel.BoolAttribute
+	Rtti                bazel.BoolAttribute
 
 	// This is shared only.
 	Version_script bazel.LabelAttribute
@@ -323,6 +324,7 @@
 		Includes:            exportedIncludes,
 		Linkopts:            linkerAttrs.linkopts,
 		Use_libcrt:          linkerAttrs.useLibcrt,
+		Rtti:                compilerAttrs.rtti,
 
 		Version_script: linkerAttrs.versionScript,
 
@@ -2335,6 +2337,7 @@
 	Linkopts            bazel.StringListAttribute
 	Linkstatic          bool
 	Use_libcrt          bazel.BoolAttribute
+	Rtti                bazel.BoolAttribute
 	Includes            bazel.StringListAttribute
 	Hdrs                bazel.LabelListAttribute
 
@@ -2396,6 +2399,7 @@
 		Linkopts:   linkerAttrs.linkopts,
 		Linkstatic: true,
 		Use_libcrt: linkerAttrs.useLibcrt,
+		Rtti:       compilerAttrs.rtti,
 		Includes:   exportedIncludes,
 
 		Cppflags:   compilerAttrs.cppFlags,
diff --git a/cc/tidy.go b/cc/tidy.go
index b2382e8..fefa7f0 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -146,6 +146,8 @@
 	tidyChecks = tidyChecks + ",-bugprone-signed-char-misuse"
 	// http://b/155034972
 	tidyChecks = tidyChecks + ",-bugprone-branch-clone"
+	// http://b/193716442
+	tidyChecks = tidyChecks + ",-bugprone-implicit-widening-of-multiplication-result"
 	flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
 
 	if ctx.Config().IsEnvTrue("WITH_TIDY") {
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index f1f7bc7..1280553 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -26,7 +26,7 @@
 	"io/ioutil"
 	"log"
 	"os"
-	"strings"
+	"strconv"
 )
 
 func main() {
@@ -59,20 +59,16 @@
 	fmt.Fprintln(script, "ENTRY(__dlwrap__start)")
 	fmt.Fprintln(script, "SECTIONS {")
 
+	progsWithFlagsCount := make(map[string]int)
+
 	for _, prog := range ef.Progs {
 		if prog.Type != elf.PT_LOAD {
 			continue
 		}
 
-		var progName string
-		progSection := progToFirstSection(prog, ef.Sections)
-		if progSection != nil {
-			progName = progSection.Name
-		} else {
-			progName = fmt.Sprintf(".sect%d", load)
-		}
-		sectionName := ".linker" + progName
-		symName := "__dlwrap_linker" + strings.ReplaceAll(progName, ".", "_")
+		progName := progNameFromFlags(prog.Flags, progsWithFlagsCount)
+		sectionName := ".linker_" + progName
+		symName := "__dlwrap_linker_" + progName
 
 		flags := ""
 		if prog.Flags&elf.PF_W != 0 {
@@ -83,6 +79,12 @@
 		}
 		fmt.Fprintf(asm, ".section %s, \"a%s\"\n", sectionName, flags)
 
+		if load == 0 {
+			fmt.Fprintln(asm, ".globl __dlwrap_linker")
+			fmt.Fprintln(asm, "__dlwrap_linker:")
+			fmt.Fprintln(asm)
+		}
+
 		fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName)
 
 		fmt.Fprintf(script, "  %s 0x%x : {\n", sectionName, baseLoadAddr+prog.Vaddr)
@@ -106,6 +108,10 @@
 		load += 1
 	}
 
+	fmt.Fprintln(asm, ".globl __dlwrap_linker_end")
+	fmt.Fprintln(asm, "__dlwrap_linker_end:")
+	fmt.Fprintln(asm)
+
 	fmt.Fprintln(asm, `.section .note.android.embedded_linker,"a",%note`)
 
 	fmt.Fprintln(script, "}")
@@ -139,11 +145,25 @@
 	fmt.Fprintln(asm)
 }
 
-func progToFirstSection(prog *elf.Prog, sections []*elf.Section) *elf.Section {
-	for _, section := range sections {
-		if section.Addr == prog.Vaddr {
-			return section
-		}
+func progNameFromFlags(flags elf.ProgFlag, progsWithFlagsCount map[string]int) string {
+	s := ""
+	if flags&elf.PF_R != 0 {
+		s += "r"
 	}
-	return nil
+	if flags&elf.PF_W != 0 {
+		s += "w"
+	}
+	if flags&elf.PF_X != 0 {
+		s += "x"
+	}
+
+	count := progsWithFlagsCount[s]
+	count++
+	progsWithFlagsCount[s] = count
+
+	if count > 1 {
+		s += strconv.Itoa(count)
+	}
+
+	return s
 }
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 55a5470..fcad102 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -15,12 +15,15 @@
 package main
 
 import (
+	"bufio"
 	"context"
 	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
+	"log"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"runtime"
 	"strings"
@@ -207,6 +210,14 @@
 	if *alternateResultDir {
 		args = "dist"
 	}
+
+	originalOutDir := os.Getenv("OUT_DIR")
+	if originalOutDir == "" {
+		originalOutDir = "out"
+	}
+
+	soongUi := "build/soong/soong_ui.bash"
+
 	config := build.NewConfig(buildCtx, args)
 	if *outDir == "" {
 		name := "multiproduct"
@@ -214,7 +225,7 @@
 			name += "-" + time.Now().Format("20060102150405")
 		}
 
-		*outDir = filepath.Join(config.OutDir(), name)
+		*outDir = filepath.Join(originalOutDir, name)
 
 		// Ensure the empty files exist in the output directory
 		// containing our output directory too. This is mostly for
@@ -348,7 +359,7 @@
 					if product == "" {
 						return
 					}
-					buildProduct(mpCtx, product)
+					runSoongUiForProduct(mpCtx, product, soongUi)
 				}
 			}
 		}()
@@ -380,11 +391,33 @@
 	}
 }
 
-func buildProduct(mpctx *mpContext, product string) {
-	var stdLog string
+func cleanupAfterProduct(outDir, productZip string) {
+	if *keepArtifacts {
+		args := zip.ZipArgs{
+			FileArgs: []zip.FileArg{
+				{
+					GlobDir:             outDir,
+					SourcePrefixToStrip: outDir,
+				},
+			},
+			OutputFilePath:   productZip,
+			NumParallelJobs:  runtime.NumCPU(),
+			CompressionLevel: 5,
+		}
+		if err := zip.Zip(args); err != nil {
+			log.Fatalf("Error zipping artifacts: %v", err)
+		}
+	}
+	if !*incremental {
+		os.RemoveAll(outDir)
+	}
+}
 
+func runSoongUiForProduct(mpctx *mpContext, product, soongUi string) {
 	outDir := filepath.Join(mpctx.Config.OutDir(), product)
 	logsDir := filepath.Join(mpctx.LogsDir, product)
+	productZip := filepath.Join(mpctx.Config.OutDir(), product+".zip")
+	consoleLogPath := filepath.Join(logsDir, "std.log")
 
 	if err := os.MkdirAll(outDir, 0777); err != nil {
 		mpctx.Logger.Fatalf("Error creating out directory: %v", err)
@@ -393,98 +426,65 @@
 		mpctx.Logger.Fatalf("Error creating log directory: %v", err)
 	}
 
-	stdLog = filepath.Join(logsDir, "std.log")
-	f, err := os.Create(stdLog)
+	consoleLogFile, err := os.Create(consoleLogPath)
 	if err != nil {
-		mpctx.Logger.Fatalf("Error creating std.log: %v", err)
+		mpctx.Logger.Fatalf("Error creating console log file: %v", err)
 	}
-	defer f.Close()
+	defer consoleLogFile.Close()
 
-	log := logger.New(f)
-	defer log.Cleanup()
-	log.SetOutput(filepath.Join(logsDir, "soong.log"))
+	consoleLogWriter := bufio.NewWriter(consoleLogFile)
+	defer consoleLogWriter.Flush()
+
+	args := []string{"--make-mode", "--skip-soong-tests", "--skip-ninja"}
+
+	if !*keepArtifacts {
+		args = append(args, "--empty-ninja-file")
+	}
+
+	if *onlyConfig {
+		args = append(args, "--config-only")
+	} else if *onlySoong {
+		args = append(args, "--soong-only")
+	}
+
+	if *alternateResultDir {
+		args = append(args, "dist")
+	}
+
+	cmd := exec.Command(soongUi, args...)
+	cmd.Stdout = consoleLogWriter
+	cmd.Stderr = consoleLogWriter
+	cmd.Env = append(os.Environ(),
+		"OUT_DIR="+outDir,
+		"TARGET_PRODUCT="+product,
+		"TARGET_BUILD_VARIANT="+*buildVariant,
+		"TARGET_BUILD_TYPE=release",
+		"TARGET_BUILD_APPS=",
+		"TARGET_BUILD_UNBUNDLED=")
 
 	action := &status.Action{
 		Description: product,
 		Outputs:     []string{product},
 	}
+
 	mpctx.Status.StartAction(action)
-	defer logger.Recover(func(err error) {
-		mpctx.Status.FinishAction(status.ActionResult{
-			Action: action,
-			Error:  err,
-			Output: errMsgFromLog(stdLog),
-		})
-	})
-
-	ctx := build.Context{ContextImpl: &build.ContextImpl{
-		Context: mpctx.Context,
-		Logger:  log,
-		Tracer:  mpctx.Tracer,
-		Writer:  f,
-		Thread:  mpctx.Tracer.NewThread(product),
-		Status:  &status.Status{},
-	}}
-	ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
-		build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
-
-	args := append([]string(nil), flag.Args()...)
-	args = append(args, "--skip-soong-tests")
-	config := build.NewConfig(ctx, args...)
-	config.Environment().Set("OUT_DIR", outDir)
-	if !*keepArtifacts {
-		config.SetEmptyNinjaFile(true)
-	}
-	build.FindSources(ctx, config, mpctx.Finder)
-	config.Lunch(ctx, product, *buildVariant)
-
-	defer func() {
-		if *keepArtifacts {
-			args := zip.ZipArgs{
-				FileArgs: []zip.FileArg{
-					{
-						GlobDir:             outDir,
-						SourcePrefixToStrip: outDir,
-					},
-				},
-				OutputFilePath:   filepath.Join(mpctx.Config.OutDir(), product+".zip"),
-				NumParallelJobs:  runtime.NumCPU(),
-				CompressionLevel: 5,
-			}
-			if err := zip.Zip(args); err != nil {
-				log.Fatalf("Error zipping artifacts: %v", err)
-			}
-		}
-		if !*incremental {
-			os.RemoveAll(outDir)
-		}
-	}()
-
-	config.SetSkipNinja(true)
-
-	buildWhat := build.RunProductConfig
-	if !*onlyConfig {
-		buildWhat |= build.RunSoong
-		if !*onlySoong {
-			buildWhat |= build.RunKati
-		}
-	}
+	defer cleanupAfterProduct(outDir, productZip)
 
 	before := time.Now()
-	build.Build(ctx, config)
+	err = cmd.Run()
 
-	// Save std_full.log if Kati re-read the makefiles
-	if buildWhat&build.RunKati != 0 {
-		if after, err := os.Stat(config.KatiBuildNinjaFile()); err == nil && after.ModTime().After(before) {
-			err := copyFile(stdLog, filepath.Join(filepath.Dir(stdLog), "std_full.log"))
+	if !*onlyConfig && !*onlySoong {
+		katiBuildNinjaFile := filepath.Join(outDir, "build-"+product+".ninja")
+		if after, err := os.Stat(katiBuildNinjaFile); err == nil && after.ModTime().After(before) {
+			err := copyFile(consoleLogPath, filepath.Join(filepath.Dir(consoleLogPath), "std_full.log"))
 			if err != nil {
 				log.Fatalf("Error copying log file: %s", err)
 			}
 		}
 	}
-
 	mpctx.Status.FinishAction(status.ActionResult{
 		Action: action,
+		Error:  err,
 	})
 }
 
diff --git a/rust/project_json.go b/rust/project_json.go
index e15ec0f..faa7db5 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -54,7 +54,6 @@
 }
 
 type rustProjectJson struct {
-	// Roots  []string           `json:"roots"`
 	Crates []rustProjectCrate `json:"crates"`
 }
 
@@ -248,9 +247,6 @@
 	idx := len(singleton.project.Crates)
 	singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps}
 	singleton.project.Crates = append(singleton.project.Crates, crate)
-	// rust-analyzer requires that all crates belong to at least one root:
-	// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
-	// singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule))
 	return idx, true
 }
 
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
index 622fca1..f6efc5f 100755
--- a/scripts/get_clang_version.py
+++ b/scripts/get_clang_version.py
@@ -30,7 +30,7 @@
   with open(global_go) as infile:
     contents = infile.read()
 
-  regex_rev = r'\tClangDefaultVersion\s+= "clang-(?P<rev>r\d+[a-z]?\d?)"'
+  regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-r\d+[a-z]?\d?)"'
   match_rev = re.search(regex_rev, contents)
   if match_rev is None:
     raise RuntimeError('Parsing clang info failed')
diff --git a/ui/build/build.go b/ui/build/build.go
index 1ed9014..d869bf0 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -238,6 +238,11 @@
 		ctx.Verboseln("Skipping use of Kati ninja as requested")
 		what = what &^ RunKatiNinja
 	}
+	if config.SkipSoong() {
+		ctx.Verboseln("Skipping use of Soong as requested")
+		what = what &^ RunSoong
+	}
+
 	if config.SkipNinja() {
 		ctx.Verboseln("Skipping Ninja as requested")
 		what = what &^ RunNinja
diff --git a/ui/build/config.go b/ui/build/config.go
index 918a956..9768a44 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -49,6 +49,7 @@
 	skipConfig     bool
 	skipKati       bool
 	skipKatiNinja  bool
+	skipSoong      bool
 	skipNinja      bool
 	skipSoongTests bool
 
@@ -582,6 +583,8 @@
 		arg := strings.TrimSpace(args[i])
 		if arg == "showcommands" {
 			c.verbose = true
+		} else if arg == "--empty-ninja-file" {
+			c.emptyNinjaFile = true
 		} else if arg == "--skip-ninja" {
 			c.skipNinja = true
 		} else if arg == "--skip-make" {
@@ -596,6 +599,10 @@
 		} else if arg == "--soong-only" {
 			c.skipKati = true
 			c.skipKatiNinja = true
+		} else if arg == "--config-only" {
+			c.skipKati = true
+			c.skipKatiNinja = true
+			c.skipSoong = true
 		} else if arg == "--skip-config" {
 			c.skipConfig = true
 		} else if arg == "--skip-soong-tests" {
@@ -690,54 +697,6 @@
 	}
 }
 
-// Lunch configures the environment for a specific product similarly to the
-// `lunch` bash function.
-func (c *configImpl) Lunch(ctx Context, product, variant string) {
-	if variant != "eng" && variant != "userdebug" && variant != "user" {
-		ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
-	}
-
-	c.environ.Set("TARGET_PRODUCT", product)
-	c.environ.Set("TARGET_BUILD_VARIANT", variant)
-	c.environ.Set("TARGET_BUILD_TYPE", "release")
-	c.environ.Unset("TARGET_BUILD_APPS")
-	c.environ.Unset("TARGET_BUILD_UNBUNDLED")
-}
-
-// Tapas configures the environment to build one or more unbundled apps,
-// similarly to the `tapas` bash function.
-func (c *configImpl) Tapas(ctx Context, apps []string, arch, variant string) {
-	if len(apps) == 0 {
-		apps = []string{"all"}
-	}
-	if variant == "" {
-		variant = "eng"
-	}
-
-	if variant != "eng" && variant != "userdebug" && variant != "user" {
-		ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
-	}
-
-	var product string
-	switch arch {
-	case "arm", "":
-		product = "aosp_arm"
-	case "arm64":
-		product = "aosm_arm64"
-	case "x86":
-		product = "aosp_x86"
-	case "x86_64":
-		product = "aosp_x86_64"
-	default:
-		ctx.Fatalf("Invalid architecture: %q", arch)
-	}
-
-	c.environ.Set("TARGET_PRODUCT", product)
-	c.environ.Set("TARGET_BUILD_VARIANT", variant)
-	c.environ.Set("TARGET_BUILD_TYPE", "release")
-	c.environ.Set("TARGET_BUILD_APPS", strings.Join(apps, " "))
-}
-
 func (c *configImpl) Environment() *Environment {
 	return c.environ
 }
@@ -817,6 +776,10 @@
 	return c.skipKatiNinja
 }
 
+func (c *configImpl) SkipSoong() bool {
+	return c.skipSoong
+}
+
 func (c *configImpl) SkipNinja() bool {
 	return c.skipNinja
 }