Merge "VNDK lib must not have `product_specific: true`"
diff --git a/cc/library.go b/cc/library.go
index a9d63f9..8b8fe02 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -32,19 +32,21 @@
 		Srcs   []string `android:"arch_variant"`
 		Cflags []string `android:"arch_variant"`
 
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
+		Enabled            *bool    `android:"arch_variant"`
+		Whole_static_libs  []string `android:"arch_variant"`
+		Static_libs        []string `android:"arch_variant"`
+		Shared_libs        []string `android:"arch_variant"`
+		System_shared_libs []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 	Shared struct {
 		Srcs   []string `android:"arch_variant"`
 		Cflags []string `android:"arch_variant"`
 
-		Enabled           *bool    `android:"arch_variant"`
-		Whole_static_libs []string `android:"arch_variant"`
-		Static_libs       []string `android:"arch_variant"`
-		Shared_libs       []string `android:"arch_variant"`
+		Enabled            *bool    `android:"arch_variant"`
+		Whole_static_libs  []string `android:"arch_variant"`
+		Static_libs        []string `android:"arch_variant"`
+		Shared_libs        []string `android:"arch_variant"`
+		System_shared_libs []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	// local file name to pass to the linker as -unexported_symbols_list
@@ -488,6 +490,16 @@
 }
 
 func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
