Merge "fix: "no_apex" can be put in defaults"
diff --git a/Android.bp b/Android.bp
index 3ece110..afbae17 100644
--- a/Android.bp
+++ b/Android.bp
@@ -333,6 +333,8 @@
         "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",
diff --git a/apex/apex.go b/apex/apex.go
index d078724..4e72d09 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -150,7 +150,6 @@
 var (
 	whitelistNoApex = map[string][]string{
 		"apex_test_build_features":       []string{"libbinder"},
-		"com.android.neuralnetworks":     []string{"libbinder"},
 		"com.android.media":              []string{"libbinder"},
 		"com.android.media.swcodec":      []string{"libbinder"},
 		"test_com.android.media.swcodec": []string{"libbinder"},
diff --git a/build_kzip.bash b/build_kzip.bash
index 5364e7f..c1d09f7 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -3,16 +3,22 @@
 # Build kzip files (source files for the indexing pipeline) for the given configuration,
 # merge them and place the resulting all.kzip into $DIST_DIR.
 # It is assumed that the current directory is the top of the source tree.
-# The following enviromnet variables affect the result:
-#   TARGET_PRODUCT        target device name, e.g., `aosp_blueline`
+# The following environment variables affect the result:
+#   TARGET_PRODUCT        target device name, e.g., 'aosp_blueline'
 #   TARGET_BUILD_VARIANT  variant, e.g., `userdebug`
-#   OUT_DIR               where the build is happening (./out if not specified)
+#   OUT_DIR               absolute path  where the build is happening ($PWD/out if not specified})
 #   DIST_DIR              where the resulting all.kzip will be placed
-#   XREF_CORPUS           source code repository URI, e.g.,
-#                        `android.googlesource.com/platform/superproject`
+#   XREF_CORPUS           source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
+#   BUILD_NUMBER          build number, used to generate unique ID (will use UUID if not set)
+
+# If OUT_DIR is not set, the build will use out/ as output directory, which is
+# a relative path. Make it absolute, otherwise the indexer will not know that it
+# contains only generated files.
+: ${OUT_DIR:=$PWD/out}
+[[ "$OUT_DIR" =~ ^/ ]] || { echo "$OUT_DIR is not an absolute path"; exit 1; }
 
 # The extraction might fail for some source files, so run with -k
-build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
+OUT_DIR=$OUT_DIR build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
 
 # We build with -k, so check that we have generated at least 100K files
 # (the actual number is 180K+)
@@ -22,4 +28,5 @@
 # Pack
 # TODO(asmundak): this should be done by soong.
 declare -r allkzip=all.kzip
-"${OUT_DIR:-out}/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find $OUT_DIR -name '*.kzip')
+"$OUT_DIR/soong/host/linux-x86/bin/merge_zips" "$DIST_DIR/$allkzip" @<(find $OUT_DIR -name '*.kzip')
+echo "${BUILD_NUMBER:-$(uuidgen)}" >"$DIST_DIR/revision.txt"
diff --git a/cc/cc.go b/cc/cc.go
index 2987369..744e0cb 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -401,6 +401,14 @@
 	return staticDepTag
 }
 
+func CrtBeginDepTag() dependencyTag {
+	return crtBeginDepTag
+}
+
+func CrtEndDepTag() dependencyTag {
+	return crtEndDepTag
+}
+
 // Module contains the properties and members used by all C/C++ module types, and implements
 // the blueprint.Module interface.  It delegates to compiler, linker, and installer interfaces
 // to construct the output file.  Behavior can be customized with a Customizer interface
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 325be63..7806e83 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -17,6 +17,7 @@
 import (
 	"path/filepath"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -33,6 +34,7 @@
 
 func init() {
 	android.RegisterModuleType("cc_fuzz", FuzzFactory)
+	android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
 }
 
 // cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
@@ -155,3 +157,96 @@
 
 	return module
 }
+
+// Responsible for generating GNU Make rules that package fuzz targets into
+// their architecture & target/host specific zip file.
+type fuzzPackager struct {
+}
+
+func fuzzPackagingFactory() android.Singleton {
+	return &fuzzPackager{}
+}
+
+type fileToZip struct {
+	SourceFilePath        android.Path
+	DestinationPathPrefix string
+}
+
+func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+	// Map between each architecture + host/device combination, and the files that
+	// need to be packaged (in the tuple of {source file, destination folder in
+	// archive}).
+	archDirs := make(map[android.OutputPath][]fileToZip)
+
+	ctx.VisitAllModules(func(module android.Module) {
+		// Discard non-fuzz targets.
+		ccModule, ok := module.(*Module)
+		if !ok {
+			return
+		}
+		fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
+		if !ok {
+			return
+		}
+
+		// Discard vendor-NDK-linked modules, they're duplicates of fuzz targets
+		// we're going to package anyway.
+		if ccModule.useVndk() || !ccModule.Enabled() {
+			return
+		}
+
+		hostOrTargetString := "target"
+		if ccModule.Host() {
+			hostOrTargetString = "host"
+		}
+
+		archString := ccModule.Arch().ArchType.String()
+		archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+
+		// The executable.
+		archDirs[archDir] = append(archDirs[archDir],
+			fileToZip{ccModule.outputFile.Path(), ccModule.Name()})
+
+		// The corpora.
+		for _, corpusEntry := range fuzzModule.corpus {
+			archDirs[archDir] = append(archDirs[archDir],
+				fileToZip{corpusEntry, ccModule.Name() + "/corpus/" + corpusEntry.Base()})
+		}
+
+		// The dictionary.
+		if fuzzModule.dictionary != nil {
+			archDirs[archDir] = append(archDirs[archDir],
+				fileToZip{fuzzModule.dictionary, ccModule.Name()})
+		}
+	})
+
+	// List of architecture + host/device specific packages to build via. 'make fuzz'.
+	var archDirTargets android.Paths
+
+	for archDir, filesToZip := range archDirs {
+		arch := archDir.Base()
+		hostOrTarget := filepath.Base(filepath.Dir(archDir.String()))
+		builder := android.NewRuleBuilder()
+		outputFile := android.PathForOutput(ctx, "fuzz-"+hostOrTarget+"-"+arch+".zip")
+		archDirTargets = append(archDirTargets, outputFile)
+
+		command := builder.Command().BuiltTool(ctx, "soong_zip").
+			Flag("-j").
+			FlagWithOutput("-o ", outputFile)
+
+		for _, fileToZip := range filesToZip {
+			command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix).
+				FlagWithInput("-f ", fileToZip.SourceFilePath)
+		}
+
+		builder.Build(pctx, ctx, "create-fuzz-package-"+arch+"-"+hostOrTarget,
+			"Create fuzz target packages for "+arch+"-"+hostOrTarget)
+	}
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        blueprint.Phony,
+		Output:      android.PathForPhony(ctx, "fuzz"),
+		Implicits:   archDirTargets,
+		Description: "Build all Android fuzz targets, and create packages.",
+	})
+}
diff --git a/cc/gen.go b/cc/gen.go
index 42b0cbe..17ab45f 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -113,7 +113,14 @@
 
 	aidlPackage := strings.TrimSuffix(aidlFile.Rel(), aidlFile.Base())
 	baseName := strings.TrimSuffix(aidlFile.Base(), aidlFile.Ext())
