Merge "Share certificate bp2build between android_app and apex."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 16feb74..9bba3c3 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -133,6 +133,7 @@
 		"external/jemalloc_new":                  Bp2BuildDefaultTrueRecursively,
 		"external/jsoncpp":                       Bp2BuildDefaultTrueRecursively,
 		"external/junit":                         Bp2BuildDefaultTrueRecursively,
+		"external/libaom":                        Bp2BuildDefaultTrueRecursively,
 		"external/libavc":                        Bp2BuildDefaultTrueRecursively,
 		"external/libcap":                        Bp2BuildDefaultTrueRecursively,
 		"external/libcxx":                        Bp2BuildDefaultTrueRecursively,
@@ -167,6 +168,7 @@
 
 		"frameworks/av":                                      Bp2BuildDefaultTrue,
 		"frameworks/av/media/codecs":                         Bp2BuildDefaultTrueRecursively,
+		"frameworks/av/media/codec2/components/aom":          Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/liberror":                       Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/services/minijail":                    Bp2BuildDefaultTrueRecursively,
 		"frameworks/av/media/module/minijail":                Bp2BuildDefaultTrueRecursively,
diff --git a/android/arch.go b/android/arch.go
index 9bc9d89..75ee922 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -147,10 +147,11 @@
 var (
 	archTypeList []ArchType
 
-	Arm    = newArch("arm", "lib32")
-	Arm64  = newArch("arm64", "lib64")
-	X86    = newArch("x86", "lib32")
-	X86_64 = newArch("x86_64", "lib64")
+	Arm     = newArch("arm", "lib32")
+	Arm64   = newArch("arm64", "lib64")
+	Riscv64 = newArch("riscv64", "lib64")
+	X86     = newArch("x86", "lib32")
+	X86_64  = newArch("x86_64", "lib64")
 
 	Common = ArchType{
 		Name: COMMON_VARIANT,
@@ -318,7 +319,7 @@
 	Windows = newOsType("windows", Host, true, X86, X86_64)
 	// Android is the OS for target devices that run all of Android, including the Linux kernel
 	// and the Bionic libc runtime.
-	Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64)
+	Android = newOsType("android", Device, false, Arm, Arm64, Riscv64, X86, X86_64)
 
 	// CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
 	// has dependencies on all the OS variants.
diff --git a/android/arch_test.go b/android/arch_test.go
index 6814f8a..46c018a 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -596,6 +596,7 @@
 				arm64: {
 					a:  ["arm64"],
 				},
+				riscv64: { a: ["riscv64"] },
 				x86: { a:  ["x86"] },
 				x86_64: { a:  ["x86_64"] },
 			},
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 6409292..e81086d 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -167,7 +167,8 @@
 }
 
 type bazelRunner interface {
-	issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) (string, string, error)
+	createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
+	issueBazelCommand(bazelCmd *exec.Cmd) (output string, errorMessage string, error error)
 }
 
 type bazelPaths struct {
@@ -460,16 +461,30 @@
 
 type mockBazelRunner struct {
 	bazelCommandResults map[bazelCommand]string
-	commands            []bazelCommand
-	extraFlags          []string
+	// use *exec.Cmd as a key to get the bazelCommand, the map will be used in issueBazelCommand()
+	// Register createBazelCommand() invocations. Later, an
+	// issueBazelCommand() invocation can be mapped to the *exec.Cmd instance
+	// and then to the expected result via bazelCommandResults
+	tokens     map[*exec.Cmd]bazelCommand
+	commands   []bazelCommand
+	extraFlags []string
 }
 
-func (r *mockBazelRunner) issueBazelCommand(_ *bazelPaths, _ bazel.RunName,
-	command bazelCommand, extraFlags ...string) (string, string, error) {
+func (r *mockBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName,
+	command bazelCommand, extraFlags ...string) *exec.Cmd {
 	r.commands = append(r.commands, command)
 	r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
-	if ret, ok := r.bazelCommandResults[command]; ok {
-		return ret, "", nil
+	cmd := &exec.Cmd{}
+	if r.tokens == nil {
+		r.tokens = make(map[*exec.Cmd]bazelCommand)
+	}
+	r.tokens[cmd] = command
+	return cmd
+}
+
+func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+	if command, ok := r.tokens[bazelCmd]; ok {
+		return r.bazelCommandResults[command], "", nil
 	}
 	return "", "", nil
 }
@@ -480,8 +495,20 @@
 // Returns (stdout, stderr, error). The first and second return values are strings
 // containing the stdout and stderr of the run command, and an error is returned if
 // the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
-	extraFlags ...string) (string, string, error) {
+
+func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+	stderr := &bytes.Buffer{}
+	bazelCmd.Stderr = stderr
+	if output, err := bazelCmd.Output(); err != nil {
+		return "", string(stderr.Bytes()),
+			fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
+	} else {
+		return string(output), string(stderr.Bytes()), nil
+	}
+}
+
+func (r *builtinBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
+	extraFlags ...string) *exec.Cmd {
 	cmdFlags := []string{
 		"--output_base=" + absolutePath(paths.outputBase),
 		command.command,
@@ -525,15 +552,14 @@
 		"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
 	}
 	bazelCmd.Env = append(os.Environ(), extraEnv...)
-	stderr := &bytes.Buffer{}
-	bazelCmd.Stderr = stderr
 
-	if output, err := bazelCmd.Output(); err != nil {
-		return "", string(stderr.Bytes()),
-			fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
-	} else {
-		return string(output), string(stderr.Bytes()), nil
-	}
+	return bazelCmd
+}
+
+func printableCqueryCommand(bazelCmd *exec.Cmd) string {
+	outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(bazelCmd.Args, "\" \"") + "\""
+	return outputString
+
 }
 
 func (context *bazelContext) mainBzlFileContents() []byte {
@@ -838,15 +864,16 @@
 
 	const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
 	cqueryCmd := bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
-	cqueryOutput, cqueryErr, err := context.issueBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
+	cqueryCommandWithFlag := context.createBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
 		"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
+	cqueryOutput, cqueryErr, err := context.issueBazelCommand(cqueryCommandWithFlag)
 	if err != nil {
 		return err
 	}
-	if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666); err != nil {
+	cqueryCommandPrint := fmt.Sprintf("cquery command line:\n  %s \n\n\n", printableCqueryCommand(cqueryCommandWithFlag))
+	if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
 		return err
 	}
-
 	cqueryResults := map[string]string{}
 	for _, outputLine := range strings.Split(cqueryOutput, "\n") {
 		if strings.Contains(outputLine, ">>") {
@@ -882,8 +909,8 @@
 		}
 	}
 	aqueryCmd := bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
-	if aqueryOutput, _, err := context.issueBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
-		extraFlags...); err == nil {
+	if aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+		extraFlags...)); err == nil {
 		context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
 	}
 	if err != nil {
@@ -894,7 +921,7 @@
 	// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
 	// but some of symlinks may be required to resolve source dependencies of the build.
 	buildCmd := bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
-	if _, _, err = context.issueBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd); err != nil {
+	if _, _, err = context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd)); err != nil {
 		return err
 	}
 
