Merge "Change default to require licenses property."
diff --git a/README.md b/README.md
index e92349e..a67c393 100644
--- a/README.md
+++ b/README.md
@@ -33,8 +33,9 @@
 Every module must have a `name` property, and the value must be unique across
 all Android.bp files.
 
-For a list of valid module types and their properties see
-[$OUT_DIR/soong/docs/soong_build.html](https://ci.android.com/builds/latest/branches/aosp-build-tools/targets/linux/view/soong_build.html).
+The list of valid module types and their properties can be generated by calling
+`m soong_docs`. It will be written to `$OUT_DIR/soong/docs/soong_build.html`.
+This list for the current version of Soong can be found [here](https://ci.android.com/builds/latest/branches/aosp-build-tools/targets/linux/view/soong_build.html).
 
 ### File lists
 
diff --git a/android/Android.bp b/android/Android.bp
index 1bccd7b..f3a3850 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -66,7 +66,6 @@
         "prebuilt.go",
         "prebuilt_build_tool.go",
         "proto.go",
-        "queryview.go",
         "register.go",
         "rule_builder.go",
         "sandbox.go",
@@ -81,7 +80,6 @@
         "util.go",
         "variable.go",
         "visibility.go",
-        "writedocs.go",
     ],
     testSrcs: [
         "android_test.go",
diff --git a/android/bazel.go b/android/bazel.go
index 692fbcd..373e292 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -182,6 +182,7 @@
 		"external/jemalloc_new":           Bp2BuildDefaultTrueRecursively,
 		"external/libcxx":                 Bp2BuildDefaultTrueRecursively,
 		"external/libcxxabi":              Bp2BuildDefaultTrueRecursively,
+		"external/libcap":                 Bp2BuildDefaultTrueRecursively,
 		"external/scudo":                  Bp2BuildDefaultTrueRecursively,
 		"prebuilts/clang/host/linux-x86":  Bp2BuildDefaultTrueRecursively,
 	}
@@ -231,6 +232,10 @@
 		//external/brotli/...
 		"brotli-fuzzer-corpus", // "declared output 'external/brotli/c/fuzz/73231c6592f195ffd41100b8706d1138ff6893b9' was not created by genrule"
 
+		// //external/libcap/...
+		"libcap",      // http://b/198595332, depends on _makenames, a cc_binary
+		"cap_names.h", // http://b/198596102, depends on _makenames, a cc_binary
+
 		// Tests. Handle later.
 		"libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found
 		"libjemalloc5_integrationtest",
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 9c922dd..50b79fa 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -27,9 +27,9 @@
 	"sync"
 
 	"android/soong/bazel/cquery"
+	"android/soong/shared"
 
 	"android/soong/bazel"
-	"android/soong/shared"
 )
 
 type cqueryRequest interface {
@@ -492,6 +492,12 @@
 )
 `
 
+	commonArchFilegroupString := `
+filegroup(name = "common",
+    srcs = [%s],
+)
+`
+
 	configNodesSection := ""
 
 	labelsByArch := map[string][]string{}
@@ -501,14 +507,22 @@
 		labelsByArch[archString] = append(labelsByArch[archString], labelString)
 	}
 
-	configNodeLabels := []string{}
+	allLabels := []string{}
 	for archString, labels := range labelsByArch {
-		configNodeLabels = append(configNodeLabels, fmt.Sprintf("\":%s\"", archString))
-		labelsString := strings.Join(labels, ",\n            ")
-		configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
+		if archString == "common" {
+			// arch-less labels (e.g. filegroups) don't need a config_node
+			allLabels = append(allLabels, "\":common\"")
+			labelsString := strings.Join(labels, ",\n            ")
+			configNodesSection += fmt.Sprintf(commonArchFilegroupString, labelsString)
+		} else {
+			// Create a config_node, and add the config_node's label to allLabels
+			allLabels = append(allLabels, fmt.Sprintf("\":%s\"", archString))
+			labelsString := strings.Join(labels, ",\n            ")
+			configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
+		}
 	}
 
-	return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(configNodeLabels, ",\n            ")))
+	return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n            ")))
 }
 
 func indent(original string) string {
@@ -573,6 +587,12 @@
 %s
 
 def get_arch(target):
+  # TODO(b/199363072): filegroups and file targets aren't associated with any
+  # specific platform architecture in mixed builds. This is consistent with how
+  # Soong treats filegroups, but it may not be the case with manually-written
+  # filegroup BUILD targets.
+  if target.kind in ["filegroup", ""]:
+    return "common"
   buildoptions = build_options(target)
   platforms = build_options(target)["//command_line_option:platforms"]
   if len(platforms) != 1:
@@ -671,11 +691,12 @@
 	if err != nil {
 		return err
 	}
+
 	buildrootLabel := "@soong_injection//mixed_builds:buildroot"
 	cqueryOutput, cqueryErr, err = context.issueBazelCommand(
 		context.paths,
 		bazel.CqueryBuildRootRunName,
-		bazelCommand{"cquery", fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
+		bazelCommand{"cquery", fmt.Sprintf("deps(%s)", buildrootLabel)},
 		"--output=starlark",
 		"--starlark:file="+absolutePath(cqueryFileRelpath))
 	err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 557faea..cdf1a63 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -11,7 +11,7 @@
 	label := "//foo:bar"
 	arch := Arm64
 	bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
-		bazelCommand{command: "cquery", expression: "kind(rule, deps(@soong_injection//mixed_builds:buildroot))"}: `//foo:bar|arm64>>out/foo/bar.txt`,
+		bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: `//foo:bar|arm64>>out/foo/bar.txt`,
 	})
 	g, ok := bazelContext.GetOutputFiles(label, arch)
 	if ok {
diff --git a/android/config.go b/android/config.go
index e0fc266..0767e7b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -79,10 +79,6 @@
 	return c.runGoTests
 }
 
-func (c Config) UseValidationsForGoTests() bool {
-	return c.useValidationsForGoTests
-}
-
 func (c Config) DebugCompilation() bool {
 	return false // Never compile Go code in the main build for debugging
 }
@@ -142,8 +138,7 @@
 	soongOutDir    string
 	moduleListFile string // the path to the file which lists blueprint files to parse.
 
-	runGoTests               bool
-	useValidationsForGoTests bool
+	runGoTests bool
 
 	env       map[string]string
 	envLock   sync.Mutex
@@ -157,8 +152,6 @@
 	captureBuild      bool // true for tests, saves build parameters for each module
 	ignoreEnvironment bool // true for tests, returns empty from all Getenv calls
 
-	stopBefore bootstrap.StopBefore
-
 	fs         pathtools.FileSystem
 	mockBpList string
 
@@ -420,8 +413,8 @@
 // bootstrap run. Only per-run data is reset. Data which needs to persist across
 // multiple runs in the same program execution is carried over (such as Bazel
 // context or environment deps).
-func ConfigForAdditionalRun(cmdlineArgs bootstrap.Args, c Config) (Config, error) {
-	newConfig, err := NewConfig(cmdlineArgs, c.soongOutDir, c.env)
+func ConfigForAdditionalRun(c Config) (Config, error) {
+	newConfig, err := NewConfig(c.moduleListFile, c.runGoTests, c.outDir, c.soongOutDir, c.env)
 	if err != nil {
 		return Config{}, err
 	}
@@ -432,20 +425,19 @@
 
 // NewConfig creates a new Config object. The srcDir argument specifies the path
 // to the root source directory. It also loads the config file, if found.
-func NewConfig(cmdlineArgs bootstrap.Args, soongOutDir string, availableEnv map[string]string) (Config, error) {
+func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) {
 	// Make a config with default options.
 	config := &config{
 		ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName),
 
 		env: availableEnv,
 
-		outDir:                   cmdlineArgs.OutDir,
-		soongOutDir:              soongOutDir,
-		runGoTests:               cmdlineArgs.RunGoTests,
-		useValidationsForGoTests: cmdlineArgs.UseValidations,
-		multilibConflicts:        make(map[ArchType]bool),
+		outDir:            outDir,
+		soongOutDir:       soongOutDir,
+		runGoTests:        runGoTests,
+		multilibConflicts: make(map[ArchType]bool),
 
-		moduleListFile: cmdlineArgs.ModuleListFile,
+		moduleListFile: moduleListFile,
 		fs:             pathtools.NewOsFs(absSrcDir),
 	}
 
@@ -565,21 +557,10 @@
 	c.mockBpList = blueprint.MockModuleListFile
 }
 
-func (c *config) StopBefore() bootstrap.StopBefore {
-	return c.stopBefore
-}
-
-// SetStopBefore configures soong_build to exit earlier at a specific point.
-func (c *config) SetStopBefore(stopBefore bootstrap.StopBefore) {
-	c.stopBefore = stopBefore
-}
-
 func (c *config) SetAllowMissingDependencies() {
 	c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
 }
 
-var _ bootstrap.ConfigStopBefore = (*config)(nil)
-
 // BlueprintToolLocation returns the directory containing build system tools
 // from Blueprint, like soong_zip and merge_zips.
 func (c *config) HostToolDir() string {
diff --git a/android/filegroup.go b/android/filegroup.go
index 54d01d3..4db165f 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -42,6 +42,27 @@
 
 	srcs := bazel.MakeLabelListAttribute(
 		BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
+
+	// For Bazel compatibility, don't generate the filegroup if there is only 1
+	// source file, and that the source file is named the same as the module
+	// itself. In Bazel, eponymous filegroups like this would be an error.
+	//
+	// Instead, dependents on this single-file filegroup can just depend
+	// on the file target, instead of rule target, directly.
+	//
+	// You may ask: what if a filegroup has multiple files, and one of them
+	// shares the name? The answer: we haven't seen that in the wild, and
+	// should lock Soong itself down to prevent the behavior. For now,
+	// we raise an error if bp2build sees this problem.
+	for _, f := range srcs.Value.Includes {
+		if f.Label == fg.Name() {
+			if len(srcs.Value.Includes) > 1 {
+				ctx.ModuleErrorf("filegroup '%s' cannot contain a file with the same name", fg.Name())
+			}
+			return
+		}
+	}
+
 	attrs := &bazelFilegroupAttributes{
 		Srcs: srcs,
 	}
@@ -97,7 +118,7 @@
 	}
 
 	bazelCtx := ctx.Config().BazelContext
-	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), ctx.Arch().ArchType)
+	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), Common)
 	if !ok {
 		return false
 	}
diff --git a/android/module.go b/android/module.go
index cc03418..dd6a25a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -405,6 +405,7 @@
 	PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
 
 	CheckbuildFile(srcPath Path)
+	TidyFile(srcPath Path)
 
 	InstallInData() bool
 	InstallInTestcases() bool
@@ -521,62 +522,6 @@
 	TransitivePackagingSpecs() []PackagingSpec
 }
 
-// BazelTargetModule is a lightweight wrapper interface around Module for
-// bp2build conversion purposes.
-//
-// In bp2build's bootstrap.Main execution, Soong runs an alternate pipeline of
-// mutators that creates BazelTargetModules from regular Module objects,
-// performing the mapping from Soong properties to Bazel rule attributes in the
-// process. This process may optionally create additional BazelTargetModules,
-// resulting in a 1:many mapping.
-//
-// bp2build.Codegen is then responsible for visiting all modules in the graph,
-// filtering for BazelTargetModules, and code-generating BUILD targets from
-// them.
-type BazelTargetModule interface {
-	Module
-
-	bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
-	SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties)
-
-	RuleClass() string
-	BzlLoadLocation() string
-}
-
-// InitBazelTargetModule is a wrapper function that decorates BazelTargetModule
-// with property structs containing metadata for bp2build conversion.
-func InitBazelTargetModule(module BazelTargetModule) {
-	module.AddProperties(module.bazelTargetModuleProperties())
-	InitAndroidModule(module)
-}
-
-// BazelTargetModuleBase contains the property structs with metadata for
-// bp2build conversion.
-type BazelTargetModuleBase struct {
-	ModuleBase
-	Properties bazel.BazelTargetModuleProperties
-}
-
-// bazelTargetModuleProperties getter.
-func (btmb *BazelTargetModuleBase) bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
-	return &btmb.Properties
-}
-
-// SetBazelTargetModuleProperties setter for BazelTargetModuleProperties
-func (btmb *BazelTargetModuleBase) SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties) {
-	btmb.Properties = props
-}
-
-// RuleClass returns the rule class for this Bazel target
-func (b *BazelTargetModuleBase) RuleClass() string {
-	return b.bazelTargetModuleProperties().Rule_class
-}
-
-// BzlLoadLocation returns the rule class for this Bazel target
-func (b *BazelTargetModuleBase) BzlLoadLocation() string {
-	return b.bazelTargetModuleProperties().Bzl_load_location
-}
-
 // Qualified id for a module
 type qualifiedModuleName struct {
 	// The package (i.e. directory) in which the module is defined, without trailing /
@@ -987,12 +932,12 @@
 	DeviceSupported = deviceSupported | deviceDefault
 
 	// By default, _only_ device variant is built. Device variant can be disabled with `device_supported: false`
-    // Host and HostCross are disabled by default and can be enabled with `host_supported: true`
+	// Host and HostCross are disabled by default and can be enabled with `host_supported: true`
 	HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
 
 	// Host, HostCross, and Device are built by default.
-    // Building Device can be disabled with `device_supported: false`
-    // Building Host and HostCross can be disabled with `host_supported: false`
+	// Building Device can be disabled with `device_supported: false`
+	// Building Host and HostCross can be disabled with `host_supported: false`
 	HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
 		deviceSupported | deviceDefault
 
@@ -1190,6 +1135,7 @@
 	installFiles         InstallPaths
 	installFilesDepSet   *installPathsDepSet
 	checkbuildFiles      Paths
+	tidyFiles            Paths
 	packagingSpecs       []PackagingSpec
 	packagingSpecsDepSet *packagingSpecsDepSet
 	noticeFiles          Paths
@@ -1202,6 +1148,7 @@
 	// Only set on the final variant of each module
 	installTarget    WritablePath
 	checkbuildTarget WritablePath
+	tidyTarget       WritablePath
 	blueprintDir     string
 
 	hooks hooks
@@ -1727,10 +1674,12 @@
 func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
 	var allInstalledFiles InstallPaths
 	var allCheckbuildFiles Paths
+	var allTidyFiles Paths
 	ctx.VisitAllModuleVariants(func(module Module) {
 		a := module.base()
 		allInstalledFiles = append(allInstalledFiles, a.installFiles...)
 		allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
+		allTidyFiles = append(allTidyFiles, a.tidyFiles...)
 	})
 
 	var deps Paths
@@ -1754,6 +1703,13 @@
 		deps = append(deps, m.checkbuildTarget)
 	}
 
+	if len(allTidyFiles) > 0 {
+		name := namespacePrefix + ctx.ModuleName() + "-tidy"
+		ctx.Phony(name, allTidyFiles...)
+		m.tidyTarget = PathForPhony(ctx, name)
+		deps = append(deps, m.tidyTarget)
+	}
+
 	if len(deps) > 0 {
 		suffix := ""
 		if ctx.Config().KatiEnabled() {
@@ -1962,6 +1918,7 @@
 
 		m.installFiles = append(m.installFiles, ctx.installFiles...)
 		m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
+		m.tidyFiles = append(m.tidyFiles, ctx.tidyFiles...)
 		m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
 		for k, v := range ctx.phonies {
 			m.phonies[k] = append(m.phonies[k], v...)
@@ -2160,6 +2117,7 @@
 	packagingSpecs  []PackagingSpec
 	installFiles    InstallPaths
 	checkbuildFiles Paths
+	tidyFiles       Paths
 	module          Module
 	phonies         map[string]Paths
 
@@ -2892,6 +2850,10 @@
 	m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 }
 
+func (m *moduleContext) TidyFile(srcPath Path) {
+	m.tidyFiles = append(m.tidyFiles, srcPath)
+}
+
 func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
 	return m.bp
 }
@@ -3150,19 +3112,49 @@
 
 type buildTargetSingleton struct{}
 
+func addAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(string) string) []string {
+	// Ensure ancestor directories are in dirMap
+	// Make directories build their direct subdirectories
+	dirs := SortedStringKeys(dirMap)
+	for _, dir := range dirs {
+		dir := parentDir(dir)
+		for dir != "." && dir != "/" {
+			if _, exists := dirMap[dir]; exists {
+				break
+			}
+			dirMap[dir] = nil
+			dir = parentDir(dir)
+		}
+	}
+	dirs = SortedStringKeys(dirMap)
+	for _, dir := range dirs {
+		p := parentDir(dir)
+		if p != "." && p != "/" {
+			dirMap[p] = append(dirMap[p], PathForPhony(ctx, mmName(dir)))
+		}
+	}
+	return SortedStringKeys(dirMap)
+}
+
 func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
 	var checkbuildDeps Paths
+	var tidyDeps Paths
 
 	mmTarget := func(dir string) string {
 		return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
 	}
+	mmTidyTarget := func(dir string) string {
+		return "tidy-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
+	}
 
 	modulesInDir := make(map[string]Paths)
+	tidyModulesInDir := make(map[string]Paths)
 
 	ctx.VisitAllModules(func(module Module) {
 		blueprintDir := module.base().blueprintDir
 		installTarget := module.base().installTarget
 		checkbuildTarget := module.base().checkbuildTarget
+		tidyTarget := module.base().tidyTarget
 
 		if checkbuildTarget != nil {
 			checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
@@ -3172,6 +3164,16 @@
 		if installTarget != nil {
 			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
 		}
+
+		if tidyTarget != nil {
+			tidyDeps = append(tidyDeps, tidyTarget)
+			// tidyTarget is in modulesInDir so it will be built with "mm".
+			modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], tidyTarget)
+			// tidyModulesInDir contains tidyTarget but not checkbuildTarget
+			// or installTarget, so tidy targets in a directory can be built
+			// without other checkbuild or install targets.
+			tidyModulesInDir[blueprintDir] = append(tidyModulesInDir[blueprintDir], tidyTarget)
+		}
 	})
 
 	suffix := ""
@@ -3182,31 +3184,24 @@
 	// Create a top-level checkbuild target that depends on all modules
 	ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
 
+	// Create a top-level tidy target that depends on all modules
+	ctx.Phony("tidy"+suffix, tidyDeps...)
+
+	dirs := addAncestors(ctx, tidyModulesInDir, mmTidyTarget)
+
+	// Kati does not generate tidy-* phony targets yet.
+	// Create a tidy-<directory> target that depends on all subdirectories
+	// and modules in the directory.
+	for _, dir := range dirs {
+		ctx.Phony(mmTidyTarget(dir), tidyModulesInDir[dir]...)
+	}
+
 	// Make will generate the MODULES-IN-* targets
 	if ctx.Config().KatiEnabled() {
 		return
 	}
 
-	// Ensure ancestor directories are in modulesInDir
-	dirs := SortedStringKeys(modulesInDir)
-	for _, dir := range dirs {
-		dir := parentDir(dir)
-		for dir != "." && dir != "/" {
-			if _, exists := modulesInDir[dir]; exists {
-				break
-			}
-			modulesInDir[dir] = nil
-			dir = parentDir(dir)
-		}
-	}
-
-	// Make directories build their direct subdirectories
-	for _, dir := range dirs {
-		p := parentDir(dir)
-		if p != "." && p != "/" {
-			modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir)))
-		}
-	}
+	dirs = addAncestors(ctx, modulesInDir, mmTarget)
 
 	// Create a MODULES-IN-<directory> target that depends on all modules in a directory, and
 	// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
diff --git a/android/queryview.go b/android/queryview.go
deleted file mode 100644
index 224652e..0000000
--- a/android/queryview.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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 QueryView 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_queryview", BazelQueryViewSingleton)
-}
-
-// BazelQueryViewSingleton is the singleton responsible for registering the
-// soong_build build statement that will convert the Soong module graph after
-// applying *all* mutators, enabing the feature to query the final state of the
-// Soong graph. This mode is meant for querying the build graph state, and not meant
-// for generating BUILD files to be checked in.
-func BazelQueryViewSingleton() Singleton {
-	return &bazelQueryViewSingleton{}
-}
-
-// BazelConverterSingleton is the singleton responsible for registering the soong_build
-// build statement that will convert the Soong module graph by applying an alternate
-// pipeline of mutators, with the goal of reaching semantic equivalence between the original
-// Blueprint and final BUILD files. Using this mode, the goal is to be able to
-// build with these BUILD files directly in the source tree.
-func BazelConverterSingleton() Singleton {
-	return &bazelConverterSingleton{}
-}
-
-type bazelQueryViewSingleton struct{}
-type bazelConverterSingleton struct{}
-
-func generateBuildActionsForBazelConversion(ctx SingletonContext, converterMode bool) {
-	name := "queryview"
-	descriptionTemplate := "[EXPERIMENTAL, PRE-PRODUCTION] Creating the Bazel QueryView workspace with %s at $outDir"
-
-	// Create a build and rule statement, using the Bazel QueryView'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))
-
-	bazelQueryViewDirectory := PathForOutput(ctx, name)
-	bazelQueryViewWorkspaceFile := bazelQueryViewDirectory.Join(ctx, "WORKSPACE")
-	primaryBuilder := primaryBuilderPath(ctx)
-	bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
-		blueprint.RuleParams{
-			Command: fmt.Sprintf(
-				`rm -rf "${outDir}/"* && `+
-					`mkdir -p "${outDir}" && `+
-					`echo WORKSPACE: $$(cat "%s") > "${outDir}/.queryview-depfile.d" && `+
-					`BUILDER="%s" && `+
-					`echo BUILDER=$$BUILDER && `+
-					`cd "$$(dirname "$$BUILDER")" && `+
-					`echo PWD=$$PWD && `+
-					`ABSBUILDER="$$PWD/$$(basename "$$BUILDER")" && `+
-					`echo ABSBUILDER=$$ABSBUILDER && `+
-					`cd / && `+
-					`env -i "$$ABSBUILDER" --bazel_queryview_dir "${outDir}" "%s"`,
-				moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
-				primaryBuilder.String(),
-				strings.Join(os.Args[1:], "\" \""),
-			),
-			CommandDeps: []string{primaryBuilder.String()},
-			Description: fmt.Sprintf(
-				descriptionTemplate,
-				primaryBuilder.Base()),
-			Deps:    blueprint.DepsGCC,
-			Depfile: "${outDir}/.queryview-depfile.d",
-		},
-		"outDir")
-
-	ctx.Build(pctx, BuildParams{
-		Rule:   bazelQueryView,
-		Output: bazelQueryViewWorkspaceFile,
-		Inputs: deps,
-		Args: map[string]string{
-			"outDir": bazelQueryViewDirectory.String(),
-		},
-	})
-
-	// Add a phony target for generating the workspace
-	ctx.Phony(name, bazelQueryViewWorkspaceFile)
-}
-
-func (c *bazelQueryViewSingleton) GenerateBuildActions(ctx SingletonContext) {
-	generateBuildActionsForBazelConversion(ctx, false)
-}
-
-func (c *bazelConverterSingleton) GenerateBuildActions(ctx SingletonContext) {
-	generateBuildActionsForBazelConversion(ctx, true)
-}
diff --git a/android/testing.go b/android/testing.go
index e25e5c5..bd2faa2 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -509,12 +509,11 @@
 				allVariants = append(allVariants, ctx.ModuleSubDir(m))
 			}
 		})
-		sort.Strings(allModuleNames)
 		sort.Strings(allVariants)
 
 		if len(allVariants) == 0 {
 			panic(fmt.Errorf("failed to find module %q. All modules:\n  %s",
-				name, strings.Join(allModuleNames, "\n  ")))
+				name, strings.Join(SortedUniqueStrings(allModuleNames), "\n  ")))
 		} else {
 			panic(fmt.Errorf("failed to find module %q variant %q. All variants:\n  %s",
 				name, variant, strings.Join(allVariants, "\n  ")))
diff --git a/android/writedocs.go b/android/writedocs.go
deleted file mode 100644
index c380a3d..0000000
--- a/android/writedocs.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2015 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"
-	"path/filepath"
-	"strings"
-
-	"github.com/google/blueprint"
-)
-
-func init() {
-	RegisterSingletonType("writedocs", DocsSingleton)
-}
-
-func DocsSingleton() Singleton {
-	return &docsSingleton{}
-}
-
-type docsSingleton struct{}
-
-func primaryBuilderPath(ctx SingletonContext) Path {
-	soongOutDir := absolutePath(ctx.Config().SoongOutDir())
-	binary := absolutePath(os.Args[0])
-	primaryBuilder, err := filepath.Rel(soongOutDir, binary)
-	if err != nil {
-		ctx.Errorf("path to primary builder %q is not in build dir %q (%q)",
-			os.Args[0], ctx.Config().SoongOutDir(), err)
-	}
-
-	return PathForOutput(ctx, primaryBuilder)
-}
-
-func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) {
-	var deps Paths
-	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().moduleListFile))
-	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
-
-	// The dexpreopt configuration may not exist, but if it does, it's a dependency
-	// of soong_build.
-	dexpreoptConfigPath := ctx.Config().DexpreoptGlobalConfigPath(ctx)
-	if dexpreoptConfigPath.Valid() {
-		deps = append(deps, dexpreoptConfigPath.Path())
-	}
-
-	// Generate build system docs for the primary builder.  Generating docs reads the source
-	// files used to build the primary builder, but that dependency will be picked up through
-	// the dependency on the primary builder itself.  There are no dependencies on the
-	// Blueprints files, as any relevant changes to the Blueprints files would have caused
-	// a rebuild of the primary builder.
-	docsFile := PathForOutput(ctx, "docs", "soong_build.html")
-	primaryBuilder := primaryBuilderPath(ctx)
-	soongDocs := ctx.Rule(pctx, "soongDocs",
-		blueprint.RuleParams{
-			Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s",
-				primaryBuilder.String(),
-				docsFile.String(),
-				"\""+strings.Join(os.Args[1:], "\" \"")+"\""),
-			CommandDeps: []string{primaryBuilder.String()},
-			Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()),
-		},
-		"outDir")
-
-	ctx.Build(pctx, BuildParams{
-		Rule:   soongDocs,
-		Output: docsFile,
-		Inputs: deps,
-		Args: map[string]string{
-			"outDir": PathForOutput(ctx, "docs").String(),
-		},
-	})
-
-	// Add a phony target for building the documentation
-	ctx.Phony("soong_docs", docsFile)
-}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 08616a9..80801b2 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -201,6 +201,7 @@
 			"LOCAL_VENDOR_MODULE":              "vendor",
 			"LOCAL_ODM_MODULE":                 "device_specific",
 			"LOCAL_PRODUCT_MODULE":             "product_specific",