-	shortName := strings.TrimPrefix(baseName, "I")
+	shortName := baseName
+	// TODO(b/111362593): aidl_to_cpp_common.cpp uses heuristics to figure out if
+	//   an interface name has a leading I. Those same heuristics have been
+	//   moved here.
+	if len(baseName) >= 2 && baseName[0] == 'I' &&
+		strings.ToUpper(baseName)[1] == baseName[1] {
+		shortName = strings.TrimPrefix(baseName, "I")
+	}
 
 	outDir := android.PathForModuleGen(ctx, "aidl")
 	headerI := outDir.Join(ctx, aidlPackage, baseName+".h")
diff --git a/rust/binary.go b/rust/binary.go
index 279c6f5..52f840e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -71,6 +71,15 @@
 
 func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
 	flags = binary.baseCompiler.compilerFlags(ctx, flags)
+
+	if ctx.toolchain().Bionic() {
+		// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined, but we can apply this to binaries.
+		flags.LinkFlags = append(flags.LinkFlags,
+			"-Wl,--gc-sections",
+			"-Wl,-z,nocopyreloc",
+			"-Wl,--no-undefined-version")
+	}
+
 	if binary.preferDynamic() {
 		flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic")
 	}
@@ -86,6 +95,12 @@
 		}
 	}
 
