Merge "Add BoardKernelModuleInterfaceVersions."
diff --git a/android/Android.bp b/android/Android.bp
index 50faa44..ff14a70 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@
         "apex.go",
         "api_levels.go",
         "arch.go",
+        "bazel_overlay.go",
         "config.go",
         "csuite_config.go",
         "defaults.go",
diff --git a/android/apex.go b/android/apex.go
index cd84f8a..8c06b63 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -296,7 +296,10 @@
 		for i, mod := range modules {
 			platformVariation := i == 0
 			if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
-				mod.SkipInstall()
+				// Do not install the module for platform, but still allow it to output
+				// uninstallable AndroidMk entries in certain cases when they have
+				// side effects.
+				mod.MakeUninstallable()
 			}
 			if !platformVariation {
 				mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1]
diff --git a/android/bazel_overlay.go b/android/bazel_overlay.go
new file mode 100644
index 0000000..a034282
--- /dev/null
+++ b/android/bazel_overlay.go
@@ -0,0 +1,76 @@
+// 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 android
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/google/blueprint"
+)
+
+// The Bazel Overlay singleton is responsible for generating the Ninja actions
+// for calling the soong_build primary builder in the main build.ninja file.
+func init() {
+	RegisterSingletonType("bazel_overlay", BazelOverlaySingleton)
+}
+
+func BazelOverlaySingleton() Singleton {
+	return &bazelOverlaySingleton{}
+}
+
+type bazelOverlaySingleton struct{}
+
+func (c *bazelOverlaySingleton) GenerateBuildActions(ctx SingletonContext) {
+	// Create a build and rule statement, using the Bazel overlay's WORKSPACE
+	// file as the output file marker.
+	var deps Paths
+	moduleListFilePath := pathForBuildToolDep(ctx, ctx.Config().moduleListFile)
+	deps = append(deps, moduleListFilePath)
+	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
+	bazelOverlayDirectory := PathForOutput(ctx, "bazel_overlay")
+	bazelOverlayWorkspaceFile := bazelOverlayDirectory.Join(ctx, "WORKSPACE")
+	primaryBuilder := primaryBuilderPath(ctx)
+	bazelOverlay := ctx.Rule(pctx, "bazelOverlay",
+		blueprint.RuleParams{
+			Command: fmt.Sprintf(
+				"rm -rf ${outDir}/* && %s --bazel_overlay_dir ${outDir} %s && echo WORKSPACE: `cat %s` > ${outDir}/.overlay-depfile.d",
+				primaryBuilder.String(),
+				strings.Join(os.Args[1:], " "),
+				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+			),
+			CommandDeps: []string{primaryBuilder.String()},
+			Description: fmt.Sprintf(
+				"Creating the Bazel overlay workspace with %s at $outDir",
+				primaryBuilder.Base()),
+			Deps:    blueprint.DepsGCC,
+			Depfile: "${outDir}/.overlay-depfile.d",
+		},
+		"outDir")
+
+	ctx.Build(pctx, BuildParams{
+		Rule:   bazelOverlay,
+		Output: bazelOverlayWorkspaceFile,
+		Inputs: deps,
+		Args: map[string]string{
+			"outDir": bazelOverlayDirectory.String(),
+		},
+	})
+
+	// Add a phony target for building the bazel overlay
+	ctx.Phony("bazel_overlay", bazelOverlayWorkspaceFile)
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index ec522fc..68311e3 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,9 +15,7 @@
 package android
 
 import (
-	"io"
 	"strings"
-	"text/template"
 )
 
 func init() {
@@ -71,23 +69,8 @@
 	return append(Paths{}, fg.srcs...)
 }
 
-var androidMkTemplate = template.Must(template.New("filegroup").Parse(`
-ifdef {{.makeVar}}
-  $(error variable {{.makeVar}} set by soong module is already set in make)
-endif
-{{.makeVar}} := {{.value}}
-.KATI_READONLY := {{.makeVar}}
-`))
-
-func (fg *fileGroup) AndroidMk() AndroidMkData {
-	return AndroidMkData{
-		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
-			if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
-				androidMkTemplate.Execute(w, map[string]string{
-					"makeVar": makeVar,
-					"value":   strings.Join(fg.srcs.Strings(), " "),
-				})
-			}
-		},
+func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) {
+	if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
+		ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " "))
 	}
 }