diff --git a/bazel/configurability.go b/bazel/configurability.go
index b6bbd67..a93aa00 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -23,10 +23,11 @@
 
 const (
 	// ArchType names in arch.go
-	archArm    = "arm"
-	archArm64  = "arm64"
-	archX86    = "x86"
-	archX86_64 = "x86_64"
+	archArm     = "arm"
+	archArm64   = "arm64"
+	archRiscv64 = "riscv64"
+	archX86     = "x86"
+	archX86_64  = "x86_64"
 
 	// OsType names in arch.go
 	OsAndroid     = "android"
@@ -39,6 +40,7 @@
 	// Targets in arch.go
 	osArchAndroidArm        = "android_arm"
 	osArchAndroidArm64      = "android_arm64"
+	osArchAndroidRiscv64    = "android_riscv64"
 	osArchAndroidX86        = "android_x86"
 	osArchAndroidX86_64     = "android_x86_64"
 	osArchDarwinArm64       = "darwin_arm64"
@@ -99,6 +101,7 @@
 		"arm64": {
 			"dotprod",
 		},
+		"riscv64": {},
 		"x86": {
 			"ssse3",
 			"sse4",
@@ -164,6 +167,7 @@
 	platformOsArchMap = map[string]string{
 		osArchAndroidArm:           "//build/bazel/platforms/os_arch:android_arm",
 		osArchAndroidArm64:         "//build/bazel/platforms/os_arch:android_arm64",
+		osArchAndroidRiscv64:       "//build/bazel/platforms/os_arch:android_riscv64",
 		osArchAndroidX86:           "//build/bazel/platforms/os_arch:android_x86",
 		osArchAndroidX86_64:        "//build/bazel/platforms/os_arch:android_x86_64",
 		osArchDarwinArm64:          "//build/bazel/platforms/os_arch:darwin_arm64",
@@ -187,7 +191,7 @@
 	// TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
 	// in a cyclic dependency.
 	osToArchMap = map[string][]string{
-		OsAndroid:     {archArm, archArm64, archX86, archX86_64},
+		OsAndroid:     {archArm, archArm64, archRiscv64, archX86, archX86_64},
 		osLinux:       {archX86, archX86_64},
 		osLinuxMusl:   {archX86, archX86_64},
 		osDarwin:      {archArm64, archX86_64},
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index d513d04..c1fb800 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -369,6 +369,7 @@
       x86_64:  { arch_paths: ["x86_64.txt"] },
       arm:  { arch_paths: ["arm.txt"] },
       arm64:  { arch_paths: ["arm64.txt"] },
+      riscv64: { arch_paths: ["riscv64.txt"] },
     },
     target: {
       linux: { arch_paths: ["linux.txt"] },
@@ -401,6 +402,10 @@
             "arm64.txt",
             "lib64.txt",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "riscv64.txt",
+            "lib64.txt",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "x86.txt",
             "lib32.txt",
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index e3ea9a0..b47d1f1 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -836,6 +836,10 @@
             "not-for-lib32.c",
             "for-lib64.c",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "not-for-lib32.c",
+            "for-lib64.c",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "not-for-lib64.c",
             "for-lib32.c",
@@ -867,6 +871,7 @@
 			"for-lib64.c":          "",
 			"not-for-arm.c":        "",
 			"not-for-arm64.c":      "",
+			"not-for-riscv64.c":    "",
 			"not-for-x86.c":        "",
 			"not-for-x86_64.c":     "",
 			"not-for-lib32.c":      "",
@@ -881,6 +886,7 @@
    arch: {
        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
        arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
+       riscv64: { srcs: ["for-riscv64.c"], exclude_srcs: ["not-for-riscv64.c"] },
        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
        x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
    },
@@ -896,6 +902,7 @@
         "//build/bazel/platforms/arch:arm": [
             "not-for-arm64.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
             "for-arm.c",
@@ -904,15 +911,26 @@
         "//build/bazel/platforms/arch:arm64": [
             "not-for-arm.c",
             "not-for-lib32.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
             "for-arm64.c",
             "for-lib64.c",
         ],
+        "//build/bazel/platforms/arch:riscv64": [
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-lib32.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+            "for-riscv64.c",
+            "for-lib64.c",
+        ],
         "//build/bazel/platforms/arch:x86": [
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86_64.c",
             "for-x86.c",
             "for-lib32.c",
@@ -921,6 +939,7 @@
             "not-for-arm.c",
             "not-for-arm64.c",
             "not-for-lib32.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "for-x86_64.c",
             "for-lib64.c",
@@ -930,6 +949,7 @@
             "not-for-arm64.c",
             "not-for-lib32.c",
             "not-for-lib64.c",
+            "not-for-riscv64.c",
             "not-for-x86.c",
             "not-for-x86_64.c",
         ],
diff --git a/cc/builder.go b/cc/builder.go
index cb21b1f..0bea9da 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -1135,7 +1135,3 @@
 		},
 	})
 }
-
-func mingwCmd(toolchain config.Toolchain, cmd string) string {
-	return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
-}
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 64a121e..fdc94ad 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -21,6 +21,7 @@
 
         "arm_device.go",
         "arm64_device.go",
+        "riscv64_device.go",
         "x86_device.go",
         "x86_64_device.go",
 
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 66087e6..d7f9618 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -74,7 +74,7 @@
 			"-mcpu=kryo",
 		},
 		"kryo385": []string{
-			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			// Use cortex-a53 because kryo385 is not supported in clang.
 			"-mcpu=cortex-a53",
 		},
 		"exynos-m1": []string{
@@ -86,16 +86,7 @@
 	}
 )
 