+	if ctx.toolchain().Bionic() {
+		deps = binary.baseCompiler.bionicDeps(ctx, deps)
+		deps.CrtBegin = "crtbegin_dynamic"
+		deps.CrtEnd = "crtend_android"
+	}
+
 	return deps
 }
 
diff --git a/rust/builder.go b/rust/builder.go
index 64e387b..6611492 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -28,14 +28,14 @@
 		blueprint.RuleParams{
 			Command: "$rustcCmd " +
 				"-C linker=${config.RustLinker} " +
-				"-C link-args=\"${config.RustLinkerArgs} ${linkFlags}\" " +
+				"-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
 				"-o $out $in ${libFlags} $rustcFlags " +
 				"&& $rustcCmd --emit=dep-info -o $out.d $in ${libFlags} $rustcFlags",
 			CommandDeps: []string{"$rustcCmd"},
 			Depfile:     "$out.d",
 			Deps:        blueprint.DepsGCC, // Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
 		},
-		"rustcFlags", "linkFlags", "libFlags")
+		"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
 )
 
 func init() {
@@ -43,28 +43,19 @@
 }
 
 func TransformSrcToBinary(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "bin", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "bin", includeDirs)
 }
 
 func TransformSrctoRlib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "rlib", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "rlib", includeDirs)
 }
 
 func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "dylib", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs)
 }
 
 func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) {
-	// Proc macros are compiler plugins, and thus should target the host compiler
-	targetTriple := ""
-
-	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, flags, outputFile, "proc-macro", includeDirs, targetTriple)
+	transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs)
 }
 
 func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -76,23 +67,28 @@
 }
 
 func transformSrctoCrate(ctx android.ModuleContext, main android.Path,
-	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string, targetTriple string) {
+	rlibs, dylibs, proc_macros RustLibraries, static_libs, shared_libs android.Paths, crtBegin, crtEnd android.OptionalPath, flags Flags, outputFile android.WritablePath, crate_type string, includeDirs []string) {
 
 	var inputs android.Paths
 	var deps android.Paths
-	var libFlags, rustcFlags []string
+	var libFlags, rustcFlags, linkFlags []string
 	crate_name := ctx.(ModuleContext).CrateName()
+	targetTriple := ctx.(ModuleContext).toolchain().RustTriple()
 
 	inputs = append(inputs, main)
 
 	// Collect rustc flags
-	rustcFlags = append(rustcFlags, flags.GlobalFlags...)
+	rustcFlags = append(rustcFlags, flags.GlobalRustFlags...)
 	rustcFlags = append(rustcFlags, flags.RustFlags...)
 	rustcFlags = append(rustcFlags, "--crate-type="+crate_type)
 	rustcFlags = append(rustcFlags, "--crate-name="+crate_name)
 	if targetTriple != "" {
 		rustcFlags = append(rustcFlags, "--target="+targetTriple)
+		linkFlags = append(linkFlags, "-target "+targetTriple)
 	}
+	// Collect linker flags
+	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
+	linkFlags = append(linkFlags, flags.LinkFlags...)
 
 	// Collect library/crate flags
 	for _, lib := range rlibs {
@@ -115,6 +111,9 @@
 	deps = append(deps, rustLibsToPaths(proc_macros)...)
 	deps = append(deps, static_libs...)
 	deps = append(deps, shared_libs...)
+	if crtBegin.Valid() {
+		deps = append(deps, crtBegin.Path(), crtEnd.Path())
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rustc,
@@ -124,8 +123,10 @@
 		Implicits:   deps,
 		Args: map[string]string{
 			"rustcFlags": strings.Join(rustcFlags, " "),
-			"linkFlags":  strings.Join(flags.LinkFlags, " "),
+			"linkFlags":  strings.Join(linkFlags, " "),
 			"libFlags":   strings.Join(libFlags, " "),
+			"crtBegin":   crtBegin.String(),
+			"crtEnd":     crtEnd.String(),
 		},
 	})
 
diff --git a/rust/compiler.go b/rust/compiler.go
index 87cf08b..f45744b 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -113,7 +113,8 @@
 	flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags(compiler.Properties.Features)...)
 	flags.RustFlags = append(flags.RustFlags, "--edition="+*compiler.Properties.Edition)
 	flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