diff --git a/android/makevars.go b/android/makevars.go
index ff7c8e4..86f4b42 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,6 +17,7 @@
 import (
 	"bytes"
 	"fmt"
+	"sort"
 	"strconv"
 	"strings"
 
@@ -34,43 +35,16 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Interface for other packages to use to declare make variables
-type MakeVarsContext interface {
+
+// BaseMakeVarsContext contains the common functions for other packages to use
+// to declare make variables
+type BaseMakeVarsContext interface {
 	Config() Config
 	DeviceConfig() DeviceConfig
 	AddNinjaFileDeps(deps ...string)
 
-	ModuleName(module blueprint.Module) string
-	ModuleDir(module blueprint.Module) string
-	ModuleSubDir(module blueprint.Module) string
-	ModuleType(module blueprint.Module) string
-	BlueprintFile(module blueprint.Module) string
-
-	ModuleErrorf(module blueprint.Module, format string, args ...interface{})
-	Errorf(format string, args ...interface{})
 	Failed() bool
 
-	VisitAllModules(visit func(Module))
-	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
-
-	// Verify the make variable matches the Soong version, fail the build
-	// if it does not. If the make variable is empty, just set it.
-	Strict(name, ninjaStr string)
-	// Check to see if the make variable matches the Soong version, warn if
-	// it does not. If the make variable is empty, just set it.
-	Check(name, ninjaStr string)
-
-	// These are equivalent to the above, but sort the make and soong
-	// variables before comparing them. They also show the unique entries
-	// in each list when displaying the difference, instead of the entire
-	// string.
-	StrictSorted(name, ninjaStr string)
-	CheckSorted(name, ninjaStr string)
-
-	// Evaluates a ninja string and returns the result. Used if more
-	// complicated modification needs to happen before giving it to Make.
-	Eval(ninjaStr string) (string, error)
-
 	// These are equivalent to Strict and Check, but do not attempt to
 	// evaluate the values before writing them to the Makefile. They can
 	// be used when all ninja variables have already been evaluated through
@@ -108,6 +82,48 @@
 	DistForGoalsWithFilename(goals []string, path Path, filename string)
 }
 
+// MakeVarsContext contains the set of functions available for MakeVarsProvider
+// and SingletonMakeVarsProvider implementations.
+type MakeVarsContext interface {
+	BaseMakeVarsContext
+
+	ModuleName(module blueprint.Module) string
+	ModuleDir(module blueprint.Module) string
+	ModuleSubDir(module blueprint.Module) string
+	ModuleType(module blueprint.Module) string
+	BlueprintFile(module blueprint.Module) string
+
+	ModuleErrorf(module blueprint.Module, format string, args ...interface{})
+	Errorf(format string, args ...interface{})
+
+	VisitAllModules(visit func(Module))
+	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
+
+	// Verify the make variable matches the Soong version, fail the build
+	// if it does not. If the make variable is empty, just set it.
+	Strict(name, ninjaStr string)
+	// Check to see if the make variable matches the Soong version, warn if
+	// it does not. If the make variable is empty, just set it.
+	Check(name, ninjaStr string)
+
+	// These are equivalent to the above, but sort the make and soong
+	// variables before comparing them. They also show the unique entries
+	// in each list when displaying the difference, instead of the entire
+	// string.
+	StrictSorted(name, ninjaStr string)
+	CheckSorted(name, ninjaStr string)
+
+	// Evaluates a ninja string and returns the result. Used if more
+	// complicated modification needs to happen before giving it to Make.
+	Eval(ninjaStr string) (string, error)
+}
+
+// MakeVarsModuleContext contains the set of functions available for modules
+// implementing the ModuleMakeVarsProvider interface.
+type MakeVarsModuleContext interface {
+	BaseMakeVarsContext
+}
+
 var _ PathContext = MakeVarsContext(nil)
 
 type MakeVarsProvider func(ctx MakeVarsContext)
@@ -135,6 +151,14 @@
 	return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
 }
 
+// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
+type ModuleMakeVarsProvider interface {
+	Module
+
+	// MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
+	MakeVars(ctx MakeVarsModuleContext)
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 func makeVarsSingletonFunc() Singleton {
@@ -209,10 +233,45 @@
 		dists = append(dists, mctx.dists...)
 	}
 
+	ctx.VisitAllModules(func(m Module) {
+		if provider, ok := m.(ModuleMakeVarsProvider); ok {
+			mctx := &makeVarsContext{
+				SingletonContext: ctx,
+			}
+
+			provider.MakeVars(mctx)
+
+			vars = append(vars, mctx.vars...)
+			phonies = append(phonies, mctx.phonies...)
+			dists = append(dists, mctx.dists...)
+		}
+	})
+
 	if ctx.Failed() {
 		return
 	}
 
+	sort.Slice(vars, func(i, j int) bool {
+		return vars[i].name < vars[j].name
+	})
+	sort.Slice(phonies, func(i, j int) bool {
+		return phonies[i].name < phonies[j].name
+	})
+	lessArr := func(a, b []string) bool {
+		if len(a) == len(b) {
+			for i := range a {
+				if a[i] < b[i] {
+					return true
+				}
+			}
+			return false
+		}
+		return len(a) < len(b)
+	}
+	sort.Slice(dists, func(i, j int) bool {
+		return lessArr(dists[i].goals, dists[j].goals) || lessArr(dists[i].paths, dists[j].paths)
+	})
+
 	outBytes := s.writeVars(vars)
 
 	if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
diff --git a/android/module.go b/android/module.go
index 8605954..2dc2ac7 100644
--- a/android/module.go
+++ b/android/module.go
@@ -256,6 +256,7 @@
 	InstallForceOS() *OsType
 	SkipInstall()
 	IsSkipInstall() bool
+	MakeUninstallable()
 	ExportedToMake() bool
 	InitRc() Paths
 	VintfFragments() Paths
@@ -1046,6 +1047,15 @@
 	return m.commonProperties.SkipInstall == true
 }
 
+// Similar to SkipInstall, but if the AndroidMk entry would set
+// LOCAL_UNINSTALLABLE_MODULE then this variant may still output that entry
+// rather than leaving it out altogether. That happens in cases where it would
+// have other side effects, in particular when it adds a NOTICE file target,
+// which other install targets might depend on.
+func (m *ModuleBase) MakeUninstallable() {
+	m.SkipInstall()
+}
+
 func (m *ModuleBase) ExportedToMake() bool {
 	return m.commonProperties.NamespaceExportedToMake
 }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index e91b40a..7c747c8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -286,10 +286,8 @@
 			entries.SubName = "." + library.stubsVersion()
 		}
 		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
-			// Note library.skipInstall() has a special case to get here for static
-			// libraries that otherwise would have skipped installation and hence not
-			// have executed AndroidMkEntries at all. The reason is to ensure they get
-			// a NOTICE file make target which other libraries might depend on.
+			// library.makeUninstallable() depends on this to bypass SkipInstall() for
+			// static libraries.
 			entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
 			if library.buildStubs() {
 				entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
@@ -518,10 +516,14 @@
 		entries.Class = "HEADER_LIBRARIES"
 	}
 
+	entries.SubName = ""
+
+	if c.sanitizerProperties.CfiEnabled {
+		entries.SubName += ".cfi"
+	}
+
 	if c.androidMkVendorSuffix {
-		entries.SubName = vendorSuffix
-	} else {
-		entries.SubName = ""
+		entries.SubName += vendorSuffix
 	}
 
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
diff --git a/cc/cc.go b/cc/cc.go
index 4b36218..6f1a06d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -418,7 +418,7 @@
 	inSanitizerDir() bool
 	hostToolPath() android.OptionalPath
 	relativeInstallPath() string
-	skipInstall(mod *Module)
+	makeUninstallable(mod *Module)
 }
 
 type xref interface {
@@ -2730,12 +2730,12 @@
 	return c.InRecovery()
 }
 
