Merge "dex_import can be added to apex"
diff --git a/Android.bp b/Android.bp
index 73fad25..0b44198 100644
--- a/Android.bp
+++ b/Android.bp
@@ -11,14 +11,6 @@
 ]
 
 bootstrap_go_package {
-    name: "soong-env",
-    pkgPath: "android/soong/env",
-    srcs: [
-        "env/env.go",
-    ],
-}
-
-bootstrap_go_package {
     name: "soong",
     pkgPath: "android/soong",
     deps: [
@@ -29,546 +21,6 @@
     ],
 }
 
-bootstrap_go_package {
-    name: "soong-android",
-    pkgPath: "android/soong/android",
-    deps: [
-        "blueprint",
-        "blueprint-bootstrap",
-        "soong",
-        "soong-android-soongconfig",
-        "soong-env",
-        "soong-shared",
-        "soong-ui-metrics_proto",
-    ],
-    srcs: [
-        "android/androidmk.go",
-        "android/apex.go",
-        "android/api_levels.go",
-        "android/arch.go",
-        "android/config.go",
-        "android/csuite_config.go",
-        "android/defaults.go",
-        "android/defs.go",
-        "android/expand.go",
-        "android/filegroup.go",
-        "android/hooks.go",
-        "android/image.go",
-        "android/makevars.go",
-        "android/metrics.go",
-        "android/module.go",
-        "android/mutator.go",
-        "android/namespace.go",
-        "android/neverallow.go",
-        "android/notices.go",
-        "android/onceper.go",
-        "android/override_module.go",
-        "android/package.go",
-        "android/package_ctx.go",
-        "android/path_properties.go",
-        "android/paths.go",
-        "android/prebuilt.go",
-        "android/prebuilt_etc.go",
-        "android/proto.go",
-        "android/register.go",
-        "android/rule_builder.go",
-        "android/sandbox.go",
-        "android/sdk.go",
-        "android/sh_binary.go",
-        "android/singleton.go",
-        "android/soong_config_modules.go",
-        "android/testing.go",
-        "android/util.go",
-        "android/variable.go",
-        "android/visibility.go",
-        "android/vts_config.go",
-        "android/writedocs.go",
-
-        // Lock down environment access last
-        "android/env.go",
-    ],
-    testSrcs: [
-        "android/android_test.go",
-        "android/androidmk_test.go",
-        "android/arch_test.go",
-        "android/config_test.go",
-        "android/csuite_config_test.go",
-        "android/expand_test.go",
-        "android/module_test.go",
-        "android/mutator_test.go",
-        "android/namespace_test.go",
-        "android/neverallow_test.go",
-        "android/onceper_test.go",
-        "android/package_test.go",
-        "android/path_properties_test.go",
-        "android/paths_test.go",
-        "android/prebuilt_test.go",
-        "android/prebuilt_etc_test.go",
-        "android/rule_builder_test.go",
-        "android/soong_config_modules_test.go",
-        "android/util_test.go",
-        "android/variable_test.go",
-        "android/visibility_test.go",
-        "android/vts_config_test.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-android-soongconfig",
-    pkgPath: "android/soong/android/soongconfig",
-    deps: [
-        "blueprint",
-        "blueprint-parser",
-        "blueprint-proptools",
-    ],
-    srcs: [
-        "android/soongconfig/config.go",
-        "android/soongconfig/modules.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-cc-config",
-    pkgPath: "android/soong/cc/config",
-    deps: [
-        "soong-android",
-        "soong-remoteexec",
-    ],
-    srcs: [
-        "cc/config/clang.go",
-        "cc/config/global.go",
-        "cc/config/tidy.go",
-        "cc/config/toolchain.go",
-        "cc/config/vndk.go",
-
-        "cc/config/arm_device.go",
-        "cc/config/arm64_device.go",
-        "cc/config/arm64_fuchsia_device.go",
-        "cc/config/x86_device.go",
-        "cc/config/x86_64_device.go",
-        "cc/config/x86_64_fuchsia_device.go",
-
-        "cc/config/x86_darwin_host.go",
-        "cc/config/x86_linux_host.go",
-        "cc/config/x86_linux_bionic_host.go",
-        "cc/config/x86_windows_host.go",
-    ],
-    testSrcs: [
-        "cc/config/tidy_test.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-cc",
-    pkgPath: "android/soong/cc",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "soong",
-        "soong-android",
-        "soong-cc-config",
-        "soong-genrule",
-        "soong-tradefed",
-    ],
-    srcs: [
-        "cc/androidmk.go",
-        "cc/builder.go",
-        "cc/cc.go",
-        "cc/ccdeps.go",
-        "cc/check.go",
-        "cc/coverage.go",
-        "cc/gen.go",
-        "cc/linkable.go",
-        "cc/lto.go",
-        "cc/makevars.go",
-        "cc/pgo.go",
-        "cc/prebuilt.go",
-        "cc/proto.go",
-        "cc/rs.go",
-        "cc/sanitize.go",
-        "cc/sabi.go",
-        "cc/sdk.go",
-        "cc/snapshot_utils.go",
-        "cc/stl.go",
-        "cc/strip.go",
-        "cc/sysprop.go",
-        "cc/tidy.go",
-        "cc/util.go",
-        "cc/vendor_snapshot.go",
-        "cc/vndk.go",
-        "cc/vndk_prebuilt.go",
-
-        "cc/cflag_artifacts.go",
-        "cc/cmakelists.go",
-        "cc/compdb.go",
-        "cc/compiler.go",
-        "cc/installer.go",
-        "cc/linker.go",
-
-        "cc/binary.go",
-        "cc/binary_sdk_member.go",
-        "cc/fuzz.go",
-        "cc/library.go",
-        "cc/library_headers.go",
-        "cc/library_sdk_member.go",
-        "cc/object.go",
-        "cc/test.go",
-        "cc/toolchain_library.go",
-
-        "cc/ndk_prebuilt.go",
-        "cc/ndk_headers.go",
-        "cc/ndk_library.go",
-        "cc/ndk_sysroot.go",
-
-        "cc/llndk_library.go",
-
-        "cc/kernel_headers.go",
-
-        "cc/genrule.go",
-
-        "cc/vendor_public_library.go",
-
-        "cc/testing.go",
-    ],
-    testSrcs: [
-        "cc/cc_test.go",
-        "cc/compiler_test.go",
-        "cc/gen_test.go",
-        "cc/genrule_test.go",
-        "cc/library_headers_test.go",
-        "cc/library_test.go",
-        "cc/object_test.go",
-        "cc/prebuilt_test.go",
-        "cc/proto_test.go",
-        "cc/test_data_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-genrule",
-    pkgPath: "android/soong/genrule",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "soong",
-        "soong-android",
-        "soong-shared",
-    ],
-    srcs: [
-        "genrule/genrule.go",
-    ],
-    testSrcs: [
-        "genrule/genrule_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-phony",
-    pkgPath: "android/soong/phony",
-    deps: [
-        "blueprint",
-        "soong-android",
-    ],
-    srcs: [
-        "phony/phony.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-java",
-    pkgPath: "android/soong/java",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "soong",
-        "soong-android",
-        "soong-cc",
-        "soong-dexpreopt",
-        "soong-genrule",
-        "soong-java-config",
-        "soong-remoteexec",
-        "soong-tradefed",
-    ],
-    srcs: [
-        "java/aapt2.go",
-        "java/aar.go",
-        "java/android_manifest.go",
-        "java/android_resources.go",
-        "java/androidmk.go",
-        "java/app_builder.go",
-        "java/app.go",
-        "java/builder.go",
-        "java/device_host_converter.go",
-        "java/dex.go",
-        "java/dexpreopt.go",
-        "java/dexpreopt_bootjars.go",
-        "java/dexpreopt_config.go",
-        "java/droiddoc.go",
-        "java/gen.go",
-        "java/genrule.go",
-        "java/hiddenapi.go",
-        "java/hiddenapi_singleton.go",
-        "java/jacoco.go",
-        "java/java.go",
-        "java/jdeps.go",
-        "java/java_resources.go",
-        "java/kotlin.go",
-        "java/platform_compat_config.go",
-        "java/plugin.go",
-        "java/prebuilt_apis.go",
-        "java/proto.go",
-        "java/robolectric.go",
-        "java/sdk.go",
-        "java/sdk_library.go",
-        "java/support_libraries.go",
-        "java/sysprop.go",
-        "java/system_modules.go",
-        "java/testing.go",
-        "java/tradefed.go",
-    ],
-    testSrcs: [
-        "java/androidmk_test.go",
-        "java/app_test.go",
-        "java/device_host_converter_test.go",
-        "java/dexpreopt_test.go",
-        "java/dexpreopt_bootjars_test.go",
-        "java/java_test.go",
-        "java/jdeps_test.go",
-        "java/kotlin_test.go",
-        "java/plugin_test.go",
-        "java/sdk_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-java-config",
-    pkgPath: "android/soong/java/config",
-    deps: [
-        "blueprint-proptools",
-        "soong-android",
-        "soong-remoteexec",
-    ],
-    srcs: [
-        "java/config/config.go",
-        "java/config/error_prone.go",
-        "java/config/kotlin.go",
-        "java/config/makevars.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-rust-config",
-    pkgPath: "android/soong/rust/config",
-    deps: [
-        "soong-android",
-        "soong-cc-config",
-    ],
-    srcs: [
-        "rust/config/arm_device.go",
-        "rust/config/arm64_device.go",
-        "rust/config/global.go",
-        "rust/config/toolchain.go",
-        "rust/config/whitelist.go",
-        "rust/config/x86_darwin_host.go",
-        "rust/config/x86_linux_host.go",
-        "rust/config/x86_device.go",
-        "rust/config/x86_64_device.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-rust",
-    pkgPath: "android/soong/rust",
-    deps: [
-        "soong",
-        "soong-android",
-        "soong-cc",
-        "soong-rust-config",
-    ],
-    srcs: [
-        "rust/androidmk.go",
-        "rust/compiler.go",
-        "rust/coverage.go",
-        "rust/binary.go",
-        "rust/builder.go",
-        "rust/library.go",
-        "rust/prebuilt.go",
-        "rust/proc_macro.go",
-        "rust/rust.go",
-        "rust/test.go",
-        "rust/testing.go",
-    ],
-    testSrcs: [
-        "rust/binary_test.go",
-        "rust/compiler_test.go",
-        "rust/coverage_test.go",
-        "rust/library_test.go",
-        "rust/rust_test.go",
-        "rust/test_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-python",
-    pkgPath: "android/soong/python",
-    deps: [
-        "blueprint",
-        "soong-android",
-        "soong-tradefed",
-    ],
-    srcs: [
-        "python/androidmk.go",
-        "python/binary.go",
-        "python/builder.go",
-        "python/defaults.go",
-        "python/installer.go",
-        "python/library.go",
-        "python/proto.go",
-        "python/python.go",
-        "python/test.go",
-    ],
-    testSrcs: [
-        "python/python_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-shared",
-    pkgPath: "android/soong/shared",
-    srcs: [
-        "shared/paths.go",
-    ],
-}
-
-bootstrap_go_package {
-    name: "soong-tradefed",
-    pkgPath: "android/soong/tradefed",
-    deps: [
-        "blueprint",
-        "soong-android",
-    ],
-    srcs: [
-        "tradefed/autogen.go",
-        "tradefed/config.go",
-        "tradefed/makevars.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-xml",
-    pkgPath: "android/soong/xml",
-    deps: [
-        "blueprint",
-        "blueprint-pathtools",
-        "soong",
-        "soong-android",
-    ],
-    srcs: [
-        "xml/xml.go",
-    ],
-    testSrcs: [
-        "xml/xml_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-apex",
-    pkgPath: "android/soong/apex",
-    deps: [
-        "blueprint",
-        "soong",
-        "soong-android",
-        "soong-cc",
-        "soong-java",
-        "soong-python",
-    ],
-    srcs: [
-        "apex/androidmk.go",
-        "apex/apex.go",
-        "apex/apex_singleton.go",
-        "apex/builder.go",
-        "apex/key.go",
-        "apex/prebuilt.go",
-        "apex/vndk.go",
-    ],
-    testSrcs: [
-        "apex/apex_test.go",
-        "apex/vndk_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-sysprop",
-    pkgPath: "android/soong/sysprop",
-    deps: [
-        "blueprint",
-        "soong",
-        "soong-android",
-        "soong-cc",
-        "soong-java",
-    ],
-    srcs: [
-        "sysprop/sysprop_library.go",
-    ],
-    testSrcs: [
-        "sysprop/sysprop_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-sdk",
-    pkgPath: "android/soong/sdk",
-    deps: [
-        "blueprint",
-        "soong",
-        "soong-android",
-        "soong-apex",
-        "soong-cc",
-        "soong-java",
-    ],
-    srcs: [
-        "sdk/bp.go",
-        "sdk/exports.go",
-        "sdk/sdk.go",
-        "sdk/update.go",
-    ],
-    testSrcs: [
-        "sdk/bp_test.go",
-        "sdk/cc_sdk_test.go",
-        "sdk/exports_test.go",
-        "sdk/java_sdk_test.go",
-        "sdk/sdk_test.go",
-        "sdk/testing.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
-bootstrap_go_package {
-    name: "soong-remoteexec",
-    pkgPath: "android/soong/remoteexec",
-    deps: [
-        "blueprint",
-        "soong-android",
-    ],
-    srcs: [
-        "remoteexec/remoteexec.go",
-    ],
-    testSrcs: [
-        "remoteexec/remoteexec_test.go",
-    ],
-    pluginFor: ["soong_build"],
-}
-
 //
 // Defaults to enable various configurations of host bionic
 //
diff --git a/android/Android.bp b/android/Android.bp
new file mode 100644
index 0000000..47dbc5d
--- /dev/null
+++ b/android/Android.bp
@@ -0,0 +1,80 @@
+bootstrap_go_package {
+    name: "soong-android",
+    pkgPath: "android/soong/android",
+    deps: [
+        "blueprint",
+        "blueprint-bootstrap",
+        "soong",
+        "soong-android-soongconfig",
+        "soong-env",
+        "soong-shared",
+        "soong-ui-metrics_proto",
+    ],
+    srcs: [
+        "androidmk.go",
+        "apex.go",
+        "api_levels.go",
+        "arch.go",
+        "config.go",
+        "csuite_config.go",
+        "defaults.go",
+        "defs.go",
+        "expand.go",
+        "filegroup.go",
+        "hooks.go",
+        "image.go",
+        "makevars.go",
+        "metrics.go",
+        "module.go",
+        "mutator.go",
+        "namespace.go",
+        "neverallow.go",
+        "notices.go",
+        "onceper.go",
+        "override_module.go",
+        "package.go",
+        "package_ctx.go",
+        "path_properties.go",
+        "paths.go",
+        "prebuilt.go",
+        "proto.go",
+        "register.go",
+        "rule_builder.go",
+        "sandbox.go",
+        "sdk.go",
+        "singleton.go",
+        "soong_config_modules.go",
+        "testing.go",
+        "util.go",
+        "variable.go",
+        "visibility.go",
+        "vts_config.go",
+        "writedocs.go",
+
+        // Lock down environment access last
+        "env.go",
+    ],
+    testSrcs: [
+        "android_test.go",
+        "androidmk_test.go",
+        "arch_test.go",
+        "config_test.go",
+        "csuite_config_test.go",
+        "expand_test.go",
+        "module_test.go",
+        "mutator_test.go",
+        "namespace_test.go",
+        "neverallow_test.go",
+        "onceper_test.go",
+        "package_test.go",
+        "path_properties_test.go",
+        "paths_test.go",
+        "prebuilt_test.go",
+        "rule_builder_test.go",
+        "soong_config_modules_test.go",
+        "util_test.go",
+        "variable_test.go",
+        "visibility_test.go",
+        "vts_config_test.go",
+    ],
+}
diff --git a/android/neverallow.go b/android/neverallow.go
index 9e075b7..be3f712 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -187,6 +187,10 @@
 		// derive_sdk_prefer32 suppress the platform installation rules, but fails when
 		// the APEX modules contain the SDK variant and the platform variant still exists.
 		"frameworks/base/apex/sdkextensions/derive_sdk",
+		// These are for apps and shouldn't be used by non-SDK variant modules.
+		"prebuilts/ndk",
+		"tools/test/graphicsbenchmark/apps/sample_app",
+		"tools/test/graphicsbenchmark/functional_tests/java",
 	}
 
 	platformVariantPropertiesWhitelist := []string{
diff --git a/android/soongconfig/Android.bp b/android/soongconfig/Android.bp
new file mode 100644
index 0000000..df912e6
--- /dev/null
+++ b/android/soongconfig/Android.bp
@@ -0,0 +1,13 @@
+bootstrap_go_package {
+    name: "soong-android-soongconfig",
+    pkgPath: "android/soong/android/soongconfig",
+    deps: [
+        "blueprint",
+        "blueprint-parser",
+        "blueprint-proptools",
+    ],
+    srcs: [
+        "config.go",
+        "modules.go",
+    ],
+}
diff --git a/android/testing.go b/android/testing.go
index 90989ef..696efb6 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"path/filepath"
 	"regexp"
+	"sort"
 	"strings"
 	"testing"
 
@@ -122,9 +123,10 @@
 		ctx.VisitAllModules(func(m blueprint.Module) {
 			allModuleNames = append(allModuleNames, m.(Module).Name()+"("+ctx.ModuleSubDir(m)+")")
 		})
+		sort.Strings(allModuleNames)
 
-		panic(fmt.Errorf("failed to find module %q variant %q."+
-			"\nall modules: %v", name, variant, allModuleNames))
+		panic(fmt.Errorf("failed to find module %q variant %q. All modules:\n  %s",
+			name, variant, strings.Join(allModuleNames, "\n  ")))
 	}
 
 	return TestingModule{module}
diff --git a/apex/Android.bp b/apex/Android.bp
new file mode 100644
index 0000000..144f441
--- /dev/null
+++ b/apex/Android.bp
@@ -0,0 +1,27 @@
+bootstrap_go_package {
+    name: "soong-apex",
+    pkgPath: "android/soong/apex",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-java",
+        "soong-python",
+        "soong-sh",
+    ],
+    srcs: [
+        "androidmk.go",
+        "apex.go",
+        "apex_singleton.go",
+        "builder.go",
+        "key.go",
+        "prebuilt.go",
+        "vndk.go",
+    ],
+    testSrcs: [
+        "apex_test.go",
+        "vndk_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/apex/apex.go b/apex/apex.go
index 4b49cbf..8fd80fc 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -22,14 +22,16 @@
 	"strings"
 	"sync"
 
-	"android/soong/android"
-	"android/soong/cc"
-	"android/soong/java"
-	"android/soong/python"
-
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/cc"
+	prebuilt_etc "android/soong/etc"
+	"android/soong/java"
+	"android/soong/python"
+	"android/soong/sh"
 )
 
 const (
@@ -1639,7 +1641,7 @@
 	return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
 }
 
-func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) apexFile {
+func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
 	dirInApex := filepath.Join("bin", sh.SubDir())
 	fileToCopy := sh.OutputFile()
 	af := newApexFile(ctx, fileToCopy, sh.Name(), dirInApex, shBinary, sh)
@@ -1662,7 +1664,7 @@
 	return af
 }
 
-func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
 	dirInApex := filepath.Join("etc", prebuilt.SubDir())
 	fileToCopy := prebuilt.OutputFile()
 	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
@@ -1966,7 +1968,7 @@
 				if cc, ok := child.(*cc.Module); ok {
 					filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
 					return true // track transitive dependencies
-				} else if sh, ok := child.(*android.ShBinary); ok {
+				} else if sh, ok := child.(*sh.ShBinary); ok {
 					filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
 				} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
 					filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
@@ -2006,7 +2008,7 @@
 					ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
 				}
 			case prebuiltTag:
-				if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
+				if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
 					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
 				} else if prebuilt, ok := child.(java.PlatformCompatConfigIntf); ok {
 					filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, prebuilt, depName))
@@ -2103,7 +2105,7 @@
 					// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
 					return false
 				} else if java.IsXmlPermissionsFileDepTag(depTag) {
-					if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
+					if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
 						filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
 					}
 				} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1142cbc..e45cd00 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -29,7 +29,9 @@
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/dexpreopt"
+	prebuilt_etc "android/soong/etc"
 	"android/soong/java"
+	"android/soong/sh"
 )
 
 var buildDir string
@@ -230,9 +232,9 @@
 	ctx.RegisterModuleType("cc_test", cc.TestFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
 	ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
-	ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
+	ctx.RegisterModuleType("prebuilt_etc", prebuilt_etc.PrebuiltEtcFactory)
 	ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
-	ctx.RegisterModuleType("sh_binary", android.ShBinaryFactory)
+	ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	java.RegisterJavaBuildComponents(ctx)
 	java.RegisterSystemModulesBuildComponents(ctx)
diff --git a/cc/Android.bp b/cc/Android.bp
new file mode 100644
index 0000000..9ece05f
--- /dev/null
+++ b/cc/Android.bp
@@ -0,0 +1,87 @@
+bootstrap_go_package {
+    name: "soong-cc",
+    pkgPath: "android/soong/cc",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "soong",
+        "soong-android",
+        "soong-cc-config",
+        "soong-etc",
+        "soong-genrule",
+        "soong-tradefed",
+    ],
+    srcs: [
+        "androidmk.go",
+        "builder.go",
+        "cc.go",
+        "ccdeps.go",
+        "check.go",
+        "coverage.go",
+        "gen.go",
+        "linkable.go",
+        "lto.go",
+        "makevars.go",
+        "pgo.go",
+        "prebuilt.go",
+        "proto.go",
+        "rs.go",
+        "sanitize.go",
+        "sabi.go",
+        "sdk.go",
+        "snapshot_utils.go",
+        "stl.go",
+        "strip.go",
+        "sysprop.go",
+        "tidy.go",
+        "util.go",
+        "vendor_snapshot.go",
+        "vndk.go",
+        "vndk_prebuilt.go",
+
+        "cflag_artifacts.go",
+        "cmakelists.go",
+        "compdb.go",
+        "compiler.go",
+        "installer.go",
+        "linker.go",
+
+        "binary.go",
+        "binary_sdk_member.go",
+        "fuzz.go",
+        "library.go",
+        "library_headers.go",
+        "library_sdk_member.go",
+        "object.go",
+        "test.go",
+        "toolchain_library.go",
+
+        "ndk_prebuilt.go",
+        "ndk_headers.go",
+        "ndk_library.go",
+        "ndk_sysroot.go",
+
+        "llndk_library.go",
+
+        "kernel_headers.go",
+
+        "genrule.go",
+
+        "vendor_public_library.go",
+
+        "testing.go",
+    ],
+    testSrcs: [
+        "cc_test.go",
+        "compiler_test.go",
+        "gen_test.go",
+        "genrule_test.go",
+        "library_headers_test.go",
+        "library_test.go",
+        "object_test.go",
+        "prebuilt_test.go",
+        "proto_test.go",
+        "test_data_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index 88ac513..372a72e 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -20,6 +20,7 @@
 	"android/soong/android"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -65,7 +66,15 @@
 }
 
 func (mt *binarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
-	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary")
+	pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary")
+
+	ccModule := member.Variants()[0].(*Module)
+
+	if stl := ccModule.stl.Properties.Stl; stl != nil {
+		pbm.AddProperty("stl", proptools.String(stl))
+	}
+
+	return pbm
 }
 
 func (mt *binarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
@@ -105,6 +114,10 @@
 	//
 	// This field is exported as its contents may not be arch specific.
 	SystemSharedLibs []string
+
+	// Arch specific flags.
+	StaticExecutable bool
+	Nocrt            bool
 }
 
 func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -113,6 +126,10 @@
 	p.archType = ccModule.Target().Arch.ArchType.String()
 	p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
 
+	binaryLinker := ccModule.linker.(*binaryDecorator)
+	p.StaticExecutable = binaryLinker.static()
+	p.Nocrt = Bool(binaryLinker.baseLinker.Properties.Nocrt)
+
 	if ccModule.linker != nil {
 		specifiedDeps := specifiedDeps{}
 		specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
@@ -143,4 +160,11 @@
 	if p.SystemSharedLibs != nil {
 		propertySet.AddPropertyWithTag("system_shared_libs", p.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
 	}
+
+	if p.StaticExecutable {
+		propertySet.AddProperty("static_executable", p.StaticExecutable)
+	}
+	if p.Nocrt {
+		propertySet.AddProperty("nocrt", p.Nocrt)
+	}
 }
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
new file mode 100644
index 0000000..6275064
--- /dev/null
+++ b/cc/config/Android.bp
@@ -0,0 +1,30 @@
+bootstrap_go_package {
+    name: "soong-cc-config",
+    pkgPath: "android/soong/cc/config",
+    deps: [
+        "soong-android",
+        "soong-remoteexec",
+    ],
+    srcs: [
+        "clang.go",
+        "global.go",
+        "tidy.go",
+        "toolchain.go",
+        "vndk.go",
+
+        "arm_device.go",
+        "arm64_device.go",
+        "arm64_fuchsia_device.go",
+        "x86_device.go",
+        "x86_64_device.go",
+        "x86_64_fuchsia_device.go",
+
+        "x86_darwin_host.go",
+        "x86_linux_host.go",
+        "x86_linux_bionic_host.go",
+        "x86_windows_host.go",
+    ],
+    testSrcs: [
+        "tidy_test.go",
+    ],
+}
diff --git a/cc/library.go b/cc/library.go
index 47485ce..ba8b0f4 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -407,6 +407,31 @@
 		if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
 			continue
 		}
+		// libeigen wrongly exports the root directory "external/eigen". But only two
+		// subdirectories "Eigen" and "unsupported" contain exported header files. Even worse
+		// some of them have no extension. So we need special treatment for libeigen in order
+		// to glob correctly.
+		if dir == "external/eigen" {
+			// Only these two directories contains exported headers.
+			for _, subdir := range []string{"Eigen", "unsupported/Eigen"} {
+				glob, err := ctx.GlobWithDeps("external/eigen/"+subdir+"/**/*", nil)
+				if err != nil {
+					ctx.ModuleErrorf("glob failed: %#v", err)
+					return
+				}
+				for _, header := range glob {
+					if strings.HasSuffix(header, "/") {
+						continue
+					}
+					ext := filepath.Ext(header)
+					if ext != "" && ext != ".h" {
+						continue
+					}
+					ret = append(ret, android.PathForSource(ctx, header))
+				}
+			}
+			continue
+		}
 		exts := headerExts
 		// Glob all files under this special directory, because of C++ headers.
 		if strings.HasPrefix(dir, "external/libcxx/include") {
diff --git a/cc/vndk.go b/cc/vndk.go
index e5e4533..04b865f 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -25,6 +25,7 @@
 
 	"android/soong/android"
 	"android/soong/cc/config"
+	"android/soong/etc"
 )
 
 const (
@@ -416,7 +417,7 @@
 	outputFile android.OutputPath
 }
 
-var _ android.PrebuiltEtcModule = &vndkLibrariesTxt{}
+var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
 var _ android.OutputFileProducer = &vndkLibrariesTxt{}
 
 // vndk_libraries_txt is a special kind of module type in that it name is one of
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 1d94f02..d0cad78 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -117,6 +117,8 @@
 // Command is the type of soong_ui execution. Only one type of
 // execution is specified. The args are specific to the command.
 func main() {
+	buildStartedMilli := time.Now().UnixNano() / int64(time.Millisecond)
+
 	c, args := getCommand(os.Args)
 	if c == nil {
 		fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
@@ -166,12 +168,17 @@
 		logsDir = filepath.Join(config.DistDir(), "logs")
 	}
 
+	buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
+	rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
+	soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
+	defer build.UploadMetrics(buildCtx, config, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+
 	os.MkdirAll(logsDir, 0777)
 	log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
 	trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
 	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
 	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
-	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
+	stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
 	stat.AddOutput(status.NewCriticalPath(log))
 	stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
 
@@ -179,7 +186,7 @@
 	buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
 		config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
 
-	defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
+	defer met.Dump(soongMetricsFile)
 
 	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
 		if !strings.HasSuffix(start, "N") {
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 15d2ed2..5275e8f 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -37,6 +37,7 @@
 	"fmt"
 	"path/filepath"
 	"runtime"
+	"sort"
 	"strings"
 
 	"android/soong/android"
@@ -192,6 +193,55 @@
 	return profilePath
 }
 
+type classLoaderContext struct {
+	// The class loader context using paths in the build.
+	Host android.Paths
+
+	// The class loader context using paths as they will be on the device.
+	Target []string
+}
+
+// A map of class loader contexts for each SDK version.
+// A map entry for "any" version contains libraries that are unconditionally added to class loader
+// context. Map entries for existing versions contains libraries that were in the default classpath
+// until that API version, and should be added to class loader context if and only if the
+// targetSdkVersion in the manifest or APK is less than that API version.
+type classLoaderContextMap map[int]*classLoaderContext
+
+const anySdkVersion int = -1
+
+func (m classLoaderContextMap) getSortedKeys() []int {
+	keys := make([]int, 0, len(m))
+	for k := range m {
+		keys = append(keys, k)
+	}
+	sort.Ints(keys)
+	return keys
+}
+
+func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
+	if _, ok := m[sdkVer]; !ok {
+		m[sdkVer] = &classLoaderContext{}
+	}
+	return m[sdkVer]
+}
+
+func (m classLoaderContextMap) addLibs(sdkVer int, module *ModuleConfig, libs ...string) {
+	clc := m.getValue(sdkVer)
+	for _, lib := range libs {
+		clc.Host = append(clc.Host, pathForLibrary(module, lib))
+		clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
+	}
+}
+
+func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
+	clc := m.getValue(sdkVer)
+	for _, lib := range libs {
+		clc.Host = append(clc.Host, SystemServerDexJarHostPath(ctx, lib))
+		clc.Target = append(clc.Target, filepath.Join("/system/framework", lib+".jar"))
+	}
+}
+
 func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
 	module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
 	appImage bool, generateDM bool) {
@@ -227,66 +277,38 @@
 
 	systemServerJars := NonUpdatableSystemServerJars(ctx, global)
 
-	// The class loader context using paths in the build
-	var classLoaderContextHost android.Paths
-
-	// The class loader context using paths as they will be on the device
-	var classLoaderContextTarget []string
-
-	// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 28
-	var conditionalClassLoaderContextHost28 android.Paths
-	var conditionalClassLoaderContextTarget28 []string
-
-	// Extra paths that will be appended to the class loader if the APK manifest has targetSdkVersion < 29
-	var conditionalClassLoaderContextHost29 android.Paths
-	var conditionalClassLoaderContextTarget29 []string
+	classLoaderContexts := make(classLoaderContextMap)
 
 	// A flag indicating if the '&' class loader context is used.
 	unknownClassLoaderContext := false
 
 	if module.EnforceUsesLibraries {
+		// Unconditional class loader context.
 		usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
+		classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...)
 
-		// Create class loader context for dex2oat from uses libraries and filtered optional libraries
-		for _, l := range usesLibs {
-
-			classLoaderContextHost = append(classLoaderContextHost,
-				pathForLibrary(module, l))
-			classLoaderContextTarget = append(classLoaderContextTarget,
-				filepath.Join("/system/framework", l+".jar"))
-		}
-
-		// org.apache.http.legacy contains classes that were in the default classpath until API 28.
-		// If the targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly
-		// depend on org.apache.http.legacy, then implicitly add it to the classpath for dexpreopt.
+		// Conditional class loader context for API version < 28.
 		const httpLegacy = "org.apache.http.legacy"
 		if !contains(usesLibs, httpLegacy) {
-			conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
-				pathForLibrary(module, httpLegacy))
-			conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
-				filepath.Join("/system/framework", httpLegacy+".jar"))
+			classLoaderContexts.addLibs(28, module, httpLegacy)
 		}
 
-		// android.hidl.base-V1.0-java and android.hidl.manager-V1.0 contain classes that were in the default
-		// classpath until API 29.  If the targetSdkVersion in the manifest or APK is < 29 then implicitly add
-		// the classes to the classpath for dexpreopt.
-		const hidlBase = "android.hidl.base-V1.0-java"
-		const hidlManager = "android.hidl.manager-V1.0-java"
-		conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29,
-			pathForLibrary(module, hidlManager))
-		conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
-			filepath.Join("/system/framework", hidlManager+".jar"))
-		conditionalClassLoaderContextHost29 = append(conditionalClassLoaderContextHost29,
-			pathForLibrary(module, hidlBase))
-		conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29,
-			filepath.Join("/system/framework", hidlBase+".jar"))
+		// Conditional class loader context for API version < 29.
+		usesLibs29 := []string{
+			"android.hidl.base-V1.0-java",
+			"android.hidl.manager-V1.0-java",
+		}
+		classLoaderContexts.addLibs(29, module, usesLibs29...)
+
+		// Conditional class loader context for API version < 30.
+		const testBase = "android.test.base"
+		if !contains(usesLibs, testBase) {
+			classLoaderContexts.addLibs(30, module, testBase)
+		}
 	} else if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
 		// System server jars should be dexpreopted together: class loader context of each jar
 		// should include all preceding jars on the system server classpath.
-		for _, otherJar := range systemServerJars[:jarIndex] {
-			classLoaderContextHost = append(classLoaderContextHost, SystemServerDexJarHostPath(ctx, otherJar))
-			classLoaderContextTarget = append(classLoaderContextTarget, "/system/framework/"+otherJar+".jar")
-		}
+		classLoaderContexts.addSystemServerLibs(anySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
 
 		// Copy the system server jar to a predefined location where dex2oat will find it.
 		dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
@@ -308,10 +330,11 @@
 			Text(`class_loader_context_arg=--class-loader-context=\&`).
 			Text(`stored_class_loader_context_arg=""`)
 	} else {
+		clc := classLoaderContexts[anySdkVersion]
 		rule.Command().
-			Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(classLoaderContextHost.Strings(), ":") + "]").
-			Implicits(classLoaderContextHost).
-			Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(classLoaderContextTarget, ":") + "]")
+			Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
+			Implicits(clc.Host).
+			Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
 	}
 
 	if module.EnforceUsesLibraries {
@@ -330,21 +353,19 @@
 				Text(`| grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p"`).
 				Text(`)"`)
 		}
