Merge "Reorganize and cull cc_library_static denylist."
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/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 6762416..d9cd22d 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -199,6 +199,55 @@
     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"],
+)`},
+		},
 	}
 
 	dir := "."