-func (c *Module) SkipInstall() {
+func (c *Module) MakeUninstallable() {
 	if c.installer == nil {
-		c.ModuleBase.SkipInstall()
+		c.ModuleBase.MakeUninstallable()
 		return
 	}
-	c.installer.skipInstall(c)
+	c.installer.makeUninstallable(c)
 }
 
 func (c *Module) HostToolPath() android.OptionalPath {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 38a5c2d..77b5c52 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1013,17 +1013,25 @@
 			filepath.Join(sharedDir, "libvendor_available.so.json"))
 
 		// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+		// Also cfi variants are captured, except for prebuilts like toolchain_library
 		staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
+		staticCfiVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static_cfi", archType, archVariant)
 		staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
 		checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
 		checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+		checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
 		checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+		checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
 		checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+		checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
 		jsonFiles = append(jsonFiles,
 			filepath.Join(staticDir, "libb.a.json"),
 			filepath.Join(staticDir, "libvndk.a.json"),
+			filepath.Join(staticDir, "libvndk.cfi.a.json"),
 			filepath.Join(staticDir, "libvendor.a.json"),
-			filepath.Join(staticDir, "libvendor_available.a.json"))
+			filepath.Join(staticDir, "libvendor.cfi.a.json"),
+			filepath.Join(staticDir, "libvendor_available.a.json"),
+			filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
 
 		// For binary executables, all vendor:true and vendor_available modules are captured.
 		if archType == "arm64" {
@@ -1055,6 +1063,39 @@
 	}
 }
 
+func TestVendorSnapshotSanitizer(t *testing.T) {
+	bp := `
+	vendor_snapshot_static {
+		name: "libsnapshot",
+		vendor: true,
+		target_arch: "arm64",
+		version: "BOARD",
+		arch: {
+			arm64: {
+				src: "libsnapshot.a",
+				cfi: {
+					src: "libsnapshot.cfi.a",
+				}
+			},
+		},
+	}
+`
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	ctx := testCcWithConfig(t, config)
+
+	// Check non-cfi and cfi variant.
+	staticVariant := "android_vendor.BOARD_arm64_armv8-a_static"
+	staticCfiVariant := "android_vendor.BOARD_arm64_armv8-a_static_cfi"
+
+	staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticVariant).Module().(*Module)
+	assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
+
+	staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticCfiVariant).Module().(*Module)
+	assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
+}
+
 func TestDoubleLoadableDepError(t *testing.T) {
 	// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
 	testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
diff --git a/cc/installer.go b/cc/installer.go
index 0b4a68c..e551c63 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -107,6 +107,6 @@
 	return String(installer.Properties.Relative_install_path)
 }
 
-func (installer *baseInstaller) skipInstall(mod *Module) {
-	mod.ModuleBase.SkipInstall()
+func (installer *baseInstaller) makeUninstallable(mod *Module) {
+	mod.ModuleBase.MakeUninstallable()
 }
diff --git a/cc/library.go b/cc/library.go
index 2a329ac..441c7b8 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1365,16 +1365,15 @@
 	return android.CheckAvailableForApex(what, list)
 }
 
-func (library *libraryDecorator) skipInstall(mod *Module) {
+func (library *libraryDecorator) makeUninstallable(mod *Module) {
 	if library.static() && library.buildStatic() && !library.buildStubs() {
-		// If we're asked to skip installation of a static library (in particular
-		// when it's not //apex_available:platform) we still want an AndroidMk entry
-		// for it to ensure we get the relevant NOTICE file targets (cf.
-		// notice_files.mk) that other libraries might depend on. AndroidMkEntries
-		// always sets LOCAL_UNINSTALLABLE_MODULE for these entries.
+		// If we're asked to make a static library uninstallable we don't do
+		// anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
+		// for these entries. This is done to still get the make targets for NOTICE
+		// files from notice_files.mk, which other libraries might depend on.
 		return
 	}
-	mod.ModuleBase.SkipInstall()
+	mod.ModuleBase.MakeUninstallable()
 }
 
 var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 653b43e..baf43ce 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -199,10 +199,6 @@
 	p.properties.Srcs = nil
 }
 
-func (p *prebuiltLibraryLinker) skipInstall(mod *Module) {
-	mod.ModuleBase.SkipInstall()
-}
-
 func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module, library := NewLibrary(hod)
 	module.compiler = nil
@@ -211,7 +207,6 @@
 		libraryDecorator: library,
 	}
 	module.linker = prebuilt
-	module.installer = prebuilt
 
 	module.AddProperties(&prebuilt.properties)
 
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 3433dd3..6db6348 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -321,14 +321,14 @@
 
 	// Is CFI actually enabled?
 	if !ctx.Config().EnableCFI() {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
+		s.Cfi = boolPtr(false)
+		s.Diag.Cfi = boolPtr(false)
 	}
 
 	// Also disable CFI for arm32 until b/35157333 is fixed.
 	if ctx.Arch().ArchType == android.Arm {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
+		s.Cfi = boolPtr(false)
+		s.Diag.Cfi = boolPtr(false)
 	}
 
 	// HWASan requires AArch64 hardware feature (top-byte-ignore).
@@ -343,14 +343,14 @@
 
 	// Also disable CFI if ASAN is enabled.
 	if Bool(s.Address) || Bool(s.Hwaddress) {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
+		s.Cfi = boolPtr(false)
+		s.Diag.Cfi = boolPtr(false)
 	}
 
 	// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
 	if !ctx.Os().Linux() {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
+		s.Cfi = boolPtr(false)
+		s.Diag.Cfi = boolPtr(false)
 		s.Misc_undefined = nil
 		s.Undefined = nil
 		s.All_undefined = nil
@@ -359,14 +359,15 @@
 
 	// Also disable CFI for VNDK variants of components
 	if ctx.isVndk() && ctx.useVndk() {
-		s.Cfi = nil
-		s.Diag.Cfi = nil
-	}
-
-	// Also disable CFI if building against snapshot.
-	vndkVersion := ctx.DeviceConfig().VndkVersion()
-	if ctx.useVndk() && vndkVersion != "current" && vndkVersion != "" {
-		s.Cfi = nil
+		if ctx.static() {
+			// Cfi variant for static vndk should be captured as vendor snapshot,
+			// so don't strictly disable Cfi.
+			s.Cfi = nil
+			s.Diag.Cfi = nil
+		} else {
+			s.Cfi = boolPtr(false)
+			s.Diag.Cfi = boolPtr(false)
+		}
 	}
 
 	// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
@@ -411,7 +412,7 @@
 	// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
 	// mutually incompatible.
 	if Bool(s.Fuzzer) {
-		s.Cfi = nil
+		s.Cfi = boolPtr(false)
 	}
 }
 