+			"LOCAL_PRODUCT_SERVICES_MODULE":    "product_specific",
 			"LOCAL_SYSTEM_EXT_MODULE":          "system_ext_specific",
 			"LOCAL_EXPORT_PACKAGE_RESOURCES":   "export_package_resources",
 			"LOCAL_PRIVILEGED_MODULE":          "privileged",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 2f10904..94b8116 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -382,7 +382,7 @@
 				fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.ToMakePath().String())
 				stemSuffix := apexType.suffix()
 				if a.isCompressed {
-					stemSuffix = ".capex"
+					stemSuffix = imageCapexSuffix
 				}
 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix)
 				fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
diff --git a/apex/apex.go b/apex/apex.go
index fbf6a6f..e3edc68 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1152,9 +1152,10 @@
 
 const (
 	// File extensions of an APEX for different packaging methods
-	imageApexSuffix = ".apex"
-	zipApexSuffix   = ".zipapex"
-	flattenedSuffix = ".flattened"
+	imageApexSuffix  = ".apex"
+	imageCapexSuffix = ".capex"
+	zipApexSuffix    = ".zipapex"
+	flattenedSuffix  = ".flattened"
 
 	// variant names each of which is for a packaging method
 	imageApexType     = "image"
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 5c7c90b..6027f9b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4640,6 +4640,35 @@
 	}
 }
 
+func TestApexSetFilenameOverride(t *testing.T) {
+	testApex(t, `
+		apex_set {
+ 			name: "com.company.android.myapex",
+			apex_name: "com.android.myapex",
+			set: "company-myapex.apks",
+      filename: "com.company.android.myapex.apex"
+		}
+	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+
+	testApex(t, `
+		apex_set {
+ 			name: "com.company.android.myapex",
+			apex_name: "com.android.myapex",
+			set: "company-myapex.apks",
+      filename: "com.company.android.myapex.capex"
+		}
+	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+
+	testApexError(t, `filename should end in .apex or .capex for apex_set`, `
+		apex_set {
+ 			name: "com.company.android.myapex",
+			apex_name: "com.android.myapex",
+			set: "company-myapex.apks",
+      filename: "some-random-suffix"
+		}
+	`)
+}
+
 func TestPrebuiltOverrides(t *testing.T) {
 	ctx := testApex(t, `
 		prebuilt_apex {
diff --git a/apex/builder.go b/apex/builder.go
index 5baa5c0..3177ee0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -786,7 +786,7 @@
 
 	if apexType == imageApex && (compressionEnabled || a.testOnlyShouldForceCompression()) {
 		a.isCompressed = true
-		unsignedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+".capex.unsigned")
+		unsignedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+imageCapexSuffix+".unsigned")
 
 		compressRule := android.NewRuleBuilder(pctx, ctx)
 		compressRule.Command().
@@ -800,7 +800,7 @@
 			FlagWithOutput("--output ", unsignedCompressedOutputFile)
 		compressRule.Build("compressRule", "Generate unsigned compressed APEX file")
 
-		signedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+".capex")
+		signedCompressedOutputFile := android.PathForModuleOut(ctx, a.Name()+imageCapexSuffix)
 		if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
 			args["outCommaList"] = signedCompressedOutputFile.String()
 		}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 1bb0fb5..c4794dc 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -924,8 +924,8 @@
 
 func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	a.installFilename = a.InstallFilename()
-	if !strings.HasSuffix(a.installFilename, imageApexSuffix) {
-		ctx.ModuleErrorf("filename should end in %s for apex_set", imageApexSuffix)
+	if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
+		ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
 	}
 
 	inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path()
diff --git a/bazel/properties.go b/bazel/properties.go
index 1a846ba..ed4e9fc 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -743,6 +743,31 @@
 	return keys
 }
 
+// DeduplicateAxesFromBase ensures no duplication of items between the no-configuration value and
+// configuration-specific values. For example, if we would convert this StringListAttribute as:
+// ["a", "b", "c"] + select({
+//    "//condition:one": ["a", "d"],
+//    "//conditions:default": [],
+// })
+// after this function, we would convert this StringListAttribute as:
+// ["a", "b", "c"] + select({
+//    "//condition:one": ["d"],
+//    "//conditions:default": [],
+// })
+func (sla *StringListAttribute) DeduplicateAxesFromBase() {
+	base := sla.Value
+	for axis, configToList := range sla.ConfigurableValues {
+		for config, list := range configToList {
+			remaining := SubtractStrings(list, base)
+			if len(remaining) == 0 {
+				delete(sla.ConfigurableValues[axis], config)
+			} else {
+				sla.ConfigurableValues[axis][config] = remaining
+			}
+		}
+	}
+}
+
 // TryVariableSubstitution, replace string substitution formatting within each string in slice with
 // Starlark string.format compatible tag for productVariable.
 func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index 9464245..85596e2 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -293,3 +293,74 @@
 		}
 	}
 }
+
+func TestDeduplicateAxesFromBase(t *testing.T) {
+	attr := StringListAttribute{
+		Value: []string{
+			"all_include",
+			"arm_include",
+			"android_include",
+			"linux_x86_include",
+		},
+		ConfigurableValues: configurableStringLists{
+			ArchConfigurationAxis: stringListSelectValues{
+				"arm": []string{"arm_include"},
+				"x86": []string{"x86_include"},
+			},
+			OsConfigurationAxis: stringListSelectValues{
+				"android": []string{"android_include"},
+				"linux":   []string{"linux_include"},
+			},
+			OsArchConfigurationAxis: stringListSelectValues{
+				"linux_x86": {"linux_x86_include"},
+			},
+			ProductVariableConfigurationAxis("a"): stringListSelectValues{
+				"a": []string{"not_in_value"},
+			},
+		},
+	}
+
+	attr.DeduplicateAxesFromBase()
+
+	expectedBaseIncludes := []string{
+		"all_include",
+		"arm_include",
+		"android_include",
+		"linux_x86_include",
+	}
+	if !reflect.DeepEqual(expectedBaseIncludes, attr.Value) {
+		t.Errorf("Expected Value includes %q, got %q", attr.Value, expectedBaseIncludes)
+	}
+	expectedConfiguredIncludes := configurableStringLists{
+		ArchConfigurationAxis: stringListSelectValues{
+			"x86": []string{"x86_include"},
+		},
+		OsConfigurationAxis: stringListSelectValues{
+			"linux": []string{"linux_include"},
+		},
+		OsArchConfigurationAxis: stringListSelectValues{},
+		ProductVariableConfigurationAxis("a"): stringListSelectValues{
+			"a": []string{"not_in_value"},
+		},
+	}
+	for _, axis := range attr.SortedConfigurationAxes() {
+		if _, ok := expectedConfiguredIncludes[axis]; !ok {
+			t.Errorf("Found unexpected axis %s", axis)
+			continue
+		}
+		expectedForAxis := expectedConfiguredIncludes[axis]
+		gotForAxis := attr.ConfigurableValues[axis]
+		if len(expectedForAxis) != len(gotForAxis) {
+			t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
+		}
+		for config, value := range gotForAxis {
+			if expected, ok := expectedForAxis[config]; ok {
+				if !reflect.DeepEqual(expected, value) {
+					t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value)
+				}
+			} else {
+				t.Errorf("Got unexpected config %q for %s", config, axis)
+			}
+		}
+	}
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b1ccc96..5ee04f9 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -39,6 +39,8 @@
         "cc_library_static_conversion_test.go",
         "cc_object_conversion_test.go",
         "conversion_test.go",
+        "filegroup_conversion_test.go",
+        "genrule_conversion_test.go",
         "performance_test.go",
         "prebuilt_etc_conversion_test.go",
         "python_binary_conversion_test.go",
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 0d9106c..ecea6b2 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -16,7 +16,6 @@
 
 import (
 	"android/soong/android"
-	"android/soong/genrule"
 	"strings"
 	"testing"
 )
@@ -218,13 +217,9 @@
 }
 
 func TestGenerateBazelTargetModules(t *testing.T) {
-	testCases := []struct {
-		name                 string
-		bp                   string
-		expectedBazelTargets []string
-	}{
+	testCases := []bp2buildTestCase{
 		{
-			bp: `custom {
+			blueprint: `custom {
 	name: "foo",
     string_list_prop: ["a", "b"],
     string_prop: "a",
@@ -241,7 +236,7 @@
 			},
 		},
 		{
-			bp: `custom {
+			blueprint: `custom {
 	name: "control_characters",
     string_list_prop: ["\t", "\n"],
     string_prop: "a\t\n\r",
@@ -258,7 +253,7 @@
 			},
 		},
 		{
-			bp: `custom {
+			blueprint: `custom {
   name: "has_dep",
   arch_paths: [":dep"],
   bazel_module: { bp2build_available: true },
@@ -280,7 +275,7 @@
 			},
 		},
 		{
-			bp: `custom {
+			blueprint: `custom {
     name: "arch_paths",
     arch: {
       x86: {
@@ -299,7 +294,7 @@
 			},
 		},
 		{
-			bp: `custom {
+			blueprint: `custom {
   name: "has_dep",
   arch: {
     x86: {
@@ -331,17 +326,17 @@
 
 	dir := "."
 	for _, testCase := range testCases {
-		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+		config := android.TestConfig(buildDir, nil, testCase.blueprint, nil)
 		ctx := android.NewTestContext(config)
 
 		registerCustomModuleForBp2buildConversion(ctx)
 
 		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		if errored(t, "", errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 		_, errs = ctx.ResolveDependencies(config)
-		if errored(t, "", errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 
@@ -533,38 +528,13 @@
 }
 
 func TestModuleTypeBp2Build(t *testing.T) {
-	otherGenruleBp := map[string]string{
-		"other/Android.bp": `genrule {
-    name: "foo.tool",
-    out: ["foo_tool.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-}
-genrule {
-    name: "other.tool",
-    out: ["other_tool.out"],
-    srcs: ["other_tool.in"],
-    cmd: "cp $(in) $(out)",
-}`,
-	}
-
-	testCases := []struct {
-		description                        string
-		moduleTypeUnderTest                string
-		moduleTypeUnderTestFactory         android.ModuleFactory
-		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
-		preArchMutators                    []android.RegisterMutatorFunc
-		bp                                 string
-		expectedBazelTargets               []string
-		fs                                 map[string]string
-		dir                                string
-	}{
+	testCases := []bp2buildTestCase{
 		{
 			description:                        "filegroup with does not specify srcs",
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     bazel_module: { bp2build_available: true },
 }`,
@@ -579,7 +549,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     srcs: [],
     bazel_module: { bp2build_available: true },
@@ -595,7 +565,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     srcs: ["a", "b"],
     bazel_module: { bp2build_available: true },
@@ -614,7 +584,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     srcs: ["a", "b"],
     exclude_srcs: ["a"],
@@ -631,7 +601,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "foo",
     srcs: ["**/*.txt"],
     bazel_module: { bp2build_available: true },
@@ -645,7 +615,7 @@
     ],
 )`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/a.txt":        "",
 				"other/b.txt":        "",
 				"other/subdir/a.txt": "",
@@ -657,7 +627,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "foo",
     srcs: ["a.txt"],
     bazel_module: { bp2build_available: true },
@@ -672,7 +642,7 @@
     ],
 )`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/Android.bp": `filegroup {
     name: "fg_foo",
     srcs: ["**/*.txt"],
@@ -689,7 +659,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "foobar",
     srcs: [
         ":foo",
@@ -705,207 +675,13 @@
     ],
 )`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/Android.bp": `filegroup {
     name: "foo",
     srcs: ["a", "b"],
 }`,
 			},
 		},
-		{
-			description:                        "genrule with command line variable replacements",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo.tool",
-    out: ["foo_tool.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}
-
-genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tool"],
-    cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{
-				`genrule(
-    name = "foo",
-    cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-    tools = [":foo.tool"],
-)`,
-				`genrule(
-    name = "foo.tool",
-    cmd = "cp $(SRCS) $(OUTS)",
-    outs = ["foo_tool.out"],
-    srcs = ["foo_tool.in"],
-)`,
-			},
-		},
-		{
-			description:                        "genrule using $(locations :label)",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo.tools",
-    out: ["foo_tool.out", "foo_tool2.out"],
-    srcs: ["foo_tool.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}
-
-genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tools"],
-    cmd: "$(locations :foo.tools) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-    tools = [":foo.tools"],
-)`,
-				`genrule(
-    name = "foo.tools",
-    cmd = "cp $(SRCS) $(OUTS)",
-    outs = [
-        "foo_tool.out",
-        "foo_tool2.out",
-    ],
-    srcs = ["foo_tool.in"],
-)`,
-			},
-		},
-		{
-			description:                        "genrule using $(locations //absolute:label)",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tool_files: [":foo.tool"],
-    cmd: "$(locations :foo.tool) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-    tools = ["//other:foo.tool"],
-)`,
-			},
-			fs: otherGenruleBp,
-		},
-		{
-			description:                        "genrule srcs using $(locations //absolute:label)",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: [":other.tool"],
-    tool_files: [":foo.tool"],
-    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
-    outs = ["foo.out"],
-    srcs = ["//other:other.tool"],
-    tools = ["//other:foo.tool"],
-)`,
-			},
-			fs: otherGenruleBp,
-		},
-		{
-			description:                        "genrule using $(location) label should substitute first tool label automatically",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tool_files: [":foo.tool", ":other.tool"],
-    cmd: "$(location) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-    tools = [
-        "//other:foo.tool",
-        "//other:other.tool",
-    ],
-)`,
-			},
-			fs: otherGenruleBp,
-		},
-		{
-			description:                        "genrule using $(locations) label should substitute first tool label automatically",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    tools: [":foo.tool", ":other.tool"],
-    cmd: "$(locations) -s $(out) $(in)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-    tools = [
-        "//other:foo.tool",
-        "//other:other.tool",
-    ],
-)`,
-			},
-			fs: otherGenruleBp,
-		},
-		{
-			description:                        "genrule without tools or tool_files can convert successfully",
-			moduleTypeUnderTest:                "genrule",
-			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
-			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
-			bp: `genrule {
-    name: "foo",
-    out: ["foo.out"],
-    srcs: ["foo.in"],
-    cmd: "cp $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}`,
-			expectedBazelTargets: []string{`genrule(
-    name = "foo",
-    cmd = "cp $(SRCS) $(OUTS)",
-    outs = ["foo.out"],
-    srcs = ["foo.in"],
-)`,
-			},
-		},
 	}
 
 	dir := "."
@@ -914,24 +690,24 @@
 		toParse := []string{
 			"Android.bp",
 		}
-		for f, content := range testCase.fs {
+		for f, content := range testCase.filesystem {
 			if strings.HasSuffix(f, "Android.bp") {
 				toParse = append(toParse, f)
 			}
 			fs[f] = []byte(content)
 		}
-		config := android.TestConfig(buildDir, nil, testCase.bp, fs)
+		config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
 		ctx := android.NewTestContext(config)
 		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
 		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
 		ctx.RegisterForBazelConversion()
 
 		_, errs := ctx.ParseFileList(dir, toParse)
-		if errored(t, testCase.description, errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 		_, errs = ctx.ResolveDependencies(config)
-		if errored(t, testCase.description, errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 
@@ -961,199 +737,6 @@
 
 type bp2buildMutator = func(android.TopDownMutatorContext)
 
-func TestBp2BuildInlinesDefaults(t *testing.T) {
-	testCases := []struct {
-		moduleTypesUnderTest      map[string]android.ModuleFactory
-		bp2buildMutatorsUnderTest map[string]bp2buildMutator
-		bp                        string
-		expectedBazelTarget       string
-		description               string
-	}{
-		{
-			moduleTypesUnderTest: map[string]android.ModuleFactory{
-				"genrule":          genrule.GenRuleFactory,
-				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
-			},
-			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
-				"genrule": genrule.GenruleBp2Build,
-			},
-			bp: `genrule_defaults {
-    name: "gen_defaults",
-    cmd: "do-something $(in) $(out)",
-}
-genrule {
-    name: "gen",
-    out: ["out"],
-    srcs: ["in1"],
-    defaults: ["gen_defaults"],
-    bazel_module: { bp2build_available: true },
-}
-`,
-			expectedBazelTarget: `genrule(
-    name = "gen",
-    cmd = "do-something $(SRCS) $(OUTS)",
-    outs = ["out"],
-    srcs = ["in1"],
-)`,
-			description: "genrule applies properties from a genrule_defaults dependency if not specified",
-		},
-		{
-			moduleTypesUnderTest: map[string]android.ModuleFactory{
-				"genrule":          genrule.GenRuleFactory,
-				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
-			},
-			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
-				"genrule": genrule.GenruleBp2Build,
-			},
-			bp: `genrule_defaults {
-    name: "gen_defaults",
-    out: ["out-from-defaults"],
-    srcs: ["in-from-defaults"],
-    cmd: "cmd-from-defaults",
-}
-genrule {
-    name: "gen",
-    out: ["out"],
-    srcs: ["in1"],
-    defaults: ["gen_defaults"],
-    cmd: "do-something $(in) $(out)",
-    bazel_module: { bp2build_available: true },
-}
-`,
-			expectedBazelTarget: `genrule(
-    name = "gen",
-    cmd = "do-something $(SRCS) $(OUTS)",
-    outs = [
-        "out-from-defaults",
-        "out",
-    ],
-    srcs = [
-        "in-from-defaults",
-        "in1",
-    ],
-)`,
-			description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
-		},
-		{
-			moduleTypesUnderTest: map[string]android.ModuleFactory{
-				"genrule":          genrule.GenRuleFactory,
-				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
-			},
-			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
-				"genrule": genrule.GenruleBp2Build,
-			},
-			bp: `genrule_defaults {
-    name: "gen_defaults1",
-    cmd: "cp $(in) $(out)",
-}
-
-genrule_defaults {
-    name: "gen_defaults2",
-    srcs: ["in1"],
-}
-
-genrule {
-    name: "gen",
-    out: ["out"],
-    defaults: ["gen_defaults1", "gen_defaults2"],
-    bazel_module: { bp2build_available: true },
-}
-`,
-			expectedBazelTarget: `genrule(
-    name = "gen",
-    cmd = "cp $(SRCS) $(OUTS)",
-    outs = ["out"],
-    srcs = ["in1"],
-)`,
-			description: "genrule applies properties from list of genrule_defaults",
-		},
-		{
-			moduleTypesUnderTest: map[string]android.ModuleFactory{
-				"genrule":          genrule.GenRuleFactory,
-				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
-			},
-			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
-				"genrule": genrule.GenruleBp2Build,
-			},
-			bp: `genrule_defaults {
-    name: "gen_defaults1",
-    defaults: ["gen_defaults2"],
-    cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
-}
-
-genrule_defaults {
-    name: "gen_defaults2",
-    defaults: ["gen_defaults3"],
-    cmd: "cmd2 $(in) $(out)",
-    out: ["out-from-2"],
-    srcs: ["in1"],
-}
-
-genrule_defaults {
-    name: "gen_defaults3",
-    out: ["out-from-3"],
-    srcs: ["srcs-from-3"],
-}
-
-genrule {
-    name: "gen",
-    out: ["out"],
-    defaults: ["gen_defaults1"],
-    bazel_module: { bp2build_available: true },
-}
-`,
-			expectedBazelTarget: `genrule(
-    name = "gen",
-    cmd = "cmd1 $(SRCS) $(OUTS)",
-    outs = [
-        "out-from-3",
-        "out-from-2",
-        "out",
-    ],
-    srcs = [
-        "srcs-from-3",
-        "in1",
-    ],
-)`,
-			description: "genrule applies properties from genrule_defaults transitively",
-		},
-	}
-
-	dir := "."
-	for _, testCase := range testCases {
-		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
-		ctx := android.NewTestContext(config)
-		for m, factory := range testCase.moduleTypesUnderTest {
-			ctx.RegisterModuleType(m, factory)
-		}
-		for mutator, f := range testCase.bp2buildMutatorsUnderTest {
-			ctx.RegisterBp2BuildMutator(mutator, f)
-		}
-		ctx.RegisterForBazelConversion()
-
-		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
-		android.FailIfErrored(t, errs)
-		_, errs = ctx.ResolveDependencies(config)
-		android.FailIfErrored(t, errs)
-
-		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
-		if actualCount := len(bazelTargets); actualCount != 1 {
-			t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
-		}
-
-		actualBazelTarget := bazelTargets[0]
-		if actualBazelTarget.content != testCase.expectedBazelTarget {
-			t.Errorf(
-				"%s: Expected generated Bazel target to be '%s', got '%s'",
-				testCase.description,
-				testCase.expectedBazelTarget,
-				actualBazelTarget.content,
-			)
-		}
-	}
-}
-
 func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
 	testCases := []struct {
 		moduleTypeUnderTest                string
@@ -1353,30 +936,20 @@
 }
 
 func TestCombineBuildFilesBp2buildTargets(t *testing.T) {
-	testCases := []struct {
-		description                        string
-		moduleTypeUnderTest                string
-		moduleTypeUnderTestFactory         android.ModuleFactory
-		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
-		preArchMutators                    []android.RegisterMutatorFunc
-		bp                                 string
-		expectedBazelTargets               []string
-		fs                                 map[string]string
-		dir                                string
-	}{
+	testCases := []bp2buildTestCase{
 		{
 			description:                        "filegroup bazel_module.label",
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     bazel_module: { label: "//other:fg_foo" },
 }`,
 			expectedBazelTargets: []string{
 				`// BUILD file`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/BUILD.bazel": `// BUILD file`,
 			},
 		},
@@ -1385,7 +958,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
 		    name: "fg_foo",
 		    bazel_module: { label: "//other:fg_foo" },
 		}
@@ -1397,7 +970,7 @@
 			expectedBazelTargets: []string{
 				`// BUILD file`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/BUILD.bazel": `// BUILD file`,
 			},
 		},
@@ -1407,8 +980,8 @@
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
 			dir:                                "other",
-			bp:                                 ``,
-			fs: map[string]string{
+			blueprint:                          ``,
+			filesystem: map[string]string{
 				"other/Android.bp": `filegroup {
 				name: "fg_foo",
 				bazel_module: {
@@ -1434,7 +1007,7 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
 		    name: "fg_foo",
 		    bazel_module: {
 		      label: "//other:fg_foo",
@@ -1453,7 +1026,7 @@
 )`,
 				`// BUILD file`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"other/BUILD.bazel": `// BUILD file`,
 			},
 		},
@@ -1466,24 +1039,24 @@
 			toParse := []string{
 				"Android.bp",
 			}