-		rule.Command().Textf(`dex_preopt_host_libraries="%s"`,
-			strings.Join(classLoaderContextHost.Strings(), " ")).
-			Implicits(classLoaderContextHost)
-		rule.Command().Textf(`dex_preopt_target_libraries="%s"`,
-			strings.Join(classLoaderContextTarget, " "))
-		rule.Command().Textf(`conditional_host_libs_28="%s"`,
-			strings.Join(conditionalClassLoaderContextHost28.Strings(), " ")).
-			Implicits(conditionalClassLoaderContextHost28)
-		rule.Command().Textf(`conditional_target_libs_28="%s"`,
-			strings.Join(conditionalClassLoaderContextTarget28, " "))
-		rule.Command().Textf(`conditional_host_libs_29="%s"`,
-			strings.Join(conditionalClassLoaderContextHost29.Strings(), " ")).
-			Implicits(conditionalClassLoaderContextHost29)
-		rule.Command().Textf(`conditional_target_libs_29="%s"`,
-			strings.Join(conditionalClassLoaderContextTarget29, " "))
+		for _, ver := range classLoaderContexts.getSortedKeys() {
+			clc := classLoaderContexts.getValue(ver)
+			var varHost, varTarget string
+			if ver == anySdkVersion {
+				varHost = "dex_preopt_host_libraries"
+				varTarget = "dex_preopt_target_libraries"
+			} else {
+				varHost = fmt.Sprintf("conditional_host_libs_%d", ver)
+				varTarget = fmt.Sprintf("conditional_target_libs_%d", ver)
+			}
+			rule.Command().Textf(varHost+`="%s"`, strings.Join(clc.Host.Strings(), " ")).Implicits(clc.Host)
+			rule.Command().Textf(varTarget+`="%s"`, strings.Join(clc.Target, " "))
+		}
 		rule.Command().Text("source").Tool(globalSoong.ConstructContext).Input(module.DexPath)
 	}
 