@@ -741,27 +742,64 @@
 	}
 }
 
+// Determines if the current module is a static library going to be captured
+// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
+// except for ones which explicitly disable cfi.
+func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
+	if isVendorProprietaryPath(mctx.ModuleDir()) {
+		return false
+	}
+
+	c := mctx.Module().(*Module)
+
+	if !c.inVendor() {
+		return false
+	}
+
+	if !c.static() {
+		return false
+	}
+
+	if c.Prebuilt() != nil {
+		return false
+	}
+
+	return c.sanitize != nil &&
+		!Bool(c.sanitize.Properties.Sanitize.Never) &&
+		!c.sanitize.isSanitizerExplicitlyDisabled(cfi)
+}
+
 // Propagate sanitizer requirements down from binaries
 func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
 	return func(mctx android.TopDownMutatorContext) {
-		if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
-			mctx.WalkDeps(func(child, parent android.Module) bool {
-				if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
-					return false
-				}
-				if d, ok := child.(*Module); ok && d.sanitize != nil &&
-					!Bool(d.sanitize.Properties.Sanitize.Never) &&
-					!d.sanitize.isSanitizerExplicitlyDisabled(t) {
-					if t == cfi || t == hwasan || t == scs {
-						if d.static() {
+		if c, ok := mctx.Module().(*Module); ok {
+			enabled := c.sanitize.isSanitizerEnabled(t)
+			if t == cfi && needsCfiForVendorSnapshot(mctx) {
+				// We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
+				// determine defaultVariation in sanitizerMutator below.
+				// Instead, just mark SanitizeDep to forcefully create cfi variant.
+				enabled = true
+				c.sanitize.Properties.SanitizeDep = true
+			}
+			if enabled {
+				mctx.WalkDeps(func(child, parent android.Module) bool {
+					if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
+						return false
+					}
+					if d, ok := child.(*Module); ok && d.sanitize != nil &&
+						!Bool(d.sanitize.Properties.Sanitize.Never) &&
+						!d.sanitize.isSanitizerExplicitlyDisabled(t) {
+						if t == cfi || t == hwasan || t == scs {
+							if d.static() {
+								d.sanitize.Properties.SanitizeDep = true
+							}
+						} else {
 							d.sanitize.Properties.SanitizeDep = true
 						}
-					} else {
-						d.sanitize.Properties.SanitizeDep = true
 					}
-				}
-				return true
-			})
+					return true
+				})
+			}
 		} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
 			// If an APEX module includes a lib which is enabled for a sanitizer T, then
 			// the APEX module is also enabled for the same sanitizer type.
@@ -1095,6 +1133,24 @@
 			// APEX modules fall here
 			sanitizeable.AddSanitizerDependencies(mctx, t.name())
 			mctx.CreateVariations(t.variationName())
+		} else if c, ok := mctx.Module().(*Module); ok {
+			// Check if it's a snapshot module supporting sanitizer
+			if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
+				// Set default variation as above.
+				defaultVariation := t.variationName()
+				mctx.SetDefaultDependencyVariation(&defaultVariation)
+				modules := mctx.CreateVariations("", t.variationName())
+				modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
+				modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
+
+				// Export the static lib name to make
+				if c.static() && c.ExportedToMake() {
+					if t == cfi {
+						// use BaseModuleName which is the name for Make.
+						cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
+					}
+				}
+			}
 		}
 	}
 }
diff --git a/cc/testing.go b/cc/testing.go
index c2353d8..4113fd2 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -567,6 +567,7 @@
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
 	ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
+	ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	android.RegisterPrebuiltMutators(ctx)
 	RegisterRequiredBuildComponentsForTest(ctx)
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 6df940c..e17a6d0 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -80,23 +80,75 @@
 	}).(*snapshotMap)
 }
 
-type vendorSnapshotLibraryProperties struct {
+type vendorSnapshotBaseProperties struct {
 	// snapshot version.
 	Version string
 
 	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
 	Target_arch string
+}
 
+// vendorSnapshotModuleBase provides common basic functions for all snapshot modules.
+type vendorSnapshotModuleBase struct {
+	baseProperties vendorSnapshotBaseProperties
+	moduleSuffix   string
+}
+
+func (p *vendorSnapshotModuleBase) Name(name string) string {
+	return name + p.NameSuffix()
+}
+
+func (p *vendorSnapshotModuleBase) NameSuffix() string {
+	versionSuffix := p.version()
+	if p.arch() != "" {
+		versionSuffix += "." + p.arch()
+	}
+
+	return p.moduleSuffix + versionSuffix
+}
+
+func (p *vendorSnapshotModuleBase) version() string {
+	return p.baseProperties.Version
+}
+
+func (p *vendorSnapshotModuleBase) arch() string {
+	return p.baseProperties.Target_arch
+}
+
+func (p *vendorSnapshotModuleBase) isSnapshotPrebuilt() bool {
+	return true
+}
+
+// Call this after creating a snapshot module with module suffix
+// such as vendorSnapshotSharedSuffix
+func (p *vendorSnapshotModuleBase) init(m *Module, suffix string) {
+	p.moduleSuffix = suffix
+	m.AddProperties(&p.baseProperties)
+	android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+		vendorSnapshotLoadHook(ctx, p)
+	})
+}
+
+func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *vendorSnapshotModuleBase) {
+	if p.version() != ctx.DeviceConfig().VndkVersion() {
+		ctx.Module().Disable()
+		return
+	}
+}
+
+type vendorSnapshotLibraryProperties struct {
 	// Prebuilt file for each arch.
 	Src *string `android:"arch_variant"`
 
+	// list of directories that will be added to the include path (using -I).
+	Export_include_dirs []string `android:"arch_variant"`
+
+	// list of directories that will be added to the system path (using -isystem).
+	Export_system_include_dirs []string `android:"arch_variant"`
+
 	// list of flags that will be used for any module that links against this module.
 	Export_flags []string `android:"arch_variant"`
 
-	// Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
-	// etc).
-	Check_elf_files *bool
-
 	// Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
 	Sanitize_ubsan_dep *bool `android:"arch_variant"`
 
@@ -104,42 +156,24 @@
 	Sanitize_minimal_dep *bool `android:"arch_variant"`
 }
 
