Merge "Add support for cc_library_headers to replace llndk_headers"
diff --git a/android/bazel.go b/android/bazel.go
index ba5ae31..49fc0ad 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -172,56 +172,59 @@
 
 	// Per-module denylist to always opt modules out of both bp2build and mixed builds.
 	bp2buildModuleDoNotConvertList = []string{
-		"libBionicBenchmarksUtils",      // ruperts@, cc_library_static, 'map' file not found
-		"libbionic_spawn_benchmark",     // ruperts@, cc_library_static, depends on //system/libbase
-		"libc_jemalloc_wrapper",         // ruperts@, cc_library_static, depends on //external/jemalloc_new
-		"libc_bootstrap",                // ruperts@, cc_library_static, 'private/bionic_auxv.h' file not found
-		"libc_init_static",              // ruperts@, cc_library_static, 'private/bionic_elf_tls.h' file not found
-		"libc_init_dynamic",             // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found
-		"libc_tzcode",                   // ruperts@, cc_library_static, error: expected expression
-		"libc_netbsd",                   // ruperts@, cc_library_static, 'engine.c' file not found
-		"libc_fortify",                  // ruperts@, cc_library_static, 'private/bionic_fortify.h' file not found
-		"libc_bionic",                   // ruperts@, cc_library_static, 'private/bionic_asm.h' file not found
-		"libc_bionic_ndk",               // ruperts@, cc_library_static, depends on //bionic/libc/system_properties
-		"libc_bionic_systrace",          // ruperts@, cc_library_static, 'private/bionic_systrace.h' file not found
-		"libc_pthread",                  // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found
-		"libc_syscalls",                 // eakammer@, cc_library_static,  'private/bionic_asm.h' file not found
-		"libc_ndk",                      // ruperts@, cc_library_static, depends on //bionic/libm:libm
-		"libc_nopthread",                // ruperts@, cc_library_static, depends on //external/arm-optimized-routines
-		"libc_common",                   // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
-		"libc_common_static",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libc_common_shared",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libc_unwind_static",            // ruperts@, cc_library_static, 'private/bionic_elf_tls.h' file not found
-		"libc_nomalloc",                 // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libasync_safe",                 // ruperts@, cc_library_static, 'private/CachedProperty.h' file not found
-		"libc_malloc_debug_backtrace",   // ruperts@, cc_library_static, depends on //system/libbase
-		"libsystemproperties",           // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
-		"libdl_static",                  // ruperts@, cc_library_static, 'private/CFIShadow.h' file not found
-		"liblinker_main",                // ruperts@, cc_library_static, depends on //system/libbase
-		"liblinker_malloc",              // ruperts@, cc_library_static, depends on //system/logging/liblog:liblog
-		"liblinker_debuggerd_stub",      // ruperts@, cc_library_static, depends on //system/libbase
-		"libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'complex.h' file not found
-		"libc_dns",                      // ruperts@, cc_library_static, 'private/android_filesystem_config.h' file not found
-		"libc_static_dispatch",          // eakammer@, cc_library_static, 'private/bionic_asm.h' file not found
-		"libc_dynamic_dispatch",         // eakammer@, cc_library_static, 'private/bionic_ifuncs.h' file not found
-		"note_memtag_heap_async",        // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
-		"note_memtag_heap_sync",         // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
+		// Things that transitively depend on //external/arm-optimized-routines. That one fails
+		// with a linker error: "ld.lld: no input files"
+		"libc_common",        // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
+		"libc_common_static", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_common_shared", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_nomalloc",      // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_nopthread",     // ruperts@, cc_library_static, depends on //external/arm-optimized-routine
 
-		// List of all full_cc_libraries in //bionic, with their immediate failures
-		"libc",              // jingwen@, cc_library, depends on //external/gwp_asan
-		"libc_malloc_debug", // jingwen@, cc_library, fatal error: 'assert.h' file not found
-		"libc_malloc_hooks", // jingwen@, cc_library, fatal error: 'errno.h' file not found
-		"libdl",             // jingwen@, cc_library, ld.lld: error: no input files
-		"libm",              // lberki@, cc_library, compiler error: "Unexpected token in argument list"
-		"libseccomp_policy", // lberki@, cc_library, 'linux/filter.h' not found, caused by missing -isystem bionic/libc/kernel/uapi, dunno where it comes from in Soong
-		"libstdc++",         // jingwen@, cc_library, depends on //external/gwp_asan
+		// Things that transitively depend on //system/libbase. libbase doesn't work because:
+		// "Multiple dependencies having same BaseModuleName() "fmtlib" found from "libbase""
+		"libbionic_spawn_benchmark",   // ruperts@, cc_library_static, depends on libbase, libgoogle-benchmark
+		"libc_malloc_debug",           // ruperts@, cc_library_static, depends on libbase
+		"libc_malloc_debug_backtrace", // ruperts@, cc_library_static, depends on libbase
+		"liblinker_debuggerd_stub",    // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
+		"liblinker_main",              // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
+		"liblinker_malloc",            // ruperts@, cc_library_static, depends on libziparchive, libz, libbase
+
+		// Requires non-libc targets, but otherwise works
+		"libc_jemalloc_wrapper", // ruperts@, cc_library_static, depends on //external/jemalloc_new
+		"libsystemproperties",   // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
+
+		// Compilation error, seems to be fixable by changing the toolchain definition
+		"libc_bionic_ndk", // ruperts@, cc_library_static, error: ISO C++ requires field designators...
+		"libc_tzcode",     // ruperts@, cc_library_static, error: expected expression
+		"libm",            // jingwen@, cc_library, error: "expected register here" (and many others)
+
+		// Linker error
+		"libc_malloc_hooks", // jingwen@, cc_library, undefined symbol: __malloc_hook, etc.
+		"libdl",             // jingwen@, cc_library, no input files
+		"libstdc++",         // jingwen@, cc_library, undefined symbol: free
+
+		// Includes not found
+		"libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'dirent.h' not found
+		"libseccomp_policy",             // jingwen@, cc_library, 'linux/filter.h' not found, missing -isystem bionic/libc/kernel/uapi/asm-arm, probably due to us not handling arch { ... { export_system_include_dirs } } correctly
+		"note_memtag_heap_async",        // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+		"note_memtag_heap_sync",         // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+
+		// Other
+		"libBionicBenchmarksUtils", // ruperts@, cc_library_static, 'map' file not found
+		"libc_syscalls",            // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls
+		"libc_ndk",                 // ruperts@, cc_library_static, depends on libc_bionic_ndk, libc_jemalloc_wrapper, libc_syscalls, libc_tzcode, libstdc++
+		"libdl_static",             // ruperts@, cc_library_static, conflicts with libdl
+
+		"libc", // jingwen@, cc_library, depends on //external/gwp_asan
 	}
 
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
 	mixedBuildsDisabledList = []string{
-		"libc_gdtoa",   // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
-		"libc_openbsd", // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
+		"libasync_safe", // lberki@, cc_library_static, 'async_safe/log.h not found' for out/combined-aosp_arm64.ninja out/soong/.intermediates/system/unwinding/libbacktrace/libbacktrace/android_arm64_armv8-a_shared/obj/system/unwinding/libbacktrace/ThreadEntry.o
+		"libc_gdtoa",    // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
+		"libc_netbsd",   // lberki@, cc_library_static, version script assignment of 'LIBC_PRIVATE' to symbol 'SHA1Final' failed: symbol not defined
+		"libc_openbsd",  // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
 	}
 
 	// Used for quicker lookups
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 63e2c50..4280bc3 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -243,6 +243,14 @@
 	labels := bazel.LabelList{
 		Includes: []bazel.Label{},
 	}