diff --git a/env/Android.bp b/env/Android.bp
new file mode 100644
index 0000000..90c6047
--- /dev/null
+++ b/env/Android.bp
@@ -0,0 +1,7 @@
+bootstrap_go_package {
+    name: "soong-env",
+    pkgPath: "android/soong/env",
+    srcs: [
+        "env.go",
+    ],
+}
diff --git a/etc/Android.bp b/etc/Android.bp
new file mode 100644
index 0000000..cfd303e
--- /dev/null
+++ b/etc/Android.bp
@@ -0,0 +1,16 @@
+bootstrap_go_package {
+    name: "soong-etc",
+    pkgPath: "android/soong/etc",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+    ],
+    srcs: [
+        "prebuilt_etc.go",
+    ],
+    testSrcs: [
+        "prebuilt_etc_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/android/prebuilt_etc.go b/etc/prebuilt_etc.go
similarity index 62%
rename from android/prebuilt_etc.go
rename to etc/prebuilt_etc.go
index f0c0767..d6eb008 100644
--- a/android/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -12,19 +12,29 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package android
+package etc
 
-import "strconv"
+import (
+	"strconv"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+var pctx = android.NewPackageContext("android/soong/etc")
 
 // TODO(jungw): Now that it handles more than the ones in etc/, consider renaming this file.
 
 func init() {
-	RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
-	RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
-	RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
-	RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
-	RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
-	RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
+	pctx.Import("android/soong/android")
+
+	android.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
+	android.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
+	android.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
+	android.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory)
+	android.RegisterModuleType("prebuilt_font", PrebuiltFontFactory)
+	android.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
 }
 
 type prebuiltEtcProperties struct {
@@ -55,24 +65,24 @@
 }
 
 type PrebuiltEtcModule interface {
-	Module
+	android.Module
 	SubDir() string
-	OutputFile() OutputPath
+	OutputFile() android.OutputPath
 }
 
 type PrebuiltEtc struct {
-	ModuleBase
+	android.ModuleBase
 
 	properties prebuiltEtcProperties
 
-	sourceFilePath Path
-	outputFilePath OutputPath
+	sourceFilePath android.Path
+	outputFilePath android.OutputPath
 	// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
 	installDirBase string
 	// The base install location when soc_specific property is set to true, e.g. "firmware" for prebuilt_firmware.
 	socInstallDirBase      string
-	installDirPath         InstallPath
-	additionalDependencies *Paths
+	installDirPath         android.InstallPath
+	additionalDependencies *android.Paths
 }
 
 func (p *PrebuiltEtc) inRamdisk() bool {
@@ -99,65 +109,65 @@
 	return p.inRecovery()
 }
 
-var _ ImageInterface = (*PrebuiltEtc)(nil)
+var _ android.ImageInterface = (*PrebuiltEtc)(nil)
 
-func (p *PrebuiltEtc) ImageMutatorBegin(ctx BaseModuleContext) {}
+func (p *PrebuiltEtc) ImageMutatorBegin(ctx android.BaseModuleContext) {}
 
-func (p *PrebuiltEtc) CoreVariantNeeded(ctx BaseModuleContext) bool {
+func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
 	return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk()
 }
 
-func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx BaseModuleContext) bool {
-	return Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
+func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+	return proptools.Bool(p.properties.Ramdisk_available) || p.ModuleBase.InstallInRamdisk()
 }
 