+type snapshotSanitizer interface {
+	isSanitizerEnabled(t sanitizerType) bool
+	setSanitizerVariation(t sanitizerType, enabled bool)
+}
+
 type vendorSnapshotLibraryDecorator struct {
+	vendorSnapshotModuleBase
 	*libraryDecorator
-	properties            vendorSnapshotLibraryProperties
+	properties          vendorSnapshotLibraryProperties
+	sanitizerProperties struct {
+		CfiEnabled bool `blueprint:"mutated"`
+
+		// Library flags for cfi variant.
+		Cfi vendorSnapshotLibraryProperties `android:"arch_variant"`
+	}
 	androidMkVendorSuffix bool
 }
 
-func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
-	return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
-	versionSuffix := p.version()
-	if p.arch() != "" {
-		versionSuffix += "." + p.arch()
-	}
-
-	var linkageSuffix string
-	if p.buildShared() {
-		linkageSuffix = vendorSnapshotSharedSuffix
-	} else if p.buildStatic() {
-		linkageSuffix = vendorSnapshotStaticSuffix
-	} else {
-		linkageSuffix = vendorSnapshotHeaderSuffix
-	}
-
-	return linkageSuffix + versionSuffix
-}
-
-func (p *vendorSnapshotLibraryDecorator) version() string {
-	return p.properties.Version
-}
-
-func (p *vendorSnapshotLibraryDecorator) arch() string {
-	return p.properties.Target_arch
-}
-
 func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
 	p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
 	return p.libraryDecorator.linkerFlags(ctx, flags)
@@ -165,11 +199,16 @@
 		return p.libraryDecorator.link(ctx, flags, deps, objs)
 	}
 
+	if p.sanitizerProperties.CfiEnabled {
+		p.properties = p.sanitizerProperties.Cfi
+	}
+
 	if !p.matchesWithDevice(ctx.DeviceConfig()) {
 		return nil
 	}
 
-	p.libraryDecorator.exportIncludes(ctx)
+	p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...)
+	p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...)
 	p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
 
 	in := android.PathForModuleSrc(ctx, *p.properties.Src)
@@ -189,32 +228,38 @@
 	return in
 }
 
-func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
-	return false
-}
-
-func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
-	return true
-}
-
 func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
 	if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
 		p.baseInstaller.install(ctx, file)
 	}
 }
 
-type vendorSnapshotInterface interface {
-	version() string
+func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
+	return false
 }
 
-func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
-	if p.version() != ctx.DeviceConfig().VndkVersion() {
-		ctx.Module().Disable()
+func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
+	switch t {
+	case cfi:
+		return p.sanitizerProperties.Cfi.Src != nil
+	default:
+		return false
+	}
+}
+
+func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
+	if !enabled {
+		return
+	}
+	switch t {
+	case cfi:
+		p.sanitizerProperties.CfiEnabled = true
+	default:
 		return
 	}
 }
 
-func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
+func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecorator) {
 	module, library := NewLibrary(android.DeviceSupported)
 
 	module.stl = nil
@@ -237,77 +282,47 @@
 	module.linker = prebuilt
 	module.installer = prebuilt
 
+	prebuilt.init(module, suffix)
 	module.AddProperties(
 		&prebuilt.properties,
+		&prebuilt.sanitizerProperties,
 	)
 
 	return module, prebuilt
 }
 
 func VendorSnapshotSharedFactory() android.Module {
-	module, prebuilt := vendorSnapshotLibrary()
+	module, prebuilt := vendorSnapshotLibrary(vendorSnapshotSharedSuffix)
 	prebuilt.libraryDecorator.BuildOnlyShared()
-	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		vendorSnapshotLoadHook(ctx, prebuilt)
-	})
 	return module.Init()
 }
 
 func VendorSnapshotStaticFactory() android.Module {
-	module, prebuilt := vendorSnapshotLibrary()
+	module, prebuilt := vendorSnapshotLibrary(vendorSnapshotStaticSuffix)
 	prebuilt.libraryDecorator.BuildOnlyStatic()
-	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		vendorSnapshotLoadHook(ctx, prebuilt)
-	})
 	return module.Init()
 }
 
 func VendorSnapshotHeaderFactory() android.Module {
-	module, prebuilt := vendorSnapshotLibrary()
+	module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix)
 	prebuilt.libraryDecorator.HeaderOnly()
-	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		vendorSnapshotLoadHook(ctx, prebuilt)
-	})
 	return module.Init()
 }
 
+var _ snapshotSanitizer = (*vendorSnapshotLibraryDecorator)(nil)
+
 type vendorSnapshotBinaryProperties struct {
-	// snapshot version.
-	Version string
-
-	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
-	Target_arch string
-
 	// Prebuilt file for each arch.
 	Src *string `android:"arch_variant"`
 }
 
 type vendorSnapshotBinaryDecorator struct {
+	vendorSnapshotModuleBase
 	*binaryDecorator
 	properties            vendorSnapshotBinaryProperties
 	androidMkVendorSuffix bool
 }
 
-func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
-	return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
-	versionSuffix := p.version()
-	if p.arch() != "" {
-		versionSuffix += "." + p.arch()
-	}
-	return vendorSnapshotBinarySuffix + versionSuffix
-}
-
-func (p *vendorSnapshotBinaryDecorator) version() string {
-	return p.properties.Version
-}
-
-func (p *vendorSnapshotBinaryDecorator) arch() string {
-	return p.properties.Target_arch
-}
-
 func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
 	if config.DeviceArch() != p.arch() {
 		return false
@@ -349,8 +364,8 @@
 	return outputFile
 }
 
-func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
-	return true
+func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool {
+	return false
 }
 
 func VendorSnapshotBinaryFactory() android.Module {
@@ -372,51 +387,23 @@
 	module.stl = nil
 	module.linker = prebuilt
 
-	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		vendorSnapshotLoadHook(ctx, prebuilt)
-	})
-
+	prebuilt.init(module, vendorSnapshotBinarySuffix)
 	module.AddProperties(&prebuilt.properties)
 	return module.Init()
 }
 
 type vendorSnapshotObjectProperties struct {
-	// snapshot version.
-	Version string
-
-	// Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
-	Target_arch string
-
 	// Prebuilt file for each arch.
 	Src *string `android:"arch_variant"`
 }
 
 type vendorSnapshotObjectLinker struct {
+	vendorSnapshotModuleBase
 	objectLinker
 	properties            vendorSnapshotObjectProperties
 	androidMkVendorSuffix bool
 }
 