+	if library.static() {
+		if library.Properties.Static.System_shared_libs != nil {
+			library.baseLinker.Properties.System_shared_libs = library.Properties.Static.System_shared_libs
+		}
+	} else if library.shared() {
+		if library.Properties.Shared.System_shared_libs != nil {
+			library.baseLinker.Properties.System_shared_libs = library.Properties.Shared.System_shared_libs
+		}
+	}
+
 	deps = library.baseLinker.linkerDeps(ctx, deps)
 
 	if library.static() {
@@ -921,8 +933,19 @@
 func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Module) {
 	if staticCompiler, ok := static.compiler.(*libraryDecorator); ok {
 		sharedCompiler := shared.compiler.(*libraryDecorator)
+
+		// Check libraries in addition to cflags, since libraries may be exporting different
+		// include directories.
 		if len(staticCompiler.Properties.Static.Cflags) == 0 &&
-			len(sharedCompiler.Properties.Shared.Cflags) == 0 {
+			len(sharedCompiler.Properties.Shared.Cflags) == 0 &&
+			len(staticCompiler.Properties.Static.Whole_static_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Whole_static_libs) == 0 &&
+			len(staticCompiler.Properties.Static.Static_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Static_libs) == 0 &&
+			len(staticCompiler.Properties.Static.Shared_libs) == 0 &&
+			len(sharedCompiler.Properties.Shared.Shared_libs) == 0 &&
+			staticCompiler.Properties.Static.System_shared_libs == nil &&
+			sharedCompiler.Properties.Shared.System_shared_libs == nil {
 
 			mctx.AddInterVariantDependency(reuseObjTag, shared, static)
 			sharedCompiler.baseCompiler.Properties.OriginalSrcs =
diff --git a/cc/linker.go b/cc/linker.go
index 3c51690..854dfc5 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -49,7 +49,7 @@
 	// list of system libraries that will be dynamically linked to
 	// shared library and executable modules.  If unset, generally defaults to libc,
 	// libm, and libdl.  Set to [] to prevent linking against the defaults.
-	System_shared_libs []string
+	System_shared_libs []string `android:"arch_variant"`
 
 	// allow the module to contain undefined symbols.  By default,
 	// modules cannot contain undefined symbols that are not satisified by their immediate
@@ -237,35 +237,34 @@
 			deps.LateStaticLibs = append(deps.LateStaticLibs, "libgcc")
 		}
 
-		if !ctx.static() {
-			systemSharedLibs := linker.Properties.System_shared_libs
-			if systemSharedLibs == nil {
-				systemSharedLibs = []string{"libc", "libm", "libdl"}
-			}
-
-			if inList("libdl", deps.SharedLibs) {
-				// If system_shared_libs has libc but not libdl, make sure shared_libs does not
-				// have libdl to avoid loading libdl before libc.
-				if inList("libc", systemSharedLibs) {
-					if !inList("libdl", systemSharedLibs) {
-						ctx.PropertyErrorf("shared_libs",
-							"libdl must be in system_shared_libs, not shared_libs")
-					}
-					_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
-				}
-			}
-
-			// If libc and libdl are both in system_shared_libs make sure libd comes after libc
-			// to avoid loading libdl before libc.
-			if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
-				indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
-				ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
-			}
-
-			deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
-		} else if ctx.useSdk() || ctx.useVndk() {
-			deps.LateSharedLibs = append(deps.LateSharedLibs, "libc", "libm", "libdl")
+		var systemSharedLibs []string
+		if !ctx.useSdk() && !ctx.useVndk() {
+			systemSharedLibs = linker.Properties.System_shared_libs
 		}
+		if systemSharedLibs == nil {
+			systemSharedLibs = []string{"libc", "libm", "libdl"}
+		}
+
+		if inList("libdl", deps.SharedLibs) {
+			// If system_shared_libs has libc but not libdl, make sure shared_libs does not
+			// have libdl to avoid loading libdl before libc.
+			if inList("libc", systemSharedLibs) {
+				if !inList("libdl", systemSharedLibs) {
+					ctx.PropertyErrorf("shared_libs",
+						"libdl must be in system_shared_libs, not shared_libs")
+				}
+				_, deps.SharedLibs = removeFromList("libdl", deps.SharedLibs)
+			}
+		}
+
+		// If libc and libdl are both in system_shared_libs make sure libdl comes after libc
+		// to avoid loading libdl before libc.
+		if inList("libdl", systemSharedLibs) && inList("libc", systemSharedLibs) &&
+			indexList("libdl", systemSharedLibs) < indexList("libc", systemSharedLibs) {
+			ctx.PropertyErrorf("system_shared_libs", "libdl must be after libc")
+		}
+
+		deps.LateSharedLibs = append(deps.LateSharedLibs, systemSharedLibs...)
 	}
 
 	if ctx.Windows() {
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index 8e71a97..c21da44 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -19,6 +19,7 @@
 	"flag"
 	"fmt"
 	"hash/crc32"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
@@ -66,6 +67,7 @@
 	manifest         = flag.String("m", "", "manifest file to insert in jar")
 	pyMain           = flag.String("pm", "", "__main__.py file to insert in par")
 	entrypoint       = flag.String("e", "", "par entrypoint file to insert in par")
+	prefix           = flag.String("prefix", "", "A file to prefix to the zip file")
 	ignoreDuplicates = flag.Bool("ignore-duplicates", false, "take each entry from the first zip it exists in and don't warn")
 )
 
@@ -77,7 +79,7 @@
 
 func main() {
 	flag.Usage = func() {
-		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [-e entrypoint] [-pm __main__.py] output [inputs...]")
+		fmt.Fprintln(os.Stderr, "usage: merge_zips [-jpsD] [-m manifest] [--prefix script] [-e entrypoint] [-pm __main__.py] output [inputs...]")
 		flag.PrintDefaults()
 	}
 
@@ -99,6 +101,19 @@
 		log.Fatal(err)
 	}
 	defer output.Close()
+
+	var offset int64
+	if *prefix != "" {
+		prefixFile, err := os.Open(*prefix)
+		if err != nil {
+			log.Fatal(err)
+		}
+		offset, err = io.Copy(output, prefixFile)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+
 	writer := zip.NewWriter(output)
 	defer func() {
 		err := writer.Close()
@@ -106,6 +121,7 @@
 			log.Fatal(err)
 		}
 	}()
+	writer.SetOffset(offset)
 
 	// make readers
 	readers := []namedZipReader{}
diff --git a/python/builder.go b/python/builder.go
index 11a792a..7ecd4b5 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -45,20 +45,22 @@
 	hostPar = pctx.AndroidStaticRule("hostPar",
 		blueprint.RuleParams{
 			Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
-				`$mergeParCmd -p -pm $stub $mergedZip $srcsZips && echo '#!/usr/bin/env python' | cat - $mergedZip > $out && ` +
-				`chmod +x $out && (rm -f $stub; rm -f $mergedZip)`,
+				`echo "#!/usr/bin/env python" >${out}.prefix &&` +
+				`$mergeParCmd -p --prefix ${out}.prefix -pm $stub $out $srcsZips && ` +
+				`chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
 			CommandDeps: []string{"$mergeParCmd"},
 		},
-		"interp", "main", "template", "stub", "mergedZip", "srcsZips")
+		"interp", "main", "template", "stub", "srcsZips")
 
 	embeddedPar = pctx.AndroidStaticRule("embeddedPar",
 		blueprint.RuleParams{
-			Command: `echo '$main' > $entryPoint &&` +
-				`$mergeParCmd -p -e $entryPoint $mergedZip $srcsZips && cat $launcher | cat - $mergedZip > $out && ` +
-				`chmod +x $out && (rm -f $entryPoint; rm -f $mergedZip)`,
+			// `echo -n` to trim the newline, since the python code just wants the name
+			Command: `echo -n '$main' > $entryPoint &&` +
+				`$mergeParCmd -p --prefix $launcher -e $entryPoint $out $srcsZips && ` +
+				`chmod +x $out && (rm -f $entryPoint)`,
 			CommandDeps: []string{"$mergeParCmd"},
 		},
-		"main", "entryPoint", "mergedZip", "srcsZips", "launcher")
+		"main", "entryPoint", "srcsZips", "launcher")
 )
 
 func init() {
@@ -73,9 +75,6 @@
 	launcherPath android.OptionalPath, interpreter, main, binName string,
 	srcsZips android.Paths) android.Path {
 
-	// .intermediate output path for merged zip file.
-	mergedZip := android.PathForModuleOut(ctx, binName+".mergedzip")
-
 	// .intermediate output path for bin executable.
 	binFile := android.PathForModuleOut(ctx, binName)
 
@@ -96,12 +95,11 @@
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"interp":    strings.Replace(interpreter, "/", `\/`, -1),
-				"main":      strings.Replace(main, "/", `\/`, -1),
-				"template":  template.String(),
-				"stub":      stub,
-				"mergedZip": mergedZip.String(),
-				"srcsZips":  strings.Join(srcsZips.Strings(), " "),
+				"interp":   strings.Replace(interpreter, "/", `\/`, -1),
+				"main":     strings.Replace(main, "/", `\/`, -1),
+				"template": template.String(),
+				"stub":     stub,
+				"srcsZips": strings.Join(srcsZips.Strings(), " "),
 			},
 		})
 	} else if launcherPath.Valid() {
@@ -117,9 +115,8 @@
 			Output:      binFile,
 			Implicits:   implicits,
 			Args: map[string]string{
-				"main":       main,
+				"main":       strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
 				"entryPoint": entryPoint,
-				"mergedZip":  mergedZip.String(),
 				"srcsZips":   strings.Join(srcsZips.Strings(), " "),
 				"launcher":   launcherPath.String(),
 			},