Merge "Heed SkipInstall flag when adding install rules for vendor-snapshot."
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 3af65d6..1ee096e 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -324,35 +324,68 @@
 type prebuiltBinaryLinker struct {
 	*binaryDecorator
 	prebuiltLinker
+
+	toolPath android.OptionalPath
 }
 
 var _ prebuiltLinkerInterface = (*prebuiltBinaryLinker)(nil)
 
+func (p *prebuiltBinaryLinker) hostToolPath() android.OptionalPath {
+	return p.toolPath
+}
+
 func (p *prebuiltBinaryLinker) link(ctx ModuleContext,
 	flags Flags, deps PathDeps, objs Objects) android.Path {
 	// TODO(ccross): verify shared library dependencies
 	if len(p.properties.Srcs) > 0 {
-		stripFlags := flagsToStripFlags(flags)
-
 		fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
 		in := p.Prebuilt.SingleSourcePath(ctx)
-
+		outputFile := android.PathForModuleOut(ctx, fileName)
 		p.unstrippedOutputFile = in
 
-		if p.stripper.NeedsStrip(ctx) {
-			stripped := android.PathForModuleOut(ctx, "stripped", fileName)
-			p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, stripFlags)
-			in = stripped
-		}
+		if ctx.Host() {
+			// Host binaries are symlinked to their prebuilt source locations. That
+			// way they are executed directly from there so the linker resolves their
+			// shared library dependencies relative to that location (using
+			// $ORIGIN/../lib(64):$ORIGIN/lib(64) as RUNPATH). This way the prebuilt
+			// repository can supply the expected versions of the shared libraries
+			// without interference from what is in the out tree.
 
-		// Copy binaries to a name matching the final installed name
-		outputFile := android.PathForModuleOut(ctx, fileName)
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        android.CpExecutable,
-			Description: "prebuilt",
-			Output:      outputFile,
-			Input:       in,
-		})
+			// These shared lib paths may point to copies of the libs in
+			// .intermediates, which isn't where the binary will load them from, but
+			// it's fine for dependency tracking. If a library dependency is updated,
+			// the symlink will get a new timestamp, along with any installed symlinks
+			// handled in make.
+			sharedLibPaths := deps.EarlySharedLibs
+			sharedLibPaths = append(sharedLibPaths, deps.SharedLibs...)
+			sharedLibPaths = append(sharedLibPaths, deps.LateSharedLibs...)
+
+			ctx.Build(pctx, android.BuildParams{
+				Rule:      android.Symlink,
+				Output:    outputFile,
+				Input:     in,
+				Implicits: sharedLibPaths,
+				Args: map[string]string{
+					"fromPath": "$$PWD/" + in.String(),
+				},
+			})
+
+			p.toolPath = android.OptionalPathForPath(outputFile)
+		} else {
+			if p.stripper.NeedsStrip(ctx) {
+				stripped := android.PathForModuleOut(ctx, "stripped", fileName)
+				p.stripper.StripExecutableOrSharedLib(ctx, in, stripped, flagsToStripFlags(flags))
+				in = stripped
+			}
+
+			// Copy binaries to a name matching the final installed name
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        android.CpExecutable,
+				Description: "prebuilt",
+				Output:      outputFile,
+				Input:       in,
+			})
+		}
 
 		return outputFile
 	}
@@ -379,6 +412,7 @@
 		binaryDecorator: binary,
 	}
 	module.linker = prebuilt
+	module.installer = prebuilt
 
 	module.AddProperties(&prebuilt.properties)
 
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index adb44bd..52416ac 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -15,6 +15,7 @@
 package cc
 
 import (
+	"path/filepath"
 	"testing"
 
 	"android/soong/android"
@@ -271,3 +272,52 @@
 	shared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*Module)
 	assertString(t, shared.OutputFile().Path().Base(), "libbar.so")
 }