-func (p *vendorSnapshotObjectLinker) Name(name string) string {
-	return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotObjectLinker) NameSuffix() string {
-	versionSuffix := p.version()
-	if p.arch() != "" {
-		versionSuffix += "." + p.arch()
-	}
-	return vendorSnapshotObjectSuffix + versionSuffix
-}
-
-func (p *vendorSnapshotObjectLinker) version() string {
-	return p.properties.Version
-}
-
-func (p *vendorSnapshotObjectLinker) arch() string {
-	return p.properties.Target_arch
-}
-
 func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
 	if config.DeviceArch() != p.arch() {
 		return false
@@ -443,10 +430,6 @@
 	return false
 }
 
-func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
-	return true
-}
-
 func VendorSnapshotObjectFactory() android.Module {
 	module := newObject()
 
@@ -457,10 +440,7 @@
 	}
 	module.linker = prebuilt
 
-	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
-		vendorSnapshotLoadHook(ctx, prebuilt)
-	})
-
+	prebuilt.init(module, vendorSnapshotObjectSuffix)
 	module.AddProperties(&prebuilt.properties)
 	return module.Init()
 }
@@ -568,13 +548,17 @@
 	if l, ok := m.linker.(snapshotLibraryInterface); ok {
 		// TODO(b/65377115): add full support for sanitizer
 		if m.sanitize != nil {
-			// cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
+			// scs and hwasan export both sanitized and unsanitized variants for static and header
 			// Always use unsanitized variants of them.
-			for _, t := range []sanitizerType{cfi, scs, hwasan} {
+			for _, t := range []sanitizerType{scs, hwasan} {
 				if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
 					return false
 				}
 			}
+			// cfi also exports both variants. But for static, we capture both.
+			if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) {
+				return false
+			}
 		}
 		if l.static() {
 			return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
@@ -668,6 +652,7 @@
 			ExportedDirs       []string `json:",omitempty"`
 			ExportedSystemDirs []string `json:",omitempty"`
 			ExportedFlags      []string `json:",omitempty"`
+			Sanitize           string   `json:",omitempty"`
 			SanitizeMinimalDep bool     `json:",omitempty"`
 			SanitizeUbsanDep   bool     `json:",omitempty"`
 
@@ -717,6 +702,7 @@
 		var propOut string
 
 		if l, ok := m.linker.(snapshotLibraryInterface); ok {
+
 			// library flags
 			prop.ExportedFlags = l.exportedFlags()
 			for _, dir := range l.exportedDirs() {
@@ -749,6 +735,15 @@
 			if libType != "header" {
 				libPath := m.outputFile.Path()
 				stem = libPath.Base()
+				if l.static() && m.sanitize != nil && m.sanitize.isSanitizerEnabled(cfi) {
+					// both cfi and non-cfi variant for static libraries can exist.
+					// attach .cfi to distinguish between cfi and non-cfi.
+					// e.g. libbase.a -> libbase.cfi.a
+					ext := filepath.Ext(stem)
+					stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext
+					prop.Sanitize = "cfi"
+					prop.ModuleName += ".cfi"
+				}
 				snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
 				ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
 			} else {
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index b559bac..7b8352b 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -26,6 +26,7 @@
     srcs: [
         "main.go",
         "writedocs.go",
+        "bazel_overlay.go",
     ],
     primaryBuilder: true,
 }
diff --git a/cmd/soong_build/bazel_overlay.go b/cmd/soong_build/bazel_overlay.go
new file mode 100644
index 0000000..e37c163
--- /dev/null
+++ b/cmd/soong_build/bazel_overlay.go
@@ -0,0 +1,173 @@
+// 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 main
+
+import (
+	"android/soong/android"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+
+	"github.com/google/blueprint"
+)
+
+const (
+	soongModuleLoad = `package(default_visibility = ["//visibility:public"])
+load("//:soong_module.bzl", "soong_module")
+`
+
+	// A BUILD file target snippet representing a Soong module
+	soongModuleTarget = `soong_module(
+    name = "%s",
+    module_name = "%s",
+    module_type = "%s",
+    module_variant = "%s",
+    deps = [
+        %s
+    ],
+)
+`
+
+	// The soong_module rule implementation in a .bzl file
+	soongModuleBzl = `
+SoongModuleInfo = provider(
+    fields = {
+        "name": "Name of module",
+        "type": "Type of module",
+        "variant": "Variant of module",
+    },
+)
+
+def _soong_module_impl(ctx):
+    return [
+        SoongModuleInfo(
+            name = ctx.attr.module_name,
+            type = ctx.attr.module_type,
+            variant = ctx.attr.module_variant,
+        ),
+    ]
+
+soong_module = rule(
+    implementation = _soong_module_impl,
+    attrs = {
+        "module_name": attr.string(mandatory = True),
+        "module_type": attr.string(mandatory = True),
+        "module_variant": attr.string(),
+        "deps": attr.label_list(providers = [SoongModuleInfo]),
+    },
+)
+`
+)
+
+func targetNameWithVariant(c *blueprint.Context, logicModule blueprint.Module) string {
+	name := ""
+	if c.ModuleSubDir(logicModule) != "" {
+		name = c.ModuleName(logicModule) + "--" + c.ModuleSubDir(logicModule)
+	} else {
+		name = c.ModuleName(logicModule)
+	}
+
+	return strings.Replace(name, "//", "", 1)
+}
+
+func qualifiedTargetLabel(c *blueprint.Context, logicModule blueprint.Module) string {
+	return "//" +
+		packagePath(c, logicModule) +
+		":" +
+		targetNameWithVariant(c, logicModule)
+}
+
+func packagePath(c *blueprint.Context, logicModule blueprint.Module) string {
+	return filepath.Dir(c.BlueprintFile(logicModule))
+}
+
+func createBazelOverlay(ctx *android.Context, bazelOverlayDir string) error {
+	blueprintCtx := ctx.Context
+	blueprintCtx.VisitAllModules(func(module blueprint.Module) {
+		buildFile, err := buildFileForModule(blueprintCtx, module)
+		if err != nil {
+			panic(err)
+		}
+
+		// TODO(b/163018919): DirectDeps can have duplicate (module, variant)
+		// items, if the modules are added using different DependencyTag. Figure
+		// out the implications of that.
+		depLabels := map[string]bool{}
+		blueprintCtx.VisitDirectDeps(module, func(depModule blueprint.Module) {
+			depLabels[qualifiedTargetLabel(blueprintCtx, depModule)] = true
+		})
+
+		var depLabelList string
+		for depLabel, _ := range depLabels {
+			depLabelList += "\"" + depLabel + "\",\n        "
+		}
+		buildFile.Write([]byte(
+			fmt.Sprintf(
+				soongModuleTarget,
+				targetNameWithVariant(blueprintCtx, module),
+				blueprintCtx.ModuleName(module),
+				blueprintCtx.ModuleType(module),
+				// misleading name, this actually returns the variant.
+				blueprintCtx.ModuleSubDir(module),
+				depLabelList)))
+		buildFile.Close()
+	})
+
+	if err := writeReadOnlyFile(bazelOverlayDir, "WORKSPACE", ""); err != nil {
+		return err
+	}
+
+	if err := writeReadOnlyFile(bazelOverlayDir, "BUILD", ""); err != nil {
+		return err
+	}
+
+	return writeReadOnlyFile(bazelOverlayDir, "soong_module.bzl", soongModuleBzl)
+}
+
+func buildFileForModule(ctx *blueprint.Context, module blueprint.Module) (*os.File, error) {
+	// Create nested directories for the BUILD file
+	dirPath := filepath.Join(bazelOverlayDir, packagePath(ctx, module))
+	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
+		os.MkdirAll(dirPath, os.ModePerm)
+	}
+	// Open the file for appending, and create it if it doesn't exist
+	f, err := os.OpenFile(
+		filepath.Join(dirPath, "BUILD.bazel"),
+		os.O_APPEND|os.O_CREATE|os.O_WRONLY,
+		0644)
+	if err != nil {
+		return nil, err
+	}
+
+	// If the file is empty, add the load statement for the `soong_module` rule
+	fi, err := f.Stat()
+	if err != nil {
+		return nil, err
+	}
+	if fi.Size() == 0 {
+		f.Write([]byte(soongModuleLoad + "\n"))
+	}
+
+	return f, nil
+}
+
+// The overlay directory should be read-only, sufficient for bazel query.
+func writeReadOnlyFile(dir string, baseName string, content string) error {
+	workspaceFile := filepath.Join(bazelOverlayDir, baseName)
+	// 0444 is read-only
+	return ioutil.WriteFile(workspaceFile, []byte(content), 0444)
+}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 532d9e4..01a39a2 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -26,11 +26,13 @@
 )
 
 var (
-	docFile string
+	docFile         string
+	bazelOverlayDir string
 )
 
 func init() {
 	flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
+	flag.StringVar(&bazelOverlayDir, "bazel_overlay_dir", "", "path to the bazel overlay directory")
 }
 
 func newNameResolver(config android.Config) *android.NameResolver {
@@ -65,7 +67,7 @@
 		os.Exit(1)
 	}
 
-	if docFile != "" {
+	if !shouldPrepareBuildActions() {
 		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
 	}
 
@@ -85,6 +87,13 @@
 
 	bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
 
+	if bazelOverlayDir != "" {
+		if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
+			fmt.Fprintf(os.Stderr, "%s", err)
+			os.Exit(1)
+		}
+	}
+
 	if docFile != "" {
 		if err := writeDocs(ctx, docFile); err != nil {
 			fmt.Fprintf(os.Stderr, "%s", err)
@@ -94,7 +103,7 @@
 
 	// TODO(ccross): make this a command line argument.  Requires plumbing through blueprint
 	//  to affect the command line of the primary builder.
-	if docFile == "" {
+	if shouldPrepareBuildActions() {
 		metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
 		err = android.WriteMetrics(configuration, metricsFile)
 		if err != nil {
@@ -103,3 +112,9 @@
 		}
 	}
 }
+
+func shouldPrepareBuildActions() bool {
+	// If we're writing soong_docs or bazel_overlay, don't write build.ninja or
+	// collect metrics.
+	return docFile == "" && bazelOverlayDir == ""
+}
diff --git a/rust/project_json.go b/rust/project_json.go
index 41dd194..8310479 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -75,17 +75,16 @@
 	knownCrates map[string]crateInfo, module android.Module,
 	crate *rustProjectCrate, deps map[string]int) {
 
-	//TODO(tweek): The stdlib dependencies do not appear here. We need to manually add them.
 	ctx.VisitDirectDeps(module, func(child android.Module) {
-		childId, childName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+		childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
 		if !ok {
 			return
 		}
-		if _, ok = deps[childName]; ok {
+		if _, ok = deps[ctx.ModuleName(child)]; ok {
 			return
 		}
-		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childName})
-		deps[childName] = childId
+		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childCrateName})
+		deps[ctx.ModuleName(child)] = childId
 	})
 }
 