-			for f, content := range testCase.fs {
+			for f, content := range testCase.filesystem {
 				if strings.HasSuffix(f, "Android.bp") {
 					toParse = append(toParse, f)
 				}
 				fs[f] = []byte(content)
 			}
-			config := android.TestConfig(buildDir, nil, testCase.bp, fs)
+			config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
 			ctx := android.NewTestContext(config)
 			ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
 			ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
 			ctx.RegisterForBazelConversion()
 
 			_, errs := ctx.ParseFileList(dir, toParse)
-			if errored(t, testCase.description, errs) {
+			if errored(t, testCase, errs) {
 				return
 			}
 			_, errs = ctx.ResolveDependencies(config)
-			if errored(t, testCase.description, errs) {
+			if errored(t, testCase, errs) {
 				return
 			}
 
@@ -1517,22 +1090,13 @@
 }
 
 func TestGlobExcludeSrcs(t *testing.T) {
-	testCases := []struct {
-		description                        string
-		moduleTypeUnderTest                string
-		moduleTypeUnderTestFactory         android.ModuleFactory
-		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
-		bp                                 string
-		expectedBazelTargets               []string
-		fs                                 map[string]string
-		dir                                string
-	}{
+	testCases := []bp2buildTestCase{
 		{
 			description:                        "filegroup top level exclude_srcs",
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp: `filegroup {
+			blueprint: `filegroup {
     name: "fg_foo",
     srcs: ["**/*.txt"],
     exclude_srcs: ["c.txt"],
@@ -1548,7 +1112,7 @@
     ],
 )`,
 			},
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"a.txt":          "",
 				"b.txt":          "",
 				"c.txt":          "",
@@ -1562,9 +1126,9 @@
 			moduleTypeUnderTest:                "filegroup",
 			moduleTypeUnderTestFactory:         android.FileGroupFactory,
 			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
-			bp:                                 "",
+			blueprint:                          "",
 			dir:                                "dir",
-			fs: map[string]string{
+			filesystem: map[string]string{
 				"dir/Android.bp": `filegroup {
     name: "fg_foo",
     srcs: ["**/*.txt"],
@@ -1596,24 +1160,24 @@
 		toParse := []string{
 			"Android.bp",
 		}
-		for f, content := range testCase.fs {
+		for f, content := range testCase.filesystem {
 			if strings.HasSuffix(f, "Android.bp") {
 				toParse = append(toParse, f)
 			}
 			fs[f] = []byte(content)
 		}
-		config := android.TestConfig(buildDir, nil, testCase.bp, fs)
+		config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
 		ctx := android.NewTestContext(config)
 		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
 		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
 		ctx.RegisterForBazelConversion()
 
 		_, errs := ctx.ParseFileList(dir, toParse)
-		if errored(t, testCase.description, errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 		_, errs = ctx.ResolveDependencies(config)
-		if errored(t, testCase.description, errs) {
+		if errored(t, testCase, errs) {
 			continue
 		}
 
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index c840016..c2c35e7 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -25,18 +25,18 @@
 	// See cc/testing.go for more context
 	soongCcLibraryPreamble = `
 cc_defaults {
-  name: "linux_bionic_supported",
+    name: "linux_bionic_supported",
 }
 
 toolchain_library {
-  name: "libclang_rt.builtins-x86_64-android",
-  defaults: ["linux_bionic_supported"],
-  vendor_available: true,
-  vendor_ramdisk_available: true,
-  product_available: true,
-  recovery_available: true,
-  native_bridge_supported: true,
-  src: "",
+    name: "libclang_rt.builtins-x86_64-android",
+    defaults: ["linux_bionic_supported"],
+    vendor_available: true,
+    vendor_ramdisk_available: true,
+    product_available: true,
+    recovery_available: true,
+    native_bridge_supported: true,
+    src: "",
 }`
 )
 
@@ -113,17 +113,14 @@
           srcs: ["bionic.cpp"]
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo-lib",
-    copts = [
-        "-Wall",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
+    copts = ["-Wall"],
+    export_includes = ["foo-dir"],
     implementation_deps = [":some-headers"],
-    includes = ["foo-dir"],
     linkopts = ["-Wl,--exclude-libs=bar.a"] + select({
         "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
         "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
@@ -186,6 +183,7 @@
             ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
@@ -195,8 +193,6 @@
         "-Wextra",
         "-Wunused",
         "-Werror",
-        "-I.",
-        "-I$(BINDIR)/.",
     ],
     implementation_deps = [":libc_headers"],
     linkopts = [
@@ -277,12 +273,12 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
 		filesystem: map[string]string{
-			"foo/bar/both.cpp":       "",
-			"foo/bar/sharedonly.cpp": "",
-			"foo/bar/staticonly.cpp": "",
-			"foo/bar/Android.bp": `
+			"both.cpp":       "",
+			"sharedonly.cpp": "",
+			"staticonly.cpp": "",
+		},
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "a",
     srcs: ["both.cpp"],
@@ -304,36 +300,57 @@
         static_libs: ["static_dep_for_shared"],
         whole_static_libs: ["whole_static_lib_for_shared"],
     },
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 
-cc_library_static { name: "static_dep_for_shared" }
+cc_library_static {
+    name: "static_dep_for_shared",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library_static { name: "static_dep_for_static" }
+cc_library_static {
+    name: "static_dep_for_static",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library_static { name: "static_dep_for_both" }
+cc_library_static {
+    name: "static_dep_for_both",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library_static { name: "whole_static_lib_for_shared" }
+cc_library_static {
+    name: "whole_static_lib_for_shared",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library_static { name: "whole_static_lib_for_static" }
+cc_library_static {
+    name: "whole_static_lib_for_static",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library_static { name: "whole_static_lib_for_both" }
+cc_library_static {
+    name: "whole_static_lib_for_both",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library { name: "shared_dep_for_shared" }
+cc_library {
+    name: "shared_dep_for_shared",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library { name: "shared_dep_for_static" }
+cc_library {
+    name: "shared_dep_for_static",
+    bazel_module: { bp2build_available: false },
+}
 
-cc_library { name: "shared_dep_for_both" }
+cc_library {
+    name: "shared_dep_for_both",
+    bazel_module: { bp2build_available: false },
+}
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "bothflag",
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
+    copts = ["bothflag"],
     dynamic_deps = [":shared_dep_for_both"],
     implementation_deps = [":static_dep_for_both"],
     shared = {
@@ -374,6 +391,7 @@
         whole_static_libs: ["whole_static_lib_for_shared"],
     },
     bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 
 cc_prebuilt_library_static { name: "whole_static_lib_for_shared" }
@@ -386,10 +404,6 @@
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     shared = {
         "whole_archive_deps": [":whole_static_lib_for_shared_alwayslink"],
     },
@@ -574,24 +588,24 @@
         ":both_filegroup",
   ],
     static: {
-    srcs: [
-      "static_source.cpp",
-      "static_source.cc",
-      "static_source.c",
-      "static_source.s",
-      "static_source.S",
-      ":static_filegroup",
-    ],
+        srcs: [
+          "static_source.cpp",
+          "static_source.cc",
+          "static_source.c",
+          "static_source.s",
+          "static_source.S",
+          ":static_filegroup",
+        ],
     },
     shared: {
-    srcs: [
-      "shared_source.cpp",
-      "shared_source.cc",
-      "shared_source.c",
-      "shared_source.s",
-      "shared_source.S",
-      ":shared_filegroup",
-    ],
+        srcs: [
+          "shared_source.cpp",
+          "shared_source.cc",
+          "shared_source.c",
+          "shared_source.s",
+          "shared_source.S",
+          ":shared_filegroup",
+        ],
     },
     bazel_module: { bp2build_available: true },
 }
@@ -693,16 +707,13 @@
     srcs: ["a.cpp"],
     version_script: "v.map",
     bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 `,
 		},
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     srcs = ["a.cpp"],
     version_script = "v.map",
 )`},
@@ -718,29 +729,26 @@
 		dir:                                "foo/bar",
 		filesystem: map[string]string{
 			"foo/bar/Android.bp": `
-    cc_library {
-       name: "a",
-       srcs: ["a.cpp"],
-       arch: {
-         arm: {
-           version_script: "arm.map",
-         },
-         arm64: {
-           version_script: "arm64.map",
-         },
-       },
+cc_library {
+   name: "a",
+   srcs: ["a.cpp"],
+   arch: {
+     arm: {
+       version_script: "arm.map",
+     },
+     arm64: {
+       version_script: "arm64.map",
+     },
+   },
 
-       bazel_module: { bp2build_available: true },
-    }
+   bazel_module: { bp2build_available: true },
+    include_build_directory: false,
+}
     `,
 		},
 		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     srcs = ["a.cpp"],
     version_script = select({
         "//build/bazel/platforms/arch:arm": "arm.map",
@@ -757,35 +765,21 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "mylib",
-    bazel_module: { bp2build_available: true },
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library {
     name: "a",
     shared_libs: ["mylib",],
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     dynamic_deps = [":mylib"],
-)`, `cc_library(
-    name = "mylib",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
 )`},
 	})
 }
@@ -796,14 +790,12 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "a",
     srcs: ["a.cpp"],
     pack_relocations: false,
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 
 cc_library {
@@ -811,10 +803,10 @@
     srcs: ["b.cpp"],
     arch: {
         x86_64: {
-    pack_relocations: false,
-  },
+            pack_relocations: false,
+        },
     },
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 
 cc_library {
@@ -822,27 +814,17 @@
     srcs: ["c.cpp"],
     target: {
         darwin: {
-    pack_relocations: false,
-  },
+            pack_relocations: false,
+        },
     },
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }`,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     linkopts = ["-Wl,--pack-dyn-relocs=none"],
     srcs = ["a.cpp"],
 )`, `cc_library(
     name = "b",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     linkopts = select({
         "//build/bazel/platforms/arch:x86_64": ["-Wl,--pack-dyn-relocs=none"],
         "//conditions:default": [],
@@ -850,10 +832,6 @@
     srcs = ["b.cpp"],
 )`, `cc_library(
     name = "c",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     linkopts = select({
         "//build/bazel/platforms/os:darwin": ["-Wl,--pack-dyn-relocs=none"],
         "//conditions:default": [],
@@ -869,24 +847,18 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "a",
     cflags: ["-include header.h",],
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
     copts = [
         "-include",
         "header.h",
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
     ],
 )`},
 	})
@@ -898,40 +870,30 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `cc_library {
+		blueprint: soongCcLibraryPreamble + `cc_library {
     name: "a",
     srcs: ["a.cpp"],
-    cflags: [
-    "-Wall",
-  ],
+    cflags: ["-Wall"],
     cppflags: [
         "-fsigned-char",
         "-pedantic",
-  ],
+    ],
     arch: {
         arm64: {
             cppflags: ["-DARM64=1"],
+        },
     },
-  },
     target: {
         android: {
             cppflags: ["-DANDROID=1"],
+        },
     },
-  },
-    bazel_module: { bp2build_available: true  },
+    include_build_directory: false,
 }
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Wall",
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
+    copts = ["-Wall"],
     cppflags = [
         "-fsigned-char",
         "-pedantic",
@@ -953,32 +915,23 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
-    cc_library {
-       name: "a",
-       srcs: ["a.cpp"],
-       target: {
-         android_arm: {
-           version_script: "android_arm.map",
-         },
-         linux_bionic_arm64: {
-           version_script: "linux_bionic_arm64.map",
-         },
-       },
-
-       bazel_module: { bp2build_available: true },
-    }
+		blueprint: soongCcLibraryPreamble + `
+cc_library {
+   name: "a",
+   srcs: ["a.cpp"],
+   target: {
+     android_arm: {
+       version_script: "android_arm.map",
+     },
+     linux_bionic_arm64: {
+       version_script: "linux_bionic_arm64.map",
+     },
+   },
+    include_build_directory: false,
+}
     `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     srcs = ["a.cpp"],
     version_script = select({
         "//build/bazel/platforms/os_arch:android_arm": "android_arm.map",
@@ -1031,6 +984,7 @@
             ],
         },
     },
+    include_build_directory: false,
 }
 
 cc_library {
@@ -1071,10 +1025,6 @@
 		expectedBazelTargets: []string{
 			`cc_library(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     dynamic_deps = select({
         "//build/bazel/platforms/arch:arm": [],
         "//conditions:default": [":arm_shared_lib_excludes"],
@@ -1117,14 +1067,11 @@
     name: "foo-lib",
     srcs: ["impl.cpp"],
     no_libcrt: true,
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     srcs = ["impl.cpp"],
     use_libcrt = False,
 )`}})
@@ -1144,14 +1091,11 @@
     name: "foo-lib",
     srcs: ["impl.cpp"],
     no_libcrt: false,
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     srcs = ["impl.cpp"],
     use_libcrt = True,
 )`}})
@@ -1166,7 +1110,6 @@
 			"impl.cpp": "",
 		},
 		blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
 cc_library {
     name: "foo-lib",
     srcs: ["impl.cpp"],
@@ -1178,14 +1121,11 @@
             no_libcrt: true,
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     srcs = ["impl.cpp"],
     use_libcrt = select({
         "//build/bazel/platforms/arch:arm": False,
@@ -1204,7 +1144,6 @@
 			"impl.cpp": "",
 		},
 		blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
 cc_library {
     name: "foo-lib",
     srcs: ["impl.cpp"],
@@ -1217,14 +1156,11 @@
             no_libcrt: true,
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     srcs = ["impl.cpp"],
     use_libcrt = select({
         "//build/bazel/platforms/arch:arm": False,
@@ -1240,102 +1176,74 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "nothing",
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }
 cc_library {
     name: "keep_symbols",
-    bazel_module: { bp2build_available: true },
     strip: {
-		keep_symbols: true,
-	}
+        keep_symbols: true,
+    },
+    include_build_directory: false,
 }
 cc_library {
     name: "keep_symbols_and_debug_frame",
-    bazel_module: { bp2build_available: true },
     strip: {
-		keep_symbols_and_debug_frame: true,
-	}
+        keep_symbols_and_debug_frame: true,
+    },
+    include_build_directory: false,
 }
 cc_library {
     name: "none",
-    bazel_module: { bp2build_available: true },
     strip: {
-		none: true,
-	}
+        none: true,
+    },
+    include_build_directory: false,
 }
 cc_library {
     name: "keep_symbols_list",
-    bazel_module: { bp2build_available: true },
     strip: {
-		keep_symbols_list: ["symbol"],
-	}
+        keep_symbols_list: ["symbol"],
+    },
+    include_build_directory: false,
 }
 cc_library {
     name: "all",
-    bazel_module: { bp2build_available: true },
     strip: {
-		all: true,
-	}
+        all: true,
+    },
+    include_build_directory: false,
 }
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "all",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "all": True,
     },
 )`, `cc_library(
     name = "keep_symbols",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "keep_symbols": True,
     },
 )`, `cc_library(
     name = "keep_symbols_and_debug_frame",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "keep_symbols_and_debug_frame": True,
     },
 )`, `cc_library(
     name = "keep_symbols_list",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "keep_symbols_list": ["symbol"],
     },
 )`, `cc_library(
     name = "none",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "none": True,
     },
 )`, `cc_library(
     name = "nothing",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
 )`},
 	})
 }
@@ -1346,12 +1254,9 @@
 		moduleTypeUnderTest:                "cc_library",
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
-		dir:                                "foo/bar",
-		filesystem: map[string]string{
-			"foo/bar/Android.bp": `
+		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "multi-arch",
-    bazel_module: { bp2build_available: true },
     target: {
         darwin: {
             strip: {
@@ -1370,17 +1275,12 @@
                 keep_symbols: true,
             },
         },
-    }
+    },
+    include_build_directory: false,
 }
 `,
-		},
-		blueprint: soongCcLibraryPreamble,
 		expectedBazelTargets: []string{`cc_library(
     name = "multi-arch",
-    copts = [
-        "-Ifoo/bar",
-        "-I$(BINDIR)/foo/bar",
-    ],
     strip = {
         "keep_symbols": select({
             "//build/bazel/platforms/arch:arm64": True,
@@ -1411,15 +1311,12 @@
 		blueprint: soongCcLibraryPreamble + `
 cc_library {
     name: "root_empty",
-	  system_shared_libs: [],
+    system_shared_libs: [],
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "root_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     system_dynamic_deps = [],
 )`},
 	})
@@ -1435,16 +1332,13 @@
 cc_library {
     name: "static_empty",
     static: {
-				system_shared_libs: [],
-		},
+        system_shared_libs: [],
+    },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "static_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     static = {
         "system_dynamic_deps": [],
     },
@@ -1462,16 +1356,13 @@
 cc_library {
     name: "shared_empty",
     shared: {
-				system_shared_libs: [],
-		},
+        system_shared_libs: [],
+    },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "shared_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     shared = {
         "system_dynamic_deps": [],
     },
@@ -1494,15 +1385,12 @@
                 system_shared_libs: [],
             }
         }
-		},
+    },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "shared_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     shared = {
         "system_dynamic_deps": [],
     },
@@ -1528,14 +1416,11 @@
             system_shared_libs: [],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "target_linux_bionic_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     system_dynamic_deps = [],
 )`},
 	})
@@ -1555,14 +1440,11 @@
             system_shared_libs: [],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "target_bionic_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     system_dynamic_deps = [],
 )`},
 	})
@@ -1575,39 +1457,30 @@
 		moduleTypeUnderTestFactory:         cc.LibraryFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
 		blueprint: soongCcLibraryPreamble + `
-cc_library {name: "libc"}
-cc_library {name: "libm"}
+cc_library {
+    name: "libc",
+    bazel_module: { bp2build_available: false },
+}
+cc_library {
+    name: "libm",
+    bazel_module: { bp2build_available: false },
+}
 
 cc_library {
     name: "foo",
     system_shared_libs: ["libc"],
     shared: {
-				system_shared_libs: ["libm"],
+        system_shared_libs: ["libm"],
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "foo",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     shared = {
         "system_dynamic_deps": [":libm"],
     },
     system_dynamic_deps = [":libc"],
-)`, `cc_library(
-    name = "libc",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library(
-    name = "libm",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
 )`},
 	})
 }
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index ea2c10a..8b490f8 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -25,18 +25,18 @@
 	// See cc/testing.go for more context
 	soongCcLibraryHeadersPreamble = `
 cc_defaults {
-	name: "linux_bionic_supported",
+    name: "linux_bionic_supported",
 }
 
 toolchain_library {
-	name: "libclang_rt.builtins-x86_64-android",
-	defaults: ["linux_bionic_supported"],
-	vendor_available: true,
-	vendor_ramdisk_available: true,
-	product_available: true,
-	recovery_available: true,
-	native_bridge_supported: true,
-	src: "",
+    name: "libclang_rt.builtins-x86_64-android",
+    defaults: ["linux_bionic_supported"],
+    vendor_available: true,
+    vendor_ramdisk_available: true,
+    product_available: true,
+    recovery_available: true,
+    native_bridge_supported: true,
+    src: "",
 }`
 )
 
@@ -99,11 +99,13 @@
 cc_library_headers {
     name: "lib-1",
     export_include_dirs: ["lib-1"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_headers {
     name: "lib-2",
     export_include_dirs: ["lib-2"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_headers {
@@ -113,7 +115,7 @@
 
     arch: {
         arm64: {
-	    // We expect dir-1 headers to be dropped, because dir-1 is already in export_include_dirs
+      // We expect dir-1 headers to be dropped, because dir-1 is already in export_include_dirs
             export_include_dirs: ["arch_arm64_exported_include_dir", "dir-1"],
         },
         x86: {
@@ -132,11 +134,7 @@
         "-I.",
         "-I$(BINDIR)/.",
     ],
-    implementation_deps = [
-        ":lib-1",
-        ":lib-2",
-    ],
-    includes = [
+    export_includes = [
         "dir-1",
         "dir-2",
     ] + select({
@@ -145,25 +143,15 @@
         "//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir"],
         "//conditions:default": [],
     }),
-)`, `cc_library_headers(
-    name = "lib-1",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
+    implementation_deps = [
+        ":lib-1",
+        ":lib-2",
     ],
-    includes = ["lib-1"],
-)`, `cc_library_headers(
-    name = "lib-2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    includes = ["lib-2"],
 )`},
 	})
 }
 
-func TestCcLibraryHeadersOSSpecificHeader(t *testing.T) {
+func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
 	runCcLibraryHeadersTestCase(t, bp2buildTestCase{
 		description:                        "cc_library_headers test with os-specific header_libs props",
 		moduleTypeUnderTest:                "cc_library_headers",
@@ -171,12 +159,30 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "android-lib" }
-cc_library_headers { name: "base-lib" }
-cc_library_headers { name: "darwin-lib" }
-cc_library_headers { name: "linux-lib" }
-cc_library_headers { name: "linux_bionic-lib" }
-cc_library_headers { name: "windows-lib" }
+cc_library_headers {
+    name: "android-lib",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_headers {
+    name: "base-lib",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_headers {
+    name: "darwin-lib",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_headers {
+    name: "linux-lib",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_headers {
+    name: "linux_bionic-lib",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_headers {
+    name: "windows-lib",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_headers {
     name: "foo_headers",
     header_libs: ["base-lib"],
@@ -187,32 +193,10 @@
         linux_glibc: { header_libs: ["linux-lib"] },
         windows: { header_libs: ["windows-lib"] },
     },
-    bazel_module: { bp2build_available: true },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_headers(
-    name = "android-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
-    name = "base-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
-    name = "darwin-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
     name = "foo_headers",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     implementation_deps = [":base-lib"] + select({
         "//build/bazel/platforms/os:android": [":android-lib"],
         "//build/bazel/platforms/os:darwin": [":darwin-lib"],
@@ -221,24 +205,6 @@
         "//build/bazel/platforms/os:windows": [":windows-lib"],
         "//conditions:default": [],
     }),
-)`, `cc_library_headers(
-    name = "linux-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
-    name = "linux_bionic-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
-    name = "windows-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
 )`},
 	})
 }
@@ -251,32 +217,23 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "android-lib" }
-cc_library_headers { name: "exported-lib" }
+cc_library_headers {
+    name: "android-lib",
+    bazel_module: { bp2build_available: false },
+  }
+cc_library_headers {
+    name: "exported-lib",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_headers {
     name: "foo_headers",
     target: {
         android: { header_libs: ["android-lib"], export_header_lib_headers: ["exported-lib"] },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_headers(
-    name = "android-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
-    name = "exported-lib",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-)`, `cc_library_headers(
     name = "foo_headers",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     deps = select({
         "//build/bazel/platforms/os:android": [":exported-lib"],
         "//conditions:default": [],
@@ -299,14 +256,14 @@
 		blueprint: soongCcLibraryPreamble + `cc_library_headers {
     name: "foo_headers",
     export_system_include_dirs: [
-	"shared_include_dir",
+        "shared_include_dir",
     ],
     target: {
-	android: {
-	    export_system_include_dirs: [
-		"android_include_dir",
+        android: {
+            export_system_include_dirs: [
+                "android_include_dir",
             ],
-	},
+        },
         linux_glibc: {
             export_system_include_dirs: [
                 "linux_include_dir",
@@ -320,24 +277,21 @@
     },
     arch: {
         arm: {
-	    export_system_include_dirs: [
-		"arm_include_dir",
+            export_system_include_dirs: [
+                "arm_include_dir",
             ],
-	},
+        },
         x86_64: {
             export_system_include_dirs: [
                 "x86_64_include_dir",
             ],
         },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_headers(
     name = "foo_headers",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    includes = ["shared_include_dir"] + select({
+    export_system_includes = ["shared_include_dir"] + select({
         "//build/bazel/platforms/arch:arm": ["arm_include_dir"],
         "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
         "//conditions:default": [],
@@ -375,14 +329,11 @@
     name: "lib-1",
     export_include_dirs: ["lib-1"],
     no_libcrt: true,
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_headers(
     name = "lib-1",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    includes = ["lib-1"],
+    export_includes = ["lib-1"],
 )`},
 	})
 }
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index d9145f6..5c9afbf 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -26,18 +26,18 @@
 	// See cc/testing.go for more context
 	soongCcLibraryStaticPreamble = `
 cc_defaults {
-	name: "linux_bionic_supported",
+    name: "linux_bionic_supported",
 }
 
 toolchain_library {
-	name: "libclang_rt.builtins-x86_64-android",
-	defaults: ["linux_bionic_supported"],
-	vendor_available: true,
-	vendor_ramdisk_available: true,
-	product_available: true,
-	recovery_available: true,
-	native_bridge_supported: true,
-	src: "",
+    name: "libclang_rt.builtins-x86_64-android",
+    defaults: ["linux_bionic_supported"],
+    vendor_available: true,
+    vendor_ramdisk_available: true,
+    product_available: true,
+    recovery_available: true,
+    native_bridge_supported: true,
+    src: "",
 }`
 )
 
@@ -112,31 +112,37 @@
 cc_library_headers {
     name: "header_lib_1",
     export_include_dirs: ["header_lib_1"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_headers {
     name: "header_lib_2",
     export_include_dirs: ["header_lib_2"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_lib_1",
     srcs: ["static_lib_1.cc"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "static_lib_2",
     srcs: ["static_lib_2.cc"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_1",
     srcs: ["whole_static_lib_1.cc"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
     name: "whole_static_lib_2",
     srcs: ["whole_static_lib_2.cc"],
+    bazel_module: { bp2build_available: false },
 }
 
 cc_library_static {
@@ -192,16 +198,16 @@
         "-I.",
         "-I$(BINDIR)/.",
     ],
+    export_includes = [
+        "export_include_dir_1",
+        "export_include_dir_2",
+    ],
     implementation_deps = [
         ":header_lib_1",
         ":header_lib_2",
         ":static_lib_1",
         ":static_lib_2",
     ],
-    includes = [
-        "export_include_dir_1",
-        "export_include_dir_2",
-    ],
     linkstatic = True,
     srcs = [
         "foo_static1.cc",
@@ -211,38 +217,6 @@
         ":whole_static_lib_1",
         ":whole_static_lib_2",
     ],
-)`, `cc_library_static(
-    name = "static_lib_1",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-    srcs = ["static_lib_1.cc"],
-)`, `cc_library_static(
-    name = "static_lib_2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-    srcs = ["static_lib_2.cc"],
-)`, `cc_library_static(
-    name = "whole_static_lib_1",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-    srcs = ["whole_static_lib_1.cc"],
-)`, `cc_library_static(
-    name = "whole_static_lib_2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-    srcs = ["whole_static_lib_2.cc"],
 )`},
 	})
 }
@@ -273,7 +247,7 @@
     srcs: [
     ],
     include_dirs: [
-	"subpackage",
+  "subpackage",
     ],
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
@@ -305,14 +279,11 @@
 cc_library_static {
     name: "foo_static",
     export_include_dirs: ["subpackage"],
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    includes = ["subpackage"],
+    export_includes = ["subpackage"],
     linkstatic = True,
 )`},
 	})
@@ -334,14 +305,11 @@
 cc_library_static {
     name: "foo_static",
     export_system_include_dirs: ["subpackage"],
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    includes = ["subpackage"],
+    export_system_includes = ["subpackage"],
     linkstatic = True,
 )`},
 	})
@@ -391,7 +359,7 @@
         "-Isubpackage",
         "-I$(BINDIR)/subpackage",
     ],
-    includes = ["./exported_subsubpackage"],
+    export_includes = ["./exported_subsubpackage"],
     linkstatic = True,
 )`},
 	})
@@ -473,18 +441,21 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static { name: "static_dep" }
-cc_library_static { name: "static_dep2" }
+cc_library_static {
+    name: "static_dep",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_static {
+    name: "static_dep2",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_static {
     name: "foo_static",
     arch: { arm64: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     implementation_deps = select({
         "//build/bazel/platforms/arch:arm64": [":static_dep"],
         "//conditions:default": [],
@@ -494,20 +465,6 @@
         "//build/bazel/platforms/arch:arm64": [":static_dep2"],
         "//conditions:default": [],
     }),
-)`, `cc_library_static(
-    name = "static_dep",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
 )`},
 	})
 }
@@ -520,18 +477,21 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static { name: "static_dep" }
-cc_library_static { name: "static_dep2" }
+cc_library_static {
+    name: "static_dep",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_static {
+    name: "static_dep2",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_static {
     name: "foo_static",
     target: { android: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     implementation_deps = select({
         "//build/bazel/platforms/os:android": [":static_dep"],
         "//conditions:default": [],
@@ -541,20 +501,6 @@
         "//build/bazel/platforms/os:android": [":static_dep2"],
         "//conditions:default": [],
     }),
-)`, `cc_library_static(
-    name = "static_dep",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
 )`},
 	})
 }
@@ -567,23 +513,32 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static { name: "static_dep" }
-cc_library_static { name: "static_dep2" }
-cc_library_static { name: "static_dep3" }
-cc_library_static { name: "static_dep4" }
+cc_library_static {
+    name: "static_dep",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_static {
+    name: "static_dep2",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_static {
+    name: "static_dep3",
+    bazel_module: { bp2build_available: false },
+}
+cc_library_static {
+    name: "static_dep4",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_static {
     name: "foo_static",
     static_libs: ["static_dep"],
     whole_static_libs: ["static_dep2"],
     target: { android: { static_libs: ["static_dep3"] } },
     arch: { arm64: { static_libs: ["static_dep4"] } },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     implementation_deps = [":static_dep"] + select({
         "//build/bazel/platforms/arch:arm64": [":static_dep4"],
         "//conditions:default": [],
@@ -593,34 +548,6 @@
     }),
     linkstatic = True,
     whole_archive_deps = [":static_dep2"],
-)`, `cc_library_static(
-    name = "static_dep",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep3",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep4",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
 )`},
 	})
 }
@@ -641,13 +568,10 @@
     name: "foo_static",
     srcs: ["common.c", "foo-*.c"],
     exclude_srcs: ["foo-excluded.c"],
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = [
         "common.c",
@@ -671,14 +595,11 @@
 cc_library_static {
     name: "foo_static",
     srcs: ["common.c"],
-    arch: { arm: { srcs: ["foo-arm.c"] } }
+    arch: { arm: { srcs: ["foo-arm.c"] } },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": ["foo-arm.c"],
@@ -708,13 +629,10 @@
     arch: {
         arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": ["for-arm.c"],
@@ -746,13 +664,10 @@
         arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
         x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
     },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
@@ -799,14 +714,11 @@
         arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
         x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
         x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
-	},
+  },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
@@ -863,13 +775,10 @@
     arch: {
         arm: { exclude_srcs: ["foo-no-arm.cc"] },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs = ["common.cc"] + select({
         "//build/bazel/platforms/arch:arm": [],
@@ -900,13 +809,10 @@
         arm: { exclude_srcs: ["foo-no-arm.cc"] },
         x86: { srcs: ["x86-only.cc"] },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs = ["common.cc"] + select({
         "//build/bazel/platforms/arch:arm": [],
@@ -928,26 +834,19 @@
 		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
 		filesystem:                         map[string]string{},
 		blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static { name: "static_dep" }
+cc_library_static {
+    name: "static_dep",
+    bazel_module: { bp2build_available: false },
+}
 cc_library_static {
     name: "foo_static",
     static_libs: ["static_dep", "static_dep"],
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     implementation_deps = [":static_dep"],
     linkstatic = True,
-)`, `cc_library_static(
-    name = "static_dep",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
-    linkstatic = True,
 )`},
 	})
 }
@@ -970,13 +869,10 @@
     multilib: {
         lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
     },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": ["for-lib32.c"],
@@ -1008,13 +904,10 @@
         lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
         lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
     },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static2",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
@@ -1079,13 +972,10 @@
        lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
        lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
    },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static3",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = ["common.c"] + select({
         "//build/bazel/platforms/arch:arm": [
@@ -1146,21 +1036,21 @@
 			"not-for-everything.cpp": "",
 			"dep/Android.bp": `
 genrule {
-	name: "generated_src_other_pkg",
-	out: ["generated_src_other_pkg.cpp"],
-	cmd: "nothing to see here",
+  name: "generated_src_other_pkg",
+  out: ["generated_src_other_pkg.cpp"],
+  cmd: "nothing to see here",
 }
 
 genrule {
-	name: "generated_hdr_other_pkg",
-	out: ["generated_hdr_other_pkg.cpp"],
-	cmd: "nothing to see here",
+  name: "generated_hdr_other_pkg",
+  out: ["generated_hdr_other_pkg.cpp"],
+  cmd: "nothing to see here",
 }
 
 genrule {
-	name: "generated_hdr_other_pkg_x86",
-	out: ["generated_hdr_other_pkg_x86.cpp"],
-	cmd: "nothing to see here",
+  name: "generated_hdr_other_pkg_x86",
+  out: ["generated_hdr_other_pkg_x86.cpp"],
+  cmd: "nothing to see here",
 }`,
 		},
 		blueprint: soongCcLibraryStaticPreamble + `
@@ -1196,14 +1086,11 @@
            generated_headers: ["generated_hdr_other_pkg_x86"],
        },
    },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static3",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs = [
         "//dep:generated_hdr_other_pkg",
@@ -1256,13 +1143,10 @@
             srcs: ["linux_bionic_x86_64_src.c"],
         },
     },
+    include_build_directory: false,
 }`,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_c = select({
         "//build/bazel/platforms/os:android": ["android_src.c"],
@@ -1301,13 +1185,11 @@
         cflags: ["-Wbinder32bit"],
       },
     },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    copts = select({
         "//build/bazel/product_variables:binder32bit": ["-Wbinder32bit"],
         "//conditions:default": [],
     }) + select({
@@ -1339,40 +1221,38 @@
         cflags: ["-Wmalloc_not_svelte"],
       },
     },
-		arch: {
-				arm64: {
-						product_variables: {
-								malloc_not_svelte: {
-										cflags: ["-Warm64_malloc_not_svelte"],
-								},
-						},
-				},
-		},
-		multilib: {
-				lib32: {
-						product_variables: {
-								malloc_not_svelte: {
-										cflags: ["-Wlib32_malloc_not_svelte"],
-								},
-						},
-				},
-		},
-		target: {
-				android: {
-						product_variables: {
-								malloc_not_svelte: {
-										cflags: ["-Wandroid_malloc_not_svelte"],
-								},
-						},
-				}
-		},
+    arch: {
+        arm64: {
+            product_variables: {
+                malloc_not_svelte: {
+                    cflags: ["-Warm64_malloc_not_svelte"],
+                },
+            },
+        },
+    },
+    multilib: {
+        lib32: {
+            product_variables: {
+                malloc_not_svelte: {
+                    cflags: ["-Wlib32_malloc_not_svelte"],
+                },
+            },
+        },
+    },
+    target: {
+        android: {
+            product_variables: {
+                malloc_not_svelte: {
+                    cflags: ["-Wandroid_malloc_not_svelte"],
+                },
+            },
+        }
+    },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    copts = select({
         "//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"],
         "//conditions:default": [],
     }) + select({
@@ -1410,20 +1290,14 @@
           asflags: ["-DPLATFORM_SDK_VERSION=%d"],
       },
     },
+    include_build_directory: false,
 } `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
-    asflags = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    asflags = select({
         "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
         "//conditions:default": [],
     }),
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     srcs_as = ["common.S"],
 )`},
@@ -1439,15 +1313,12 @@
 		blueprint: soongCcLibraryStaticPreamble + `
 cc_library_static {
     name: "root_empty",
-	  system_shared_libs: [],
+    system_shared_libs: [],
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "root_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = [],
 )`},
@@ -1464,20 +1335,17 @@
 cc_defaults {
     name: "static_empty_defaults",
     static: {
-				system_shared_libs: [],
-		},
+        system_shared_libs: [],
+    },
+    include_build_directory: false,
 }
 cc_library_static {
     name: "static_empty",
-	  defaults: ["static_empty_defaults"],
+    defaults: ["static_empty_defaults"],
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "static_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = [],
 )`},
@@ -1498,14 +1366,11 @@
             system_shared_libs: [],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "target_bionic_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = [],
 )`},
@@ -1530,14 +1395,11 @@
             system_shared_libs: [],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "target_linux_bionic_empty",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = [],
 )`},