+
+func TestPrebuiltSymlinkedHostBinary(t *testing.T) {
+	if android.BuildOs != android.Linux {
+		t.Skipf("Skipping host prebuilt testing that is only supported on %s not %s", android.Linux, android.BuildOs)
+	}
+
+	ctx := testPrebuilt(t, `
+	cc_prebuilt_library_shared {
+		name: "libfoo",
+		device_supported: false,
+		host_supported: true,
+		target: {
+			linux_glibc_x86_64: {
+				srcs: ["linux_glibc_x86_64/lib64/libfoo.so"],
+			},
+		},
+	}
+
+	cc_prebuilt_binary {
+		name: "foo",
+		device_supported: false,
+		host_supported: true,
+		shared_libs: ["libfoo"],
+		target: {
+			linux_glibc_x86_64: {
+				srcs: ["linux_glibc_x86_64/bin/foo"],
+			},
+		},
+	}
+	`, map[string][]byte{
+		"libfoo.so": nil,
+		"foo":       nil,
+	})
+
+	fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
+	assertString(t, fooRule.Output.String(),
+		filepath.Join(buildDir, ".intermediates/foo/linux_glibc_x86_64/foo"))
+	assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
+
+	var libfooDep android.Path
+	for _, dep := range fooRule.Implicits {
+		if dep.Base() == "libfoo.so" {
+			libfooDep = dep
+			break
+		}
+	}
+	assertString(t, libfooDep.String(),
+		filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so"))
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 304935e..4dbda49 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -568,8 +568,7 @@
 	}
 
 	for _, f := range global.PatternsOnSystemOther {
-		// See comment of SYSTEM_OTHER_ODEX_FILTER for details on the matching.
-		if makefileMatch("/"+f, dexLocation) || makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
+		if makefileMatch(filepath.Join(SystemPartition, f), dexLocation) {
 			return true
 		}
 	}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 727081c..ec31549 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -109,12 +109,13 @@
 				{module: productModule, expectedPartition: "product"},
 			},
 		},
+		// product/app/% only applies to product apps inside the system partition
 		{
 			patterns: []string{"app/%", "product/app/%"},
 			moduleTests: []moduleTest{
 				{module: systemModule, expectedPartition: "system_other/system"},
 				{module: systemProductModule, expectedPartition: "system_other/system/product"},
-				{module: productModule, expectedPartition: "system_other/product"},
+				{module: productModule, expectedPartition: "product"},
 			},
 		},
 	}
@@ -134,7 +135,7 @@
 			}
 
 			if rule.Installs().String() != wantInstalls.String() {
-				t.Errorf("\npatterns: %v\nwant installs:\n   %v\ngot:\n   %v", test.patterns, wantInstalls, rule.Installs())
+				t.Errorf("\nwant installs:\n   %v\ngot:\n   %v", wantInstalls, rule.Installs())
 			}
 		}
 	}
diff --git a/rust/compiler.go b/rust/compiler.go
index ddf1fac..664578d 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -216,8 +216,8 @@
 
 	if !Bool(compiler.Properties.No_stdlibs) {
 		for _, stdlib := range config.Stdlibs {
-			// If we're building for the primary host target, use the compiler's stdlibs
-			if ctx.Host() && ctx.TargetPrimary() {
+			// If we're building for the primary arch of the build host, use the compiler's stdlibs
+			if ctx.Target().Os == android.BuildOs && ctx.TargetPrimary() {
 				stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
 			}
 
diff --git a/rust/rust.go b/rust/rust.go
index 4cba6d6..b98992c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -560,21 +560,6 @@
 	android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
 
 	android.InitDefaultableModule(mod)
-
-	// Explicitly disable unsupported targets.
-	android.AddLoadHook(mod, func(ctx android.LoadHookContext) {
-		disableTargets := struct {
-			Target struct {
-				Linux_bionic struct {
-					Enabled *bool
-				}
-			}
-		}{}
-		disableTargets.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
-
-		ctx.AppendProperties(&disableTargets)
-	})
-
 	return mod
 }