@@ -106,8 +105,9 @@
 	if !ok {
 		return 0, "", false
 	}
+	moduleName := ctx.ModuleName(module)
 	crateName := rModule.CrateName()
-	if cInfo, ok := knownCrates[crateName]; ok {
+	if cInfo, ok := knownCrates[moduleName]; ok {
 		// We have seen this crate already; merge any new dependencies.
 		crate := project.Crates[cInfo.ID]
 		mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
@@ -115,15 +115,18 @@
 		return cInfo.ID, crateName, true
 	}
 	crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
-	src := rustLib.baseCompiler.Properties.Srcs[0]
-	crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
+	srcs := rustLib.baseCompiler.Properties.Srcs
+	if len(srcs) == 0 {
+		return 0, "", false
+	}
+	crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0])
 	crate.Edition = rustLib.baseCompiler.edition()
 
 	deps := make(map[string]int)
 	mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
 
 	id := len(project.Crates)
-	knownCrates[crateName] = crateInfo{ID: id, Deps: deps}
+	knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
 	project.Crates = append(project.Crates, crate)
 	// rust-analyzer requires that all crates belong to at least one root:
 	// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 6786e72..8521940 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -15,6 +15,7 @@
 package rust
 
 import (
+	"encoding/json"
 	"io/ioutil"
 	"path/filepath"
 	"testing"
@@ -23,20 +24,12 @@
 	"android/soong/cc"
 )
 