-const (
-	arm64GccVersion = "4.9"
-)
-
 func init() {
-	pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
-
-	pctx.SourcePathVariable("Arm64GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
 	exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
 
@@ -164,24 +155,12 @@
 	return "arm64"
 }
 
-func (t *toolchainArm64) GccRoot() string {
-	return "${config.Arm64GccRoot}"
-}
-
-func (t *toolchainArm64) GccTriple() string {
-	return "aarch64-linux-android"
-}
-
-func (t *toolchainArm64) GccVersion() string {
-	return arm64GccVersion
-}
-
 func (t *toolchainArm64) IncludeFlags() string {
 	return ""
 }
 
 func (t *toolchainArm64) ClangTriple() string {
-	return t.GccTriple()
+	return "aarch64-linux-android"
 }
 
 func (t *toolchainArm64) Cflags() string {
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index d702c61..b53a097 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -79,7 +79,7 @@
 		"cortex-a7": []string{
 			"-mcpu=cortex-a7",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -91,7 +91,7 @@
 		"cortex-a15": []string{
 			"-mcpu=cortex-a15",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -100,7 +100,7 @@
 		"cortex-a53": []string{
 			"-mcpu=cortex-a53",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -109,7 +109,7 @@
 		"cortex-a55": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -118,7 +118,7 @@
 		"cortex-a75": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -127,7 +127,7 @@
 		"cortex-a76": []string{
 			"-mcpu=cortex-a55",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -136,7 +136,7 @@
 		"krait": []string{
 			"-mcpu=krait",
 			"-mfpu=neon-vfpv4",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -147,16 +147,16 @@
 			// even though clang does.
 			"-mcpu=cortex-a53",
 			"-mfpu=neon-fp-armv8",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
 			"-D__ARM_FEATURE_LPAE=1",
 		},
 		"kryo385": []string{
-			// Use cortex-a53 because kryo385 is not supported in GCC/clang.
+			// Use cortex-a53 because kryo385 is not supported in clang.
 			"-mcpu=cortex-a53",
-			// Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+			// Fake an ARM compiler flag as these processors support LPAE which clang
 			// don't advertise.
 			// TODO This is a hack and we need to add it for each processor that supports LPAE until some
 			// better solution comes around. See Bug 27340895
@@ -166,17 +166,12 @@
 )
 
 const (
-	name          = "arm"
-	armGccVersion = "4.9"
-	gccTriple     = "arm-linux-androideabi"
-	clangTriple   = "armv7a-linux-androideabi"
+	name        = "arm"
+	ndkTriple   = "arm-linux-androideabi"
+	clangTriple = "armv7a-linux-androideabi"
 )
 
 func init() {
-	pctx.StaticVariable("armGccVersion", armGccVersion)
-
-	pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
-
 	// Just exported. Not created as a Ninja static variable.
 	exportedVars.ExportString("ArmClangTriple", clangTriple)
 
@@ -255,18 +250,6 @@
 	return name
 }
 
-func (t *toolchainArm) GccRoot() string {
-	return "${config.ArmGccRoot}"
-}
-
-func (t *toolchainArm) GccTriple() string {
-	return gccTriple
-}
-
-func (t *toolchainArm) GccVersion() string {
-	return armGccVersion
-}
-
 func (t *toolchainArm) IncludeFlags() string {
 	return ""
 }
@@ -278,7 +261,7 @@
 
 func (t *toolchainArm) ndkTriple() string {
 	// Use current NDK include path, while ClangTriple is changed.
-	return t.GccTriple()
+	return ndkTriple
 }
 
 func (t *toolchainArm) ToolchainCflags() string {
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 01b1e63..2cabdc8 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -75,10 +75,6 @@
 	)
 )
 
-const (
-	darwinGccVersion = "4.2.1"
-)
-
 func init() {
 	pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
 		return getMacTools(ctx).sdkRoot
@@ -100,12 +96,6 @@
 		return getMacTools(ctx).toolPath
 	})
 
-	pctx.StaticVariable("DarwinGccVersion", darwinGccVersion)
-	pctx.SourcePathVariable("DarwinGccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${DarwinGccVersion}")
-
-	pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
-
 	pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
 	pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
 	pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
@@ -196,30 +186,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainDarwinArm) GccRoot() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccTriple() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccVersion() string {
-	panic("unimplemented")
-}
-
-func (t *toolchainDarwinX86) GccRoot() string {
-	return "${config.DarwinGccRoot}"
-}
-
-func (t *toolchainDarwinX86) GccTriple() string {
-	return "${config.DarwinGccTriple}"
-}
-
-func (t *toolchainDarwinX86) GccVersion() string {
-	return darwinGccVersion
-}
-
 func (t *toolchainDarwin) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
new file mode 100644
index 0000000..d8918f1
--- /dev/null
+++ b/cc/config/riscv64_device.go
@@ -0,0 +1,140 @@
+// Copyright 2022 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 config
+
+import (
+	"fmt"
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	riscv64Cflags = []string{
+		// Help catch common 32/64-bit errors.
+		"-Werror=implicit-function-declaration",
+	}
+
+	riscv64ArchVariantCflags = map[string][]string{}
+
+	riscv64Ldflags = []string{
+		"-Wl,--hash-style=gnu",
+		"-Wl,-z,separate-code",
+	}
+
+	riscv64Lldflags = append(riscv64Ldflags,
+		"-Wl,-z,max-page-size=4096")
+
+	riscv64Cppflags = []string{}
+
+	riscv64CpuVariantCflags = map[string][]string{}
+)
+
+const ()
+
+func init() {
+
+	exportedVars.ExportStringListStaticVariable("Riscv64Ldflags", riscv64Ldflags)
+	exportedVars.ExportStringListStaticVariable("Riscv64Lldflags", riscv64Lldflags)
+
+	exportedVars.ExportStringListStaticVariable("Riscv64Cflags", riscv64Cflags)
+	exportedVars.ExportStringListStaticVariable("Riscv64Cppflags", riscv64Cppflags)
+
+	exportedVars.ExportVariableReferenceDict("Riscv64ArchVariantCflags", riscv64ArchVariantCflagsVar)
+	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantCflags", riscv64CpuVariantCflagsVar)
+	exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantLdflags", riscv64CpuVariantLdflags)
+}
+
+var (
+	riscv64ArchVariantCflagsVar = map[string]string{}
+
+	riscv64CpuVariantCflagsVar = map[string]string{}
+
+	riscv64CpuVariantLdflags = map[string]string{}
+)
+
+type toolchainRiscv64 struct {
+	toolchainBionic
+	toolchain64Bit
+
+	ldflags         string
+	lldflags        string
+	toolchainCflags string
+}
+
+func (t *toolchainRiscv64) Name() string {
+	return "riscv64"
+}
+
+func (t *toolchainRiscv64) IncludeFlags() string {
+	return ""
+}
+
+func (t *toolchainRiscv64) ClangTriple() string {
+	return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) Cflags() string {
+	return "${config.Riscv64Cflags}"
+}
+
+func (t *toolchainRiscv64) Cppflags() string {
+	return "${config.Riscv64Cppflags}"
+}
+
+func (t *toolchainRiscv64) Ldflags() string {
+	return t.ldflags
+}
+
+func (t *toolchainRiscv64) Lldflags() string {
+	return t.lldflags
+}
+
+func (t *toolchainRiscv64) ToolchainCflags() string {
+	return t.toolchainCflags
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+	return "riscv64"
+}
+
+func riscv64ToolchainFactory(arch android.Arch) Toolchain {
+	switch arch.ArchVariant {
+	case "":
+	default:
+		panic(fmt.Sprintf("Unknown Riscv64 architecture version: %q", arch.ArchVariant))
+	}
+
+	toolchainCflags := []string{riscv64ArchVariantCflagsVar[arch.ArchVariant]}
+	toolchainCflags = append(toolchainCflags,
+		variantOrDefault(riscv64CpuVariantCflagsVar, arch.CpuVariant))
+
+	extraLdflags := variantOrDefault(riscv64CpuVariantLdflags, arch.CpuVariant)
+	return &toolchainRiscv64{
+		ldflags: strings.Join([]string{
+			"${config.Riscv64Ldflags}",
+			extraLdflags,
+		}, " "),
+		lldflags: strings.Join([]string{
+			"${config.Riscv64Lldflags}",
+			extraLdflags,
+		}, " "),
+		toolchainCflags: strings.Join(toolchainCflags, " "),
+	}
+}
+
+func init() {
+	registerToolchainFactory(android.Android, android.Riscv64, riscv64ToolchainFactory)
+}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index d9eaf53..eb71aa1 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -63,11 +63,6 @@
 type Toolchain interface {
 	Name() string
 
-	GccRoot() string
-	GccTriple() string
-	// GccVersion should return a real value, not a ninja reference
-	GccVersion() string
-
 	IncludeFlags() string
 
 	ClangTriple() string
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index aebda0b..e2b0f06 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -80,17 +80,7 @@
 	}
 )
 
-const (
-	x86_64GccVersion = "4.9"
-)
-
 func init() {
-
-	pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
-
-	pctx.SourcePathVariable("X86_64GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
 	exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
 
@@ -128,24 +118,12 @@
 	return "x86_64"
 }
 
-func (t *toolchainX86_64) GccRoot() string {
-	return "${config.X86_64GccRoot}"
-}
-
-func (t *toolchainX86_64) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainX86_64) GccVersion() string {
-	return x86_64GccVersion
-}
-
 func (t *toolchainX86_64) IncludeFlags() string {
 	return ""
 }
 
 func (t *toolchainX86_64) ClangTriple() string {
-	return t.GccTriple()
+	return "x86_64-linux-android"
 }
 
 func (t *toolchainX86_64) ToolchainLdflags() string {
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 421b083..3001ab4 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -88,16 +88,7 @@
 	}
 )
 
-const (
-	x86GccVersion = "4.9"
-)
-
 func init() {
-	pctx.StaticVariable("x86GccVersion", x86GccVersion)
-
-	pctx.SourcePathVariable("X86GccRoot",
-		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
-
 	exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
 	exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
 
@@ -134,18 +125,6 @@
 	return "x86"
 }
 
-func (t *toolchainX86) GccRoot() string {
-	return "${config.X86GccRoot}"
-}
-
-func (t *toolchainX86) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainX86) GccVersion() string {
-	return x86GccVersion
-}
-
 func (t *toolchainX86) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 976cc25..96a53bf 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -66,13 +66,20 @@
 		"host_bionic_linker_script")
 )
 