+
+	// expandedExcludes contain module-dir relative paths, but root-relative paths
+	// are needed for GlobFiles later.
+	var rootRelativeExpandedExcludes []string
+	for _, e := range expandedExcludes {
+		rootRelativeExpandedExcludes = append(rootRelativeExpandedExcludes, filepath.Join(ctx.ModuleDir(), e))
+	}
+
 	for _, p := range paths {
 		if m, tag := SrcIsModuleWithTag(p); m != "" {
 			l := getOtherModuleLabel(ctx, m, tag)
@@ -253,7 +261,10 @@
 		} else {
 			var expandedPaths []bazel.Label
 			if pathtools.IsGlob(p) {
-				globbedPaths := GlobFiles(ctx, pathForModuleSrc(ctx, p).String(), expandedExcludes)
+				// e.g. turn "math/*.c" in
+				// external/arm-optimized-routines to external/arm-optimized-routines/math/*.c
+				rootRelativeGlobPath := pathForModuleSrc(ctx, p).String()
+				globbedPaths := GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes)
 				globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
 				for _, path := range globbedPaths {
 					s := path.Rel()
diff --git a/android/neverallow.go b/android/neverallow.go
index a385bbc..d4a1ff1 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -63,8 +63,7 @@
 }
 
 func createIncludeDirsRules() []Rule {
-	// The list of paths that cannot be referenced using include_dirs
-	paths := []string{
+	notInIncludeDir := []string{
 		"art",
 		"art/libnativebridge",
 		"art/libnativeloader",
@@ -80,12 +79,13 @@
 		"external/vixl",
 		"external/wycheproof",
 	}
+	noUseIncludeDir := []string{
+		"system/libfmq",
+	}
 
-	// Create a composite matcher that will match if the value starts with any of the restricted
-	// paths. A / is appended to the prefix to ensure that restricting path X does not affect paths
-	// XY.
-	rules := make([]Rule, 0, len(paths))
-	for _, path := range paths {
+	rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
+
+	for _, path := range notInIncludeDir {
 		rule :=
 			NeverAllow().
 				WithMatcher("include_dirs", StartsWith(path+"/")).
@@ -95,6 +95,13 @@
 		rules = append(rules, rule)
 	}
 
+	for _, path := range noUseIncludeDir {
+		rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
+			Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
+				" to use alternate mechanisms and so can no longer be used.")
+		rules = append(rules, rule)
+	}
+
 	return rules
 }
 
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 268346a..35aadd8 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -76,7 +76,20 @@
 		},
 	},
 	{
-		name: "include_dir can reference another location",
+		name: "include_dir not allowed to reference art",
+		fs: map[string][]byte{
+			"system/libfmq/Android.bp": []byte(`
+				cc_library {
+					name: "libother",
+					include_dirs: ["any/random/file"],
+				}`),
+		},
+		expectedErrors: []string{
+			"all usages of them in 'system/libfmq' have been migrated",
+		},
+	},
+	{
+		name: "include_dir can work",
 		fs: map[string][]byte{
 			"other/Android.bp": []byte(`
 				cc_library {
diff --git a/bazel/properties.go b/bazel/properties.go
index 48d9589..037150d 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -64,43 +64,6 @@
 	Excludes []Label
 }
 
-// GlobsInDir returns a list of glob expressions for a list of extensions
-// (optionally recursive) within a directory.
-func GlobsInDir(dir string, recursive bool, extensions []string) []string {
-	globs := []string{}
-
-	globInfix := ""
-	if dir == "." {
-		if recursive {
-			// e.g "**/*.h"
-			globInfix = "**/"
-		} // else e.g. "*.h"
-		for _, ext := range extensions {
-			globs = append(globs, globInfix+"*"+ext)
-		}
-	} else {
-		if recursive {
-			// e.g. "foo/bar/**/*.h"
-			dir += "/**"
-		} // else e.g. "foo/bar/*.h"
-		for _, ext := range extensions {
-			globs = append(globs, dir+"/*"+ext)
-		}
-	}
-	return globs
-}
-
-// LooseHdrsGlobs returns the list of non-recursive header globs for each parent directory of
-// each source file in this LabelList's Includes.
-func (ll *LabelList) LooseHdrsGlobs(exts []string) []string {
-	var globs []string
-	for _, parentDir := range ll.uniqueParentDirectories() {
-		globs = append(globs,
-			GlobsInDir(parentDir, false, exts)...)
-	}
-	return globs
-}
-
 // uniqueParentDirectories returns a list of the unique parent directories for
 // all files in ll.Includes.
 func (ll *LabelList) uniqueParentDirectories() []string {
@@ -220,6 +183,15 @@
 	OS_LINUX        = "linux_glibc"
 	OS_LINUX_BIONIC = "linux_bionic"
 	OS_WINDOWS      = "windows"
+
+	// This is the string representation of the default condition wherever a
+	// configurable attribute is used in a select statement, i.e.
+	// //conditions:default for Bazel.
+	//
+	// This is consistently named "conditions_default" to mirror the Soong
+	// config variable default key in an Android.bp file, although there's no
+	// integration with Soong config variables (yet).
+	CONDITIONS_DEFAULT = "conditions_default"
 )
 
 var (
@@ -231,21 +203,23 @@
 	// A map of architectures to the Bazel label of the constraint_value
 	// for the @platforms//cpu:cpu constraint_setting
 	PlatformArchMap = map[string]string{
-		ARCH_ARM:    "//build/bazel/platforms/arch:arm",
-		ARCH_ARM64:  "//build/bazel/platforms/arch:arm64",
-		ARCH_X86:    "//build/bazel/platforms/arch:x86",
-		ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
+		ARCH_ARM:           "//build/bazel/platforms/arch:arm",
+		ARCH_ARM64:         "//build/bazel/platforms/arch:arm64",
+		ARCH_X86:           "//build/bazel/platforms/arch:x86",
+		ARCH_X86_64:        "//build/bazel/platforms/arch:x86_64",
+		CONDITIONS_DEFAULT: "//conditions:default", // The default condition of as arch select map.
 	}
 
 	// A map of target operating systems to the Bazel label of the
 	// constraint_value for the @platforms//os:os constraint_setting
 	PlatformOsMap = map[string]string{
-		OS_ANDROID:      "//build/bazel/platforms/os:android",
-		OS_DARWIN:       "//build/bazel/platforms/os:darwin",
-		OS_FUCHSIA:      "//build/bazel/platforms/os:fuchsia",
-		OS_LINUX:        "//build/bazel/platforms/os:linux",
-		OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
-		OS_WINDOWS:      "//build/bazel/platforms/os:windows",
+		OS_ANDROID:         "//build/bazel/platforms/os:android",
+		OS_DARWIN:          "//build/bazel/platforms/os:darwin",
+		OS_FUCHSIA:         "//build/bazel/platforms/os:fuchsia",
+		OS_LINUX:           "//build/bazel/platforms/os:linux",
+		OS_LINUX_BIONIC:    "//build/bazel/platforms/os:linux_bionic",
+		OS_WINDOWS:         "//build/bazel/platforms/os:windows",
+		CONDITIONS_DEFAULT: "//conditions:default", // The default condition of an os select map.
 	}
 )
 
@@ -261,6 +235,8 @@
 	Arm    LabelList
 	Arm64  LabelList
 	Common LabelList
+
+	ConditionsDefault LabelList
 }
 
 type labelListOsValues struct {
@@ -270,6 +246,8 @@
 	Linux       LabelList
 	LinuxBionic LabelList
 	Windows     LabelList
+
+	ConditionsDefault LabelList
 }
 
 // LabelListAttribute is used to represent a list of Bazel labels as an
@@ -333,10 +311,11 @@
 
 func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
 	return map[string]*LabelList{
-		ARCH_X86:    &attrs.ArchValues.X86,
-		ARCH_X86_64: &attrs.ArchValues.X86_64,
-		ARCH_ARM:    &attrs.ArchValues.Arm,
-		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+		ARCH_X86:           &attrs.ArchValues.X86,
+		ARCH_X86_64:        &attrs.ArchValues.X86_64,
+		ARCH_ARM:           &attrs.ArchValues.Arm,
+		ARCH_ARM64:         &attrs.ArchValues.Arm64,
+		CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
 	}
 }
 
@@ -360,12 +339,13 @@
 
 func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
 	return map[string]*LabelList{
-		OS_ANDROID:      &attrs.OsValues.Android,
-		OS_DARWIN:       &attrs.OsValues.Darwin,
-		OS_FUCHSIA:      &attrs.OsValues.Fuchsia,
-		OS_LINUX:        &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:      &attrs.OsValues.Windows,
+		OS_ANDROID:         &attrs.OsValues.Android,
+		OS_DARWIN:          &attrs.OsValues.Darwin,
+		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
+		OS_LINUX:           &attrs.OsValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.OsValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
 	}
 }
 
@@ -418,6 +398,8 @@
 	Arm    []string
 	Arm64  []string
 	Common []string
+
+	ConditionsDefault []string
 }
 
 type stringListOsValues struct {
@@ -427,6 +409,8 @@
 	Linux       []string
 	LinuxBionic []string
 	Windows     []string
+
+	ConditionsDefault []string
 }
 
 // HasConfigurableValues returns true if the attribute contains
@@ -448,10 +432,11 @@
 
 func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
 	return map[string]*[]string{
-		ARCH_X86:    &attrs.ArchValues.X86,
-		ARCH_X86_64: &attrs.ArchValues.X86_64,
-		ARCH_ARM:    &attrs.ArchValues.Arm,
-		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+		ARCH_X86:           &attrs.ArchValues.X86,
+		ARCH_X86_64:        &attrs.ArchValues.X86_64,
+		ARCH_ARM:           &attrs.ArchValues.Arm,
+		ARCH_ARM64:         &attrs.ArchValues.Arm64,
+		CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
 	}
 }
 
@@ -475,12 +460,13 @@
 
 func (attrs *StringListAttribute) osValuePtrs() map[string]*[]string {
 	return map[string]*[]string{
-		OS_ANDROID:      &attrs.OsValues.Android,
-		OS_DARWIN:       &attrs.OsValues.Darwin,
-		OS_FUCHSIA:      &attrs.OsValues.Fuchsia,
-		OS_LINUX:        &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:      &attrs.OsValues.Windows,
+		OS_ANDROID:         &attrs.OsValues.Android,
+		OS_DARWIN:          &attrs.OsValues.Darwin,
+		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
+		OS_LINUX:           &attrs.OsValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.OsValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
 	}
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 21d7062..63a6c2e 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1512,3 +1512,126 @@
 		}
 	}
 }
+
+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
+	}{
+		{
+			description:                        "filegroup top level exclude_srcs",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "fg_foo",
+    srcs: ["**/*.txt"],
+    exclude_srcs: ["c.txt"],
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "//dir:e.txt",
+        "//dir:f.txt",
+        "a.txt",
+        "b.txt",
+    ],
+)`,
+			},
+			fs: map[string]string{
+				"a.txt":          "",
+				"b.txt":          "",
+				"c.txt":          "",
+				"dir/Android.bp": "",
+				"dir/e.txt":      "",
+				"dir/f.txt":      "",
+			},
+		},
+		{
+			description:                        "filegroup in subdir exclude_srcs",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp:                                 "",
+			dir:                                "dir",
+			fs: map[string]string{
+				"dir/Android.bp": `filegroup {
+    name: "fg_foo",
+    srcs: ["**/*.txt"],
+    exclude_srcs: ["b.txt"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+				"dir/a.txt":             "",
+				"dir/b.txt":             "",
+				"dir/subdir/Android.bp": "",
+				"dir/subdir/e.txt":      "",
+				"dir/subdir/f.txt":      "",
+			},
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "//dir/subdir:e.txt",
+        "//dir/subdir:f.txt",
+        "a.txt",
+    ],
+)`,
+			},
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		fs := make(map[string][]byte)
+		toParse := []string{
+			"Android.bp",
+		}
+		for f, content := range testCase.fs {
+			if strings.HasSuffix(f, "Android.bp") {
+				toParse = append(toParse, f)
+			}
+			fs[f] = []byte(content)
+		}
+		config := android.TestConfig(buildDir, nil, testCase.bp, 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) {
+			continue
+		}
+		_, errs = ctx.ResolveDependencies(config)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
+
+		checkDir := dir
+		if testCase.dir != "" {
+			checkDir = testCase.dir
+		}
+		bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+			t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
+		} 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,
+					)
+				}
+			}
+		}
+	}
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 4b6e888..d9cd22d 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -114,26 +114,13 @@
         "-I.",
     ],
     deps = [":some-headers"],