-func TestProjectJson(t *testing.T) {
-	bp := `rust_library {
-		  name: "liba",
-		  srcs: ["src/lib.rs"],
-		  crate_name: "a"
-		}` + GatherRequiredDepsForTest()
-	env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
-	fs := map[string][]byte{
-		"foo.rs":     nil,
-		"src/lib.rs": nil,
-	}
-
+// testProjectJson run the generation of rust-project.json. It returns the raw
+// content of the generated file.
+func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
 	cc.GatherRequiredFilesForTest(fs)
 
+	env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
 	config := android.TestArchConfig(buildDir, env, bp, fs)
 	ctx := CreateTestContext()
 	ctx.Register(config)
@@ -48,8 +41,131 @@
 	// The JSON file is generated via WriteFileToOutputDir. Therefore, it
 	// won't appear in the Output of the TestingSingleton. Manually verify
 	// it exists.
-	_, err := ioutil.ReadFile(filepath.Join(buildDir, "rust-project.json"))
+	content, err := ioutil.ReadFile(filepath.Join(buildDir, rustProjectJsonFileName))
 	if err != nil {
 		t.Errorf("rust-project.json has not been generated")
 	}
+	return content
+}
+
+// validateJsonCrates validates that content follows the basic structure of
+// rust-project.json. It returns the crates attribute if the validation
+// succeeded.
+// It uses an empty interface instead of relying on a defined structure to
+// avoid a strong dependency on our implementation.
+func validateJsonCrates(t *testing.T, rawContent []byte) []interface{} {
+	var content interface{}
+	err := json.Unmarshal(rawContent, &content)
+	if err != nil {
+		t.Errorf("Unable to parse the rust-project.json as JSON: %v", err)
+	}
+	root, ok := content.(map[string]interface{})
+	if !ok {
+		t.Errorf("Unexpected JSON format: %v", content)
+	}
+	if _, ok = root["crates"]; !ok {
+		t.Errorf("No crates attribute in rust-project.json: %v", root)
+	}
+	crates, ok := root["crates"].([]interface{})
+	if !ok {
+		t.Errorf("Unexpected crates format: %v", root["crates"])
+	}
+	return crates
+}
+
+func TestProjectJsonDep(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba",
+		srcs: ["a/src/lib.rs"],
+		crate_name: "a"
+	}
+	rust_library {
+		name: "libb",
+		srcs: ["b/src/lib.rs"],
+		crate_name: "b",
+		rlibs: ["liba"],
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"a/src/lib.rs": nil,
+		"b/src/lib.rs": nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonBindGen(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba",
+		srcs: ["src/lib.rs"],
+		rlibs: ["libbindings"],
+		crate_name: "a"
+	}
+	rust_bindgen {
+		name: "libbindings",
+		crate_name: "bindings",
+		source_stem: "bindings",
+		host_supported: true,
+		wrapper_src: "src/any.h",
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"src/lib.rs": nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonMultiVersion(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba1",
+		srcs: ["a1/src/lib.rs"],
+		crate_name: "a"
+	}
+	rust_library {
+		name: "liba2",
+		srcs: ["a2/src/lib.rs"],
+		crate_name: "a",
+	}
+	rust_library {
+		name: "libb",
+		srcs: ["b/src/lib.rs"],
+		crate_name: "b",
+		rustlibs: ["liba1", "liba2"],
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"a1/src/lib.rs": nil,
+		"a2/src/lib.rs": nil,
+		"b/src/lib.rs":  nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	crates := validateJsonCrates(t, jsonContent)
+	for _, crate := range crates {
+		c := crate.(map[string]interface{})
+		if c["root_module"] == "b/src/lib.rs" {
+			deps, ok := c["deps"].([]interface{})
+			if !ok {
+				t.Errorf("Unexpected format for deps: %v", c["deps"])
+			}
+			aCount := 0
+			for _, dep := range deps {
+				d, ok := dep.(map[string]interface{})
+				if !ok {
+					t.Errorf("Unexpected format for dep: %v", dep)
+				}
+				if d["name"] == "a" {
+					aCount++
+				}
+			}
+			if aCount != 2 {
+				t.Errorf("Unexpected number of liba dependencies want %v, got %v: %v", 2, aCount, deps)
+			}
+			return
+		}
+	}
+	t.Errorf("libb crate has not been found: %v", crates)
 }
diff --git a/rust/rust.go b/rust/rust.go
index edfa5d8..113b0b2 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -807,8 +807,8 @@
 				directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
 			}
 
-			//Append the dependencies exportedDirs
-			if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok {
+			//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
+			if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag {
 				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...)
 				depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
 			}
diff --git a/rust/testing.go b/rust/testing.go
index 83b2828..925b02c 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -44,7 +44,28 @@
                                 },
 				host_supported: true,
 		}
-
+		rust_prebuilt_library {
+				name: "libstd_x86_64-apple-darwin",
+                                crate_name: "std",
+                                rlib: {
+                                    srcs: ["libstd.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libstd.so"],
+                                },
+				host_supported: true,
+		}
+		rust_prebuilt_library {
+				name: "libtest_x86_64-apple-darwin",
+                                crate_name: "test",
+                                rlib: {
+                                    srcs: ["libtest.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libtest.so"],
+                                },
+				host_supported: true,
+		}
 		//////////////////////////////
 		// Device module requirements
 
diff --git a/third_party/zip/android.go b/third_party/zip/android.go
index 8d387cc..f8e45c5 100644
--- a/third_party/zip/android.go
+++ b/third_party/zip/android.go
@@ -43,6 +43,15 @@
 		offset:     uint64(w.cw.count),
 	}
 	w.dir = append(w.dir, h)
+	if !fh.isZip64() {
+		// Some writers will generate 64 bit sizes and set 32 bit fields to
+		// uint32max even if the actual size fits in 32 bit. So we should
+		// make sure CompressedSize contains the correct value in such
+		// cases. With out the two lines below we would be writing invalid(-1)
+		// sizes in such case.
+		fh.CompressedSize = uint32(fh.CompressedSize64)
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
 
 	if err := writeHeader(w.cw, fh); err != nil {
 		return err