@@ -1560,14 +1422,11 @@
             system_shared_libs: ["libc"],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "target_bionic",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = select({
         "//build/bazel/platforms/os:bionic": [":libc"],
@@ -1589,20 +1448,17 @@
 
 cc_library_static {
     name: "target_linux_bionic",
-		system_shared_libs: ["libc"],
+    system_shared_libs: ["libc"],
     target: {
         linux_bionic: {
             system_shared_libs: ["libm"],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_library_static(
     name = "target_linux_bionic",
-    copts = [
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
     linkstatic = True,
     system_dynamic_deps = [":libc"] + select({
         "//build/bazel/platforms/os:linux_bionic": [":libm"],
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 9ac28a5..4bda539 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -78,14 +78,12 @@
 
 func TestCcObjectDefaults(t *testing.T) {
 	runCcObjectTestCase(t, bp2buildTestCase{
-		description:                        "simple cc_object with defaults",
 		moduleTypeUnderTest:                "cc_object",
 		moduleTypeUnderTestFactory:         cc.ObjectFactory,
 		moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
 		blueprint: `cc_object {
     name: "foo",
     system_shared_libs: [],
-    local_include_dirs: ["include"],
     srcs: [
         "a/b/*.h",
         "a/b/c.c"
@@ -115,8 +113,6 @@
         "-Wall",
         "-Werror",
         "-fno-addrsig",
-        "-Iinclude",
-        "-I$(BINDIR)/include",
         "-I.",
         "-I$(BINDIR)/.",
     ],
@@ -140,29 +136,23 @@
     system_shared_libs: [],
     srcs: ["a/b/c.c"],
     objs: ["bar"],
+    include_build_directory: false,
 }
 
 cc_object {
     name: "bar",
     system_shared_libs: [],
     srcs: ["x/y/z.c"],
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{`cc_object(
     name = "bar",
-    copts = [
-        "-fno-addrsig",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
+    copts = ["-fno-addrsig"],
     srcs = ["x/y/z.c"],
 )`, `cc_object(
     name = "foo",
-    copts = [
-        "-fno-addrsig",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ],
+    copts = ["-fno-addrsig"],
     deps = [":bar"],
     srcs = ["a/b/c.c"],
 )`,
@@ -245,16 +235,13 @@
             srcs: ["arch/arm/file.cpp"], // label list
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{
 			`cc_object(
     name = "foo",
-    copts = [
-        "-fno-addrsig",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    copts = ["-fno-addrsig"] + select({
         "//build/bazel/platforms/arch:x86": ["-fPIC"],
         "//conditions:default": [],
     }),
@@ -295,16 +282,13 @@
             cflags: ["-Wall"],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{
 			`cc_object(
     name = "foo",
-    copts = [
-        "-fno-addrsig",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    copts = ["-fno-addrsig"] + select({
         "//build/bazel/platforms/arch:arm": ["-Wall"],
         "//build/bazel/platforms/arch:arm64": ["-Wall"],
         "//build/bazel/platforms/arch:x86": ["-fPIC"],
@@ -344,16 +328,13 @@
             cflags: ["-Wall"],
         },
     },
+    include_build_directory: false,
 }
 `,
 		expectedBazelTargets: []string{
 			`cc_object(
     name = "foo",
-    copts = [
-        "-fno-addrsig",
-        "-I.",
-        "-I$(BINDIR)/.",
-    ] + select({
+    copts = ["-fno-addrsig"] + select({
         "//build/bazel/platforms/os:android": ["-fPIC"],
         "//build/bazel/platforms/os:darwin": ["-Wall"],
         "//build/bazel/platforms/os:windows": ["-fPIC"],
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
new file mode 100644
index 0000000..ad99236
--- /dev/null
+++ b/bp2build/filegroup_conversion_test.go
@@ -0,0 +1,62 @@
+// Copyright 2021 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 bp2build
+
+import (
+	"android/soong/android"
+	"fmt"
+
+	"testing"
+)
+
+func runFilegroupTestCase(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	runBp2BuildTestCase(t, registerFilegroupModuleTypes, tc)
+}
+
+func registerFilegroupModuleTypes(ctx android.RegistrationContext) {}
+
+func TestFilegroupSameNameAsFile_OneFile(t *testing.T) {
+	runFilegroupTestCase(t, bp2buildTestCase{
+		description:                        "filegroup - same name as file, with one file",
+		moduleTypeUnderTest:                "filegroup",
+		moduleTypeUnderTestFactory:         android.FileGroupFactory,
+		moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+		filesystem:                         map[string]string{},
+		blueprint: `
+filegroup {
+    name: "foo",
+    srcs: ["foo"],
+}
+`,
+		expectedBazelTargets: []string{}})
+}
+
+func TestFilegroupSameNameAsFile_MultipleFiles(t *testing.T) {
+	runFilegroupTestCase(t, bp2buildTestCase{
+		description:                        "filegroup - same name as file, with multiple files",
+		moduleTypeUnderTest:                "filegroup",
+		moduleTypeUnderTestFactory:         android.FileGroupFactory,
+		moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+		filesystem:                         map[string]string{},
+		blueprint: `
+filegroup {
+	name: "foo",
+	srcs: ["foo", "bar"],
+}
+`,
+		expectedErr: fmt.Errorf("filegroup 'foo' cannot contain a file with the same name"),
+	})
+}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
new file mode 100644
index 0000000..a991180
--- /dev/null
+++ b/bp2build/genrule_conversion_test.go
@@ -0,0 +1,479 @@
+// Copyright 2021 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 bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/genrule"
+	"strings"
+	"testing"
+)
+
+func TestGenruleBp2Build(t *testing.T) {
+	otherGenruleBp := map[string]string{
+		"other/Android.bp": `genrule {
+    name: "foo.tool",
+    out: ["foo_tool.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+}
+genrule {
+    name: "other.tool",
+    out: ["other_tool.out"],
+    srcs: ["other_tool.in"],
+    cmd: "cp $(in) $(out)",
+}`,
+	}
+
+	testCases := []bp2buildTestCase{
+		{
+			description:                        "genrule with command line variable replacements",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo.tool",
+    out: ["foo_tool.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+    bazel_module: { bp2build_available: true },
+}
+
+genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tools: [":foo.tool"],
+    cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{
+				`genrule(
+    name = "foo",
+    cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+    tools = [":foo.tool"],
+)`,
+				`genrule(
+    name = "foo.tool",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = ["foo_tool.out"],
+    srcs = ["foo_tool.in"],
+)`,
+			},
+		},
+		{
+			description:                        "genrule using $(locations :label)",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo.tools",
+    out: ["foo_tool.out", "foo_tool2.out"],
+    srcs: ["foo_tool.in"],
+    cmd: "cp $(in) $(out)",
+    bazel_module: { bp2build_available: true },
+}
+
+genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tools: [":foo.tools"],
+    cmd: "$(locations :foo.tools) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+    tools = [":foo.tools"],
+)`,
+				`genrule(
+    name = "foo.tools",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = [
+        "foo_tool.out",
+        "foo_tool2.out",
+    ],
+    srcs = ["foo_tool.in"],
+)`,
+			},
+		},
+		{
+			description:                        "genrule using $(locations //absolute:label)",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tool_files: [":foo.tool"],
+    cmd: "$(locations :foo.tool) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+    tools = ["//other:foo.tool"],
+)`,
+			},
+			filesystem: otherGenruleBp,
+		},
+		{
+			description:                        "genrule srcs using $(locations //absolute:label)",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: [":other.tool"],
+    tool_files: [":foo.tool"],
+    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
+    outs = ["foo.out"],
+    srcs = ["//other:other.tool"],
+    tools = ["//other:foo.tool"],
+)`,
+			},
+			filesystem: otherGenruleBp,
+		},
+		{
+			description:                        "genrule using $(location) label should substitute first tool label automatically",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tool_files: [":foo.tool", ":other.tool"],
+    cmd: "$(location) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+    tools = [
+        "//other:foo.tool",
+        "//other:other.tool",
+    ],
+)`,
+			},
+			filesystem: otherGenruleBp,
+		},
+		{
+			description:                        "genrule using $(locations) label should substitute first tool label automatically",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    tools: [":foo.tool", ":other.tool"],
+    cmd: "$(locations) -s $(out) $(in)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+    tools = [
+        "//other:foo.tool",
+        "//other:other.tool",
+    ],
+)`,
+			},
+			filesystem: otherGenruleBp,
+		},
+		{
+			description:                        "genrule without tools or tool_files can convert successfully",
+			moduleTypeUnderTest:                "genrule",
+			moduleTypeUnderTestFactory:         genrule.GenRuleFactory,
+			moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+			blueprint: `genrule {
+    name: "foo",
+    out: ["foo.out"],
+    srcs: ["foo.in"],
+    cmd: "cp $(in) $(out)",
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`genrule(
+    name = "foo",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = ["foo.out"],
+    srcs = ["foo.in"],
+)`,
+			},
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		fs := make(map[string][]byte)
+		toParse := []string{
+			"Android.bp",
+		}
+		for f, content := range testCase.filesystem {
+			if strings.HasSuffix(f, "Android.bp") {
+				toParse = append(toParse, f)
+			}
+			fs[f] = []byte(content)
+		}
+		config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
+		ctx := android.NewTestContext(config)
+		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+		ctx.RegisterForBazelConversion()
+
+		_, errs := ctx.ParseFileList(dir, toParse)
+		if errored(t, testCase, errs) {
+			continue
+		}
+		_, errs = ctx.ResolveDependencies(config)
+		if errored(t, testCase, errs) {
+			continue
+		}
+
+		checkDir := dir
+		if testCase.dir != "" {
+			checkDir = testCase.dir
+		}
+
+		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+			t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+		} else {
+			for i, target := range bazelTargets {
+				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+					t.Errorf(
+						"%s: Expected generated Bazel target to be '%s', got '%s'",
+						testCase.description,
+						w,
+						g,
+					)
+				}
+			}
+		}
+	}
+}
+
+func TestBp2BuildInlinesDefaults(t *testing.T) {
+	testCases := []struct {
+		moduleTypesUnderTest      map[string]android.ModuleFactory
+		bp2buildMutatorsUnderTest map[string]bp2buildMutator
+		bp                        string
+		expectedBazelTarget       string
+		description               string
+	}{
+		{
+			moduleTypesUnderTest: map[string]android.ModuleFactory{
+				"genrule":          genrule.GenRuleFactory,
+				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+			},
+			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+				"genrule": genrule.GenruleBp2Build,
+			},
+			bp: `genrule_defaults {
+    name: "gen_defaults",
+    cmd: "do-something $(in) $(out)",
+}
+genrule {
+    name: "gen",
+    out: ["out"],
+    srcs: ["in1"],
+    defaults: ["gen_defaults"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTarget: `genrule(
+    name = "gen",
+    cmd = "do-something $(SRCS) $(OUTS)",
+    outs = ["out"],
+    srcs = ["in1"],
+)`,
+			description: "genrule applies properties from a genrule_defaults dependency if not specified",
+		},
+		{
+			moduleTypesUnderTest: map[string]android.ModuleFactory{
+				"genrule":          genrule.GenRuleFactory,
+				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+			},
+			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+				"genrule": genrule.GenruleBp2Build,
+			},
+			bp: `genrule_defaults {
+    name: "gen_defaults",
+    out: ["out-from-defaults"],
+    srcs: ["in-from-defaults"],
+    cmd: "cmd-from-defaults",
+}
+genrule {
+    name: "gen",
+    out: ["out"],
+    srcs: ["in1"],
+    defaults: ["gen_defaults"],
+    cmd: "do-something $(in) $(out)",
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTarget: `genrule(
+    name = "gen",
+    cmd = "do-something $(SRCS) $(OUTS)",
+    outs = [
+        "out-from-defaults",
+        "out",
+    ],
+    srcs = [
+        "in-from-defaults",
+        "in1",
+    ],
+)`,
+			description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
+		},
+		{
+			moduleTypesUnderTest: map[string]android.ModuleFactory{
+				"genrule":          genrule.GenRuleFactory,
+				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+			},
+			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+				"genrule": genrule.GenruleBp2Build,
+			},
+			bp: `genrule_defaults {
+    name: "gen_defaults1",
+    cmd: "cp $(in) $(out)",
+}
+
+genrule_defaults {
+    name: "gen_defaults2",
+    srcs: ["in1"],
+}
+
+genrule {
+    name: "gen",
+    out: ["out"],
+    defaults: ["gen_defaults1", "gen_defaults2"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTarget: `genrule(
+    name = "gen",
+    cmd = "cp $(SRCS) $(OUTS)",
+    outs = ["out"],
+    srcs = ["in1"],
+)`,
+			description: "genrule applies properties from list of genrule_defaults",
+		},
+		{
+			moduleTypesUnderTest: map[string]android.ModuleFactory{
+				"genrule":          genrule.GenRuleFactory,
+				"genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
+			},
+			bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
+				"genrule": genrule.GenruleBp2Build,
+			},
+			bp: `genrule_defaults {
+    name: "gen_defaults1",
+    defaults: ["gen_defaults2"],
+    cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
+}
+
+genrule_defaults {
+    name: "gen_defaults2",
+    defaults: ["gen_defaults3"],
+    cmd: "cmd2 $(in) $(out)",
+    out: ["out-from-2"],
+    srcs: ["in1"],
+}
+
+genrule_defaults {
+    name: "gen_defaults3",
+    out: ["out-from-3"],
+    srcs: ["srcs-from-3"],
+}
+
+genrule {
+    name: "gen",
+    out: ["out"],
+    defaults: ["gen_defaults1"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+			expectedBazelTarget: `genrule(
+    name = "gen",
+    cmd = "cmd1 $(SRCS) $(OUTS)",
+    outs = [
+        "out-from-3",
+        "out-from-2",
+        "out",
+    ],
+    srcs = [
+        "srcs-from-3",
+        "in1",
+    ],
+)`,
+			description: "genrule applies properties from genrule_defaults transitively",
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+		ctx := android.NewTestContext(config)
+		for m, factory := range testCase.moduleTypesUnderTest {
+			ctx.RegisterModuleType(m, factory)
+		}
+		for mutator, f := range testCase.bp2buildMutatorsUnderTest {
+			ctx.RegisterBp2BuildMutator(mutator, f)
+		}
+		ctx.RegisterForBazelConversion()
+
+		_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+		android.FailIfErrored(t, errs)
+		_, errs = ctx.ResolveDependencies(config)
+		android.FailIfErrored(t, errs)
+
+		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+		if actualCount := len(bazelTargets); actualCount != 1 {
+			t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
+		}
+
+		actualBazelTarget := bazelTargets[0]
+		if actualBazelTarget.content != testCase.expectedBazelTarget {
+			t.Errorf(
+				"%s: Expected generated Bazel target to be '%s', got '%s'",
+				testCase.description,
+				testCase.expectedBazelTarget,
+				actualBazelTarget.content,
+			)
+		}
+	}
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index a549a93..3ebe63d 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -36,14 +36,35 @@
 	buildDir string
 )
 
-func errored(t *testing.T, desc string, errs []error) bool {
+func checkError(t *testing.T, errs []error, expectedErr error) bool {
 	t.Helper()
+
+	// expectedErr is not nil, find it in the list of errors
+	if len(errs) != 1 {
+		t.Errorf("Expected only 1 error, got %d: %q", len(errs), errs)
+	}
+	if errs[0].Error() == expectedErr.Error() {
+		return true
+	}
+
+	return false
+}
+
+func errored(t *testing.T, tc bp2buildTestCase, errs []error) bool {
+	t.Helper()
+	if tc.expectedErr != nil {
+		// Rely on checkErrors, as this test case is expected to have an error.
+		return false
+	}
+
 	if len(errs) > 0 {
 		for _, err := range errs {
-			t.Errorf("%s: %s", desc, err)
+			t.Errorf("%s: %s", tc.description, err)
 		}
 		return true
 	}
+
+	// All good, continue execution.
 	return false
 }
 
@@ -61,6 +82,7 @@
 	expectedBazelTargets               []string
 	filesystem                         map[string]string
 	dir                                string
+	expectedErr                        error
 }
 
 func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
@@ -85,12 +107,17 @@
 	ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
 	ctx.RegisterForBazelConversion()
 
-	_, errs := ctx.ParseFileList(dir, toParse)
-	if errored(t, tc.description, errs) {
+	_, parseErrs := ctx.ParseFileList(dir, toParse)
+	if errored(t, tc, parseErrs) {
 		return
 	}
-	_, errs = ctx.ResolveDependencies(config)
-	if errored(t, tc.description, errs) {
+	_, resolveDepsErrs := ctx.ResolveDependencies(config)
+	if errored(t, tc, resolveDepsErrs) {
+		return
+	}
+
+	errs := append(parseErrs, resolveDepsErrs...)
+	if tc.expectedErr != nil && checkError(t, errs, tc.expectedErr) {
 		return
 	}
 
@@ -225,11 +252,6 @@
 	Arch_paths       bazel.LabelListAttribute
 }
 
-type customBazelModule struct {
-	android.BazelTargetModuleBase
-	customBazelModuleAttributes
-}
-
 func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
 		if !m.ConvertWithBp2build(ctx) {
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 537f01c..fffb093 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -535,12 +535,21 @@
 	return relativePaths
 }
 
-func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute {
+// BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel
+// attributes.
+type BazelIncludes struct {
+	Includes       bazel.StringListAttribute
+	SystemIncludes bazel.StringListAttribute
+}
+
+func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
 	libraryDecorator := module.linker.(*libraryDecorator)
 	return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
 }
 
-func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute {
+// Bp2buildParseExportedIncludesForPrebuiltLibrary returns a BazelIncludes with Bazel-ified values
+// to export includes from the underlying module's properties.
+func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.TopDownMutatorContext, module *Module) BazelIncludes {
 	prebuiltLibraryLinker := module.linker.(*prebuiltLibraryLinker)
 	libraryDecorator := prebuiltLibraryLinker.libraryDecorator
 	return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
@@ -548,36 +557,22 @@
 
 // bp2BuildParseExportedIncludes creates a string list attribute contains the
 // exported included directories of a module.
-func bp2BuildParseExportedIncludesHelper(ctx android.TopDownMutatorContext, module *Module, libraryDecorator *libraryDecorator) bazel.StringListAttribute {
-	// Export_system_include_dirs and export_include_dirs are already module dir
-	// relative, so they don't need to be relativized like include_dirs, which
-	// are root-relative.
-	includeDirs := libraryDecorator.flagExporter.Properties.Export_system_include_dirs
-	includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)
-	var includeDirsAttribute bazel.StringListAttribute
-
-	getVariantIncludeDirs := func(includeDirs []string, flagExporterProperties *FlagExporterProperties, subtract bool) []string {
-		variantIncludeDirs := flagExporterProperties.Export_system_include_dirs
-		variantIncludeDirs = append(variantIncludeDirs, flagExporterProperties.Export_include_dirs...)
-
-		if subtract {
-			// To avoid duplicate includes when base includes + arch includes are combined
-			// TODO: Add something similar to ResolveExcludes() in bazel/properties.go
-			variantIncludeDirs = bazel.SubtractStrings(variantIncludeDirs, includeDirs)
-		}
-		return variantIncludeDirs
-	}
-
+func bp2BuildParseExportedIncludesHelper(ctx android.TopDownMutatorContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes {
+	exported := BazelIncludes{}
 	for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
 		for config, props := range configToProps {
 			if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
-				archVariantIncludeDirs := getVariantIncludeDirs(includeDirs, flagExporterProperties, axis != bazel.NoConfigAxis)
-				if len(archVariantIncludeDirs) > 0 {
-					includeDirsAttribute.SetSelectValue(axis, config, archVariantIncludeDirs)
+				if len(flagExporterProperties.Export_include_dirs) > 0 {
+					exported.Includes.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs)
+				}
+				if len(flagExporterProperties.Export_system_include_dirs) > 0 {
+					exported.SystemIncludes.SetSelectValue(axis, config, flagExporterProperties.Export_system_include_dirs)
 				}
 			}
 		}
 	}
+	exported.Includes.DeduplicateAxesFromBase()
+	exported.SystemIncludes.DeduplicateAxesFromBase()
 
-	return includeDirsAttribute
+	return exported
 }
diff --git a/cc/builder.go b/cc/builder.go
index 748377b..6a4d940 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -198,13 +198,14 @@
 	// Rule for invoking clang-tidy (a clang-based linter).
 	clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
 		blueprint.RuleParams{
-			Command:     "rm -f $out && $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
+			Command:     "rm -f $out && $tidyVars $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && touch $out",
 			CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
 		},
 		&remoteexec.REParams{
-			Labels:       map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
-			ExecStrategy: "${config.REClangTidyExecStrategy}",
-			Inputs:       []string{"$in"},
+			Labels:               map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
+			ExecStrategy:         "${config.REClangTidyExecStrategy}",
+			Inputs:               []string{"$in"},
+			EnvironmentVariables: []string{"TIDY_TIMEOUT"},
 			// Although clang-tidy has an option to "fix" source files, that feature is hardly useable
 			// under parallel compilation and RBE. So we assume no OutputFiles here.
 			// The clang-tidy fix option is best run locally in single thread.
@@ -212,7 +213,7 @@
 			// (1) New timestamps trigger clang and clang-tidy compilations again.
 			// (2) Changing source files caused concurrent clang or clang-tidy jobs to crash.
 			Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
-		}, []string{"cFlags", "tidyFlags"}, []string{})
+		}, []string{"cFlags", "tidyFlags", "tidyVars"}, []string{})
 
 	_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
 
@@ -442,8 +443,13 @@
 	// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
 	objFiles := make(android.Paths, len(srcFiles))
 	var tidyFiles android.Paths
+	var tidyVars string
 	if flags.tidy {
 		tidyFiles = make(android.Paths, 0, len(srcFiles))
+		tidyTimeout := ctx.Config().Getenv("TIDY_TIMEOUT")
+		if len(tidyTimeout) > 0 {
+			tidyVars += "TIDY_TIMEOUT=" + tidyTimeout
+		}
 	}
 	var coverageFiles android.Paths
 	if flags.gcovCoverage {
@@ -633,6 +639,7 @@
 				rule = clangTidyRE
 			}
 
+			ctx.TidyFile(tidyFile)
 			ctx.Build(pctx, android.BuildParams{
 				Rule:        rule,
 				Description: "clang-tidy " + srcFile.Rel(),
@@ -646,6 +653,7 @@
 				Args: map[string]string{
 					"cFlags":    moduleToolingFlags,
 					"tidyFlags": config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags),
+					"tidyVars":  tidyVars,
 				},
 			})
 		}
diff --git a/cc/config/OWNERS b/cc/config/OWNERS
index 701db92..580f215 100644
--- a/cc/config/OWNERS
+++ b/cc/config/OWNERS
@@ -1,3 +1,3 @@
 per-file vndk.go = smoreland@google.com, victoryang@google.com
-per-file clang.go,global.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
+per-file clang.go,global.go,tidy.go = srhines@google.com, chh@google.com, pirama@google.com, yikong@google.com
 
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 53a7306..3caa688 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -31,23 +31,15 @@
 	"-fno-tree-sra",
 	"-fprefetch-loop-arrays",
 	"-funswitch-loops",
-	"-Werror=unused-but-set-parameter",
-	"-Werror=unused-but-set-variable",
 	"-Wmaybe-uninitialized",
 	"-Wno-error=clobbered",
 	"-Wno-error=maybe-uninitialized",
-	"-Wno-error=unused-but-set-parameter",
-	"-Wno-error=unused-but-set-variable",
 	"-Wno-extended-offsetof",
 	"-Wno-free-nonheap-object",
 	"-Wno-literal-suffix",
 	"-Wno-maybe-uninitialized",
 	"-Wno-old-style-declaration",
-	"-Wno-unused-but-set-parameter",
-	"-Wno-unused-but-set-variable",
 	"-Wno-unused-local-typedefs",
-	"-Wunused-but-set-parameter",
-	"-Wunused-but-set-variable",
 	"-fdiagnostics-color",
 	// http://b/153759688
 	"-fuse-init-array",
diff --git a/cc/config/global.go b/cc/config/global.go
index 9773345..5f41f9e 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -230,6 +230,9 @@
 		"-Wno-string-concatenation", // http://b/175068488
 		// New warnings to be fixed after clang-r428724
 		"-Wno-align-mismatch", // http://b/193679946
+		// New warnings to be fixed after clang-r433403
+		"-Wno-error=unused-but-set-variable",  // http://b/197240255
+		"-Wno-error=unused-but-set-parameter", // http://b/197240255
 	}
 
 	// Extra cflags for external third-party projects to disable warnings that
@@ -255,6 +258,9 @@
 
 		// http://b/165945989
 		"-Wno-psabi",
+
+		// http://b/199369603
+		"-Wno-null-pointer-subtraction",
 	}
 
 	IllegalFlags = []string{
@@ -268,8 +274,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r428724"
-	ClangDefaultShortVersion = "13.0.1"
+	ClangDefaultVersion      = "clang-r433403"
+	ClangDefaultShortVersion = "13.0.2"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index cf13503..fdc246c 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -39,6 +39,7 @@
 			"misc-*",
 			"performance-*",
 			"portability-*",
+			"-bugprone-easily-swappable-parameters",
 			"-bugprone-narrowing-conversions",
 			"-google-readability*",
 			"-google-runtime-references",
@@ -115,6 +116,7 @@
 	{"external/", tidyExternalVendor},
 	{"external/google", tidyDefault},
 	{"external/webrtc", tidyDefault},
+	{"external/googletest/", tidyExternalVendor},
 	{"frameworks/compile/mclinker/", tidyExternalVendor},
 	{"hardware/qcom", tidyExternalVendor},
 	{"vendor/", tidyExternalVendor},
@@ -133,6 +135,7 @@
 }
 
 func TidyChecksForDir(dir string) string {
+	dir = dir + "/"
 	for _, pathCheck := range reversedDefaultLocalTidyChecks {
 		if strings.HasPrefix(dir, pathCheck.PathPrefix) {
 			return pathCheck.Checks
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 24e8fa4..8c678a1 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -53,6 +53,8 @@
 	"android.hardware.power.stats-V1-ndk_platform",
 	"android.hardware.power.stats-ndk_platform",
 	"android.hardware.power.stats-unstable-ndk_platform",
+	"android.hardware.radio-V1-ndk",
+	"android.hardware.radio-V1-ndk_platform",
 	"android.hardware.rebootescrow-ndk_platform",
 	"android.hardware.security.keymint-V1-ndk",
 	"android.hardware.security.keymint-V1-ndk_platform",
@@ -74,6 +76,8 @@
 	"android.hardware.weaver-ndk_platform",
 	"android.hardware.weaver-unstable-ndk_platform",
 	"android.system.keystore2-V1-ndk",
+	"android.hardware.wifi.hostapd-V1-ndk",
+	"android.hardware.wifi.hostapd-V1-ndk_platform",
 	"android.system.keystore2-V1-ndk_platform",
 	"android.system.keystore2-ndk_platform",
 	"android.system.keystore2-unstable-ndk_platform",
diff --git a/cc/library.go b/cc/library.go
index 196116b..28bd741 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -228,16 +228,17 @@
 	Conlyflags bazel.StringListAttribute
 	Asflags    bazel.StringListAttribute
 
-	Hdrs                bazel.LabelListAttribute
-	Deps                bazel.LabelListAttribute
-	Implementation_deps bazel.LabelListAttribute
-	Dynamic_deps        bazel.LabelListAttribute
-	Whole_archive_deps  bazel.LabelListAttribute
-	System_dynamic_deps bazel.LabelListAttribute
-	Includes            bazel.StringListAttribute
-	Linkopts            bazel.StringListAttribute
-	Use_libcrt          bazel.BoolAttribute
-	Rtti                bazel.BoolAttribute
+	Hdrs                   bazel.LabelListAttribute
+	Deps                   bazel.LabelListAttribute
+	Implementation_deps    bazel.LabelListAttribute
+	Dynamic_deps           bazel.LabelListAttribute
+	Whole_archive_deps     bazel.LabelListAttribute
+	System_dynamic_deps    bazel.LabelListAttribute
+	Export_includes        bazel.StringListAttribute
+	Export_system_includes bazel.StringListAttribute
+	Linkopts               bazel.StringListAttribute
+	Use_libcrt             bazel.BoolAttribute
+	Rtti                   bazel.BoolAttribute
 
 	// This is shared only.
 	Version_script bazel.LabelAttribute
@@ -299,15 +300,16 @@
 		Conlyflags: compilerAttrs.conlyFlags,
 		Asflags:    asFlags,
 
-		Implementation_deps: linkerAttrs.deps,
-		Deps:                linkerAttrs.exportedDeps,
-		Dynamic_deps:        linkerAttrs.dynamicDeps,
-		Whole_archive_deps:  linkerAttrs.wholeArchiveDeps,
-		System_dynamic_deps: linkerAttrs.systemDynamicDeps,
-		Includes:            exportedIncludes,
-		Linkopts:            linkerAttrs.linkopts,
-		Use_libcrt:          linkerAttrs.useLibcrt,
-		Rtti:                compilerAttrs.rtti,
+		Implementation_deps:    linkerAttrs.deps,
+		Deps:                   linkerAttrs.exportedDeps,
+		Dynamic_deps:           linkerAttrs.dynamicDeps,
+		Whole_archive_deps:     linkerAttrs.wholeArchiveDeps,
+		System_dynamic_deps:    linkerAttrs.systemDynamicDeps,
+		Export_includes:        exportedIncludes.Includes,
+		Export_system_includes: exportedIncludes.SystemIncludes,
+		Linkopts:               linkerAttrs.linkopts,
+		Use_libcrt:             linkerAttrs.useLibcrt,
+		Rtti:                   compilerAttrs.rtti,
 
 		Version_script: linkerAttrs.versionScript,
 
@@ -2318,19 +2320,20 @@
 }
 
 type bazelCcLibraryStaticAttributes struct {
-	Copts               bazel.StringListAttribute
-	Srcs                bazel.LabelListAttribute
-	Implementation_deps bazel.LabelListAttribute
-	Deps                bazel.LabelListAttribute
-	Whole_archive_deps  bazel.LabelListAttribute
-	Dynamic_deps        bazel.LabelListAttribute
-	System_dynamic_deps bazel.LabelListAttribute
-	Linkopts            bazel.StringListAttribute
-	Linkstatic          bool
-	Use_libcrt          bazel.BoolAttribute
-	Rtti                bazel.BoolAttribute
-	Includes            bazel.StringListAttribute
-	Hdrs                bazel.LabelListAttribute
+	Copts                  bazel.StringListAttribute
+	Srcs                   bazel.LabelListAttribute
+	Implementation_deps    bazel.LabelListAttribute
+	Deps                   bazel.LabelListAttribute
+	Whole_archive_deps     bazel.LabelListAttribute
+	Dynamic_deps           bazel.LabelListAttribute
+	System_dynamic_deps    bazel.LabelListAttribute
+	Linkopts               bazel.StringListAttribute
+	Linkstatic             bool
+	Use_libcrt             bazel.BoolAttribute
+	Rtti                   bazel.BoolAttribute
+	Export_includes        bazel.StringListAttribute
+	Export_system_includes bazel.StringListAttribute
+	Hdrs                   bazel.LabelListAttribute
 
 	Cppflags   bazel.StringListAttribute
 	Srcs_c     bazel.LabelListAttribute
@@ -2341,18 +2344,6 @@
 	Static staticOrSharedAttributes
 }
 
-type bazelCcLibraryStatic struct {
-	android.BazelTargetModuleBase
-	bazelCcLibraryStaticAttributes
-}
-
-func BazelCcLibraryStaticFactory() android.Module {
-	module := &bazelCcLibraryStatic{}
-	module.AddProperties(&module.bazelCcLibraryStaticAttributes)
-	android.InitBazelTargetModule(module)
-	return module
-}
-
 func ccLibraryStaticBp2BuildInternal(ctx android.TopDownMutatorContext, module *Module) {
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
@@ -2387,11 +2378,12 @@
 		Dynamic_deps:        linkerAttrs.dynamicDeps,
 		System_dynamic_deps: linkerAttrs.systemDynamicDeps,
 
-		Linkopts:   linkerAttrs.linkopts,
-		Linkstatic: true,
-		Use_libcrt: linkerAttrs.useLibcrt,
-		Rtti:       compilerAttrs.rtti,
-		Includes:   exportedIncludes,
+		Linkopts:               linkerAttrs.linkopts,
+		Linkstatic:             true,
+		Use_libcrt:             linkerAttrs.useLibcrt,
+		Rtti:                   compilerAttrs.rtti,
+		Export_includes:        exportedIncludes.Includes,
+		Export_system_includes: exportedIncludes.SystemIncludes,
 
 		Cppflags:   compilerAttrs.cppFlags,
 		Srcs_c:     compilerAttrs.cSrcs,
@@ -2423,9 +2415,3 @@
 
 	ccLibraryStaticBp2BuildInternal(ctx, module)
 }
-
-func (m *bazelCcLibraryStatic) Name() string {
-	return m.BaseModuleName()
-}
-
-func (m *bazelCcLibraryStatic) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 44a7a71..30a81cc 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -103,12 +103,13 @@
 }
 
 type bazelCcLibraryHeadersAttributes struct {
-	Copts               bazel.StringListAttribute
-	Hdrs                bazel.LabelListAttribute
-	Includes            bazel.StringListAttribute
-	Deps                bazel.LabelListAttribute
-	Implementation_deps bazel.LabelListAttribute
-	System_dynamic_deps bazel.LabelListAttribute
+	Copts                  bazel.StringListAttribute
+	Hdrs                   bazel.LabelListAttribute
+	Export_includes        bazel.StringListAttribute
+	Export_system_includes bazel.StringListAttribute
+	Deps                   bazel.LabelListAttribute
+	Implementation_deps    bazel.LabelListAttribute
+	System_dynamic_deps    bazel.LabelListAttribute
 }
 
 func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
@@ -131,11 +132,12 @@
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
 
 	attrs := &bazelCcLibraryHeadersAttributes{
-		Copts:               compilerAttrs.copts,
-		Includes:            exportedIncludes,
-		Implementation_deps: linkerAttrs.deps,
-		Deps:                linkerAttrs.exportedDeps,
-		System_dynamic_deps: linkerAttrs.systemDynamicDeps,
+		Copts:                  compilerAttrs.copts,
+		Export_includes:        exportedIncludes.Includes,
+		Export_system_includes: exportedIncludes.SystemIncludes,
+		Implementation_deps:    linkerAttrs.deps,
+		Deps:                   linkerAttrs.exportedDeps,
+		System_dynamic_deps:    linkerAttrs.systemDynamicDeps,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/cc/tidy.go b/cc/tidy.go
index fefa7f0..53ff156 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -148,6 +148,9 @@
 	tidyChecks = tidyChecks + ",-bugprone-branch-clone"
 	// http://b/193716442
 	tidyChecks = tidyChecks + ",-bugprone-implicit-widening-of-multiplication-result"
+	// Too many existing functions trigger this rule, and fixing it requires large code
+	// refactoring. The cost of maintaining this tidy rule outweighs the benefit it brings.
+	tidyChecks = tidyChecks + ",-bugprone-easily-swappable-parameters"
 	flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
 
 	if ctx.Config().IsEnvTrue("WITH_TIDY") {
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index d31489e..5770a7f 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -93,6 +93,8 @@
 
 var extraLibs = make(ExtraDeps)
 
+var optionalUsesLibs = make(ExtraDeps)
+
 type Exclude map[string]bool
 
 func (e Exclude) String() string {
@@ -269,6 +271,10 @@
 	return extraLibs[p.BpName()]
 }
 
+func (p Pom) BpOptionalUsesLibs() []string {
+	return optionalUsesLibs[p.BpName()]
+}
+
 // BpDeps obtains dependencies filtered by type and scope. The results of this
 // method are formatted as Android.bp targets, e.g. run through MavenToBp rules.
 func (p Pom) BpDeps(typeExt string, scopes []string) []string {
@@ -400,6 +406,12 @@
         "{{.}}",
         {{- end}}
     ],
+    {{- if .BpOptionalUsesLibs}}
+    optional_uses_libs: [
+        {{- range .BpOptionalUsesLibs}}
+        "{{.}}",
+        {{- end}}
+    ],
     {{- end}}
     {{- else if not .IsHostOnly}}
     min_sdk_version: "{{.DefaultMinSdkVersion}}",
@@ -443,6 +455,12 @@
         "{{.}}",
         {{- end}}
     ],
+    {{- if .BpOptionalUsesLibs}}
+    optional_uses_libs: [
+        {{- range .BpOptionalUsesLibs}}
+        "{{.}}",
+        {{- end}}
+    ],
     {{- end}}
     {{- else if not .IsHostOnly}}
     min_sdk_version: "{{.DefaultMinSdkVersion}}",
@@ -487,6 +505,12 @@
         "{{.}}",
         {{- end}}
     ],
+    {{- if .BpOptionalUsesLibs}}
+    optional_uses_libs: [
+        {{- range .BpOptionalUsesLibs}}
+        "{{.}}",
+        {{- end}}
+    ],
     {{- end}}
     java_version: "1.7",
 }
@@ -587,7 +611,7 @@
 The tool will extract the necessary information from *.pom files to create an Android.bp whose
 aar libraries can be linked against when using AAPT2.
 
-Usage: %s [--rewrite <regex>=<replace>] [-exclude <module>] [--extra-static-libs <module>=<module>[,<module>]] [--extra-libs <module>=<module>[,<module>]] [<dir>] [-regen <file>]
+Usage: %s [--rewrite <regex>=<replace>] [--exclude <module>] [--extra-static-libs <module>=<module>[,<module>]] [--extra-libs <module>=<module>[,<module>]] [--optional-uses-libs <module>=<module>[,<module>]] [<dir>] [-regen <file>]
 
   -rewrite <regex>=<replace>
      rewrite can be used to specify mappings between Maven projects and Android.bp modules. The -rewrite
@@ -605,6 +629,11 @@
      Some Android.bp modules have transitive runtime dependencies that must be specified when they
      are depended upon (like androidx.test.rules requires android.test.base).
      This may be specified multiple times to declare these dependencies.
+  -optional-uses-libs <module>=<module>[,<module>]
+     Some Android.bp modules have optional dependencies (typically specified with <uses-library> in
+     the module's AndroidManifest.xml) that must be specified when they are depended upon (like
+     androidx.window:window optionally requires androidx.window:window-extensions).
+     This may be specified multiple times to declare these dependencies.
   -sdk-version <version>
      Sets sdk_version: "<version>" for all modules.
   -default-min-sdk-version
@@ -629,6 +658,7 @@
 	flag.Var(&excludes, "exclude", "Exclude module")
 	flag.Var(&extraStaticLibs, "extra-static-libs", "Extra static dependencies needed when depending on a module")
 	flag.Var(&extraLibs, "extra-libs", "Extra runtime dependencies needed when depending on a module")
+	flag.Var(&optionalUsesLibs, "optional-uses-libs", "Extra optional dependencies needed when depending on a module")
 	flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
 	flag.Var(&hostModuleNames, "host", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is a host module")
 	flag.Var(&hostAndDeviceModuleNames, "host-and-device", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is both a host and device module.")
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 3e724ee..09a2234 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -35,10 +35,13 @@
 
 var (
 	topDir           string
+	outDir           string
 	soongOutDir      string
 	availableEnvFile string
 	usedEnvFile      string
 
+	runGoTests bool
+
 	globFile    string
 	globListDir string
 	delveListen string
@@ -60,7 +63,7 @@
 	flag.StringVar(&usedEnvFile, "used_env", "", "File containing used environment variables")
 	flag.StringVar(&globFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
 	flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
-	flag.StringVar(&cmdlineArgs.OutDir, "out", "", "the ninja builddir directory")
+	flag.StringVar(&outDir, "out", "", "the ninja builddir directory")
 	flag.StringVar(&cmdlineArgs.ModuleListFile, "l", "", "file that lists filepaths to parse")
 
 	// Debug flags
@@ -81,8 +84,7 @@
 
 	// Flags that probably shouldn't be flags of soong_build but we haven't found
 	// the time to remove them yet
-	flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
-	flag.BoolVar(&cmdlineArgs.UseValidations, "use-validations", false, "use validations to depend on go tests")
+	flag.BoolVar(&runGoTests, "t", false, "build and run go tests during bootstrap")
 }
 
 func newNameResolver(config android.Config) *android.NameResolver {
@@ -101,19 +103,16 @@
 	return android.NewNameResolver(exportFilter)
 }
 
-func newContext(configuration android.Config, prepareBuildActions bool) *android.Context {
+func newContext(configuration android.Config) *android.Context {
 	ctx := android.NewContext(configuration)
 	ctx.Register()
-	if !prepareBuildActions {
-		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
-	}
 	ctx.SetNameInterface(newNameResolver(configuration))
 	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
 	return ctx
 }
 
-func newConfig(cmdlineArgs bootstrap.Args, outDir string, availableEnv map[string]string) android.Config {
-	configuration, err := android.NewConfig(cmdlineArgs, outDir, availableEnv)
+func newConfig(availableEnv map[string]string) android.Config {
+	configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, runGoTests, outDir, soongOutDir, availableEnv)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
@@ -127,11 +126,7 @@
 // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
 // the incorrect results from the first pass, and file I/O is expensive.
 func runMixedModeBuild(configuration android.Config, firstCtx *android.Context, extraNinjaDeps []string) {
-	var firstArgs, secondArgs bootstrap.Args
-
-	firstArgs = cmdlineArgs
-	configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
-	bootstrap.RunBlueprint(firstArgs, firstCtx.Context, configuration)
+	bootstrap.RunBlueprint(cmdlineArgs, bootstrap.StopBeforeWriteNinja, firstCtx.Context, configuration)
 
 	// Invoke bazel commands and save results for second pass.
 	if err := configuration.BazelContext.InvokeBazel(); err != nil {
@@ -139,40 +134,31 @@
 		os.Exit(1)
 	}
 	// Second pass: Full analysis, using the bazel command results. Output ninja file.
-	secondArgs = cmdlineArgs
-	secondConfig, err := android.ConfigForAdditionalRun(secondArgs, configuration)
+	secondConfig, err := android.ConfigForAdditionalRun(configuration)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
 	}
-	secondCtx := newContext(secondConfig, true)
-	ninjaDeps := bootstrap.RunBlueprint(secondArgs, secondCtx.Context, secondConfig)
+	secondCtx := newContext(secondConfig)
+	ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, secondCtx.Context, secondConfig)
 	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
 
 	globListFiles := writeBuildGlobsNinjaFile(secondCtx.SrcDir(), configuration.SoongOutDir(), secondCtx.Globs, configuration)
 	ninjaDeps = append(ninjaDeps, globListFiles...)
 
-	writeDepFile(secondArgs.OutFile, ninjaDeps)
+	writeDepFile(cmdlineArgs.OutFile, ninjaDeps)
 }
 
 // Run the code-generation phase to convert BazelTargetModules to BUILD files.
-func runQueryView(configuration android.Config, ctx *android.Context) {
+func runQueryView(queryviewDir, queryviewMarker string, configuration android.Config, ctx *android.Context) {
 	codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
-	absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
+	absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
 	if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
 	}
-}
 
-func runSoongDocs(configuration android.Config) {
-	ctx := newContext(configuration, false)
-	soongDocsArgs := cmdlineArgs
-	bootstrap.RunBlueprint(soongDocsArgs, ctx.Context, configuration)
-	if err := writeDocs(ctx, configuration, docFile); err != nil {
-		fmt.Fprintf(os.Stderr, "%s", err)
-		os.Exit(1)
-	}
+	touch(shared.JoinPath(topDir, queryviewMarker))
 }
 
 func writeMetrics(configuration android.Config) {
@@ -219,24 +205,33 @@
 // or the actual Soong build for the build.ninja file. Returns the top level
 // output file of the specific activity.
 func doChosenActivity(configuration android.Config, extraNinjaDeps []string) string {
-	bazelConversionRequested := bp2buildMarker != ""
 	mixedModeBuild := configuration.BazelContext.BazelEnabled()
+	generateBazelWorkspace := bp2buildMarker != ""
 	generateQueryView := bazelQueryViewDir != ""
+	generateModuleGraphFile := moduleGraphFile != ""
+	generateDocFile := docFile != ""
 
 	blueprintArgs := cmdlineArgs
-	prepareBuildActions := !generateQueryView && moduleGraphFile == ""
-	if bazelConversionRequested {
+
+	var stopBefore bootstrap.StopBefore
+	if !generateModuleGraphFile && !generateQueryView && !generateDocFile {
+		stopBefore = bootstrap.DoEverything
+	} else {
+		stopBefore = bootstrap.StopBeforePrepareBuildActions
+	}
+
+	if generateBazelWorkspace {
 		// Run the alternate pipeline of bp2build mutators and singleton to convert
 		// Blueprint to BUILD files before everything else.
 		runBp2Build(configuration, extraNinjaDeps)
 		return bp2buildMarker
 	}
 
-	ctx := newContext(configuration, prepareBuildActions)
+	ctx := newContext(configuration)
 	if mixedModeBuild {
 		runMixedModeBuild(configuration, ctx, extraNinjaDeps)
 	} else {
-		ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, ctx.Context, configuration)
+		ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, stopBefore, ctx.Context, configuration)
 		ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
 
 		globListFiles := writeBuildGlobsNinjaFile(ctx.SrcDir(), configuration.SoongOutDir(), ctx.Globs, configuration)
@@ -244,12 +239,24 @@
 
 		// Convert the Soong module graph into Bazel BUILD files.
 		if generateQueryView {
-			runQueryView(configuration, ctx)
-			return cmdlineArgs.OutFile // TODO: This is a lie
-		} else if moduleGraphFile != "" {
+			queryviewMarkerFile := bazelQueryViewDir + ".marker"
+			runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
+			writeDepFile(queryviewMarkerFile, ninjaDeps)
+			return queryviewMarkerFile
+		} else if generateModuleGraphFile {
 			writeJsonModuleGraph(ctx, moduleGraphFile)
 			writeDepFile(moduleGraphFile, ninjaDeps)
 			return moduleGraphFile
+		} else if generateDocFile {
+			// TODO: we could make writeDocs() return the list of documentation files
+			// written and add them to the .d file. Then soong_docs would be re-run
+			// whenever one is deleted.
+			if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
+				fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
+				os.Exit(1)
+			}
+			writeDepFile(docFile, ninjaDeps)
+			return docFile
 		} else {
 			// The actual output (build.ninja) was written in the RunBlueprint() call
 			// above
@@ -297,7 +304,7 @@
 
 	availableEnv := parseAvailableEnv()
 
-	configuration := newConfig(cmdlineArgs, soongOutDir, availableEnv)
+	configuration := newConfig(availableEnv)
 	extraNinjaDeps := []string{
 		configuration.ProductVariablesFileName,
 		usedEnvFile,
@@ -313,16 +320,6 @@
 		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.SoongOutDir(), "always_rerun_for_delve"))
 	}
 
-	if docFile != "" {
-		// We don't write an used variables file when generating documentation
-		// because that is done from within the actual builds as a Ninja action and
-		// thus it would overwrite the actual used variables file so this is
-		// special-cased.
-		// TODO: Fix this by not passing --used_env to the soong_docs invocation
-		runSoongDocs(configuration)
-		return
-	}
-
 	finalOutputFile := doChosenActivity(configuration, extraNinjaDeps)
 	writeUsedEnvironmentFile(configuration, finalOutputFile)
 }
@@ -475,14 +472,11 @@
 
 	extraNinjaDeps = append(extraNinjaDeps, modulePaths...)
 
-	// No need to generate Ninja build rules/statements from Modules and Singletons.
-	configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
-
 	// Run the loading and analysis pipeline to prepare the graph of regular
 	// Modules parsed from Android.bp files, and the BazelTargetModules mapped
 	// from the regular Modules.
 	blueprintArgs := cmdlineArgs
-	ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, bp2buildCtx.Context, configuration)
+	ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, bp2buildCtx.Context, configuration)
 	ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
 
 	globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx.SrcDir(), configuration.SoongOutDir(), bp2buildCtx.Globs, configuration)
@@ -504,8 +498,8 @@
 		"bazel-" + filepath.Base(topDir),
 	}
 
-	if cmdlineArgs.OutDir[0] != '/' {
-		excludes = append(excludes, cmdlineArgs.OutDir)
+	if outDir[0] != '/' {
+		excludes = append(excludes, outDir)
 	}
 
 	existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index a8602de..98e27c6 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -15,14 +15,16 @@
 package main
 
 import (
-	"android/soong/android"
-	"android/soong/bp2build"
 	"io/ioutil"
 	"os"
 	"path/filepath"
+
+	"android/soong/android"
+	"android/soong/bp2build"
 )
 
 func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string) error {
+	os.RemoveAll(bazelQueryViewDir)
 	ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
 
 	// Ignore metrics reporting and compat layers for queryview, since queryview
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index b7c260c..8d8f37f 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -15,13 +15,14 @@
 package main
 
 import (
-	"android/soong/android"
 	"bytes"
 	"html/template"
 	"io/ioutil"
 	"path/filepath"
 	"sort"
 
+	"android/soong/android"
+
 	"github.com/google/blueprint/bootstrap"
 	"github.com/google/blueprint/bootstrap/bpdoc"
 )
@@ -95,13 +96,13 @@
 	return result
 }
 
-func getPackages(ctx *android.Context, config interface{}) ([]*bpdoc.Package, error) {
+func getPackages(ctx *android.Context) ([]*bpdoc.Package, error) {
 	moduleTypeFactories := android.ModuleTypeFactoriesForDocs()
-	return bootstrap.ModuleTypeDocs(ctx.Context, config, moduleTypeFactories)
+	return bootstrap.ModuleTypeDocs(ctx.Context, moduleTypeFactories)
 }
 
-func writeDocs(ctx *android.Context, config interface{}, filename string) error {
-	packages, err := getPackages(ctx, config)
+func writeDocs(ctx *android.Context, filename string) error {
+	packages, err := getPackages(ctx)
 	if err != nil {
 		return err
 	}
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index 72525c4..209e82b 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -202,8 +202,7 @@
 func buildProductConfigMap() map[string]string {
 	const androidProductsMk = "AndroidProducts.mk"
 	// Build the list of AndroidProducts.mk files: it's
-	// build/make/target/product/AndroidProducts.mk plus
-	// device/**/AndroidProducts.mk
+	// build/make/target/product/AndroidProducts.mk + device/**/AndroidProducts.mk plus + vendor/**/AndroidProducts.mk
 	targetAndroidProductsFile := filepath.Join(*rootDir, "build", "make", "target", "product", androidProductsMk)
 	if _, err := os.Stat(targetAndroidProductsFile); err != nil {
 		fmt.Fprintf(os.Stderr, "%s: %s\n(hint: %s is not a source tree root)\n",
@@ -213,17 +212,19 @@
 	if err := mk2rbc.UpdateProductConfigMap(productConfigMap, targetAndroidProductsFile); err != nil {
 		fmt.Fprintf(os.Stderr, "%s: %s\n", targetAndroidProductsFile, err)
 	}
-	_ = filepath.Walk(filepath.Join(*rootDir, "device"),
-		func(path string, info os.FileInfo, err error) error {
-			if info.IsDir() || filepath.Base(path) != androidProductsMk {
+	for _, t := range []string{"device", "vendor"} {
+		_ = filepath.WalkDir(filepath.Join(*rootDir, t),
+			func(path string, d os.DirEntry, err error) error {
+				if err != nil || d.IsDir() || filepath.Base(path) != androidProductsMk {
+					return nil
+				}
+				if err2 := mk2rbc.UpdateProductConfigMap(productConfigMap, path); err2 != nil {
+					fmt.Fprintf(os.Stderr, "%s: %s\n", path, err)
+					// Keep going, we want to find all such errors in a single run
+				}
 				return nil
-			}
-			if err2 := mk2rbc.UpdateProductConfigMap(productConfigMap, path); err2 != nil {
-				fmt.Fprintf(os.Stderr, "%s: %s\n", path, err)
-				// Keep going, we want to find all such errors in a single run
-			}
-			return nil
-		})
+			})
+	}
 	return productConfigMap
 }
 
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 46212ee..ca7fe6f 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -414,7 +414,7 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if rblf.filter(g.get("PRODUCT_LIST", ""), g["TARGET_PRODUCT"]):
+  if rblf.filter(g.get("PRODUCT_LIST", []), g["TARGET_PRODUCT"]):
     pass
 `,
 	},
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index 88d63c9..4bb9ed5 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -299,6 +299,10 @@
 					vt = vi.valueType
 				}
 			}
+			if strings.HasSuffix(name, "_LIST") && vt == starlarkTypeUnknown {
+				// Heuristics: Variables with "_LIST" suffix are lists
+				vt = starlarkTypeList
+			}
 			v = &otherGlobalVariable{baseVariable{nam: name, typ: vt}}
 		}
 		ctx.variables[name] = v
diff --git a/rust/bindgen.go b/rust/bindgen.go
index be9e71e..845f258 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
 	defaultBindgenFlags = []string{""}
 
 	// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
-	bindgenClangVersion = "clang-r428724"
+	bindgenClangVersion = "clang-r433403"
 
 	_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
 		if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/config/global.go b/rust/config/global.go
index e5b334d..b163bb6 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
 var pctx = android.NewPackageContext("android/soong/rust/config")
 
 var (
-	RustDefaultVersion = "1.54.0"
+	RustDefaultVersion = "1.55.0"
 	RustDefaultBase    = "prebuilts/rust/"
 	DefaultEdition     = "2018"
 	Stdlibs            = []string{
diff --git a/rust/config/x86_linux_host.go b/rust/config/x86_linux_host.go
index 0aa534f..c10afd8 100644
--- a/rust/config/x86_linux_host.go
+++ b/rust/config/x86_linux_host.go
@@ -26,6 +26,7 @@
 		"-B${cc_config.ClangBin}",
 		"-fuse-ld=lld",
 		"-Wl,--undefined-version",
+		"--sysroot ${cc_config.LinuxGccRoot}/sysroot",
 	}
 	linuxX86Rustflags   = []string{}
 	linuxX86Linkflags   = []string{}
diff --git a/rust/coverage.go b/rust/coverage.go
index 050b811..8fdfa23 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -57,7 +57,18 @@
 		flags.RustFlags = append(flags.RustFlags,
 			"-Z instrument-coverage", "-g")
 		flags.LinkFlags = append(flags.LinkFlags,
-			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
+			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open",
+			// Upstream LLVM change 6d2d3bd0a6 made
+			// -z,start-stop-gc the default.  It drops metadata
+			// sections like __llvm_prf_data unless they are marked
+			// SHF_GNU_RETAIN.  https://reviews.llvm.org/D97448
+			// marks generated sections, including __llvm_prf_data
+			// as SHF_GNU_RETAIN.  However this change is not in
+			// the Rust toolchain.  Since we link Rust libs with
+			// new lld, we should use nostart-stop-gc until the
+			// Rust toolchain updates past D97448.
+			"-Wl,-z,nostart-stop-gc",
+		)
 		deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
 	}
 
diff --git a/scripts/check_boot_jars/check_boot_jars.py b/scripts/check_boot_jars/check_boot_jars.py
index c271211..b711f9d 100755
--- a/scripts/check_boot_jars/check_boot_jars.py
+++ b/scripts/check_boot_jars/check_boot_jars.py
@@ -1,101 +1,102 @@
 #!/usr/bin/env python
+"""Check boot jars.
 
+Usage: check_boot_jars.py <dexdump_path> <package_allow_list_file> <jar1> \
+<jar2> ...
 """
-Check boot jars.
-
-Usage: check_boot_jars.py <dexdump_path> <package_allow_list_file> <jar1> <jar2> ...
-"""
+from __future__ import print_function
 import logging
-import os.path
 import re
 import subprocess
 import sys
 import xml.etree.ElementTree
 
-
 # The compiled allow list RE.
 allow_list_re = None
 
 
 def LoadAllowList(filename):
-  """ Load and compile allow list regular expressions from filename.
-  """
-  lines = []
-  with open(filename, 'r') as f:
-    for line in f:
-      line = line.strip()
-      if not line or line.startswith('#'):
-        continue
-      lines.append(line)
-  combined_re = r'^(%s)$' % '|'.join(lines)
-  global allow_list_re
-  try:
-    allow_list_re = re.compile(combined_re)
-  except re.error:
-    logging.exception(
-        'Cannot compile package allow list regular expression: %r',
-        combined_re)
-    allow_list_re = None
-    return False
-  return True
+    """ Load and compile allow list regular expressions from filename."""
+    lines = []
+    with open(filename, 'r') as f:
+        for line in f:
+            line = line.strip()
+            if not line or line.startswith('#'):
+                continue
+            lines.append(line)
+    combined_re = r'^(%s)$' % '|'.join(lines)
+    global allow_list_re #pylint: disable=global-statement
+    try:
+        allow_list_re = re.compile(combined_re)
+    except re.error:
+        logging.exception(
+            'Cannot compile package allow list regular expression: %r',
+            combined_re)
+        allow_list_re = None
+        return False
+    return True
 
 def CheckDexJar(dexdump_path, allow_list_path, jar):
-  """Check a dex jar file.
-  """
-  # Use dexdump to generate the XML representation of the dex jar file.
-  p = subprocess.Popen(args='%s -l xml %s' % (dexdump_path, jar),
-      stdout=subprocess.PIPE, shell=True)
-  stdout, _ = p.communicate()
-  if p.returncode != 0:
-    return False
+    """Check a dex jar file."""
+    # Use dexdump to generate the XML representation of the dex jar file.
+    p = subprocess.Popen(
+        args='%s -l xml %s' % (dexdump_path, jar),
+        stdout=subprocess.PIPE,
+        shell=True)
+    stdout, _ = p.communicate()
+    if p.returncode != 0:
+        return False
 
-  packages = 0
-  try:
-    # TODO(b/172063475) - improve performance
-    root = xml.etree.ElementTree.fromstring(stdout)
-  except xml.etree.ElementTree.ParseError as e:
-    print >> sys.stderr, 'Error processing jar %s - %s' % (jar, e)
-    print >> sys.stderr, stdout
-    return False
-  for package_elt in root.iterfind('package'):
-    packages += 1
-    package_name = package_elt.get('name')
-    if not package_name or not allow_list_re.match(package_name):
-      # Report the name of a class in the package as it is easier to navigate to
-      # the source of a concrete class than to a package which is often required
-      # to investigate this failure.
-      class_name = package_elt[0].get('name')
-      if package_name != "":
-        class_name = package_name + "." + class_name
-      print >> sys.stderr, ('Error: %s contains class file %s, whose package name "%s" is empty or'
-                            ' not in the allow list %s of packages allowed on the bootclasspath.'
-                            % (jar, class_name, package_name, allow_list_path))
-      return False
-  if packages == 0:
-    print >> sys.stderr, ('Error: %s does not contain any packages.' % jar)
-    return False
-  return True
-
+    packages = 0
+    try:
+        # TODO(b/172063475) - improve performance
+        root = xml.etree.ElementTree.fromstring(stdout)
+    except xml.etree.ElementTree.ParseError as e:
+        print('Error processing jar %s - %s' % (jar, e), file=sys.stderr)
+        print(stdout, file=sys.stderr)
+        return False
+    for package_elt in root.iterfind('package'):
+        packages += 1
+        package_name = package_elt.get('name')
+        if not package_name or not allow_list_re.match(package_name):
+            # Report the name of a class in the package as it is easier to
+            # navigate to the source of a concrete class than to a package
+            # which is often required to investigate this failure.
+            class_name = package_elt[0].get('name')
+            if package_name:
+                class_name = package_name + '.' + class_name
+            print((
+                'Error: %s contains class file %s, whose package name "%s" is '
+                'empty or not in the allow list %s of packages allowed on the '
+                'bootclasspath.'
+                % (jar, class_name, package_name, allow_list_path)),
+                  file=sys.stderr)
+            return False
+    if packages == 0:
+        print(('Error: %s does not contain any packages.' % jar),
+              file=sys.stderr)
+        return False
+    return True
 
 def main(argv):
-  if len(argv) < 3:
-    print __doc__
-    return 1
-  dexdump_path = argv[0]
-  allow_list_path = argv[1]
+    if len(argv) < 3:
+        print(__doc__)
+        return 1
+    dexdump_path = argv[0]
+    allow_list_path = argv[1]
 
-  if not LoadAllowList(allow_list_path):
-    return 1
+    if not LoadAllowList(allow_list_path):
+        return 1
 
-  passed = True
-  for jar in argv[2:]:
-    if not CheckDexJar(dexdump_path, allow_list_path, jar):
-      passed = False
-  if not passed:
-    return 1
+    passed = True
+    for jar in argv[2:]:
+        if not CheckDexJar(dexdump_path, allow_list_path, jar):
+            passed = False
+    if not passed:
+        return 1
 
-  return 0
+    return 0
 
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
+    sys.exit(main(sys.argv[1:]))
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index 18ab427..942f26a 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -69,6 +69,7 @@
 javax\.xml\.transform\.stream
 javax\.xml\.validation
 javax\.xml\.xpath
+jdk\.internal\.math
 jdk\.internal\.util
 jdk\.internal\.vm\.annotation
 jdk\.net
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
index 17bc88b..64d922a 100755
--- a/scripts/get_clang_version.py
+++ b/scripts/get_clang_version.py
@@ -21,8 +21,12 @@
 
 
 ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP", ".")
+LLVM_PREBUILTS_VERSION = os.environ.get("LLVM_PREBUILTS_VERSION")
 
 def get_clang_prebuilts_version(global_go):
+  if LLVM_PREBUILTS_VERSION:
+    return LLVM_PREBUILTS_VERSION
+
   # TODO(b/187231324): Get clang version from the json file once it is no longer
   # hard-coded in global.go
   if global_go is None:
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 4ef4399..71fe358 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -25,7 +25,6 @@
 import sys
 from xml.dom import minidom
 
-
 from manifest import android_ns
 from manifest import get_children_with_tag
 from manifest import parse_manifest
@@ -33,49 +32,61 @@
 
 
 class ManifestMismatchError(Exception):
-  pass
+    pass
 
 
 def parse_args():
-  """Parse commandline arguments."""
+    """Parse commandline arguments."""
 
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--uses-library', dest='uses_libraries',
-                      action='append',
-                      help='specify uses-library entries known to the build system')
-  parser.add_argument('--optional-uses-library',
-                      dest='optional_uses_libraries',
-                      action='append',
-                      help='specify uses-library entries known to the build system with required:false')
-  parser.add_argument('--enforce-uses-libraries',
-                      dest='enforce_uses_libraries',
-                      action='store_true',
-                      help='check the uses-library entries known to the build system against the manifest')
-  parser.add_argument('--enforce-uses-libraries-relax',
-                      dest='enforce_uses_libraries_relax',
-                      action='store_true',
-                      help='do not fail immediately, just save the error message to file')
-  parser.add_argument('--enforce-uses-libraries-status',
-                      dest='enforce_uses_libraries_status',
-                      help='output file to store check status (error message)')
-  parser.add_argument('--extract-target-sdk-version',
-                      dest='extract_target_sdk_version',
-                      action='store_true',
-                      help='print the targetSdkVersion from the manifest')
-  parser.add_argument('--dexpreopt-config',
-                      dest='dexpreopt_configs',
-                      action='append',
-                      help='a paths to a dexpreopt.config of some library')
-  parser.add_argument('--aapt',
-                      dest='aapt',
-                      help='path to aapt executable')
-  parser.add_argument('--output', '-o', dest='output', help='output AndroidManifest.xml file')
-  parser.add_argument('input', help='input AndroidManifest.xml file')
-  return parser.parse_args()
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        '--uses-library',
+        dest='uses_libraries',
+        action='append',
+        help='specify uses-library entries known to the build system')
+    parser.add_argument(
+        '--optional-uses-library',
+        dest='optional_uses_libraries',
+        action='append',
+        help='specify uses-library entries known to the build system with '
+        'required:false'
+    )
+    parser.add_argument(
+        '--enforce-uses-libraries',
+        dest='enforce_uses_libraries',
+        action='store_true',
+        help='check the uses-library entries known to the build system against '
+        'the manifest'
+    )
+    parser.add_argument(
+        '--enforce-uses-libraries-relax',
+        dest='enforce_uses_libraries_relax',
+        action='store_true',
+        help='do not fail immediately, just save the error message to file')
+    parser.add_argument(
+        '--enforce-uses-libraries-status',
+        dest='enforce_uses_libraries_status',
+        help='output file to store check status (error message)')
+    parser.add_argument(
+        '--extract-target-sdk-version',
+        dest='extract_target_sdk_version',
+        action='store_true',
+        help='print the targetSdkVersion from the manifest')
+    parser.add_argument(
+        '--dexpreopt-config',
+        dest='dexpreopt_configs',
+        action='append',
+        help='a paths to a dexpreopt.config of some library')
+    parser.add_argument('--aapt', dest='aapt', help='path to aapt executable')
+    parser.add_argument(
+        '--output', '-o', dest='output', help='output AndroidManifest.xml file')
+    parser.add_argument('input', help='input AndroidManifest.xml file')
+    return parser.parse_args()
 
 
 def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
-  """Verify that the <uses-library> tags in the manifest match those provided
+    """Verify that the <uses-library> tags in the manifest match those provided
+
   by the build system.
 
   Args:
@@ -84,274 +95,294 @@
     optional: optional libs known to the build system
     relax:    if true, suppress error on mismatch and just write it to file
     is_apk:   if the manifest comes from an APK or an XML file
-  """
-  if is_apk:
-    manifest_required, manifest_optional, tags = extract_uses_libs_apk(manifest)
-  else:
-    manifest_required, manifest_optional, tags = extract_uses_libs_xml(manifest)
+    """
+    if is_apk:
+        manifest_required, manifest_optional, tags = extract_uses_libs_apk(
+            manifest)
+    else:
+        manifest_required, manifest_optional, tags = extract_uses_libs_xml(
+            manifest)
 
-  # Trim namespace component. Normally Soong does that automatically when it
-  # handles module names specified in Android.bp properties. However not all
-  # <uses-library> entries in the manifest correspond to real modules: some of
-  # the optional libraries may be missing at build time. Therefor this script
-  # accepts raw module names as spelled in Android.bp/Amdroid.mk and trims the
-  # optional namespace part manually.
-  required = trim_namespace_parts(required)
-  optional = trim_namespace_parts(optional)
+    # Trim namespace component. Normally Soong does that automatically when it
+    # handles module names specified in Android.bp properties. However not all
+    # <uses-library> entries in the manifest correspond to real modules: some of
+    # the optional libraries may be missing at build time. Therefor this script
+    # accepts raw module names as spelled in Android.bp/Amdroid.mk and trims the
+    # optional namespace part manually.
+    required = trim_namespace_parts(required)
+    optional = trim_namespace_parts(optional)
 
-  if manifest_required == required and manifest_optional == optional:
-    return None
+    if manifest_required == required and manifest_optional == optional:
+        return None
 
-  errmsg = ''.join([
-    'mismatch in the <uses-library> tags between the build system and the '
-      'manifest:\n',
-    '\t- required libraries in build system: [%s]\n' % ', '.join(required),
-    '\t                 vs. in the manifest: [%s]\n' % ', '.join(manifest_required),
-    '\t- optional libraries in build system: [%s]\n' % ', '.join(optional),
-    '\t                 vs. in the manifest: [%s]\n' % ', '.join(manifest_optional),
-    '\t- tags in the manifest (%s):\n' % path,
-    '\t\t%s\n' % '\t\t'.join(tags),
-      'note: the following options are available:\n',
-    '\t- to temporarily disable the check on command line, rebuild with ',
-      'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ',
-      'and disable AOT-compilation in dexpreopt)\n',
-    '\t- to temporarily disable the check for the whole product, set ',
-      'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n',
-    '\t- to fix the check, make build system properties coherent with the '
-      'manifest\n',
-    '\t- see build/make/Changes.md for details\n'])
+    #pylint: disable=line-too-long
+    errmsg = ''.join([
+        'mismatch in the <uses-library> tags between the build system and the '
+        'manifest:\n',
+        '\t- required libraries in build system: [%s]\n' % ', '.join(required),
+        '\t                 vs. in the manifest: [%s]\n' %
+        ', '.join(manifest_required),
+        '\t- optional libraries in build system: [%s]\n' % ', '.join(optional),
+        '\t                 vs. in the manifest: [%s]\n' %
+        ', '.join(manifest_optional),
+        '\t- tags in the manifest (%s):\n' % path,
+        '\t\t%s\n' % '\t\t'.join(tags),
+        'note: the following options are available:\n',
+        '\t- to temporarily disable the check on command line, rebuild with ',
+        'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ',
+        'and disable AOT-compilation in dexpreopt)\n',
+        '\t- to temporarily disable the check for the whole product, set ',
+        'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n',
+        '\t- to fix the check, make build system properties coherent with the '
+        'manifest\n', '\t- see build/make/Changes.md for details\n'
+    ])
+    #pylint: enable=line-too-long
 
-  if not relax:
-    raise ManifestMismatchError(errmsg)
+    if not relax:
+        raise ManifestMismatchError(errmsg)
 
-  return errmsg
+    return errmsg
 
 
-MODULE_NAMESPACE = re.compile("^//[^:]+:")
+MODULE_NAMESPACE = re.compile('^//[^:]+:')
+
 
 def trim_namespace_parts(modules):
-  """Trim the namespace part of each module, if present. Leave only the name."""
+    """Trim the namespace part of each module, if present.
 
-  trimmed = []
-  for module in modules:
-    trimmed.append(MODULE_NAMESPACE.sub('', module))
-  return trimmed
+    Leave only the name.
+    """
+
+    trimmed = []
+    for module in modules:
+        trimmed.append(MODULE_NAMESPACE.sub('', module))
+    return trimmed
 
 
 def extract_uses_libs_apk(badging):
-  """Extract <uses-library> tags from the manifest of an APK."""
+    """Extract <uses-library> tags from the manifest of an APK."""
 
-  pattern = re.compile("^uses-library(-not-required)?:'(.*)'$", re.MULTILINE)
+    pattern = re.compile("^uses-library(-not-required)?:'(.*)'$", re.MULTILINE)
 
-  required = []
-  optional = []
-  lines = []
-  for match in re.finditer(pattern, badging):
-    lines.append(match.group(0))
-    libname = match.group(2)
-    if match.group(1) == None:
-      required.append(libname)
-    else:
-      optional.append(libname)
+    required = []
+    optional = []
+    lines = []
+    for match in re.finditer(pattern, badging):
+        lines.append(match.group(0))
+        libname = match.group(2)
+        if match.group(1) is None:
+            required.append(libname)
+        else:
+            optional.append(libname)
 
-  required = first_unique_elements(required)
-  optional = first_unique_elements(optional)
-  tags = first_unique_elements(lines)
-  return required, optional, tags
+    required = first_unique_elements(required)
+    optional = first_unique_elements(optional)
+    tags = first_unique_elements(lines)
+    return required, optional, tags
 
 
-def extract_uses_libs_xml(xml):
-  """Extract <uses-library> tags from the manifest."""
+def extract_uses_libs_xml(xml): #pylint: disable=inconsistent-return-statements
+    """Extract <uses-library> tags from the manifest."""
 
-  manifest = parse_manifest(xml)
-  elems = get_children_with_tag(manifest, 'application')
-  application = elems[0] if len(elems) == 1 else None
-  if len(elems) > 1:
-    raise RuntimeError('found multiple <application> tags')
-  elif not elems:
-    if uses_libraries or optional_uses_libraries:
-      raise ManifestMismatchError('no <application> tag found')
-    return
+    manifest = parse_manifest(xml)
+    elems = get_children_with_tag(manifest, 'application')
+    application = elems[0] if len(elems) == 1 else None
+    if len(elems) > 1: #pylint: disable=no-else-raise
+        raise RuntimeError('found multiple <application> tags')
+    elif not elems:
+        if uses_libraries or optional_uses_libraries: #pylint: disable=undefined-variable
+            raise ManifestMismatchError('no <application> tag found')
+        return
 
-  libs = get_children_with_tag(application, 'uses-library')
+    libs = get_children_with_tag(application, 'uses-library')
 
-  required = [uses_library_name(x) for x in libs if uses_library_required(x)]
-  optional = [uses_library_name(x) for x in libs if not uses_library_required(x)]
+    required = [uses_library_name(x) for x in libs if uses_library_required(x)]
+    optional = [
+        uses_library_name(x) for x in libs if not uses_library_required(x)
+    ]
 
-  # render <uses-library> tags as XML for a pretty error message
-  tags = []
-  for lib in libs:
-    tags.append(lib.toprettyxml())
+    # render <uses-library> tags as XML for a pretty error message
+    tags = []
+    for lib in libs:
+        tags.append(lib.toprettyxml())
 
-  required = first_unique_elements(required)
-  optional = first_unique_elements(optional)
-  tags = first_unique_elements(tags)
-  return required, optional, tags
+    required = first_unique_elements(required)
+    optional = first_unique_elements(optional)
+    tags = first_unique_elements(tags)
+    return required, optional, tags
 
 
 def first_unique_elements(l):
-  result = []
-  [result.append(x) for x in l if x not in result]
-  return result
+    result = []
+    for x in l:
+        if x not in result:
+            result.append(x)
+    return result
 
 
 def uses_library_name(lib):
-  """Extract the name attribute of a uses-library tag.
+    """Extract the name attribute of a uses-library tag.
 
   Args:
     lib: a <uses-library> tag.
-  """
-  name = lib.getAttributeNodeNS(android_ns, 'name')
-  return name.value if name is not None else ""
+    """
+    name = lib.getAttributeNodeNS(android_ns, 'name')
+    return name.value if name is not None else ''
 
 
 def uses_library_required(lib):
-  """Extract the required attribute of a uses-library tag.
+    """Extract the required attribute of a uses-library tag.
 
   Args:
     lib: a <uses-library> tag.
-  """
-  required = lib.getAttributeNodeNS(android_ns, 'required')
-  return (required.value == 'true') if required is not None else True
+    """
+    required = lib.getAttributeNodeNS(android_ns, 'required')
+    return (required.value == 'true') if required is not None else True
 
 
-def extract_target_sdk_version(manifest, is_apk = False):
-  """Returns the targetSdkVersion from the manifest.
+def extract_target_sdk_version(manifest, is_apk=False):
+    """Returns the targetSdkVersion from the manifest.
 
   Args:
     manifest: manifest (either parsed XML or aapt dump of APK)
     is_apk:   if the manifest comes from an APK or an XML file
-  """
-  if is_apk:
-    return extract_target_sdk_version_apk(manifest)
-  else:
-    return extract_target_sdk_version_xml(manifest)
+    """
+    if is_apk: #pylint: disable=no-else-return
+        return extract_target_sdk_version_apk(manifest)
+    else:
+        return extract_target_sdk_version_xml(manifest)
 
 
 def extract_target_sdk_version_apk(badging):
-  """Extract targetSdkVersion tags from the manifest of an APK."""
+    """Extract targetSdkVersion tags from the manifest of an APK."""
 
-  pattern = re.compile("^targetSdkVersion?:'(.*)'$", re.MULTILINE)
+    pattern = re.compile("^targetSdkVersion?:'(.*)'$", re.MULTILINE)
 
-  for match in re.finditer(pattern, badging):
-    return match.group(1)
+    for match in re.finditer(pattern, badging):
+        return match.group(1)
 
-  raise RuntimeError('cannot find targetSdkVersion in the manifest')
+    raise RuntimeError('cannot find targetSdkVersion in the manifest')
 
 
 def extract_target_sdk_version_xml(xml):
-  """Extract targetSdkVersion tags from the manifest."""
+    """Extract targetSdkVersion tags from the manifest."""
 
-  manifest = parse_manifest(xml)
+    manifest = parse_manifest(xml)
 
-  # Get or insert the uses-sdk element
-  uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
-  if len(uses_sdk) > 1:
-    raise RuntimeError('found multiple uses-sdk elements')
-  elif len(uses_sdk) == 0:
-    raise RuntimeError('missing uses-sdk element')
+    # Get or insert the uses-sdk element
+    uses_sdk = get_children_with_tag(manifest, 'uses-sdk')
+    if len(uses_sdk) > 1: #pylint: disable=no-else-raise
+        raise RuntimeError('found multiple uses-sdk elements')
+    elif len(uses_sdk) == 0:
+        raise RuntimeError('missing uses-sdk element')
 
-  uses_sdk = uses_sdk[0]
+    uses_sdk = uses_sdk[0]
 
-  min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion')
-  if min_attr is None:
-    raise RuntimeError('minSdkVersion is not specified')
+    min_attr = uses_sdk.getAttributeNodeNS(android_ns, 'minSdkVersion')
+    if min_attr is None:
+        raise RuntimeError('minSdkVersion is not specified')
 
-  target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion')
-  if target_attr is None:
-    target_attr = min_attr
+    target_attr = uses_sdk.getAttributeNodeNS(android_ns, 'targetSdkVersion')
+    if target_attr is None:
+        target_attr = min_attr
 
-  return target_attr.value
+    return target_attr.value
 
 
 def load_dexpreopt_configs(configs):
-  """Load dexpreopt.config files and map module names to library names."""
-  module_to_libname = {}
+    """Load dexpreopt.config files and map module names to library names."""
+    module_to_libname = {}
 
-  if configs is None:
-    configs = []
+    if configs is None:
+        configs = []
 
-  for config in configs:
-    with open(config, 'r') as f:
-      contents = json.load(f)
-    module_to_libname[contents['Name']] = contents['ProvidesUsesLibrary']
+    for config in configs:
+        with open(config, 'r') as f:
+            contents = json.load(f)
+        module_to_libname[contents['Name']] = contents['ProvidesUsesLibrary']
 
-  return module_to_libname
+    return module_to_libname
 
 
 def translate_libnames(modules, module_to_libname):
-  """Translate module names into library names using the mapping."""
-  if modules is None:
-    modules = []
+    """Translate module names into library names using the mapping."""
+    if modules is None:
+        modules = []
 
-  libnames = []
-  for name in modules:
-    if name in module_to_libname:
-      name = module_to_libname[name]
-    libnames.append(name)
+    libnames = []
+    for name in modules:
+        if name in module_to_libname:
+            name = module_to_libname[name]
+        libnames.append(name)
 
-  return libnames
+    return libnames
 
 
 def main():
-  """Program entry point."""
-  try:
-    args = parse_args()
+    """Program entry point."""
+    try:
+        args = parse_args()
 
-    # The input can be either an XML manifest or an APK, they are parsed and
-    # processed in different ways.
-    is_apk = args.input.endswith('.apk')
-    if is_apk:
-      aapt = args.aapt if args.aapt != None else "aapt"
-      manifest = subprocess.check_output([aapt, "dump", "badging", args.input])
-    else:
-      manifest = minidom.parse(args.input)
+        # The input can be either an XML manifest or an APK, they are parsed and
+        # processed in different ways.
+        is_apk = args.input.endswith('.apk')
+        if is_apk:
+            aapt = args.aapt if args.aapt is not None else 'aapt'
+            manifest = subprocess.check_output(
+                [aapt, 'dump', 'badging', args.input])
+        else:
+            manifest = minidom.parse(args.input)
 
-    if args.enforce_uses_libraries:
-      # Load dexpreopt.config files and build a mapping from module names to
-      # library names. This is necessary because build system addresses
-      # libraries by their module name (`uses_libs`, `optional_uses_libs`,
-      # `LOCAL_USES_LIBRARIES`, `LOCAL_OPTIONAL_LIBRARY_NAMES` all contain
-      # module names), while the manifest addresses libraries by their name.
-      mod_to_lib = load_dexpreopt_configs(args.dexpreopt_configs)
-      required = translate_libnames(args.uses_libraries, mod_to_lib)
-      optional = translate_libnames(args.optional_uses_libraries, mod_to_lib)
+        if args.enforce_uses_libraries:
+            # Load dexpreopt.config files and build a mapping from module
+            # names to library names. This is necessary because build system
+            # addresses libraries by their module name (`uses_libs`,
+            # `optional_uses_libs`, `LOCAL_USES_LIBRARIES`,
+            # `LOCAL_OPTIONAL_LIBRARY_NAMES` all contain module names), while
+            # the manifest addresses libraries by their name.
+            mod_to_lib = load_dexpreopt_configs(args.dexpreopt_configs)
+            required = translate_libnames(args.uses_libraries, mod_to_lib)
+            optional = translate_libnames(args.optional_uses_libraries,
+                                          mod_to_lib)
 
-      # Check if the <uses-library> lists in the build system agree with those
-      # in the manifest. Raise an exception on mismatch, unless the script was
-      # passed a special parameter to suppress exceptions.
-      errmsg = enforce_uses_libraries(manifest, required, optional,
-        args.enforce_uses_libraries_relax, is_apk, args.input)
+            # Check if the <uses-library> lists in the build system agree with
+            # those in the manifest. Raise an exception on mismatch, unless the
+            # script was passed a special parameter to suppress exceptions.
+            errmsg = enforce_uses_libraries(manifest, required, optional,
+                                            args.enforce_uses_libraries_relax,
+                                            is_apk, args.input)
 
-      # Create a status file that is empty on success, or contains an error
-      # message on failure. When exceptions are suppressed, dexpreopt command
-      # command will check file size to determine if the check has failed.
-      if args.enforce_uses_libraries_status:
-        with open(args.enforce_uses_libraries_status, 'w') as f:
-          if not errmsg == None:
-            f.write("%s\n" % errmsg)
+            # Create a status file that is empty on success, or contains an
+            # error message on failure. When exceptions are suppressed,
+            # dexpreopt command command will check file size to determine if
+            # the check has failed.
+            if args.enforce_uses_libraries_status:
+                with open(args.enforce_uses_libraries_status, 'w') as f:
+                    if not errmsg is not None:
+                        f.write('%s\n' % errmsg)
 
-    if args.extract_target_sdk_version:
-      try:
-        print(extract_target_sdk_version(manifest, is_apk))
-      except:
-        # Failed; don't crash, return "any" SDK version. This will result in
-        # dexpreopt not adding any compatibility libraries.
-        print(10000)
+        if args.extract_target_sdk_version:
+            try:
+                print(extract_target_sdk_version(manifest, is_apk))
+            except: #pylint: disable=bare-except
+                # Failed; don't crash, return "any" SDK version. This will
+                # result in dexpreopt not adding any compatibility libraries.
+                print(10000)
 
-    if args.output:
-      # XML output is supposed to be written only when this script is invoked
-      # with XML input manifest, not with an APK.
-      if is_apk:
-        raise RuntimeError('cannot save APK manifest as XML')
+        if args.output:
+            # XML output is supposed to be written only when this script is
+            # invoked with XML input manifest, not with an APK.
+            if is_apk:
+                raise RuntimeError('cannot save APK manifest as XML')
 
-      with open(args.output, 'wb') as f:
-        write_xml(f, manifest)
+            with open(args.output, 'wb') as f:
+                write_xml(f, manifest)
 
-  # pylint: disable=broad-except
-  except Exception as err:
-    print('error: ' + str(err), file=sys.stderr)
-    sys.exit(-1)
+    # pylint: disable=broad-except
+    except Exception as err:
+        print('error: ' + str(err), file=sys.stderr)
+        sys.exit(-1)
+
 
 if __name__ == '__main__':
-  main()
+    main()
diff --git a/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index e3e8ac4..3be7a30 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -26,202 +26,235 @@
 
 
 def uses_library_xml(name, attr=''):
-  return '<uses-library android:name="%s"%s />' % (name, attr)
+    return '<uses-library android:name="%s"%s />' % (name, attr)
 
 
 def required_xml(value):
-  return ' android:required="%s"' % ('true' if value else 'false')
+    return ' android:required="%s"' % ('true' if value else 'false')
 
 
 def uses_library_apk(name, sfx=''):
-  return "uses-library%s:'%s'" % (sfx, name)
+    return "uses-library%s:'%s'" % (sfx, name)
 
 
 def required_apk(value):
-  return '' if value else '-not-required'
+    return '' if value else '-not-required'
 
 
 class EnforceUsesLibrariesTest(unittest.TestCase):
-  """Unit tests for add_extract_native_libs function."""
+    """Unit tests for add_extract_native_libs function."""
 
-  def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[]):
-    doc = minidom.parseString(xml)
-    try:
-      relax = False
-      manifest_check.enforce_uses_libraries(doc, uses_libraries,
-        optional_uses_libraries, relax, False, 'path/to/X/AndroidManifest.xml')
-      manifest_check.enforce_uses_libraries(apk, uses_libraries,
-        optional_uses_libraries, relax, True, 'path/to/X/X.apk')
-      return True
-    except manifest_check.ManifestMismatchError:
-      return False
+    def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
+        doc = minidom.parseString(xml)
+        try:
+            relax = False
+            manifest_check.enforce_uses_libraries(
+                doc, uses_libraries, optional_uses_libraries, relax, False,
+                'path/to/X/AndroidManifest.xml')
+            manifest_check.enforce_uses_libraries(apk, uses_libraries,
+                                                  optional_uses_libraries,
+                                                  relax, True,
+                                                  'path/to/X/X.apk')
+            return True
+        except manifest_check.ManifestMismatchError:
+            return False
 
-  xml_tmpl = (
-      '<?xml version="1.0" encoding="utf-8"?>\n'
-      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
-      '    <application>\n'
-      '    %s\n'
-      '    </application>\n'
-      '</manifest>\n')
+    xml_tmpl = (
+        '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
+        'xmlns:android="http://schemas.android.com/apk/res/android">\n    '
+        '<application>\n    %s\n    </application>\n</manifest>\n')
 
-  apk_tmpl = (
-      "package: name='com.google.android.something' versionCode='100'\n"
-      "sdkVersion:'29'\n"
-      "targetSdkVersion:'29'\n"
-      "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n"
-      "%s\n"
-      "densities: '160' '240' '320' '480' '640' '65534")
+    apk_tmpl = (
+        "package: name='com.google.android.something' versionCode='100'\n"
+        "sdkVersion:'29'\n"
+        "targetSdkVersion:'29'\n"
+        "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n"
+        '%s\n'
+        "densities: '160' '240' '320' '480' '640' '65534")
 
-  def test_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo'))
-    apk = self.apk_tmpl % (uses_library_apk('foo'))
-    matches = self.run_test(xml, apk, uses_libraries=['foo'])
-    self.assertTrue(matches)
+    def test_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo'))
+        apk = self.apk_tmpl % (uses_library_apk('foo'))
+        matches = self.run_test(xml, apk, uses_libraries=['foo'])
+        self.assertTrue(matches)
 
-  def test_uses_library_required(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True)))
-    apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True)))
-    matches = self.run_test(xml, apk, uses_libraries=['foo'])
-    self.assertTrue(matches)
+    def test_uses_library_required(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(True)))
+        apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(True)))
+        matches = self.run_test(xml, apk, uses_libraries=['foo'])
+        self.assertTrue(matches)
 
-  def test_optional_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
-    apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
-    matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
-    self.assertTrue(matches)
+    def test_optional_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
+        apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
+        matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
+        self.assertTrue(matches)
 
-  def test_expected_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
-    apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
-    matches = self.run_test(xml, apk, uses_libraries=['foo'])
-    self.assertFalse(matches)
+    def test_expected_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
+        apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
+        matches = self.run_test(xml, apk, uses_libraries=['foo'])
+        self.assertFalse(matches)
 
-  def test_expected_optional_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo'))
-    apk = self.apk_tmpl % (uses_library_apk('foo'))
-    matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
-    self.assertFalse(matches)
+    def test_expected_optional_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo'))
+        apk = self.apk_tmpl % (uses_library_apk('foo'))
+        matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
+        self.assertFalse(matches)
 
-  def test_missing_uses_library(self):
-    xml = self.xml_tmpl % ('')
-    apk = self.apk_tmpl % ('')
-    matches = self.run_test(xml, apk, uses_libraries=['foo'])
-    self.assertFalse(matches)
+    def test_missing_uses_library(self):
+        xml = self.xml_tmpl % ('')
+        apk = self.apk_tmpl % ('')
+        matches = self.run_test(xml, apk, uses_libraries=['foo'])
+        self.assertFalse(matches)
 
-  def test_missing_optional_uses_library(self):
-    xml = self.xml_tmpl % ('')
-    apk = self.apk_tmpl % ('')
-    matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
-    self.assertFalse(matches)
+    def test_missing_optional_uses_library(self):
+        xml = self.xml_tmpl % ('')
+        apk = self.apk_tmpl % ('')
+        matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
+        self.assertFalse(matches)
 
-  def test_extra_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo'))
-    apk = self.apk_tmpl % (uses_library_xml('foo'))
-    matches = self.run_test(xml, apk)
-    self.assertFalse(matches)
+    def test_extra_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo'))
+        apk = self.apk_tmpl % (uses_library_xml('foo'))
+        matches = self.run_test(xml, apk)
+        self.assertFalse(matches)
 
-  def test_extra_optional_uses_library(self):
-    xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
-    apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
-    matches = self.run_test(xml, apk)
-    self.assertFalse(matches)
+    def test_extra_optional_uses_library(self):
+        xml = self.xml_tmpl % (uses_library_xml('foo', required_xml(False)))
+        apk = self.apk_tmpl % (uses_library_apk('foo', required_apk(False)))
+        matches = self.run_test(xml, apk)
+        self.assertFalse(matches)
 
-  def test_multiple_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo'),
-                                      uses_library_xml('bar')]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo'),
-                                      uses_library_apk('bar')]))
-    matches = self.run_test(xml, apk, uses_libraries=['foo', 'bar'])
-    self.assertTrue(matches)
+    def test_multiple_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join(
+            [uses_library_xml('foo'),
+             uses_library_xml('bar')]))
+        apk = self.apk_tmpl % ('\n'.join(
+            [uses_library_apk('foo'),
+             uses_library_apk('bar')]))
+        matches = self.run_test(xml, apk, uses_libraries=['foo', 'bar'])
+        self.assertTrue(matches)
 
-  def test_multiple_optional_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo', required_xml(False)),
-                                      uses_library_xml('bar', required_xml(False))]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo', required_apk(False)),
-                                      uses_library_apk('bar', required_apk(False))]))
-    matches = self.run_test(xml, apk, optional_uses_libraries=['foo', 'bar'])
-    self.assertTrue(matches)
+    def test_multiple_optional_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join([
+            uses_library_xml('foo', required_xml(False)),
+            uses_library_xml('bar', required_xml(False))
+        ]))
+        apk = self.apk_tmpl % ('\n'.join([
+            uses_library_apk('foo', required_apk(False)),
+            uses_library_apk('bar', required_apk(False))
+        ]))
+        matches = self.run_test(
+            xml, apk, optional_uses_libraries=['foo', 'bar'])
+        self.assertTrue(matches)
 
-  def test_order_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo'),
-                                      uses_library_xml('bar')]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo'),
-                                      uses_library_apk('bar')]))
-    matches = self.run_test(xml, apk, uses_libraries=['bar', 'foo'])
-    self.assertFalse(matches)
+    def test_order_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join(
+            [uses_library_xml('foo'),
+             uses_library_xml('bar')]))
+        apk = self.apk_tmpl % ('\n'.join(
+            [uses_library_apk('foo'),
+             uses_library_apk('bar')]))
+        matches = self.run_test(xml, apk, uses_libraries=['bar', 'foo'])
+        self.assertFalse(matches)
 
-  def test_order_optional_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo', required_xml(False)),
-                                      uses_library_xml('bar', required_xml(False))]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo', required_apk(False)),
-                                      uses_library_apk('bar', required_apk(False))]))
-    matches = self.run_test(xml, apk, optional_uses_libraries=['bar', 'foo'])
-    self.assertFalse(matches)
+    def test_order_optional_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join([
+            uses_library_xml('foo', required_xml(False)),
+            uses_library_xml('bar', required_xml(False))
+        ]))
+        apk = self.apk_tmpl % ('\n'.join([
+            uses_library_apk('foo', required_apk(False)),
+            uses_library_apk('bar', required_apk(False))
+        ]))
+        matches = self.run_test(
+            xml, apk, optional_uses_libraries=['bar', 'foo'])
+        self.assertFalse(matches)
 
-  def test_duplicate_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo'),
-                                      uses_library_xml('foo')]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo'),
-                                      uses_library_apk('foo')]))
-    matches = self.run_test(xml, apk, uses_libraries=['foo'])
-    self.assertTrue(matches)
+    def test_duplicate_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join(
+            [uses_library_xml('foo'),
+             uses_library_xml('foo')]))
+        apk = self.apk_tmpl % ('\n'.join(
+            [uses_library_apk('foo'),
+             uses_library_apk('foo')]))
+        matches = self.run_test(xml, apk, uses_libraries=['foo'])
+        self.assertTrue(matches)
 
-  def test_duplicate_optional_uses_library(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo', required_xml(False)),
-                                      uses_library_xml('foo', required_xml(False))]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo', required_apk(False)),
-                                      uses_library_apk('foo', required_apk(False))]))
-    matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
-    self.assertTrue(matches)
+    def test_duplicate_optional_uses_library(self):
+        xml = self.xml_tmpl % ('\n'.join([
+            uses_library_xml('foo', required_xml(False)),
+            uses_library_xml('foo', required_xml(False))
+        ]))
+        apk = self.apk_tmpl % ('\n'.join([
+            uses_library_apk('foo', required_apk(False)),
+            uses_library_apk('foo', required_apk(False))
+        ]))
+        matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
+        self.assertTrue(matches)
 
-  def test_mixed(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo'),
-                                      uses_library_xml('bar', required_xml(False))]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo'),
-                                      uses_library_apk('bar', required_apk(False))]))
-    matches = self.run_test(xml, apk, uses_libraries=['foo'],
-                            optional_uses_libraries=['bar'])
-    self.assertTrue(matches)
+    def test_mixed(self):
+        xml = self.xml_tmpl % ('\n'.join([
+            uses_library_xml('foo'),
+            uses_library_xml('bar', required_xml(False))
+        ]))
+        apk = self.apk_tmpl % ('\n'.join([
+            uses_library_apk('foo'),
+            uses_library_apk('bar', required_apk(False))
+        ]))
+        matches = self.run_test(
+            xml, apk, uses_libraries=['foo'], optional_uses_libraries=['bar'])
+        self.assertTrue(matches)
 
-  def test_mixed_with_namespace(self):
-    xml = self.xml_tmpl % ('\n'.join([uses_library_xml('foo'),
-                                      uses_library_xml('bar', required_xml(False))]))
-    apk = self.apk_tmpl % ('\n'.join([uses_library_apk('foo'),
-                                      uses_library_apk('bar', required_apk(False))]))
-    matches = self.run_test(xml, apk, uses_libraries=['//x/y/z:foo'],
-                            optional_uses_libraries=['//x/y/z:bar'])
-    self.assertTrue(matches)
+    def test_mixed_with_namespace(self):
+        xml = self.xml_tmpl % ('\n'.join([
+            uses_library_xml('foo'),
+            uses_library_xml('bar', required_xml(False))
+        ]))
+        apk = self.apk_tmpl % ('\n'.join([
+            uses_library_apk('foo'),
+            uses_library_apk('bar', required_apk(False))
+        ]))
+        matches = self.run_test(
+            xml,
+            apk,
+            uses_libraries=['//x/y/z:foo'],
+            optional_uses_libraries=['//x/y/z:bar'])
+        self.assertTrue(matches)
 
 
 class ExtractTargetSdkVersionTest(unittest.TestCase):
-  def run_test(self, xml, apk, version):
-    doc = minidom.parseString(xml)
-    v = manifest_check.extract_target_sdk_version(doc, is_apk=False)
-    self.assertEqual(v, version)
-    v = manifest_check.extract_target_sdk_version(apk, is_apk=True)
-    self.assertEqual(v, version)
 
-  xml_tmpl = (
-      '<?xml version="1.0" encoding="utf-8"?>\n'
-      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
-      '    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="%s" />\n'
-      '</manifest>\n')
+    def run_test(self, xml, apk, version):
+        doc = minidom.parseString(xml)
+        v = manifest_check.extract_target_sdk_version(doc, is_apk=False)
+        self.assertEqual(v, version)
+        v = manifest_check.extract_target_sdk_version(apk, is_apk=True)
+        self.assertEqual(v, version)
 
-  apk_tmpl = (
-      "package: name='com.google.android.something' versionCode='100'\n"
-      "sdkVersion:'28'\n"
-      "targetSdkVersion:'%s'\n"
-      "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
+    xml_tmpl = (
+        '<?xml version="1.0" encoding="utf-8"?>\n<manifest '
+        'xmlns:android="http://schemas.android.com/apk/res/android">\n    '
+        '<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="%s" '
+        '/>\n</manifest>\n')
 
-  def test_targert_sdk_version_28(self):
-    xml = self.xml_tmpl % "28"
-    apk = self.apk_tmpl % "28"
-    self.run_test(xml, apk, "28")
+    apk_tmpl = (
+        "package: name='com.google.android.something' versionCode='100'\n"
+        "sdkVersion:'28'\n"
+        "targetSdkVersion:'%s'\n"
+        "uses-permission: name='android.permission.ACCESS_NETWORK_STATE'\n")
 
-  def test_targert_sdk_version_29(self):
-    xml = self.xml_tmpl % "29"
-    apk = self.apk_tmpl % "29"
-    self.run_test(xml, apk, "29")
+    def test_targert_sdk_version_28(self):
+        xml = self.xml_tmpl % '28'
+        apk = self.apk_tmpl % '28'
+        self.run_test(xml, apk, '28')
+
+    def test_targert_sdk_version_29(self):
+        xml = self.xml_tmpl % '29'
+        apk = self.apk_tmpl % '29'
+        self.run_test(xml, apk, '29')
+
 
 if __name__ == '__main__':
-  unittest.main(verbosity=2)
+    unittest.main(verbosity=2)
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index b37a7f8..a22adc5 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -472,17 +472,35 @@
   fi
 }
 
-function test_null_build_after_docs {
+function test_soong_docs_smoke() {
   setup
-  run_soong
-  local mtime1=$(stat -c "%y" out/soong/build.ninja)
 
-  prebuilts/build-tools/linux-x86/bin/ninja -f out/combined.ninja soong_docs
+  run_soong soong_docs
+
+  [[ -e "out/soong/docs/soong_build.html" ]] || fail "Documentation for main page not created"
+  [[ -e "out/soong/docs/cc.html" ]] || fail "Documentation for C++ modules not created"
+}
+
+function test_null_build_after_soong_docs() {
+  setup
 
   run_soong
-  local mtime2=$(stat -c "%y" out/soong/build.ninja)
+  local ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
 
-  if [[ "$mtime1" != "$mtime2" ]]; then
+  run_soong soong_docs
+  local docs_mtime1=$(stat -c "%y" out/soong/docs/soong_build.html)
+
+  run_soong soong_docs
+  local docs_mtime2=$(stat -c "%y" out/soong/docs/soong_build.html)
+
+  if [[ "$docs_mtime1" != "$docs_mtime2" ]]; then
+    fail "Output Ninja file changed on null build"
+  fi
+
+  run_soong
+  local ninja_mtime2=$(stat -c "%y" out/soong/build.ninja)
+
+  if [[ "$ninja_mtime1" != "$ninja_mtime2" ]]; then
     fail "Output Ninja file changed on null build"
   fi
 }
@@ -522,7 +540,7 @@
 
 function test_bp2build_smoke {
   setup
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -e out/soong/.bootstrap/bp2build_workspace_marker ]] || fail "bp2build marker file not created"
   [[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
 }
@@ -531,7 +549,7 @@
   setup
   create_mock_bazel
 
-  run_bp2build
+  run_soong bp2build
 
   if [[ ! -f "./out/soong/.bootstrap/bp2build_workspace_marker" ]]; then
     fail "Marker file was not generated"
@@ -551,7 +569,7 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -e out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
   [[ -L out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
 
@@ -565,7 +583,7 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -e out/soong/bp2build/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not created"
   [[ -L out/soong/workspace/b/${GENERATED_BUILD_FILE_NAME} ]] || fail "a/${GENERATED_BUILD_FILE_NAME} not symlinked"
 }
@@ -573,10 +591,10 @@
 function test_bp2build_null_build {
   setup
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   local mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   local mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
   if [[ "$mtime1" != "$mtime2" ]]; then
@@ -597,18 +615,35 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   grep -q a1.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a1.txt not in ${GENERATED_BUILD_FILE_NAME} file"
 
   touch a/a2.txt
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   grep -q a2.txt "out/soong/bp2build/a/${GENERATED_BUILD_FILE_NAME}" || fail "a2.txt not in ${GENERATED_BUILD_FILE_NAME} file"
 }
 
+function test_multiple_soong_build_modes() {
+  setup
+  run_soong json-module-graph bp2build nothing
+  if [[ ! -f "out/soong/.bootstrap/bp2build_workspace_marker" ]]; then
+    fail "bp2build marker file was not generated"
+  fi
+
+
+  if [[ ! -f "out/soong/module-graph.json" ]]; then
+    fail "JSON file was not created"
+  fi
+
+  if [[ ! -f "out/soong/build.ninja" ]]; then
+    fail "Main build.ninja file was not created"
+  fi
+}
+
 function test_dump_json_module_graph() {
   setup
-  GENERATE_JSON_MODULE_GRAPH=1 run_soong
-  if [[ ! -r "out/soong//module-graph.json" ]]; then
+  run_soong json-module-graph
+  if [[ ! -r "out/soong/module-graph.json" ]]; then
     fail "JSON file was not created"
   fi
 }
@@ -619,7 +654,7 @@
   run_soong
   local ninja_mtime1=$(stat -c "%y" out/soong/build.ninja)
 
-  GENERATE_JSON_MODULE_GRAPH=1 run_soong
+  run_soong json-module-graph
   local json_mtime1=$(stat -c "%y" out/soong/module-graph.json)
 
   run_soong
@@ -628,7 +663,7 @@
     fail "Output Ninja file changed after writing JSON module graph"
   fi
 
-  GENERATE_JSON_MODULE_GRAPH=1 run_soong
+  run_soong json-module-graph
   local json_mtime2=$(stat -c "%y" out/soong/module-graph.json)
   if [[ "$json_mtime1" != "$json_mtime2" ]]; then
     fail "JSON module graph file changed after writing Ninja file"
@@ -651,7 +686,7 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -e out/soong/workspace ]] || fail "Bazel workspace not created"
   [[ -d out/soong/workspace/a/b ]] || fail "module directory not a directory"
   [[ -L "out/soong/workspace/a/b/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
@@ -675,10 +710,10 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
 
   touch a/a2.txt  # No reference in the .bp file needed
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -L out/soong/workspace/a/a2.txt ]] || fail "a/a2.txt not symlinked"
 }
 
@@ -696,7 +731,7 @@
 }
 EOF
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   [[ -L "out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME}" ]] || fail "${GENERATED_BUILD_FILE_NAME} file not symlinked"
   [[ "$(readlink -f out/soong/workspace/a/${GENERATED_BUILD_FILE_NAME})" =~ "bp2build/a/${GENERATED_BUILD_FILE_NAME}"$ ]] \
     || fail "${GENERATED_BUILD_FILE_NAME} files symlinked to the wrong place"
@@ -725,7 +760,7 @@
 }
 EOF
 
-  if GENERATE_BAZEL_FILES=1 run_soong >& "$MOCK_TOP/errors"; then
+  if run_soong bp2build >& "$MOCK_TOP/errors"; then
     fail "Build should have failed"
   fi
 
@@ -739,7 +774,7 @@
   run_soong
   local output_mtime1=$(stat -c "%y" out/soong/build.ninja)
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   local output_mtime2=$(stat -c "%y" out/soong/build.ninja)
   if [[ "$output_mtime1" != "$output_mtime2" ]]; then
     fail "Output Ninja file changed when switching to bp2build"
@@ -757,7 +792,7 @@
     fail "bp2build marker file changed when switching to regular build from bp2build"
   fi
 
-  GENERATE_BAZEL_FILES=1 run_soong
+  run_soong bp2build
   local output_mtime4=$(stat -c "%y" out/soong/build.ninja)
   local marker_mtime3=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
   if [[ "$output_mtime1" != "$output_mtime4" ]]; then
@@ -768,9 +803,32 @@
   fi
 }
 
+function test_queryview_smoke() {
+  setup
+
+  run_soong queryview
+  [[ -e out/soong/queryview/WORKSPACE ]] || fail "queryview WORKSPACE file not created"
+
+}
+
+function test_queryview_null_build() {
+  setup
+
+  run_soong queryview
+  local output_mtime1=$(stat -c "%y" out/soong/queryview.marker)
+
+  run_soong queryview
+  local output_mtime2=$(stat -c "%y" out/soong/queryview.marker)
+
+  if [[ "$output_mtime1" != "$output_mtime2" ]]; then
+    fail "Queryview marker file changed on null build"
+  fi
+}
+
 test_smoke
 test_null_build
-test_null_build_after_docs
+test_soong_docs_smoke
+test_null_build_after_soong_docs
 test_soong_build_rebuilt_if_blueprint_changes
 test_glob_noop_incremental
 test_add_file_to_glob
@@ -780,9 +838,12 @@
 test_add_file_to_soong_build
 test_glob_during_bootstrapping
 test_soong_build_rerun_iff_environment_changes
+test_multiple_soong_build_modes
 test_dump_json_module_graph
 test_json_module_graph_back_and_forth_null_build
 test_write_to_source_tree
+test_queryview_smoke
+test_queryview_null_build
 test_bp2build_smoke
 test_bp2build_generates_marker_file
 test_bp2build_null_build
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 9bd85a4..379eb65 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -10,10 +10,10 @@
 
 function test_bp2build_null_build() {
   setup
-  run_bp2build
+  run_soong bp2build
   local output_mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
-  run_bp2build
+  run_soong bp2build
   local output_mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
   if [[ "$output_mtime1" != "$output_mtime2" ]]; then
@@ -35,10 +35,10 @@
 EOF
   touch foo/bar/a.txt foo/bar/b.txt
 
-  run_bp2build
+  run_soong bp2build
   local output_mtime1=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
-  run_bp2build
+  run_soong bp2build
   local output_mtime2=$(stat -c "%y" out/soong/.bootstrap/bp2build_workspace_marker)
 
   if [[ "$output_mtime1" != "$output_mtime2" ]]; then
@@ -80,7 +80,7 @@
   }
 EOF
 
-  run_bp2build
+  run_soong bp2build
 
   if [[ ! -f "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME}" ]]; then
     fail "./out/soong/workspace/foo/convertible_soong_module/${GENERATED_BUILD_FILE_NAME} was not generated"
diff --git a/tests/lib.sh b/tests/lib.sh
index 813a9dd..e777820 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -124,10 +124,6 @@
   tools/bazel "$@"
 }
 
-run_bp2build() {
-  GENERATE_BAZEL_FILES=true build/soong/soong_ui.bash --make-mode --skip-ninja --skip-make --skip-soong-tests nothing
-}
-
 run_ninja() {
   build/soong/soong_ui.bash --make-mode --skip-make --skip-soong-tests "$@"
 }
diff --git a/ui/build/build.go b/ui/build/build.go
index d869bf0..2e44aaa 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -248,6 +248,16 @@
 		what = what &^ RunNinja
 	}
 
+	if !config.SoongBuildInvocationNeeded() {
+		// This means that the output of soong_build is not needed and thus it would
+		// run unnecessarily. In addition, if this code wasn't there invocations
+		// with only special-cased target names like "m bp2build" would result in
+		// passing Ninja the empty target list and it would then build the default
+		// targets which is not what the user asked for.
+		what = what &^ RunNinja
+		what = what &^ RunKati
+	}
+
 	if config.StartGoma() {
 		startGoma(ctx, config)
 	}
@@ -278,16 +288,6 @@
 
 	if what&RunSoong != 0 {
 		runSoong(ctx, config)
-
-		if config.bazelBuildMode() == generateBuildFiles {
-			// Return early, if we're using Soong as solely the generator of BUILD files.
-			return
-		}
-
-		if config.bazelBuildMode() == generateJsonModuleGraph {
-			// Return early, if we're using Soong as solely the generator of the JSON module graph
-			return
-		}
 	}
 
 	if what&RunKati != 0 {
diff --git a/ui/build/config.go b/ui/build/config.go
index 6de7a05..35dacf2 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -33,7 +33,8 @@
 type Config struct{ *configImpl }
 
 type configImpl struct {
-	// From the environment
+	// Some targets that are implemented in soong_build
+	// (bp2build, json-module-graph) are not here and have their own bits below.
 	arguments     []string
 	goma          bool
 	environ       *Environment
@@ -41,17 +42,21 @@
 	buildDateTime string
 
 	// From the arguments
-	parallel       int
-	keepGoing      int
-	verbose        bool
-	checkbuild     bool
-	dist           bool
-	skipConfig     bool
-	skipKati       bool
-	skipKatiNinja  bool
-	skipSoong      bool
-	skipNinja      bool
-	skipSoongTests bool
+	parallel        int
+	keepGoing       int
+	verbose         bool
+	checkbuild      bool
+	dist            bool
+	jsonModuleGraph bool
+	bp2build        bool
+	queryview       bool
+	soongDocs       bool
+	skipConfig      bool
+	skipKati        bool
+	skipKatiNinja   bool
+	skipSoong       bool
+	skipNinja       bool
+	skipSoongTests  bool
 
 	// From the product config
 	katiArgs        []string
@@ -106,12 +111,6 @@
 	// Don't use bazel at all.
 	noBazel bazelBuildMode = iota
 
-	// Only generate build files (in a subdirectory of the out directory) and exit.
-	generateBuildFiles
-
-	// Only generate the Soong json module graph for use with jq, and exit.
-	generateJsonModuleGraph
-
 	// Generate synthetic build files and incorporate these files into a build which
 	// partially uses Bazel. Build metadata may come from Android.bp or BUILD files.
 	mixedBuild
@@ -639,6 +638,14 @@
 			c.environ.Set(k, v)
 		} else if arg == "dist" {
 			c.dist = true
+		} else if arg == "json-module-graph" {
+			c.jsonModuleGraph = true
+		} else if arg == "bp2build" {
+			c.bp2build = true
+		} else if arg == "queryview" {
+			c.queryview = true
+		} else if arg == "soong_docs" {
+			c.soongDocs = true
 		} else {
 			if arg == "checkbuild" {
 				c.checkbuild = true
@@ -705,6 +712,26 @@
 	return c.arguments
 }
 
+func (c *configImpl) SoongBuildInvocationNeeded() bool {
+	if c.Dist() {
+		return true
+	}
+
+	if len(c.Arguments()) > 0 {
+		// Explicit targets requested that are not special targets like b2pbuild
+		// or the JSON module graph
+		return true
+	}
+
+	if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() {
+		// Command line was empty, the default Ninja target is built
+		return true
+	}
+
+	// build.ninja doesn't need to be generated
+	return false
+}
+
 func (c *configImpl) OutDir() string {
 	if outDir, ok := c.environ.Get("OUT_DIR"); ok {
 		return outDir
@@ -753,6 +780,14 @@
 	return filepath.Join(c.SoongOutDir(), "host", c.PrebuiltOS(), "bin")
 }
 
+func (c *configImpl) NamedGlobFile(name string) string {
+	return shared.JoinPath(c.SoongOutDir(), ".bootstrap/build-globs."+name+".ninja")
+}
+
+func (c *configImpl) UsedEnvFile(tag string) string {
+	return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
+}
+
 func (c *configImpl) MainNinjaFile() string {
 	return shared.JoinPath(c.SoongOutDir(), "build.ninja")
 }
@@ -761,6 +796,14 @@
 	return shared.JoinPath(c.SoongOutDir(), ".bootstrap/bp2build_workspace_marker")
 }
 
+func (c *configImpl) SoongDocsHtml() string {
+	return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
+}
+
+func (c *configImpl) QueryviewMarkerFile() string {
+	return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
+}
+
 func (c *configImpl) ModuleGraphFile() string {
 	return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
 }
@@ -790,6 +833,22 @@
 	return c.dist
 }
 
+func (c *configImpl) JsonModuleGraph() bool {
+	return c.jsonModuleGraph
+}
+
+func (c *configImpl) Bp2Build() bool {
+	return c.bp2build
+}
+
+func (c *configImpl) Queryview() bool {
+	return c.queryview
+}
+
+func (c *configImpl) SoongDocs() bool {
+	return c.soongDocs
+}
+
 func (c *configImpl) IsVerbose() bool {
 	return c.verbose
 }
@@ -935,10 +994,6 @@
 func (c *configImpl) bazelBuildMode() bazelBuildMode {
 	if c.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
 		return mixedBuild
-	} else if c.Environment().IsEnvTrue("GENERATE_BAZEL_FILES") {
-		return generateBuildFiles
-	} else if c.Environment().IsEnvTrue("GENERATE_JSON_MODULE_GRAPH") {
-		return generateJsonModuleGraph
 	} else {
 		return noBazel
 	}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index d4f6f2f..617d293 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -37,6 +37,12 @@
 const (
 	availableEnvFile = "soong.environment.available"
 	usedEnvFile      = "soong.environment.used"
+
+	soongBuildTag      = "build"
+	bp2buildTag        = "bp2build"
+	jsonModuleGraphTag = "modulegraph"
+	queryviewTag       = "queryview"
+	soongDocsTag       = "soong_docs"
 )
 
 func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error {
@@ -75,7 +81,6 @@
 	soongOutDir               string
 	outDir                    string
 	runGoTests                bool
-	useValidations            bool
 	debugCompilation          bool
 	subninjas                 []string
 	primaryBuilderInvocations []bootstrap.PrimaryBuilderInvocation
@@ -97,10 +102,6 @@
 	return c.runGoTests
 }
 
-func (c BlueprintConfig) UseValidationsForGoTests() bool {
-	return c.useValidations
-}
-
 func (c BlueprintConfig) DebugCompilation() bool {
 	return c.debugCompilation
 }
@@ -113,10 +114,10 @@
 	return c.primaryBuilderInvocations
 }
 
-func environmentArgs(config Config, suffix string) []string {
+func environmentArgs(config Config, tag string) []string {
 	return []string{
 		"--available_env", shared.JoinPath(config.SoongOutDir(), availableEnvFile),
-		"--used_env", shared.JoinPath(config.SoongOutDir(), usedEnvFile+suffix),
+		"--used_env", config.UsedEnvFile(tag),
 	}
 }
 
@@ -134,116 +135,134 @@
 	}
 }
 
+func primaryBuilderInvocation(config Config, name string, output string, specificArgs []string) bootstrap.PrimaryBuilderInvocation {
+	commonArgs := make([]string, 0, 0)
+
+	if !config.skipSoongTests {
+		commonArgs = append(commonArgs, "-t")
+	}
+
+	commonArgs = append(commonArgs, "-l", filepath.Join(config.FileListDir(), "Android.bp.list"))
+
+	if os.Getenv("SOONG_DELVE") != "" {
+		commonArgs = append(commonArgs, "--delve_listen", os.Getenv("SOONG_DELVE"))
+		commonArgs = append(commonArgs, "--delve_path", shared.ResolveDelveBinary())
+	}
+
+	allArgs := make([]string, 0, 0)
+	allArgs = append(allArgs, specificArgs...)
+	allArgs = append(allArgs,
+		"--globListDir", name,
+		"--globFile", config.NamedGlobFile(name))
+
+	allArgs = append(allArgs, commonArgs...)
+	allArgs = append(allArgs, environmentArgs(config, name)...)
+	allArgs = append(allArgs, "Android.bp")
+
+	return bootstrap.PrimaryBuilderInvocation{
+		Inputs:  []string{"Android.bp"},
+		Outputs: []string{output},
+		Args:    allArgs,
+	}
+}
+
 func bootstrapBlueprint(ctx Context, config Config) {
 	ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
 	defer ctx.EndTrace()
 
-	var args bootstrap.Args
-
-	bootstrapGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.ninja")
-	bp2buildGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.bp2build.ninja")
-	moduleGraphGlobFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build-globs.modulegraph.ninja")
-
-	// The glob .ninja files are subninja'd. However, they are generated during
-	// the build itself so we write an empty file so that the subninja doesn't
-	// fail on clean builds
-	writeEmptyGlobFile(ctx, bootstrapGlobFile)
-	writeEmptyGlobFile(ctx, bp2buildGlobFile)
-	bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja.d")
-
-	args.RunGoTests = !config.skipSoongTests
-	args.UseValidations = true // Use validations to depend on tests
-	args.SoongOutDir = config.SoongOutDir()
-	args.OutDir = config.OutDir()
-	args.ModuleListFile = filepath.Join(config.FileListDir(), "Android.bp.list")
-	args.OutFile = shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja")
-	// The primary builder (aka soong_build) will use bootstrapGlobFile as the globFile to generate build.ninja(.d)
-	// Building soong_build does not require a glob file
-	// Using "" instead of "<soong_build_glob>.ninja" will ensure that an unused glob file is not written to out/soong/.bootstrap during StagePrimary
-	args.Subninjas = []string{bootstrapGlobFile, bp2buildGlobFile}
-	args.EmptyNinjaFile = config.EmptyNinjaFile()
-
-	args.DelveListen = os.Getenv("SOONG_DELVE")
-	if args.DelveListen != "" {
-		args.DelvePath = shared.ResolveDelveBinary()
+	mainSoongBuildExtraArgs := []string{"-o", config.MainNinjaFile()}
+	if config.EmptyNinjaFile() {
+		mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file")
 	}
 
-	commonArgs := bootstrap.PrimaryBuilderExtraFlags(args, config.MainNinjaFile())
-	mainSoongBuildInputs := []string{"Android.bp"}
+	mainSoongBuildInvocation := primaryBuilderInvocation(
+		config,
+		soongBuildTag,
+		config.MainNinjaFile(),
+		mainSoongBuildExtraArgs)
 
 	if config.bazelBuildMode() == mixedBuild {
-		mainSoongBuildInputs = append(mainSoongBuildInputs, config.Bp2BuildMarkerFile())
+		// Mixed builds call Bazel from soong_build and they therefore need the
+		// Bazel workspace to be available. Make that so by adding a dependency on
+		// the bp2build marker file to the action that invokes soong_build .
+		mainSoongBuildInvocation.Inputs = append(mainSoongBuildInvocation.Inputs,
+			config.Bp2BuildMarkerFile())
 	}
 
-	soongBuildArgs := []string{
-		"--globListDir", "build",
-		"--globFile", bootstrapGlobFile,
+	bp2buildInvocation := primaryBuilderInvocation(
+		config,
+		bp2buildTag,
+		config.Bp2BuildMarkerFile(),
+		[]string{
+			"--bp2build_marker", config.Bp2BuildMarkerFile(),
+		})
+
+	jsonModuleGraphInvocation := primaryBuilderInvocation(
+		config,
+		jsonModuleGraphTag,
+		config.ModuleGraphFile(),
+		[]string{
+			"--module_graph_file", config.ModuleGraphFile(),
+		})
+
+	queryviewInvocation := primaryBuilderInvocation(
+		config,
+		queryviewTag,
+		config.QueryviewMarkerFile(),
+		[]string{
+			"--bazel_queryview_dir", filepath.Join(config.SoongOutDir(), "queryview"),
+		})
+
+	soongDocsInvocation := primaryBuilderInvocation(
+		config,
+		soongDocsTag,
+		config.SoongDocsHtml(),
+		[]string{
+			"--soong_docs", config.SoongDocsHtml(),
+		})
+
+	globFiles := []string{
+		config.NamedGlobFile(soongBuildTag),
+		config.NamedGlobFile(bp2buildTag),
+		config.NamedGlobFile(jsonModuleGraphTag),
+		config.NamedGlobFile(queryviewTag),
+		config.NamedGlobFile(soongDocsTag),
 	}
 
-	soongBuildArgs = append(soongBuildArgs, commonArgs...)
-	soongBuildArgs = append(soongBuildArgs, environmentArgs(config, "")...)
-	soongBuildArgs = append(soongBuildArgs, "Android.bp")
-
-	mainSoongBuildInvocation := bootstrap.PrimaryBuilderInvocation{
-		Inputs:  mainSoongBuildInputs,
-		Outputs: []string{config.MainNinjaFile()},
-		Args:    soongBuildArgs,
+	// The glob .ninja files are subninja'd. However, they are generated during
+	// the build itself so we write an empty file if the file does not exist yet
+	// so that the subninja doesn't fail on clean builds
+	for _, globFile := range globFiles {
+		writeEmptyGlobFile(ctx, globFile)
 	}
 
-	bp2buildArgs := []string{
-		"--bp2build_marker", config.Bp2BuildMarkerFile(),
-		"--globListDir", "bp2build",
-		"--globFile", bp2buildGlobFile,
-	}
+	var blueprintArgs bootstrap.Args
 
-	bp2buildArgs = append(bp2buildArgs, commonArgs...)
-	bp2buildArgs = append(bp2buildArgs, environmentArgs(config, ".bp2build")...)
-	bp2buildArgs = append(bp2buildArgs, "Android.bp")
-
-	bp2buildInvocation := bootstrap.PrimaryBuilderInvocation{
-		Inputs:  []string{"Android.bp"},
-		Outputs: []string{config.Bp2BuildMarkerFile()},
-		Args:    bp2buildArgs,
-	}
-
-	moduleGraphArgs := []string{
-		"--module_graph_file", config.ModuleGraphFile(),
-		"--globListDir", "modulegraph",
-		"--globFile", moduleGraphGlobFile,
-	}
-
-	moduleGraphArgs = append(moduleGraphArgs, commonArgs...)
-	moduleGraphArgs = append(moduleGraphArgs, environmentArgs(config, ".modulegraph")...)
-	moduleGraphArgs = append(moduleGraphArgs, "Android.bp")
-
-	moduleGraphInvocation := bootstrap.PrimaryBuilderInvocation{
-		Inputs:  []string{"Android.bp"},
-		Outputs: []string{config.ModuleGraphFile()},
-		Args:    moduleGraphArgs,
-	}
-
-	args.PrimaryBuilderInvocations = []bootstrap.PrimaryBuilderInvocation{
-		bp2buildInvocation,
-		mainSoongBuildInvocation,
-		moduleGraphInvocation,
-	}
+	blueprintArgs.ModuleListFile = filepath.Join(config.FileListDir(), "Android.bp.list")
+	blueprintArgs.OutFile = shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja")
+	blueprintArgs.EmptyNinjaFile = false
 
 	blueprintCtx := blueprint.NewContext()
 	blueprintCtx.SetIgnoreUnknownModuleTypes(true)
 	blueprintConfig := BlueprintConfig{
-		soongOutDir:               config.SoongOutDir(),
-		toolDir:                   config.HostToolDir(),
-		outDir:                    config.OutDir(),
-		runGoTests:                !config.skipSoongTests,
-		useValidations:            true,
-		debugCompilation:          os.Getenv("SOONG_DELVE") != "",
-		subninjas:                 args.Subninjas,
-		primaryBuilderInvocations: args.PrimaryBuilderInvocations,
+		soongOutDir: config.SoongOutDir(),
+		toolDir:     config.HostToolDir(),
+		outDir:      config.OutDir(),
+		runGoTests:  !config.skipSoongTests,
+		// If we want to debug soong_build, we need to compile it for debugging
+		debugCompilation: os.Getenv("SOONG_DELVE") != "",
+		subninjas:        globFiles,
+		primaryBuilderInvocations: []bootstrap.PrimaryBuilderInvocation{
+			mainSoongBuildInvocation,
+			bp2buildInvocation,
+			jsonModuleGraphInvocation,
+			queryviewInvocation,
+			soongDocsInvocation},
 	}
 
-	args.EmptyNinjaFile = false
-	bootstrapDeps := bootstrap.RunBlueprint(args, blueprintCtx, blueprintConfig)
-	err := deptools.WriteDepFile(bootstrapDepFile, args.OutFile, bootstrapDeps)
+	bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
+	bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), ".bootstrap/build.ninja.d")
+	err := deptools.WriteDepFile(bootstrapDepFile, blueprintArgs.OutFile, bootstrapDeps)
 	if err != nil {
 		ctx.Fatalf("Error writing depfile '%s': %s", bootstrapDepFile, err)
 	}
@@ -254,6 +273,7 @@
 		v, _ := currentEnv.Get(k)
 		return v
 	}
+
 	if stale, _ := shared.StaleEnvFile(envFile, getenv); stale {
 		os.Remove(envFile)
 	}
@@ -275,7 +295,7 @@
 	}
 
 	buildMode := config.bazelBuildMode()
-	integratedBp2Build := (buildMode == mixedBuild) || (buildMode == generateBuildFiles)
+	integratedBp2Build := buildMode == mixedBuild
 
 	// This is done unconditionally, but does not take a measurable amount of time
 	bootstrapBlueprint(ctx, config)
@@ -303,12 +323,22 @@
 		ctx.BeginTrace(metrics.RunSoong, "environment check")
 		defer ctx.EndTrace()
 
-		soongBuildEnvFile := filepath.Join(config.SoongOutDir(), usedEnvFile)
-		checkEnvironmentFile(soongBuildEnv, soongBuildEnvFile)
+		checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongBuildTag))
 
-		if integratedBp2Build {
-			bp2buildEnvFile := filepath.Join(config.SoongOutDir(), usedEnvFile+".bp2build")
-			checkEnvironmentFile(soongBuildEnv, bp2buildEnvFile)
+		if integratedBp2Build || config.Bp2Build() {
+			checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildTag))
+		}
+
+		if config.JsonModuleGraph() {
+			checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(jsonModuleGraphTag))
+		}
+
+		if config.Queryview() {
+			checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(queryviewTag))
+		}
+
+		if config.SoongDocs() {
+			checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongDocsTag))
 		}
 	}()
 
@@ -351,18 +381,30 @@
 		cmd.RunAndStreamOrFatal()
 	}
 
-	var target string
+	targets := make([]string, 0, 0)
 
-	if config.bazelBuildMode() == generateBuildFiles {
-		target = config.Bp2BuildMarkerFile()
-	} else if config.bazelBuildMode() == generateJsonModuleGraph {
-		target = config.ModuleGraphFile()
-	} else {
-		// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
-		target = config.MainNinjaFile()
+	if config.JsonModuleGraph() {
+		targets = append(targets, config.ModuleGraphFile())
 	}
 
-	ninja("bootstrap", ".bootstrap/build.ninja", target)
+	if config.Bp2Build() {
+		targets = append(targets, config.Bp2BuildMarkerFile())
+	}
+
+	if config.Queryview() {
+		targets = append(targets, config.QueryviewMarkerFile())
+	}
+
+	if config.SoongDocs() {
+		targets = append(targets, config.SoongDocsHtml())
+	}
+
+	if config.SoongBuildInvocationNeeded() {
+		// This build generates <builddir>/build.ninja, which is used later by build/soong/ui/build/build.go#Build().
+		targets = append(targets, config.MainNinjaFile())
+	}
+
+	ninja("bootstrap", ".bootstrap/build.ninja", targets...)
 
 	var soongBuildMetrics *soong_metrics_proto.SoongBuildMetrics
 	if shouldCollectBuildSoongMetrics(config) {
@@ -404,7 +446,7 @@
 func shouldCollectBuildSoongMetrics(config Config) bool {
 	// Do not collect metrics protobuf if the soong_build binary ran as the
 	// bp2build converter or the JSON graph dump.
-	return config.bazelBuildMode() != generateBuildFiles && config.bazelBuildMode() != generateJsonModuleGraph
+	return config.SoongBuildInvocationNeeded()
 }
 
 func loadSoongBuildMetrics(ctx Context, config Config) *soong_metrics_proto.SoongBuildMetrics {