-	flags.GlobalFlags = append(flags.GlobalFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
+	flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
 
 	if ctx.Host() && !ctx.Windows() {
 		rpath_prefix := `\$$ORIGIN/`
@@ -148,6 +149,18 @@
 	return deps
 }
 
+func (compiler *baseCompiler) bionicDeps(ctx DepsContext, deps Deps) Deps {
+	deps.SharedLibs = append(deps.SharedLibs, "liblog")
+	deps.SharedLibs = append(deps.SharedLibs, "libc")
+	deps.SharedLibs = append(deps.SharedLibs, "libm")
+	deps.SharedLibs = append(deps.SharedLibs, "libdl")
+
+	//TODO(b/141331117) libstd requires libgcc on Android
+	deps.StaticLibs = append(deps.StaticLibs, "libgcc")
+
+	return deps
+}
+
 func (compiler *baseCompiler) crateName() string {
 	return compiler.Properties.Crate_name
 }
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 5369096..bbf9f8d 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -64,7 +64,6 @@
 		rust_proc_macro {
 			name: "foo-bar-proc-macro",
 			srcs: ["foo.rs", "src/bar.rs"],
-			host_supported: true,
 		}`)
 
 	// Test prebuilts
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
new file mode 100644
index 0000000..0264052
--- /dev/null
+++ b/rust/config/arm64_device.go
@@ -0,0 +1,92 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	Arm64RustFlags            = []string{}
+	Arm64ArchFeatureRustFlags = map[string][]string{}
+	Arm64LinkFlags            = []string{
+		"-Wl,--icf=safe",
+		"-Wl,-z,max-page-size=4096",
+
+		"-Wl,-execute-only",
+	}
+
+	Arm64ArchVariantRustFlags = map[string][]string{
+		"armv8-a":  []string{},
+		"armv8-2a": []string{},
+	}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm64, Arm64ToolchainFactory)
+
+	pctx.StaticVariable("Arm64ToolchainRustFlags", strings.Join(Arm64RustFlags, " "))
+	pctx.StaticVariable("Arm64ToolchainLinkFlags", strings.Join(Arm64LinkFlags, " "))
+
+	for variant, rustFlags := range Arm64ArchVariantRustFlags {
+		pctx.StaticVariable("Arm64"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainArm64 struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainArm64) RustTriple() string {
+	return "aarch64-linux-android"
+}
+
+func (t *toolchainArm64) ToolchainLinkFlags() string {
+	return "${config.DeviceGlobalLinkFlags} ${config.Arm64ToolchainLinkFlags}"
+}
+
+func (t *toolchainArm64) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainArm64) RustFlags() string {
+	return "${config.Arm64ToolchainRustFlags}"
+}
+
+func (t *toolchainArm64) Supported() bool {
+	return true
+}
+
+func Arm64ToolchainFactory(arch android.Arch) Toolchain {
+	toolchainRustFlags := []string{
+		"${config.Arm64ToolchainRustFlags}",
+		"${config.Arm64" + arch.ArchVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, Arm64ArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainArm64{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
new file mode 100644
index 0000000..aedb42b
--- /dev/null
+++ b/rust/config/arm_device.go
@@ -0,0 +1,92 @@
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package config
+
+import (
+	"strings"
+
+	"android/soong/android"
+)
+
+var (
+	ArmRustFlags            = []string{}
+	ArmArchFeatureRustFlags = map[string][]string{}
+	ArmLinkFlags            = []string{
+		"-Wl,--icf=safe",
+		"-Wl,-m,armelf",
+	}
+
+	ArmArchVariantRustFlags = map[string][]string{
+		"armv7-a":      []string{},
+		"armv7-a-neon": []string{},
+		"armv8-a":      []string{},
+		"armv8-2a":     []string{},
+	}
+)
+
+func init() {
+	registerToolchainFactory(android.Android, android.Arm, ArmToolchainFactory)
+
+	pctx.StaticVariable("ArmToolchainRustFlags", strings.Join(ArmRustFlags, " "))
+	pctx.StaticVariable("ArmToolchainLinkFlags", strings.Join(ArmLinkFlags, " "))
+
+	for variant, rustFlags := range ArmArchVariantRustFlags {
+		pctx.StaticVariable("Arm"+variant+"VariantRustFlags",
+			strings.Join(rustFlags, " "))
+	}
+
+}
+
+type toolchainArm struct {
+	toolchain64Bit
+	toolchainRustFlags string
+}
+
+func (t *toolchainArm) RustTriple() string {
+	return "arm-linux-androideabi"
+}
+
+func (t *toolchainArm) ToolchainLinkFlags() string {
+	return "${config.DeviceGlobalLinkFlags} ${config.ArmToolchainLinkFlags}"
+}
+
+func (t *toolchainArm) ToolchainRustFlags() string {
+	return t.toolchainRustFlags
+}
+
+func (t *toolchainArm) RustFlags() string {
+	return "${config.ArmToolchainRustFlags}"
+}
+
+func (t *toolchainArm) Supported() bool {
+	return true
+}
+
+func ArmToolchainFactory(arch android.Arch) Toolchain {
+	toolchainRustFlags := []string{
+		"${config.ArmToolchainRustFlags}",
+		"${config.Arm" + arch.ArchVariant + "VariantRustFlags}",
+	}
+
+	toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+	for _, feature := range arch.ArchFeatures {
+		toolchainRustFlags = append(toolchainRustFlags, ArmArchFeatureRustFlags[feature]...)
+	}
+
+	return &toolchainArm{
+		toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+	}
+}
diff --git a/rust/config/global.go b/rust/config/global.go
index 903a424..cec5a74 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -15,6 +15,8 @@
 package config
 
 import (
+	"strings"
+
 	"android/soong/android"
 	_ "android/soong/cc/config"
 )
@@ -30,6 +32,24 @@
 		"libterm",
 		"libtest",
 	}
+
+	deviceGlobalRustFlags = []string{}
+
+	deviceGlobalLinkFlags = []string{
+		"-Bdynamic",
+		"-nostdlib",
+		"-Wl,-z,noexecstack",
+		"-Wl,-z,relro",
+		"-Wl,-z,now",
+		"-Wl,--build-id=md5",
+		"-Wl,--warn-shared-textrel",
+		"-Wl,--fatal-warnings",
+
+		"-Wl,--pack-dyn-relocs=android+relr",
+		"-Wl,--use-android-relr-tags",
+		"-Wl,--no-undefined",
+		"-Wl,--hash-style=gnu",
+	}
 )
 
 func init() {
@@ -56,4 +76,7 @@
 	pctx.ImportAs("ccConfig", "android/soong/cc/config")
 	pctx.StaticVariable("RustLinker", "${ccConfig.ClangBin}/clang++")
 	pctx.StaticVariable("RustLinkerArgs", "-B ${ccConfig.ClangBin} -fuse-ld=lld")
+
+	pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
+
 }
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index a36d61b..328bca3 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -32,6 +32,8 @@
 
 	Is64Bit() bool
 	Supported() bool
+
+	Bionic() bool
 }
 
 type toolchainBase struct {
@@ -53,6 +55,10 @@
 	panic("toolchainBase cannot determine datapath width.")
 }
 
+func (toolchainBase) Bionic() bool {
+	return true
+}
+
 type toolchain64Bit struct {
 	toolchainBase
 }
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index cb6bf1a..5376e5b 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -61,6 +61,10 @@
 	return true
 }
 
+func (toolchainLinuxX8664) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX8664) Name() string {
 	return "x86_64"
 }
@@ -85,6 +89,10 @@
 	return true
 }
 
+func (toolchainLinuxX86) Bionic() bool {
+	return false
+}
+
 func (t *toolchainLinuxX86) Name() string {
 	return "x86"
 }
diff --git a/rust/library.go b/rust/library.go
index 5cf8ac7..c831727 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -191,6 +191,16 @@
 		&library.MutatedProperties)
 }
 
+func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = library.baseCompiler.compilerDeps(ctx, deps)
+
+	if ctx.toolchain().Bionic() && library.dylib() {
+		deps = library.baseCompiler.bionicDeps(ctx, deps)
+	}
+
+	return deps
+}
+
 func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
 	var outputFile android.WritablePath
 
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index d4e631b..fa69fbb 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -63,3 +63,8 @@
 
 	return srcPath
 }
+
+func (prebuilt *prebuiltLibraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
+	deps = prebuilt.baseCompiler.compilerDeps(ctx, deps)
+	return deps
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 4acb06f..1a247d9 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -45,7 +45,7 @@
 var _ compiler = (*procMacroDecorator)(nil)
 
 func ProcMacroFactory() android.Module {
-	module, _ := NewProcMacro(android.HostAndDeviceSupported)
+	module, _ := NewProcMacro(android.HostSupportedNoCross)
 	return module.Init()
 }
 
diff --git a/rust/rust.go b/rust/rust.go
index 2120916..61b51e5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -43,11 +43,12 @@
 }
 
 type Flags struct {
-	GlobalFlags   []string      // Flags that apply globally
-	RustFlags     []string      // Flags that apply to rust
-	LinkFlags     []string      // Flags that apply to linker
-	RustFlagsDeps android.Paths // Files depended on by compiler flags
-	Toolchain     config.Toolchain
+	GlobalRustFlags []string      // Flags that apply globally to rust
+	GlobalLinkFlags []string      // Flags that apply globally to linker
+	RustFlags       []string      // Flags that apply to rust
+	LinkFlags       []string      // Flags that apply to linker
+	RustFlagsDeps   android.Paths // Files depended on by compiler flags
+	Toolchain       config.Toolchain
 }
 
 type BaseProperties struct {
@@ -92,6 +93,9 @@
 	linkDirs   []string
 	depFlags   []string
 	//ReexportedDeps android.Paths
+
+	CrtBegin android.OptionalPath
+	CrtEnd   android.OptionalPath
 }
 
 type RustLibraries []RustLibrary
@@ -321,15 +325,6 @@
 		if rustDep, ok := dep.(*Module); ok {
 			//Handle Rust Modules
 
-			if rustDep.Target().Os != ctx.Os() {
-				ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
-				return
-			}
-			if rustDep.Target().Arch.ArchType != ctx.Arch().ArchType {
-				ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
-				return
-			}
-
 			linkFile := rustDep.outputFile
 			if !linkFile.Valid() {
 				ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
@@ -361,9 +356,6 @@
 			if lib, ok := rustDep.compiler.(*libraryDecorator); ok {
 				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedDirs()...)
 				depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
-			} else if procMacro, ok := rustDep.compiler.(*libraryDecorator); ok {
-				depPaths.linkDirs = append(depPaths.linkDirs, procMacro.exportedDirs()...)
-				depPaths.depFlags = append(depPaths.depFlags, procMacro.exportedDepFlags()...)
 			}
 
 			// Append this dependencies output to this mod's linkDirs so they can be exported to dependencies
@@ -410,6 +402,10 @@
 				directSharedLibDeps = append(directSharedLibDeps, ccDep)
 				mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
 				exportDep = true
+			case cc.CrtBeginDepTag():
+				depPaths.CrtBegin = linkFile
+			case cc.CrtEndDepTag():
+				depPaths.CrtEnd = linkFile
 			}
 
 			// Make sure these dependencies are propagated
@@ -491,7 +487,16 @@
 	}
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...)
 	actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...)
-	actx.AddDependency(mod, procMacroDepTag, deps.ProcMacros...)
+
+	if deps.CrtBegin != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin)
+	}
+	if deps.CrtEnd != "" {
+		actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd)
+	}
+
+	// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
+	actx.AddFarVariationDependencies([]blueprint.Variation{{Mutator: "arch", Variation: ctx.Config().BuildOsVariant}}, procMacroDepTag, deps.ProcMacros...)
 }
 
 func (mod *Module) Name() string {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index f7c96dd..0c8d355 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -18,6 +18,7 @@
 	"io/ioutil"
 	"os"
 	"runtime"
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -150,7 +151,6 @@
 		rust_proc_macro {
 			name: "libpm",
 			srcs: ["foo.rs"],
-			host_supported: true,
 		}
 		rust_binary_host {
 			name: "fizz-buzz",
@@ -176,3 +176,28 @@
 	}
 
 }
+
+// Test to make sure proc_macros use host variants when building device modules.
+func TestProcMacroDeviceDeps(t *testing.T) {
+	ctx := testRust(t, `
+		rust_library_host_rlib {
+			name: "libbar",
+			srcs: ["foo.rs"],
+		}
+		rust_proc_macro {
+			name: "libpm",
+			rlibs: ["libbar"],
+			srcs: ["foo.rs"],
+		}
+		rust_binary {
+			name: "fizz-buzz",
+			proc_macros: ["libpm"],
+			srcs: ["foo.rs"],
+		}
+	`)
+	rustc := ctx.ModuleForTests("libpm", "linux_glibc_x86_64").Rule("rustc")
+
+	if !strings.Contains(rustc.Args["libFlags"], "libbar/linux_glibc_x86_64") {
+		t.Errorf("Proc_macro is not using host variant of dependent modules.")
+	}
+}
diff --git a/rust/testing.go b/rust/testing.go
index a38697f..92347f1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/cc"
 )
 
 func GatherRequiredDepsForTest() string {
@@ -70,12 +71,101 @@
 				srcs: [""],
 				host_supported: true,
 		}
+
+		//////////////////////////////
+		// Device module requirements
+
+		toolchain_library {
+			name: "libgcc",
+			no_libcrt: true,
+			nocrt: true,
+			src: "",
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libc",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libm",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_library {
+			name: "libdl",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+		cc_object {
+			name: "crtbegin_dynamic",
+		}
+
+		cc_object {
+			name: "crtend_android",
+		}
+		cc_library {
+			name: "liblog",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+		}
+
+		//////////////////////////////
+		// cc module requirements
+
+		toolchain_library {
+			name: "libatomic",
+			src: "",
+		}
+		toolchain_library {
+			name: "libclang_rt.builtins-aarch64-android",
+			src: "",
+		}
+		toolchain_library {
+			name: "libgcc_stripped",
+			src: "",
+		}
+		cc_library {
+			name: "libc++_static",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+		cc_library {
+			name: "libc++demangle",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+			host_supported: false,
+		}
+		cc_library {
+			name: "libc++",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
+		cc_library {
+			name: "libunwind_llvm",
+			no_libcrt: true,
+			nocrt: true,
+			system_shared_libs: [],
+			stl: "none",
+		}
 		`
 	return bp
 }
 
 func CreateTestContext(bp string) *android.TestContext {
 	ctx := android.NewTestArchContext()
+	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
+	ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(cc.ObjectFactory))
 	ctx.RegisterModuleType("rust_binary", android.ModuleFactoryAdaptor(RustBinaryFactory))
 	ctx.RegisterModuleType("rust_binary_host", android.ModuleFactoryAdaptor(RustBinaryHostFactory))
 	ctx.RegisterModuleType("rust_library", android.ModuleFactoryAdaptor(RustLibraryFactory))
@@ -86,9 +176,16 @@
 	ctx.RegisterModuleType("rust_library_dylib", android.ModuleFactoryAdaptor(RustLibraryDylibFactory))
 	ctx.RegisterModuleType("rust_proc_macro", android.ModuleFactoryAdaptor(ProcMacroFactory))
 	ctx.RegisterModuleType("rust_prebuilt_dylib", android.ModuleFactoryAdaptor(PrebuiltDylibFactory))
+	ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory))
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
+
+		ctx.BottomUp("image", cc.ImageMutator).Parallel()
+		ctx.BottomUp("link", cc.LinkageMutator).Parallel()
+		ctx.BottomUp("version", cc.VersionMutator).Parallel()
+		ctx.BottomUp("begin", cc.BeginMutator).Parallel()
 	})
+
 	bp = bp + GatherRequiredDepsForTest()
 
 	mockFS := map[string][]byte{