+const (
+	x86_64GccVersion = "4.9"
+)
+
 func init() {
+
 	pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
 	pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
 	pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLdflags, " "))
 
 	// Use the device gcc toolchain for now
-	pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}")
+	pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+	pctx.SourcePathVariable("LinuxBionicGccRoot",
+		"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
 }
 
 type toolchainLinuxBionic struct {
@@ -84,18 +91,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinuxBionic) GccRoot() string {
-	return "${config.LinuxBionicGccRoot}"
-}
-
-func (t *toolchainLinuxBionic) GccTriple() string {
-	return "x86_64-linux-android"
-}
-
-func (t *toolchainLinuxBionic) GccVersion() string {
-	return "4.9"
-}
-
 func (t *toolchainLinuxBionic) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 07b95e1..740405e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -180,18 +180,6 @@
 	return "x86_64"
 }
 
-func (t *toolchainLinux) GccRoot() string {
-	return "${config.LinuxGccRoot}"
-}
-
-func (t *toolchainLinux) GccTriple() string {
-	return "${config.LinuxGccTriple}"
-}
-
-func (t *toolchainLinux) GccVersion() string {
-	return linuxGccVersion
-}
-
 func (t *toolchainLinux) IncludeFlags() string {
 	return ""
 }
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index a33606f..561c500 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -175,24 +175,12 @@
 	return "x86_64"
 }
 