-    hdrs = ["foo-dir/a.h"],
     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"],
         "//conditions:default": [],
     }),
-    srcs = [
-        "impl.cpp",
-        "header.h",
-        "foo-dir/a.h",
-        "header.hh",
-        "header.hpp",
-        "header.hxx",
-        "header.h++",
-        "header.inl",
-        "header.inc",
-        "header.ipp",
-        "header.h.generic",
-    ] + select({
+    srcs = ["impl.cpp"] + select({
         "//build/bazel/platforms/arch:x86": ["x86.cpp"],
         "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
         "//conditions:default": [],
@@ -209,13 +196,56 @@
         "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
         "//conditions:default": [],
     }),
-    srcs = [
-        "ld_android.cpp",
-        "linked_list.h",
-        "linker.h",
-        "linker_block_allocator.h",
-        "linker_cfi.h",
+    srcs = ["ld_android.cpp"],
+)`},
+		},
+		{
+			description:                        "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
+			moduleTypeUnderTest:                "cc_library",
+			moduleTypeUnderTestFactory:         cc.LibraryFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+			dir:                                "external",
+			filesystem: map[string]string{
+				"external/math/cosf.c":      "",
+				"external/math/erf.c":       "",
+				"external/math/erf_data.c":  "",
+				"external/math/erff.c":      "",
+				"external/math/erff_data.c": "",
+				"external/Android.bp": `
+cc_library {
+    name: "fake-libarm-optimized-routines-math",
+    exclude_srcs: [
+        // Provided by:
+        // bionic/libm/upstream-freebsd/lib/msun/src/s_erf.c
+        // bionic/libm/upstream-freebsd/lib/msun/src/s_erff.c
+        "math/erf.c",
+        "math/erf_data.c",
+        "math/erff.c",
+        "math/erff_data.c",
     ],
+    srcs: [
+        "math/*.c",
+    ],
+    // arch-specific settings
+    arch: {
+        arm64: {
+            cflags: [
+                "-DHAVE_FAST_FMA=1",
+            ],
+        },
+    },
+    bazel_module: { bp2build_available: true },
+}
+`,
+			},
+			bp: soongCcLibraryPreamble,
+			expectedBazelTargets: []string{`cc_library(
+    name = "fake-libarm-optimized-routines-math",
+    copts = ["-Iexternal"] + select({
+        "//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
+        "//conditions:default": [],
+    }),
+    srcs = ["math/cosf.c"],
 )`},
 		},
 	}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 00042ab..0905aba 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -136,17 +136,6 @@
         ":lib-1",
         ":lib-2",
     ],
-    hdrs = [
-        "dir-1/dir1a.h",
-        "dir-1/dir1b.h",
-        "dir-2/dir2a.h",
-        "dir-2/dir2b.h",
-    ] + select({
-        "//build/bazel/platforms/arch:arm64": ["arch_arm64_exported_include_dir/a.h"],
-        "//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir/b.h"],
-        "//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir/c.h"],
-        "//conditions:default": [],
-    }),
     includes = [
         "dir-1",
         "dir-2",
@@ -159,18 +148,10 @@
 )`, `cc_library_headers(
     name = "lib-1",
     copts = ["-I."],
-    hdrs = [
-        "lib-1/lib1a.h",
-        "lib-1/lib1b.h",
-    ],
     includes = ["lib-1"],
 )`, `cc_library_headers(
     name = "lib-2",
     copts = ["-I."],
-    hdrs = [
-        "lib-2/lib2a.h",
-        "lib-2/lib2b.h",
-    ],
     includes = ["lib-2"],
 )`},
 		},
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 00325fb..9d23cc5 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -192,12 +192,6 @@
         ":whole_static_lib_1",
         ":whole_static_lib_2",
     ],