-func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx BaseModuleContext) bool {
-	return Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
+func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+	return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
 }
 
-func (p *PrebuiltEtc) ExtraImageVariations(ctx BaseModuleContext) []string {
+func (p *PrebuiltEtc) ExtraImageVariations(ctx android.BaseModuleContext) []string {
 	return nil
 }
 
-func (p *PrebuiltEtc) SetImageVariation(ctx BaseModuleContext, variation string, module Module) {
+func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
 }
 
-func (p *PrebuiltEtc) DepsMutator(ctx BottomUpMutatorContext) {
+func (p *PrebuiltEtc) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if p.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
 	}
 }
 
-func (p *PrebuiltEtc) SourceFilePath(ctx ModuleContext) Path {
-	return PathForModuleSrc(ctx, String(p.properties.Src))
+func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
+	return android.PathForModuleSrc(ctx, android.String(p.properties.Src))
 }
 
-func (p *PrebuiltEtc) InstallDirPath() InstallPath {
+func (p *PrebuiltEtc) InstallDirPath() android.InstallPath {
 	return p.installDirPath
 }
 
 // This allows other derivative modules (e.g. prebuilt_etc_xml) to perform
 // additional steps (like validating the src) before the file is installed.
-func (p *PrebuiltEtc) SetAdditionalDependencies(paths Paths) {
+func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) {
 	p.additionalDependencies = &paths
 }
 
-func (p *PrebuiltEtc) OutputFile() OutputPath {
+func (p *PrebuiltEtc) OutputFile() android.OutputPath {
 	return p.outputFilePath
 }
 
 func (p *PrebuiltEtc) SubDir() string {
-	return String(p.properties.Sub_dir)
+	return android.String(p.properties.Sub_dir)
 }
 
 func (p *PrebuiltEtc) Installable() bool {
-	return p.properties.Installable == nil || Bool(p.properties.Installable)
+	return p.properties.Installable == nil || android.Bool(p.properties.Installable)
 }
 
-func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
-	p.sourceFilePath = PathForModuleSrc(ctx, String(p.properties.Src))
-	filename := String(p.properties.Filename)
-	filename_from_src := Bool(p.properties.Filename_from_src)
+func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	p.sourceFilePath = android.PathForModuleSrc(ctx, android.String(p.properties.Src))
+	filename := android.String(p.properties.Filename)
+	filename_from_src := android.Bool(p.properties.Filename_from_src)
 	if filename == "" {
 		if filename_from_src {
 			filename = p.sourceFilePath.Base()
@@ -168,7 +178,7 @@
 		ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
 		return
 	}
-	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
+	p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
 
 	// If soc install dir was specified and SOC specific is set, set the installDirPath to the specified
 	// socInstallDirBase.
@@ -176,18 +186,18 @@
 	if ctx.SocSpecific() && p.socInstallDirBase != "" {
 		installBaseDir = p.socInstallDirBase
 	}
-	p.installDirPath = PathForModuleInstall(ctx, installBaseDir, String(p.properties.Sub_dir))
+	p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, proptools.String(p.properties.Sub_dir))
 
 	// This ensures that outputFilePath has the correct name for others to
 	// use, as the source file may have a different name.
-	ctx.Build(pctx, BuildParams{
-		Rule:   Cp,
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Cp,
 		Output: p.outputFilePath,
 		Input:  p.sourceFilePath,
 	})
 }
 
-func (p *PrebuiltEtc) AndroidMkEntries() []AndroidMkEntries {
+func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
 	nameSuffix := ""
 	if p.inRamdisk() && !p.onlyInRamdisk() {
 		nameSuffix = ".ramdisk"
@@ -195,12 +205,12 @@
 	if p.inRecovery() && !p.onlyInRecovery() {
 		nameSuffix = ".recovery"
 	}
-	return []AndroidMkEntries{AndroidMkEntries{
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "ETC",
 		SubName:    nameSuffix,
-		OutputFile: OptionalPathForPath(p.outputFilePath),
-		ExtraEntries: []AndroidMkExtraEntriesFunc{
-			func(entries *AndroidMkEntries) {
+		OutputFile: android.OptionalPathForPath(p.outputFilePath),
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
 				entries.SetString("LOCAL_MODULE_TAGS", "optional")
 				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.ToMakePath().String())
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
@@ -225,61 +235,61 @@
 
 // prebuilt_etc is for a prebuilt artifact that is installed in
 // <partition>/etc/<sub_dir> directory.
-func PrebuiltEtcFactory() Module {
+func PrebuiltEtcFactory() android.Module {
 	module := &PrebuiltEtc{}
 	InitPrebuiltEtcModule(module, "etc")
 	// This module is device-only
-	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
 
 // prebuilt_etc_host is for a host prebuilt artifact that is installed in
 // $(HOST_OUT)/etc/<sub_dir> directory.
-func PrebuiltEtcHostFactory() Module {
+func PrebuiltEtcHostFactory() android.Module {
 	module := &PrebuiltEtc{}
 	InitPrebuiltEtcModule(module, "etc")
 	// This module is host-only
-	InitAndroidArchModule(module, HostSupported, MultilibCommon)
+	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
 	return module
 }
 
 // prebuilt_usr_share is for a prebuilt artifact that is installed in
 // <partition>/usr/share/<sub_dir> directory.
-func PrebuiltUserShareFactory() Module {
+func PrebuiltUserShareFactory() android.Module {
 	module := &PrebuiltEtc{}
 	InitPrebuiltEtcModule(module, "usr/share")
 	// This module is device-only
-	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
 
 // prebuild_usr_share_host is for a host prebuilt artifact that is installed in
 // $(HOST_OUT)/usr/share/<sub_dir> directory.
-func PrebuiltUserShareHostFactory() Module {
+func PrebuiltUserShareHostFactory() android.Module {
 	module := &PrebuiltEtc{}
 	InitPrebuiltEtcModule(module, "usr/share")
 	// This module is host-only
-	InitAndroidArchModule(module, HostSupported, MultilibCommon)
+	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
 	return module
 }
 
 // prebuilt_font installs a font in <partition>/fonts directory.
-func PrebuiltFontFactory() Module {
+func PrebuiltFontFactory() android.Module {
 	module := &PrebuiltEtc{}
 	InitPrebuiltEtcModule(module, "fonts")
 	// This module is device-only
-	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
 
 // prebuilt_firmware installs a firmware file to <partition>/etc/firmware directory for system image.
 // If soc_specific property is set to true, the firmware file is installed to the vendor <partition>/firmware
 // directory for vendor image.
-func PrebuiltFirmwareFactory() Module {
+func PrebuiltFirmwareFactory() android.Module {
 	module := &PrebuiltEtc{}
 	module.socInstallDirBase = "firmware"
 	InitPrebuiltEtcModule(module, "etc/firmware")
 	// This module is device-only
-	InitAndroidArchModule(module, DeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
 }
diff --git a/android/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
similarity index 89%
rename from android/prebuilt_etc_test.go
rename to etc/prebuilt_etc_test.go
index 6e751e7..e13cb3c 100644
--- a/android/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -12,24 +12,53 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package android
+package etc
 
 import (
+	"io/ioutil"
+	"os"
 	"path/filepath"
 	"reflect"
 	"testing"
+
+	"android/soong/android"
 )
 
-func testPrebuiltEtc(t *testing.T, bp string) (*TestContext, Config) {
+var buildDir string
+
+func setUp() {
+	var err error
+	buildDir, err = ioutil.TempDir("", "soong_etc_test")
+	if err != nil {
+		panic(err)
+	}
+}
+
+func tearDown() {
+	os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+	run := func() int {
+		setUp()
+		defer tearDown()
+
+		return m.Run()
+	}
+
+	os.Exit(run())
+}
+
+func testPrebuiltEtc(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	fs := map[string][]byte{
 		"foo.conf": nil,
 		"bar.conf": nil,
 		"baz.conf": nil,
 	}
 
-	config := TestArchConfig(buildDir, nil, bp, fs)
+	config := android.TestArchConfig(buildDir, nil, bp, fs)
 
-	ctx := NewTestArchContext()
+	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
 	ctx.RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
 	ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory)
@@ -38,9 +67,9 @@
 	ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
 	ctx.Register(config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	FailIfErrored(t, errs)
+	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
-	FailIfErrored(t, errs)
+	android.FailIfErrored(t, errs)
 
 	return ctx, config
 }
@@ -142,7 +171,7 @@
 	}
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*PrebuiltEtc)
-	entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
 			if !reflect.DeepEqual(value, expectedValue) {
@@ -162,7 +191,7 @@
 		}
 	`)
 
-	buildOS := BuildOs.String()
+	buildOS := android.BuildOs.String()
 	p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
 	if !p.Host() {
 		t.Errorf("host bit is not set for a prebuilt_etc_host module.")
@@ -194,7 +223,7 @@
 		}
 	`)
 
-	buildOS := BuildOs.String()
+	buildOS := android.BuildOs.String()
 	p := ctx.ModuleForTests("foo.conf", buildOS+"_common").Module().(*PrebuiltEtc)
 	expected := filepath.Join(buildDir, "host", config.PrebuiltOS(), "usr", "share", "bar")
 	if p.installDirPath.String() != expected {
diff --git a/genrule/Android.bp b/genrule/Android.bp
new file mode 100644
index 0000000..ff543a6
--- /dev/null
+++ b/genrule/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+    name: "soong-genrule",
+    pkgPath: "android/soong/genrule",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "soong",
+        "soong-android",
+        "soong-shared",
+    ],
+    srcs: [
+        "genrule.go",
+    ],
+    testSrcs: [
+        "genrule_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/java/Android.bp b/java/Android.bp
new file mode 100644
index 0000000..2de1b8e
--- /dev/null
+++ b/java/Android.bp
@@ -0,0 +1,66 @@
+bootstrap_go_package {
+    name: "soong-java",
+    pkgPath: "android/soong/java",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-dexpreopt",
+        "soong-genrule",
+        "soong-java-config",
+        "soong-remoteexec",
+        "soong-tradefed",
+    ],
+    srcs: [
+        "aapt2.go",
+        "aar.go",
+        "android_manifest.go",
+        "android_resources.go",
+        "androidmk.go",
+        "app_builder.go",
+        "app.go",
+        "builder.go",
+        "device_host_converter.go",
+        "dex.go",
+        "dexpreopt.go",
+        "dexpreopt_bootjars.go",
+        "dexpreopt_config.go",
+        "droiddoc.go",
+        "gen.go",
+        "genrule.go",
+        "hiddenapi.go",
+        "hiddenapi_singleton.go",
+        "jacoco.go",
+        "java.go",
+        "jdeps.go",
+        "java_resources.go",
+        "kotlin.go",
+        "platform_compat_config.go",
+        "plugin.go",
+        "prebuilt_apis.go",
+        "proto.go",
+        "robolectric.go",
+        "sdk.go",
+        "sdk_library.go",
+        "support_libraries.go",
+        "sysprop.go",
+        "system_modules.go",
+        "testing.go",
+        "tradefed.go",
+    ],
+    testSrcs: [
+        "androidmk_test.go",
+        "app_test.go",
+        "device_host_converter_test.go",
+        "dexpreopt_test.go",
+        "dexpreopt_bootjars_test.go",
+        "java_test.go",
+        "jdeps_test.go",
+        "kotlin_test.go",
+        "plugin_test.go",
+        "sdk_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/java/app.go b/java/app.go
index 6aa8cd6..a45ab6f 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1863,6 +1863,7 @@
 				"org.apache.http.legacy",
 				"android.hidl.base-V1.0-java",
 				"android.hidl.manager-V1.0-java")
+			ctx.AddVariationDependencies(nil, usesLibTag, optionalUsesLibs...)
 		}
 	}
 }
diff --git a/java/config/Android.bp b/java/config/Android.bp
new file mode 100644
index 0000000..1983521
--- /dev/null
+++ b/java/config/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+    name: "soong-java-config",
+    pkgPath: "android/soong/java/config",
+    deps: [
+        "blueprint-proptools",
+        "soong-android",
+        "soong-remoteexec",
+    ],
+    srcs: [
+        "config.go",
+        "error_prone.go",
+        "kotlin.go",
+        "makevars.go",
+    ],
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index c4d257f..67b0bd6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -2083,7 +2083,7 @@
 
 			if properties.RemovedApiFile != nil {
 				removedApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"-removed.txt")
-				ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, removedApiSnapshotPath)
+				ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
 				scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
 			}
 
diff --git a/java/testing.go b/java/testing.go
index 1967148..faf4d32 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -230,6 +230,22 @@
 			system_modules: "core-platform-api-stubs-system-modules",
 			installable: true,
 		}
+
+		java_library {
+			name: "android.test.base",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "core-platform-api-stubs-system-modules",
+			installable: true,
+		}
+  
+		java_library {
+			name: "android.test.mock",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "core-platform-api-stubs-system-modules",
+			installable: true,
+		}
 	`
 
 	systemModules := []string{
diff --git a/phony/Android.bp b/phony/Android.bp
new file mode 100644
index 0000000..2c423ef
--- /dev/null
+++ b/phony/Android.bp
@@ -0,0 +1,12 @@
+bootstrap_go_package {
+    name: "soong-phony",
+    pkgPath: "android/soong/phony",
+    deps: [
+        "blueprint",
+        "soong-android",
+    ],
+    srcs: [
+        "phony.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/python/Android.bp b/python/Android.bp
new file mode 100644
index 0000000..ffd03fe
--- /dev/null
+++ b/python/Android.bp
@@ -0,0 +1,24 @@
+bootstrap_go_package {
+    name: "soong-python",
+    pkgPath: "android/soong/python",
+    deps: [
+        "blueprint",
+        "soong-android",
+        "soong-tradefed",
+    ],
+    srcs: [
+        "androidmk.go",
+        "binary.go",
+        "builder.go",
+        "defaults.go",
+        "installer.go",
+        "library.go",
+        "proto.go",
+        "python.go",
+        "test.go",
+    ],
+    testSrcs: [
+        "python_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/remoteexec/Android.bp b/remoteexec/Android.bp
new file mode 100644
index 0000000..fc2c0e3
--- /dev/null
+++ b/remoteexec/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+    name: "soong-remoteexec",
+    pkgPath: "android/soong/remoteexec",
+    deps: [
+        "blueprint",
+        "soong-android",
+    ],
+    srcs: [
+        "remoteexec.go",
+    ],
+    testSrcs: [
+        "remoteexec_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/rust/Android.bp b/rust/Android.bp
new file mode 100644
index 0000000..684db0b
--- /dev/null
+++ b/rust/Android.bp
@@ -0,0 +1,32 @@
+bootstrap_go_package {
+    name: "soong-rust",
+    pkgPath: "android/soong/rust",
+    deps: [
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-rust-config",
+    ],
+    srcs: [
+        "androidmk.go",
+        "compiler.go",
+        "coverage.go",
+        "binary.go",
+        "builder.go",
+        "library.go",
+        "prebuilt.go",
+        "proc_macro.go",
+        "rust.go",
+        "test.go",
+        "testing.go",
+    ],
+    testSrcs: [
+        "binary_test.go",
+        "compiler_test.go",
+        "coverage_test.go",
+        "library_test.go",
+        "rust_test.go",
+        "test_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
new file mode 100644
index 0000000..1a10312
--- /dev/null
+++ b/rust/config/Android.bp
@@ -0,0 +1,19 @@
+bootstrap_go_package {
+    name: "soong-rust-config",
+    pkgPath: "android/soong/rust/config",
+    deps: [
+        "soong-android",
+        "soong-cc-config",
+    ],
+    srcs: [
+        "arm_device.go",
+        "arm64_device.go",
+        "global.go",
+        "toolchain.go",
+        "whitelist.go",
+        "x86_darwin_host.go",
+        "x86_linux_host.go",
+        "x86_device.go",
+        "x86_64_device.go",
+    ],
+}
diff --git a/sdk/Android.bp b/sdk/Android.bp
new file mode 100644
index 0000000..cb93351
--- /dev/null
+++ b/sdk/Android.bp
@@ -0,0 +1,27 @@
+bootstrap_go_package {
+    name: "soong-sdk",
+    pkgPath: "android/soong/sdk",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-apex",
+        "soong-cc",
+        "soong-java",
+    ],
+    srcs: [
+        "bp.go",
+        "exports.go",
+        "sdk.go",
+        "update.go",
+    ],
+    testSrcs: [
+        "bp_test.go",
+        "cc_sdk_test.go",
+        "exports_test.go",
+        "java_sdk_test.go",
+        "sdk_test.go",
+        "testing.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index dded153..4a09081 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -401,7 +401,6 @@
 				"Test.cpp",
 			],
 			compile_multilib: "both",
-			stl: "none",
 		}
 	`)
 
@@ -494,6 +493,7 @@
     device_supported: false,
     host_supported: true,
     installable: false,
+    stl: "none",
     target: {
         linux_glibc: {
             compile_multilib: "both",
@@ -518,6 +518,7 @@
     prefer: false,
     device_supported: false,
     host_supported: true,
+    stl: "none",
     target: {
         linux_glibc: {
             compile_multilib: "both",
@@ -557,6 +558,90 @@
 	)
 }
 
+// Test that we support the necessary flags for the linker binary, which is
+// special in several ways.
+func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
+	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
+	SkipIfNotLinux(t)
+
+	result := testSdkWithCc(t, `
+		module_exports {
+			name: "mymodule_exports",
+			host_supported: true,
+			device_supported: false,
+			native_binaries: ["linker"],
+		}
+
+		cc_binary {
+			name: "linker",
+			host_supported: true,
+			static_executable: true,
+			nocrt: true,
+			stl: "none",
+			srcs: [
+				"Test.cpp",
+			],
+			compile_multilib: "both",
+		}
+	`)
+
+	result.CheckSnapshot("mymodule_exports", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_binary {
+    name: "mymodule_exports_linker@current",
+    sdk_member_name: "linker",
+    device_supported: false,
+    host_supported: true,
+    installable: false,
+    stl: "none",
+    static_executable: true,
+    nocrt: true,
+    compile_multilib: "both",
+    arch: {
+        x86_64: {
+            srcs: ["x86_64/bin/linker"],
+        },
+        x86: {
+            srcs: ["x86/bin/linker"],
+        },
+    },
+}
+
+cc_prebuilt_binary {
+    name: "linker",
+    prefer: false,
+    device_supported: false,
+    host_supported: true,
+    stl: "none",
+    static_executable: true,
+    nocrt: true,
+    compile_multilib: "both",
+    arch: {
+        x86_64: {
+            srcs: ["x86_64/bin/linker"],
+        },
+        x86: {
+            srcs: ["x86/bin/linker"],
+        },
+    },
+}
+
+module_exports_snapshot {
+    name: "mymodule_exports@current",
+    device_supported: false,
+    host_supported: true,
+    native_binaries: ["mymodule_exports_linker@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/linker/linux_glibc_x86_64/linker -> x86_64/bin/linker
+.intermediates/linker/linux_glibc_x86/linker -> x86/bin/linker
+`),
+	)
+}
+
 func TestSnapshotWithCcSharedLibrary(t *testing.T) {
 	result := testSdkWithCc(t, `
 		sdk {
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index f8e9fc1..af792f2 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -1063,13 +1063,13 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
 .intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
 .intermediates/myjavalib.stubs.test/android_common/javac/myjavalib.stubs.test.jar -> sdk_library/test/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
-.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.test/android_common/myjavalib.stubs.source.test_removed.txt -> sdk_library/test/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1131,7 +1131,7 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1195,7 +1195,7 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1278,10 +1278,10 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
 .intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1382,13 +1382,13 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
 .intermediates/myjavalib.stubs.system/android_common/javac/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
 .intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source.system/android_common/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
 .intermediates/myjavalib.stubs.module_lib/android_common/javac/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar
 .intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
-.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_api.txt -> sdk_library/module-lib/myjavalib-removed.txt
+.intermediates/myjavalib.api.module_lib/android_common/myjavalib.api.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1459,7 +1459,7 @@
 		checkAllCopyRules(`
 .intermediates/myjavalib-stubs-publicapi/android_common/javac/myjavalib-stubs-publicapi.jar -> sdk_library/public/myjavalib-stubs.jar
 .intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_api.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib-stubs-srcs-publicapi/android_common/myjavalib-stubs-srcs-publicapi_removed.txt -> sdk_library/public/myjavalib-removed.txt
 `),
 		checkMergeZips(
 			".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
diff --git a/sh/Android.bp b/sh/Android.bp
new file mode 100644
index 0000000..0b04e7d
--- /dev/null
+++ b/sh/Android.bp
@@ -0,0 +1,16 @@
+bootstrap_go_package {
+    name: "soong-sh",
+    pkgPath: "android/soong/sh",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+    ],
+    srcs: [
+        "sh_binary.go",
+    ],
+    testSrcs: [
+        "sh_binary_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/android/sh_binary.go b/sh/sh_binary.go
similarity index 61%
rename from android/sh_binary.go
rename to sh/sh_binary.go
index 7d9dc67..2dcd716 100644
--- a/android/sh_binary.go
+++ b/sh/sh_binary.go
@@ -12,12 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package android
+package sh
 
 import (
 	"fmt"
 	"path/filepath"
 	"strings"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
 )
 
 // sh_binary is for shell scripts (and batch files) that are installed as
@@ -26,11 +30,15 @@
 // Do not use them for prebuilt C/C++/etc files.  Use cc_prebuilt_binary
 // instead.
 
+var pctx = android.NewPackageContext("android/soong/sh")
+
 func init() {
-	RegisterModuleType("sh_binary", ShBinaryFactory)
-	RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
-	RegisterModuleType("sh_test", ShTestFactory)
-	RegisterModuleType("sh_test_host", ShTestHostFactory)
+	pctx.Import("android/soong/android")
+
+	android.RegisterModuleType("sh_binary", ShBinaryFactory)
+	android.RegisterModuleType("sh_binary_host", ShBinaryHostFactory)
+	android.RegisterModuleType("sh_test", ShTestFactory)
+	android.RegisterModuleType("sh_test_host", ShTestHostFactory)
 }
 
 type shBinaryProperties struct {
@@ -69,55 +77,55 @@
 }
 
 type ShBinary struct {
-	ModuleBase
+	android.ModuleBase
 
 	properties shBinaryProperties
 
-	sourceFilePath Path
-	outputFilePath OutputPath
-	installedFile  InstallPath
+	sourceFilePath android.Path
+	outputFilePath android.OutputPath
+	installedFile  android.InstallPath
 }
 
-var _ HostToolProvider = (*ShBinary)(nil)
+var _ android.HostToolProvider = (*ShBinary)(nil)
 
 type ShTest struct {
 	ShBinary
 
 	testProperties TestProperties
 
-	data Paths
+	data android.Paths
 }
 
-func (s *ShBinary) HostToolPath() OptionalPath {
-	return OptionalPathForPath(s.installedFile)
+func (s *ShBinary) HostToolPath() android.OptionalPath {
+	return android.OptionalPathForPath(s.installedFile)
 }
 
-func (s *ShBinary) DepsMutator(ctx BottomUpMutatorContext) {
+func (s *ShBinary) DepsMutator(ctx android.BottomUpMutatorContext) {
 	if s.properties.Src == nil {
 		ctx.PropertyErrorf("src", "missing prebuilt source file")
 	}
 }
 
-func (s *ShBinary) OutputFile() OutputPath {
+func (s *ShBinary) OutputFile() android.OutputPath {
 	return s.outputFilePath
 }
 
 func (s *ShBinary) SubDir() string {
-	return String(s.properties.Sub_dir)
+	return proptools.String(s.properties.Sub_dir)
 }
 
 func (s *ShBinary) Installable() bool {
-	return s.properties.Installable == nil || Bool(s.properties.Installable)
+	return s.properties.Installable == nil || proptools.Bool(s.properties.Installable)
 }
 
 func (s *ShBinary) Symlinks() []string {
 	return s.properties.Symlinks
 }
 
-func (s *ShBinary) generateAndroidBuildActions(ctx ModuleContext) {
-	s.sourceFilePath = PathForModuleSrc(ctx, String(s.properties.Src))
-	filename := String(s.properties.Filename)
-	filename_from_src := Bool(s.properties.Filename_from_src)
+func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) {
+	s.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(s.properties.Src))
+	filename := proptools.String(s.properties.Filename)
+	filename_from_src := proptools.Bool(s.properties.Filename_from_src)
 	if filename == "" {
 		if filename_from_src {
 			filename = s.sourceFilePath.Base()
@@ -128,38 +136,38 @@
 		ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
 		return
 	}
-	s.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
+	s.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
 
 	// This ensures that outputFilePath has the correct name for others to
 	// use, as the source file may have a different name.
-	ctx.Build(pctx, BuildParams{
-		Rule:   CpExecutable,
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.CpExecutable,
 		Output: s.outputFilePath,
 		Input:  s.sourceFilePath,
 	})
 }
 
-func (s *ShBinary) GenerateAndroidBuildActions(ctx ModuleContext) {
+func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	s.generateAndroidBuildActions(ctx)
-	installDir := PathForModuleInstall(ctx, "bin", String(s.properties.Sub_dir))
+	installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
 	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
 }
 
-func (s *ShBinary) AndroidMkEntries() []AndroidMkEntries {
-	return []AndroidMkEntries{AndroidMkEntries{
+func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "EXECUTABLES",
-		OutputFile: OptionalPathForPath(s.outputFilePath),
+		OutputFile: android.OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
-		ExtraEntries: []AndroidMkExtraEntriesFunc{
-			func(entries *AndroidMkEntries) {
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
 			},
 		},
 	}}
 }
 
-func (s *ShBinary) customAndroidMkEntries(entries *AndroidMkEntries) {
-	entries.SetString("LOCAL_MODULE_RELATIVE_PATH", String(s.properties.Sub_dir))
+func (s *ShBinary) customAndroidMkEntries(entries *android.AndroidMkEntries) {
+	entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
 	entries.SetString("LOCAL_MODULE_SUFFIX", "")
 	entries.SetString("LOCAL_MODULE_STEM", s.outputFilePath.Rel())
 	if len(s.properties.Symlinks) > 0 {
@@ -167,38 +175,38 @@
 	}
 }
 
-func (s *ShTest) GenerateAndroidBuildActions(ctx ModuleContext) {
+func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	s.ShBinary.generateAndroidBuildActions(ctx)
 	testDir := "nativetest"
 	if ctx.Target().Arch.ArchType.Multilib == "lib64" {
 		testDir = "nativetest64"
 	}
-	if ctx.Target().NativeBridge == NativeBridgeEnabled {
+	if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
 		testDir = filepath.Join(testDir, ctx.Target().NativeBridgeRelativePath)
 	} else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
 		testDir = filepath.Join(testDir, ctx.Arch().ArchType.String())
 	}
-	installDir := PathForModuleInstall(ctx, testDir, String(s.properties.Sub_dir))
+	installDir := android.PathForModuleInstall(ctx, testDir, proptools.String(s.properties.Sub_dir))
 	s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
 
-	s.data = PathsForModuleSrc(ctx, s.testProperties.Data)
+	s.data = android.PathsForModuleSrc(ctx, s.testProperties.Data)
 }
 
 func (s *ShTest) InstallInData() bool {
 	return true
 }
 
-func (s *ShTest) AndroidMkEntries() []AndroidMkEntries {
-	return []AndroidMkEntries{AndroidMkEntries{
+func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "NATIVE_TESTS",
-		OutputFile: OptionalPathForPath(s.outputFilePath),
+		OutputFile: android.OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
-		ExtraEntries: []AndroidMkExtraEntriesFunc{
-			func(entries *AndroidMkEntries) {
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(entries *android.AndroidMkEntries) {
 				s.customAndroidMkEntries(entries)
 
 				entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
-				entries.SetString("LOCAL_TEST_CONFIG", String(s.testProperties.Test_config))
+				entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
 				for _, d := range s.data {
 					rel := d.Rel()
 					path := d.String()
@@ -219,41 +227,41 @@
 
 // sh_binary is for a shell script or batch file to be installed as an
 // executable binary to <partition>/bin.
-func ShBinaryFactory() Module {
+func ShBinaryFactory() android.Module {
 	module := &ShBinary{}
-	module.Prefer32(func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool {
-		return class == Device && ctx.Config().DevicePrefer32BitExecutables()
+	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
+		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
 	})
 	InitShBinaryModule(module)
-	InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
 	return module
 }
 
 // sh_binary_host is for a shell script to be installed as an executable binary
 // to $(HOST_OUT)/bin.
-func ShBinaryHostFactory() Module {
+func ShBinaryHostFactory() android.Module {
 	module := &ShBinary{}
 	InitShBinaryModule(module)
-	InitAndroidArchModule(module, HostSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
 	return module
 }
 
 // sh_test defines a shell script based test module.
-func ShTestFactory() Module {
+func ShTestFactory() android.Module {
 	module := &ShTest{}
 	InitShBinaryModule(&module.ShBinary)
 	module.AddProperties(&module.testProperties)
 
-	InitAndroidArchModule(module, HostAndDeviceSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
 	return module
 }
 
 // sh_test_host defines a shell script based test module that runs on a host.
-func ShTestHostFactory() Module {
+func ShTestHostFactory() android.Module {
 	module := &ShTest{}
 	InitShBinaryModule(&module.ShBinary)
 	module.AddProperties(&module.testProperties)
 
-	InitAndroidArchModule(module, HostSupported, MultilibFirst)
+	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
 	return module
 }
diff --git a/android/sh_binary_test.go b/sh/sh_binary_test.go
similarity index 64%
rename from android/sh_binary_test.go
rename to sh/sh_binary_test.go
index 137e773..6c0d96a 100644
--- a/android/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -1,27 +1,56 @@
-package android
+package sh
 
 import (
+	"io/ioutil"
+	"os"
 	"reflect"
 	"testing"
+
+	"android/soong/android"
 )
 
-func testShBinary(t *testing.T, bp string) (*TestContext, Config) {
+var buildDir string
+
+func setUp() {
+	var err error
+	buildDir, err = ioutil.TempDir("", "soong_sh_test")
+	if err != nil {
+		panic(err)
+	}
+}
+
+func tearDown() {
+	os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+	run := func() int {
+		setUp()
+		defer tearDown()
+
+		return m.Run()
+	}
+
+	os.Exit(run())
+}
+
+func testShBinary(t *testing.T, bp string) (*android.TestContext, android.Config) {
 	fs := map[string][]byte{
 		"test.sh":            nil,
 		"testdata/data1":     nil,
 		"testdata/sub/data2": nil,
 	}
 
-	config := TestArchConfig(buildDir, nil, bp, fs)
+	config := android.TestArchConfig(buildDir, nil, bp, fs)
 
-	ctx := NewTestArchContext()
+	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("sh_test", ShTestFactory)
 	ctx.RegisterModuleType("sh_test_host", ShTestHostFactory)
 	ctx.Register(config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	FailIfErrored(t, errs)
+	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
-	FailIfErrored(t, errs)
+	android.FailIfErrored(t, errs)
 
 	return ctx, config
 }
@@ -41,7 +70,7 @@
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
-	entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
+	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
 	expected := []string{":testdata/data1", ":testdata/sub/data2"}
 	actual := entries.EntryMap["LOCAL_TEST_DATA"]
 	if !reflect.DeepEqual(expected, actual) {
@@ -62,7 +91,7 @@
 		}
 	`)
 
-	buildOS := BuildOs.String()
+	buildOS := android.BuildOs.String()
 	mod := ctx.ModuleForTests("foo", buildOS+"_x86_64").Module().(*ShTest)
 	if !mod.Host() {
 		t.Errorf("host bit is not set for a sh_test_host module.")
diff --git a/shared/Android.bp b/shared/Android.bp
new file mode 100644
index 0000000..07dfe11
--- /dev/null
+++ b/shared/Android.bp
@@ -0,0 +1,7 @@
+bootstrap_go_package {
+    name: "soong-shared",
+    pkgPath: "android/soong/shared",
+    srcs: [
+        "paths.go",
+    ],
+}
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
new file mode 100644
index 0000000..48094f1
--- /dev/null
+++ b/sysprop/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+    name: "soong-sysprop",
+    pkgPath: "android/soong/sysprop",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-java",
+    ],
+    srcs: [
+        "sysprop_library.go",
+    ],
+    testSrcs: [
+        "sysprop_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
new file mode 100644
index 0000000..6e5e533
--- /dev/null
+++ b/tradefed/Android.bp
@@ -0,0 +1,14 @@
+bootstrap_go_package {
+    name: "soong-tradefed",
+    pkgPath: "android/soong/tradefed",
+    deps: [
+        "blueprint",
+        "soong-android",
+    ],
+    srcs: [
+        "autogen.go",
+        "config.go",
+        "makevars.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 2a5a51a..0a0bb16 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -56,12 +56,14 @@
         "signal.go",
         "soong.go",
         "test_build.go",
+        "upload.go",
         "util.go",
     ],
     testSrcs: [
         "cleanbuild_test.go",
         "config_test.go",
         "environment_test.go",
+        "upload_test.go",
         "util_test.go",
         "proc_sync_test.go",
     ],
diff --git a/ui/build/config.go b/ui/build/config.go
index d66a86c..49f506e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -961,3 +961,14 @@
 func (c *configImpl) IsPdkBuild() bool {
 	return c.pdkBuild
 }
+
+func (c *configImpl) BuildDateTime() string {
+	return c.buildDateTime
+}
+
+func (c *configImpl) MetricsUploaderApp() string {
+	if p, ok := c.environ.Get("ANDROID_ENABLE_METRICS_UPLOAD"); ok {
+		return p
+	}
+	return ""
+}
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index df618c4..7b14c47 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -26,6 +26,7 @@
 	"testing"
 
 	"android/soong/ui/logger"
+	"android/soong/ui/status"
 )
 
 func testContext() Context {
@@ -33,6 +34,7 @@
 		Context: context.Background(),
 		Logger:  logger.New(&bytes.Buffer{}),
 		Writer:  &bytes.Buffer{},
+		Status:  &status.Status{},
 	}}
 }
 
diff --git a/ui/build/upload.go b/ui/build/upload.go
new file mode 100644
index 0000000..75a5e2f
--- /dev/null
+++ b/ui/build/upload.go
@@ -0,0 +1,80 @@
+// Copyright 2020 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 build
+
+// This file contains the functionality to upload data from one location to
+// another.
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/golang/protobuf/proto"
+
+	upload_proto "android/soong/ui/metrics/upload_proto"
+)
+
+const (
+	uploadPbFilename = ".uploader.pb"
+)
+
+// UploadMetrics uploads a set of metrics files to a server for analysis. An
+// uploader full path is required to be specified in order to upload the set
+// of metrics files. This is accomplished by defining the ANDROID_ENABLE_METRICS_UPLOAD
+// environment variable.
+func UploadMetrics(ctx Context, config Config, buildStartedMilli int64, files ...string) {
+	uploader := config.MetricsUploaderApp()
+	// No metrics to upload if the path to the uploader was not specified.
+	if uploader == "" {
+		return
+	}
+
+	// Some files may not exist. For example, build errors protobuf file
+	// may not exist since the build was successful.
+	var metricsFiles []string
+	for _, f := range files {
+		if _, err := os.Stat(f); err == nil {
+			metricsFiles = append(metricsFiles, f)
+		}
+	}
+
+	if len(metricsFiles) == 0 {
+		return
+	}
+
+	// For platform builds, the branch and target name is hardcoded to specific
+	// values for later extraction of the metrics in the data metrics pipeline.
+	data, err := proto.Marshal(&upload_proto.Upload{
+		CreationTimestampMs:   proto.Uint64(uint64(buildStartedMilli)),
+		CompletionTimestampMs: proto.Uint64(uint64(time.Now().UnixNano() / int64(time.Millisecond))),
+		BranchName:            proto.String("developer-metrics"),
+		TargetName:            proto.String("platform-build-systems-metrics"),
+		MetricsFiles:          metricsFiles,
+	})
+	if err != nil {
+		ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
+	}
+
+	pbFile := filepath.Join(config.OutDir(), uploadPbFilename)
+	if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
+		ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
+	}
+	// Remove the upload file as it's not longer needed after it has been processed by the uploader.
+	defer os.Remove(pbFile)
+
+	Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile).RunAndStreamOrFatal()
+}
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
new file mode 100644
index 0000000..adaa08d
--- /dev/null
+++ b/ui/build/upload_test.go
@@ -0,0 +1,120 @@
+// Copyright 2020 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 build
+
+import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+
+	"android/soong/ui/logger"
+)
+
+func TestUploadMetrics(t *testing.T) {
+	ctx := testContext()
+	tests := []struct {
+		description string
+		uploader    string
+		createFiles bool
+		files       []string
+	}{{
+		description: "ANDROID_ENABLE_METRICS_UPLOAD not set",
+	}, {
+		description: "no metrics files to upload",
+		uploader:    "fake",
+	}, {
+		description: "non-existent metrics files no upload",
+		uploader:    "fake",
+		files:       []string{"metrics_file_1", "metrics_file_2", "metrics_file_3"},
+	}, {
+		description: "trigger upload",
+		uploader:    "echo",
+		createFiles: true,
+		files:       []string{"metrics_file_1", "metrics_file_2"},
+	}}
+
+	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)
+			})
+
+			outDir, err := ioutil.TempDir("", "")
+			if err != nil {
+				t.Fatalf("failed to create out directory: %v", outDir)
+			}
+			defer os.RemoveAll(outDir)
+
+			var metricsFiles []string
+			if tt.createFiles {
+				for _, f := range tt.files {
+					filename := filepath.Join(outDir, f)
+					metricsFiles = append(metricsFiles, filename)
+					if err := ioutil.WriteFile(filename, []byte("test file"), 0644); err != nil {
+						t.Fatalf("failed to create a fake metrics file %q for uploading: %v", filename, err)
+					}
+				}
+			}
+
+			config := Config{&configImpl{
+				environ: &Environment{
+					"OUT_DIR=" + outDir,
+					"ANDROID_ENABLE_METRICS_UPLOAD=" + tt.uploader,
+				},
+				buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
+			}}
+
+			UploadMetrics(ctx, config, 1591031903, metricsFiles...)
+
+			if _, err := os.Stat(filepath.Join(outDir, uploadPbFilename)); err == nil {
+				t.Error("got true, want false for upload protobuf file to exist")
+			}
+		})
+	}
+}
+
+func TestUploadMetricsErrors(t *testing.T) {
+	expectedErr := "failed to write the marshaled"
+	defer logger.Recover(func(err error) {
+		got := err.Error()
+		if !strings.Contains(got, expectedErr) {
+			t.Errorf("got %q, want %q to be contained in error", got, expectedErr)
+		}
+	})
+
+	outDir, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Fatalf("failed to create out directory: %v", outDir)
+	}
+	defer os.RemoveAll(outDir)
+
+	metricsFile := filepath.Join(outDir, "metrics_file_1")
+	if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
+		t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
+	}
+
+	config := Config{&configImpl{
+		environ: &Environment{
+			"ANDROID_ENABLE_METRICS_UPLOAD=fake",
+			"OUT_DIR=/bad",
+		}}}
+
+	UploadMetrics(testContext(), config, 1591031903, metricsFile)
+	t.Errorf("got nil, expecting %q as a failure", expectedErr)
+}
diff --git a/xml/Android.bp b/xml/Android.bp
new file mode 100644
index 0000000..cd25cff
--- /dev/null
+++ b/xml/Android.bp
@@ -0,0 +1,18 @@
+bootstrap_go_package {
+    name: "soong-xml",
+    pkgPath: "android/soong/xml",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "soong",
+        "soong-android",
+        "soong-etc",
+    ],
+    srcs: [
+        "xml.go",
+    ],
+    testSrcs: [
+        "xml_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/xml/xml.go b/xml/xml.go
index 3a680ec..8810ae4 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/etc"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -62,7 +63,7 @@
 }
 
 type prebuiltEtcXml struct {
-	android.PrebuiltEtc
+	etc.PrebuiltEtc
 
 	properties prebuiltEtcXmlProperties
 }
@@ -121,7 +122,7 @@
 func PrebuiltEtcXmlFactory() android.Module {
 	module := &prebuiltEtcXml{}
 	module.AddProperties(&module.properties)
-	android.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
+	etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
 	// This module is device-only
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
 	return module
diff --git a/xml/xml_test.go b/xml/xml_test.go
index f8ec823..abcb108 100644
--- a/xml/xml_test.go
+++ b/xml/xml_test.go
@@ -20,6 +20,7 @@
 	"testing"
 
 	"android/soong/android"
+	"android/soong/etc"
 )
 
 var buildDir string
@@ -57,7 +58,7 @@
 	}
 	config := android.TestArchConfig(buildDir, nil, bp, fs)
 	ctx := android.NewTestArchContext()
-	ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
+	ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
 	ctx.RegisterModuleType("prebuilt_etc_xml", PrebuiltEtcXmlFactory)
 	ctx.Register(config)
 	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})