-func (t *toolchainWindows) GccRoot() string {
-	return "${config.WindowsGccRoot}"
-}
-
-func (t *toolchainWindows) GccTriple() string {
-	return "${config.WindowsGccTriple}"
-}
-
 func (t *toolchainWindows) ToolchainCflags() string {
-	return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
+	return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
 }
 
 func (t *toolchainWindows) ToolchainLdflags() string {
-	return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
-}
-
-func (t *toolchainWindows) GccVersion() string {
-	return windowsGccVersion
+	return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
 }
 
 func (t *toolchainWindows) IncludeFlags() string {
diff --git a/cc/makevars.go b/cc/makevars.go
index de8a8f2..c70d4a6 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -314,8 +314,6 @@
 		ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld")
 		ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain))
 		ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-")
-		// TODO: GCC version is obsolete now that GCC has been removed.
-		ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
 	}
 
 	if target.Os.Class == android.Host {
diff --git a/rust/binary.go b/rust/binary.go
index 41110f9..056888e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -106,7 +106,7 @@
 		if static {
 			deps.CrtBegin = []string{"libc_musl_crtbegin_static"}
 		} else {
-			deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}
+			deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic"}
 		}
 		deps.CrtEnd = []string{"libc_musl_crtend"}
 	}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index be73d69..79ea7a1 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -15,6 +15,7 @@
         "arm64_device.go",
         "global.go",
         "lints.go",