-    hdrs = [
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-    ],
     includes = [
         "export_include_dir_1",
         "export_include_dir_2",
@@ -206,105 +200,27 @@
     srcs = [
         "foo_static1.cc",
         "foo_static2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
     ],
 )`, `cc_library_static(
     name = "static_lib_1",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "static_lib_1.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["static_lib_1.cc"],
 )`, `cc_library_static(
     name = "static_lib_2",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "static_lib_2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["static_lib_2.cc"],
 )`, `cc_library_static(
     name = "whole_static_lib_1",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "whole_static_lib_1.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["whole_static_lib_1.cc"],
 )`, `cc_library_static(
     name = "whole_static_lib_2",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "whole_static_lib_2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["whole_static_lib_2.cc"],
 )`},
 		},
 		{
@@ -342,14 +258,6 @@
         "-I.",
     ],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage/subsubpackage:subsubpackage_header.h",
-        "//subpackage/subsubpackage:subdirectory/subdirectory_header.h",
-        "//subpackage/subsubpackage/subsubsubpackage:subsubsubpackage_header.h",
-        "//subpackage/subsubpackage/subsubsubpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -371,16 +279,8 @@
 			expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
     copts = ["-I."],
-    hdrs = [
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage:subpackage_header.h",
-    ],
     includes = ["subpackage"],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -402,16 +302,8 @@
 			expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
     copts = ["-I."],
-    hdrs = [
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage:subpackage_header.h",
-    ],
     includes = ["subpackage"],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -452,14 +344,8 @@
         "-Isubpackage/subsubpackage2",
         "-Isubpackage",
     ],
-    hdrs = ["exported_subsubpackage/header.h"],
     includes = ["./exported_subsubpackage"],
     linkstatic = True,
-    srcs = [
-        "exported_subsubpackage/header.h",
-        "subsubpackage/header.h",
-        "subsubpackage2/header.h",
-    ],
 )`},
 		},
 		{
@@ -517,11 +403,6 @@
         "-I.",
     ],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage2:subpackage2_header.h",