+        "riscv64_device.go",
         "toolchain.go",
         "darwin_host.go",
         "x86_linux_bionic_host.go",
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
new file mode 100644
index 0000000..3b41a10
--- /dev/null
+++ b/rust/config/riscv64_device.go
@@ -0,0 +1,91 @@
+// Copyright 2022 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 config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	Riscv64RustFlags            = []string{}
+	Riscv64ArchFeatureRustFlags = map[string][]string{"": {}}
+	Riscv64LinkFlags            = []string{}
+
+	Riscv64ArchVariantRustFlags = map[string][]string{}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Riscv64, Riscv64ToolchainFactory)
+
+	pctx.StaticVariable("Riscv64ToolchainRustFlags", strings.Join(Riscv64RustFlags, " "))
+	pctx.StaticVariable("Riscv64ToolchainLinkFlags", strings.Join(Riscv64LinkFlags, " "))
+
+	for variant, rustFlags := range Riscv64ArchVariantRustFlags {
+		pctx.StaticVariable("Riscv64"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainRiscv64 struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainRiscv64) RustTriple() string {
+	return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) ToolchainLinkFlags() string {
+	// Prepend the lld flags from cc_config so we stay in sync with cc
+	return "${config.DeviceGlobalLinkFlags} ${cc_config.Riscv64Lldflags} ${config.Riscv64ToolchainLinkFlags}"
+}
+
+func (t *toolchainRiscv64) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainRiscv64) RustFlags() string {
+	return "${config.Riscv64ToolchainRustFlags}"
+}
+
+func (t *toolchainRiscv64) Supported() bool {
+	return true
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+	return "riscv64"
+}
+
+func Riscv64ToolchainFactory(arch android.Arch) Toolchain {
+	archVariant := arch.ArchVariant
+
+	toolchainRustFlags := []string{
+		"${config.Riscv64ToolchainRustFlags}",
+		"${config.Riscv64" + archVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, Riscv64ArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainRiscv64{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}