-    ],
 )`},
 		},
 		{
@@ -645,6 +526,201 @@
     linkstatic = True,
 )`},
 		},
+		{
+			description:                        "cc_library_static simple exclude_srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":       "",
+				"foo-a.c":        "",
+				"foo-excluded.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "foo-*.c"],
+    exclude_srcs: ["foo-excluded.c"],
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = [
+        "common.c",
+        "foo-a.c",
+    ],
+)`},
+		},
+		{
+			description:                        "cc_library_static one arch specific srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":  "",
+				"foo-arm.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c"],
+    arch: { arm: { srcs: ["foo-arm.c"] } }
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": ["foo-arm.c"],
+        "//conditions:default": [],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static one arch specific srcs and exclude_srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":           "",
+				"for-arm.c":          "",
+				"not-for-arm.c":      "",
+				"not-for-anything.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-anything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+    },
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": ["for-arm.c"],
+        "//conditions:default": ["not-for-arm.c"],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static arch specific exclude_srcs for 2 architectures",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":      "",
+				"for-arm.c":     "",
+				"for-x86.c":     "",
+				"not-for-arm.c": "",
+				"not-for-x86.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-everything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
+    },
+} `,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": [
+            "for-arm.c",
+            "not-for-x86.c",
+        ],
+        "//build/bazel/platforms/arch:x86": [
+            "for-x86.c",
+            "not-for-arm.c",
+        ],
+        "//conditions:default": [
+            "not-for-arm.c",
+            "not-for-x86.c",
+        ],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static arch specific exclude_srcs for 4 architectures",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":             "",
+				"for-arm.c":            "",
+				"for-arm64.c":          "",
+				"for-x86.c":            "",
+				"for-x86_64.c":         "",
+				"not-for-arm.c":        "",
+				"not-for-arm64.c":      "",
+				"not-for-x86.c":        "",
+				"not-for-x86_64.c":     "",
+				"not-for-everything.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-everything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+        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"] },
+	},
+} `,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": [
+            "for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:arm64": [
+            "for-arm64.c",
+            "not-for-arm.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:x86": [
+            "for-x86.c",
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:x86_64": [
+            "for-x86_64.c",
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+        ],
+        "//conditions:default": [
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+    }),
+)`},
+		},
 	}
 
 	dir := "."
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index d00a1cb..9efdb53 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -67,11 +67,7 @@
         "-Iinclude",
         "-I.",
     ],
-    srcs = [
-        "a/b/c.c",
-        "a/b/bar.h",
-        "a/b/foo.h",
-    ],
+    srcs = ["a/b/c.c"],
 )`,
 			},
 		},
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index b9ffc04..52afb55 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -99,8 +99,15 @@
 		return "", nil
 	}
 
+	// addConditionsDefault := false
+	conditionsDefaultKey := bazel.PlatformArchMap[bazel.CONDITIONS_DEFAULT]
+
 	var selects string
 	for _, selectKey := range android.SortedStringKeys(selectMap) {
+		if selectKey == conditionsDefaultKey {
+			// Handle default condition later.
+			continue
+		}
 		value := selectMap[selectKey]
 		if isZero(value) {
 			// Ignore zero values to not generate empty lists.
@@ -125,8 +132,22 @@
 	// Create the map.
 	ret := "select({\n"
 	ret += selects
-	// default condition comes last.
-	ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
+
+	// Handle the default condition
+	s, err := prettyPrintSelectEntry(selectMap[conditionsDefaultKey], conditionsDefaultKey, indent)
+	if err != nil {
+		return "", err
+	}
+	if s == "" {
+		// Print an explicit empty list (the default value) even if the value is
+		// empty, to avoid errors about not finding a configuration that matches.
+		ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
+	} else {
+		// Print the custom default value.
+		ret += s
+		ret += ",\n"
+	}
+
 	ret += makeIndent(indent)
 	ret += "})"
 
diff --git a/cc/bp2build.go b/cc/bp2build.go
index efa2752..9c4bf6e5 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -80,7 +80,7 @@
 
 // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
 func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Module) compilerAttributes {
-	var localHdrs, srcs bazel.LabelListAttribute
+	var srcs bazel.LabelListAttribute
 	var copts bazel.StringListAttribute
 
 	// Creates the -I flag for a directory, while making the directory relative
@@ -90,11 +90,6 @@
 		return "-I" + filepath.Join(ctx.ModuleDir(), dir)
 	}
 
-	// Parse the list of srcs, excluding files from exclude_srcs.
-	parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
-		return android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs)
-	}
-
 	// Parse the list of module-relative include directories (-I).
 	parseLocalIncludeDirs := func(baseCompilerProps *BaseCompilerProperties) []string {
 		// include_dirs are root-relative, not module-relative.
@@ -111,40 +106,85 @@
 		return copts
 	}
 
+	// baseSrcs contain the list of src files that are used for every configuration.
+	var baseSrcs []string
+	// baseExcludeSrcs contain the list of src files that are excluded for every configuration.
+	var baseExcludeSrcs []string
+	// baseSrcsLabelList is a clone of the base srcs LabelList, used for computing the
+	// arch or os specific srcs later.
+	var baseSrcsLabelList bazel.LabelList
+
+	// Parse srcs from an arch or OS's props value, taking the base srcs and
+	// exclude srcs into account.
+	parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
+		// Combine the base srcs and arch-specific srcs
+		allSrcs := append(baseSrcs, baseCompilerProps.Srcs...)
+		// Combine the base exclude_srcs and configuration-specific exclude_srcs
+		allExcludeSrcs := append(baseExcludeSrcs, baseCompilerProps.Exclude_srcs...)
+		return android.BazelLabelForModuleSrcExcludes(ctx, allSrcs, allExcludeSrcs)
+	}
+
 	for _, props := range module.compiler.compilerProps() {
 		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
 			srcs.Value = parseSrcs(baseCompilerProps)
 			copts.Value = parseCopts(baseCompilerProps)
+
+			// Used for arch-specific srcs later.
+			baseSrcs = baseCompilerProps.Srcs
+			baseExcludeSrcs = baseCompilerProps.Exclude_srcs
+			baseSrcsLabelList = parseSrcs(baseCompilerProps)
 			break
 		}
 	}
 
+	// Handle include_build_directory prop. If the property is true, then the
+	// target has access to all headers recursively in the package, and has
+	// "-I<module-dir>" in its copts.
 	if c, ok := module.compiler.(*baseCompiler); ok && c.includeBuildDirectory() {
 		copts.Value = append(copts.Value, includeFlag("."))
-		localHdrs.Value = bp2BuildListHeadersInDir(ctx, ".")
 	} else if c, ok := module.compiler.(*libraryDecorator); ok && c.includeBuildDirectory() {
 		copts.Value = append(copts.Value, includeFlag("."))
-		localHdrs.Value = bp2BuildListHeadersInDir(ctx, ".")
 	}
 
 	for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
 		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
-			srcsList := parseSrcs(baseCompilerProps)
-			srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcsList, srcs.Value))
+			// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
+			// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
+			if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
+				srcsList := parseSrcs(baseCompilerProps)
+				srcs.SetValueForArch(arch.Name, srcsList)
+				// The base srcs value should not contain any arch-specific excludes.
+				srcs.Value = bazel.SubtractBazelLabelList(srcs.Value, bazel.LabelList{Includes: srcsList.Excludes})
+			}
+
 			copts.SetValueForArch(arch.Name, parseCopts(baseCompilerProps))
 		}
 	}
 
-	for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) {
-		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
-			srcsList := parseSrcs(baseCompilerProps)
-			srcs.SetValueForOS(os.Name, bazel.SubtractBazelLabelList(srcsList, srcs.Value))
-			copts.SetValueForOS(os.Name, parseCopts(baseCompilerProps))
+	// After going through all archs, delete the duplicate files in the arch
+	// values that are already in the base srcs.Value.
+	for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
+		if _, ok := props.(*BaseCompilerProperties); ok {
+			srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcs.GetValueForArch(arch.Name), srcs.Value))
 		}
 	}
 
-	// Combine local, non-exported hdrs into srcs
-	srcs.Append(localHdrs)
+	// Now that the srcs.Value list is finalized, compare it with the original
+	// list, and put the difference into the default condition for the arch
+	// select.
+	defaultsSrcs := bazel.SubtractBazelLabelList(baseSrcsLabelList, srcs.Value)
+	// TODO(b/186153868): handle the case with multiple variant types, e.g. when arch and os are both used.
+	srcs.SetValueForArch(bazel.CONDITIONS_DEFAULT, defaultsSrcs)
+
+	// Handle OS specific props.
+	for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) {
+		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+			srcsList := parseSrcs(baseCompilerProps)
+			// TODO(b/186153868): add support for os-specific srcs and exclude_srcs
+			srcs.SetValueForOS(os.Name, bazel.SubtractBazelLabelList(srcsList, baseSrcsLabelList))
+			copts.SetValueForOS(os.Name, parseCopts(baseCompilerProps))
+		}
+	}
 
 	return compilerAttributes{
 		srcs:  srcs,
@@ -207,11 +247,6 @@
 	}
 }
 
-func bp2BuildListHeadersInDir(ctx android.TopDownMutatorContext, includeDir string) bazel.LabelList {
-	globs := bazel.GlobsInDir(includeDir, true, headerExts)
-	return android.BazelLabelForModuleSrc(ctx, globs)
-}
-
 // Relativize a list of root-relative paths with respect to the module's
 // directory.
 //
@@ -236,9 +271,8 @@
 }
 
 // bp2BuildParseExportedIncludes creates a string list attribute contains the
-// exported included directories of a module, and a label list attribute
-// containing the exported headers of a module.
-func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.StringListAttribute, bazel.LabelListAttribute) {
+// exported included directories of a module.
+func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute {
 	libraryDecorator := module.linker.(*libraryDecorator)
 
 	// Export_system_include_dirs and export_include_dirs are already module dir
@@ -248,14 +282,6 @@
 	includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)
 	includeDirsAttribute := bazel.MakeStringListAttribute(includeDirs)
 
-	var headersAttribute bazel.LabelListAttribute
-	var headers bazel.LabelList
-	for _, includeDir := range includeDirs {
-		headers.Append(bp2BuildListHeadersInDir(ctx, includeDir))
-	}
-	headers = bazel.UniqueBazelLabelList(headers)
-	headersAttribute.Value = headers
-
 	for arch, props := range module.GetArchProperties(&FlagExporterProperties{}) {
 		if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
 			archIncludeDirs := flagExporterProperties.Export_system_include_dirs
@@ -268,20 +294,6 @@
 			if len(archIncludeDirs) > 0 {
 				includeDirsAttribute.SetValueForArch(arch.Name, archIncludeDirs)
 			}
-
-			var archHeaders bazel.LabelList
-			for _, archIncludeDir := range archIncludeDirs {
-				archHeaders.Append(bp2BuildListHeadersInDir(ctx, archIncludeDir))
-			}
-			archHeaders = bazel.UniqueBazelLabelList(archHeaders)
-
-			// To avoid duplicate headers when base headers + arch headers are combined
-			// FIXME: This doesn't take conflicts between arch and os includes into account
-			archHeaders = bazel.SubtractBazelLabelList(archHeaders, headers)
-
-			if len(archHeaders.Includes) > 0 || len(archHeaders.Excludes) > 0 {
-				headersAttribute.SetValueForArch(arch.Name, archHeaders)
-			}
 		}
 	}
 
@@ -297,22 +309,8 @@
 			if len(osIncludeDirs) > 0 {
 				includeDirsAttribute.SetValueForOS(os.Name, osIncludeDirs)
 			}
-
-			var osHeaders bazel.LabelList
-			for _, osIncludeDir := range osIncludeDirs {
-				osHeaders.Append(bp2BuildListHeadersInDir(ctx, osIncludeDir))
-			}
-			osHeaders = bazel.UniqueBazelLabelList(osHeaders)
-
-			// To avoid duplicate headers when base headers + os headers are combined
-			// FIXME: This doesn't take conflicts between arch and os includes into account
-			osHeaders = bazel.SubtractBazelLabelList(osHeaders, headers)
-
-			if len(osHeaders.Includes) > 0 || len(osHeaders.Excludes) > 0 {
-				headersAttribute.SetValueForOS(os.Name, osHeaders)
-			}
 		}
 	}
 
-	return includeDirsAttribute, headersAttribute
+	return includeDirsAttribute
 }
diff --git a/cc/library.go b/cc/library.go
index 8f2127e..3ac7e11 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -259,11 +259,10 @@
 
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, m)
-	exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, m)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, m)
 
 	attrs := &bazelCcLibraryAttributes{
 		Srcs:     compilerAttrs.srcs,
-		Hdrs:     exportedIncludesHeaders,
 		Copts:    compilerAttrs.copts,
 		Linkopts: linkerAttrs.linkopts,
 		Deps:     linkerAttrs.deps,
@@ -2183,7 +2182,7 @@
 
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
-	exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, module)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
 
 	attrs := &bazelCcLibraryStaticAttributes{
 		Copts:      compilerAttrs.copts,
@@ -2191,7 +2190,6 @@
 		Deps:       linkerAttrs.deps,
 		Linkstatic: true,
 		Includes:   exportedIncludes,
-		Hdrs:       exportedIncludesHeaders,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/cc/library_headers.go b/cc/library_headers.go
index f2cb52b..0aba8de 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -142,14 +142,13 @@
 		return
 	}
 
-	exportedIncludes, exportedHdrs := bp2BuildParseExportedIncludes(ctx, module)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
 
 	attrs := &bazelCcLibraryHeadersAttributes{
 		Copts:    compilerAttrs.copts,
 		Includes: exportedIncludes,
-		Hdrs:     exportedHdrs,
 		Deps:     linkerAttrs.deps,
 	}
 
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index a94e7af..8a656ed 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -131,7 +131,6 @@
 	ClassLoaderContexts            ClassLoaderContextMap
 
 	Archs                   []android.ArchType
-	DexPreoptImages         android.Paths
 	DexPreoptImagesDeps     []android.OutputPaths
 	DexPreoptImageLocations []string
 
@@ -276,7 +275,6 @@
 	EnforceUsesLibrariesStatusFile string
 	ClassLoaderContexts            jsonClassLoaderContextMap
 
-	DexPreoptImages     []string
 	DexPreoptImagesDeps [][]string
 
 	PreoptBootClassPathDexFiles []string
@@ -302,11 +300,10 @@
 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
 	config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile)
 	config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
-	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
 	config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
 
 	// This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON.
-	config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.DexPreoptImages))
+	config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.Archs))
 
 	return config.ModuleConfig, nil
 }
@@ -328,7 +325,6 @@
 		ProfileBootListing:             config.ProfileBootListing.String(),
 		EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(),
 		ClassLoaderContexts:            toJsonClassLoaderContext(config.ClassLoaderContexts),
-		DexPreoptImages:                config.DexPreoptImages.Strings(),
 		DexPreoptImagesDeps:            pathsListToStringLists(config.DexPreoptImagesDeps),
 		PreoptBootClassPathDexFiles:    config.PreoptBootClassPathDexFiles.Strings(),
 		ModuleConfig:                   config,
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index cd7551c..bb4e80e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -47,7 +47,6 @@
 		EnforceUsesLibraries:            false,
 		ClassLoaderContexts:             nil,
 		Archs:                           []android.ArchType{android.Arm},
-		DexPreoptImages:                 android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
 		DexPreoptImagesDeps:             []android.OutputPaths{android.OutputPaths{}},
 		DexPreoptImageLocations:         []string{},
 		PreoptBootClassPathDexFiles:     nil,
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index d00d74b..0020a2d 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -225,7 +225,6 @@
 		ClassLoaderContexts:            d.classLoaderContexts,
 
 		Archs:                   archs,
-		DexPreoptImages:         images,
 		DexPreoptImagesDeps:     imagesDeps,
 		DexPreoptImageLocations: imageLocations,