bp2build: Add support for export_.*headers props

Soong supports export_.*_headers properties, the libraries contained in
this list must also be within a shared/static/whole_static/header libs
property. For bp2build, we eliminate this duplication. The libraries
not listed in an export_.*_headers property will migrate to an attribute
prepended with implementation_, those in export_.*_headers will not have
a prefix.

Test: build/bazel/ci/bp2build.sh
Test: build/bazel/ci/mixed_libc.sh
Bug: 198241472
Change-Id: I3eb84c983ec5d241c8a568e411dfd5619d3184a7
diff --git a/android/bazel.go b/android/bazel.go
index 1cd84c9..9e8d2e3 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -218,13 +218,6 @@
 		"libc_ndk",          // http://b/187013218, cc_library_static, depends on //bionic/libm:libm (http://b/183064661)
 		"libc_malloc_hooks", // http://b/187016307, cc_library, ld.lld: error: undefined symbol: __malloc_hook
 
-		// There are unexported symbols that don't surface on a shared library build,
-		// from the source static archive
-		// e.g. _Unwind_{GetRegionStart,GetLanguageSpecificData,GetIP,Set{IP,GR},Resume,{Raise,Delete}Exception}, pthread_atfork
-		// ... from: cxa_{personality,exception}.o, system_error.o, wrappers_c_bionic.o
-		// cf. http://b/198403271
-		"libc++",
-
 		// http://b/186823769: Needs C++ STL support, includes from unconverted standard libraries in //external/libcxx
 		// c++_static
 		"libbase_ndk", // http://b/186826477, cc_library, no such target '//build/bazel/platforms/os:darwin' when --platforms //build/bazel/platforms:android_x86 is added
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index b1a6e2c..4a0eeea 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -635,6 +635,7 @@
 			// Ignore zero-valued fields
 			continue
 		}
+
 		// if the struct is embedded (anonymous), flatten the properties into the containing struct
 		if field.Anonymous {
 			if field.Type.Kind() == reflect.Ptr {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index b3a1053..ec8882b 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -349,21 +349,21 @@
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
     copts = ["bothflag"],
-    dynamic_deps = [":shared_dep_for_both"],
     implementation_deps = [":static_dep_for_both"],
+    implementation_dynamic_deps = [":shared_dep_for_both"],
     shared = {
         "copts": ["sharedflag"],
-        "dynamic_deps": [":shared_dep_for_shared"],
+        "implementation_deps": [":static_dep_for_shared"],
+        "implementation_dynamic_deps": [":shared_dep_for_shared"],
         "srcs": ["sharedonly.cpp"],
-        "static_deps": [":static_dep_for_shared"],
         "whole_archive_deps": [":whole_static_lib_for_shared"],
     },
     srcs = ["both.cpp"],
     static = {
         "copts": ["staticflag"],
-        "dynamic_deps": [":shared_dep_for_static"],
+        "implementation_deps": [":static_dep_for_static"],
+        "implementation_dynamic_deps": [":shared_dep_for_static"],
         "srcs": ["staticonly.cpp"],
-        "static_deps": [":static_dep_for_static"],
         "whole_archive_deps": [":whole_static_lib_for_static"],
     },
     whole_archive_deps = [":whole_static_lib_for_both"],
@@ -371,6 +371,105 @@
 	})
 }
 
+func TestCcLibraryDeps(t *testing.T) {
+	runCcLibraryTestCase(t, bp2buildTestCase{
+		description:                        "cc_library shared/static props",
+		moduleTypeUnderTest:                "cc_library",
+		moduleTypeUnderTestFactory:         cc.LibraryFactory,
+		moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+		filesystem: map[string]string{
+			"both.cpp":       "",
+			"sharedonly.cpp": "",
+			"staticonly.cpp": "",
+		},
+		blueprint: soongCcLibraryPreamble + `
+cc_library {
+    name: "a",
+    srcs: ["both.cpp"],
+    cflags: ["bothflag"],
+    shared_libs: ["implementation_shared_dep_for_both", "shared_dep_for_both"],
+    export_shared_lib_headers: ["shared_dep_for_both"],
+    static_libs: ["implementation_static_dep_for_both", "static_dep_for_both"],
+    export_static_lib_headers: ["static_dep_for_both", "whole_static_dep_for_both"],
+    whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_both", "whole_static_dep_for_both"],
+    static: {
+        srcs: ["staticonly.cpp"],
+        cflags: ["staticflag"],
+        shared_libs: ["implementation_shared_dep_for_static", "shared_dep_for_static"],
+        export_shared_lib_headers: ["shared_dep_for_static"],
+        static_libs: ["implementation_static_dep_for_static", "static_dep_for_static"],
+        export_static_lib_headers: ["static_dep_for_static", "whole_static_dep_for_static"],
+        whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_static", "whole_static_dep_for_static"],
+    },
+    shared: {
+        srcs: ["sharedonly.cpp"],
+        cflags: ["sharedflag"],
+        shared_libs: ["implementation_shared_dep_for_shared", "shared_dep_for_shared"],
+        export_shared_lib_headers: ["shared_dep_for_shared"],
+        static_libs: ["implementation_static_dep_for_shared", "static_dep_for_shared"],
+        export_static_lib_headers: ["static_dep_for_shared", "whole_static_dep_for_shared"],
+        whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_shared", "whole_static_dep_for_shared"],
+    },
+    include_build_directory: false,
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_both") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_both") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_both") +
+			simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") +
+			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_shared") +
+			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") +
+			simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
+			simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
+		expectedBazelTargets: []string{`cc_library(
+    name = "a",
+    copts = ["bothflag"],
+    deps = [":static_dep_for_both"],
+    dynamic_deps = [":shared_dep_for_both"],
+    implementation_deps = [":implementation_static_dep_for_both"],
+    implementation_dynamic_deps = [":implementation_shared_dep_for_both"],
+    shared = {
+        "copts": ["sharedflag"],
+        "deps": [":static_dep_for_shared"],
+        "dynamic_deps": [":shared_dep_for_shared"],
+        "implementation_deps": [":implementation_static_dep_for_shared"],
+        "implementation_dynamic_deps": [":implementation_shared_dep_for_shared"],
+        "srcs": ["sharedonly.cpp"],
+        "whole_archive_deps": [
+            ":not_explicitly_exported_whole_static_dep_for_shared",
+            ":whole_static_dep_for_shared",
+        ],
+    },
+    srcs = ["both.cpp"],
+    static = {
+        "copts": ["staticflag"],
+        "deps": [":static_dep_for_static"],
+        "dynamic_deps": [":shared_dep_for_static"],
+        "implementation_deps": [":implementation_static_dep_for_static"],
+        "implementation_dynamic_deps": [":implementation_shared_dep_for_static"],
+        "srcs": ["staticonly.cpp"],
+        "whole_archive_deps": [
+            ":not_explicitly_exported_whole_static_dep_for_static",
+            ":whole_static_dep_for_static",
+        ],
+    },
+    whole_archive_deps = [
+        ":not_explicitly_exported_whole_static_dep_for_both",
+        ":whole_static_dep_for_both",
+    ],
+)`},
+	})
+}
+
 func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) {
 	runCcLibraryTestCase(t, bp2buildTestCase{
 		moduleTypeUnderTest:                "cc_library",
@@ -506,7 +605,14 @@
             "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"],
             "//conditions:default": [],
         }),
-        "dynamic_deps": select({
+        "implementation_deps": [":static_dep_for_shared"] + select({
+            "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
+            "//conditions:default": [],
+        }) + select({
+            "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
+            "//conditions:default": [],
+        }),
+        "implementation_dynamic_deps": select({
             "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"],
             "//conditions:default": [],
         }),
@@ -517,13 +623,6 @@
             "//build/bazel/platforms/os:android": ["android_shared.cpp"],
             "//conditions:default": [],
         }),
-        "static_deps": [":static_dep_for_shared"] + select({
-            "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
-            "//conditions:default": [],
-        }) + select({
-            "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
-            "//conditions:default": [],
-        }),
         "whole_archive_deps": select({
             "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
             "//conditions:default": [],
@@ -535,12 +634,12 @@
             "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
             "//conditions:default": [],
         }),
-        "srcs": ["staticonly.cpp"] + select({
-            "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
+        "implementation_deps": [":static_dep_for_static"] + select({
+            "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
             "//conditions:default": [],
         }),
-        "static_deps": [":static_dep_for_static"] + select({
-            "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
+        "srcs": ["staticonly.cpp"] + select({
+            "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
             "//conditions:default": [],
         }),
     },
@@ -767,7 +866,7 @@
 `,
 		expectedBazelTargets: []string{`cc_library(
     name = "a",
-    dynamic_deps = [":mylib"],
+    implementation_dynamic_deps = [":mylib"],
 )`},
 	})
 }
@@ -1013,13 +1112,6 @@
 		expectedBazelTargets: []string{
 			`cc_library(
     name = "foo_static",
-    dynamic_deps = select({
-        "//build/bazel/platforms/arch:arm": [],
-        "//conditions:default": [":arm_shared_lib_excludes"],
-    }) + select({
-        "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
-        "//conditions:default": [],
-    }),
     implementation_deps = select({
         "//build/bazel/platforms/arch:arm": [],
         "//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
@@ -1027,6 +1119,13 @@
         "//build/bazel/product_variables:malloc_not_svelte": [],
         "//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
     }),
+    implementation_dynamic_deps = select({
+        "//build/bazel/platforms/arch:arm": [],
+        "//conditions:default": [":arm_shared_lib_excludes"],
+    }) + select({
+        "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
+        "//conditions:default": [],
+    }),
     srcs_c = ["common.c"],
     whole_archive_deps = select({
         "//build/bazel/platforms/arch:arm": [],
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 37d806c..e43672b 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -224,7 +224,10 @@
 cc_library_headers {
     name: "foo_headers",
     target: {
-        android: { header_libs: ["android-lib"], export_header_lib_headers: ["exported-lib"] },
+        android: {
+            header_libs: ["android-lib", "exported-lib"],
+            export_header_lib_headers: ["exported-lib"]
+        },
     },
     include_build_directory: false,
 }`,
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 52a07cc..3dcfbd7 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -149,10 +149,6 @@
         "-Dflag1",
         "-Dflag2",
     ],
-    dynamic_deps = [
-        ":shared_lib_1",
-        ":shared_lib_2",
-    ],
     export_includes = [
         "export_include_dir_1",
         "export_include_dir_2",
@@ -161,6 +157,10 @@
         ":header_lib_1",
         ":header_lib_2",
     ],
+    implementation_dynamic_deps = [
+        ":shared_lib_1",
+        ":shared_lib_2",
+    ],
     local_includes = [
         "local_include_dir_1",
         "local_include_dir_2",
@@ -201,7 +201,7 @@
 }`,
 		expectedBazelTargets: []string{`cc_library_shared(
     name = "foo_shared",
-    dynamic_deps = select({
+    implementation_dynamic_deps = select({
         "//build/bazel/platforms/arch:arm64": [":shared_dep"],
         "//conditions:default": [],
     }),
@@ -232,7 +232,7 @@
 }`,
 		expectedBazelTargets: []string{`cc_library_shared(
     name = "foo_shared",
-    dynamic_deps = select({
+    implementation_dynamic_deps = select({
         "//build/bazel/platforms/os:android": [":shared_dep"],
         "//conditions:default": [],
     }),
@@ -269,7 +269,7 @@
 }`,
 		expectedBazelTargets: []string{`cc_library_shared(
     name = "foo_shared",
-    dynamic_deps = [":shared_dep"] + select({
+    implementation_dynamic_deps = [":shared_dep"] + select({
         "//build/bazel/platforms/arch:arm64": [":shared_dep3"],
         "//conditions:default": [],
     }) + select({
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 354abf6..0a86a79 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -142,7 +142,7 @@
 }
 
 func shouldSkipStructField(field reflect.StructField) bool {
-	if field.PkgPath != "" {
+	if field.PkgPath != "" && !field.Anonymous {
 		// Skip unexported fields. Some properties are
 		// internal to Soong only, and these fields do not have PkgPath.
 		return true
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 74084b1..1e7e53c 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -20,6 +20,7 @@
 */
 
 import (
+	"fmt"
 	"strings"
 	"testing"
 
@@ -358,3 +359,11 @@
 	ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
 	ctx.RegisterForBazelConversion()
 }
+
+func simpleModuleDoNotConvertBp2build(typ, name string) string {
+	return fmt.Sprintf(`
+%s {
+		name: "%s",
+		bazel_module: { bp2build_available: false },
+}`, typ, name)
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index e48f757..1b38a75 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -20,6 +20,7 @@
 
 	"android/soong/android"
 	"android/soong/bazel"
+
 	"github.com/google/blueprint"
 
 	"github.com/google/blueprint/proptools"
@@ -33,9 +34,11 @@
 	Srcs_as bazel.LabelListAttribute
 	Copts   bazel.StringListAttribute
 
-	Static_deps        bazel.LabelListAttribute
-	Dynamic_deps       bazel.LabelListAttribute
-	Whole_archive_deps bazel.LabelListAttribute
+	Deps                        bazel.LabelListAttribute
+	Implementation_deps         bazel.LabelListAttribute
+	Dynamic_deps                bazel.LabelListAttribute
+	Implementation_dynamic_deps bazel.LabelListAttribute
+	Whole_archive_deps          bazel.LabelListAttribute
 
 	System_dynamic_deps bazel.LabelListAttribute
 }
@@ -131,16 +134,50 @@
 	return bp2BuildParseLibProps(ctx, module, true)
 }
 
+type depsPartition struct {
+	export         bazel.LabelList
+	implementation bazel.LabelList
+}
+
+type bazelLabelForDepsFn func(android.TopDownMutatorContext, []string) bazel.LabelList
+
+func partitionExportedAndImplementationsDeps(ctx android.TopDownMutatorContext, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
+	implementation, export := android.FilterList(allDeps, exportedDeps)
+
+	return depsPartition{
+		export:         fn(ctx, export),
+		implementation: fn(ctx, implementation),
+	}
+}
+
+type bazelLabelForDepsExcludesFn func(android.TopDownMutatorContext, []string, []string) bazel.LabelList
+
+func partitionExportedAndImplementationsDepsExcludes(ctx android.TopDownMutatorContext, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
+	implementation, export := android.FilterList(allDeps, exportedDeps)
+
+	return depsPartition{
+		export:         fn(ctx, export, excludes),
+		implementation: fn(ctx, implementation, excludes),
+	}
+}
+
 func bp2buildParseStaticOrSharedProps(ctx android.TopDownMutatorContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
 	attrs := staticOrSharedAttributes{}
 
 	setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
 		attrs.Copts.SetSelectValue(axis, config, props.Cflags)
 		attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
-		attrs.Static_deps.SetSelectValue(axis, config, bazelLabelForStaticDeps(ctx, props.Static_libs))
-		attrs.Dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.Shared_libs))
-		attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
 		attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
+
+		staticDeps := partitionExportedAndImplementationsDeps(ctx, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps)
+		attrs.Deps.SetSelectValue(axis, config, staticDeps.export)
+		attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation)
+
+		sharedDeps := partitionExportedAndImplementationsDeps(ctx, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps)
+		attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export)
+		attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
+
+		attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
 	}
 	// system_dynamic_deps distinguishes between nil/empty list behavior:
 	//    nil -> use default values
@@ -328,11 +365,13 @@
 
 // Convenience struct to hold all attributes parsed from linker properties.
 type linkerAttributes struct {
-	deps                          bazel.LabelListAttribute
-	dynamicDeps                   bazel.LabelListAttribute
-	systemDynamicDeps             bazel.LabelListAttribute
-	wholeArchiveDeps              bazel.LabelListAttribute
-	exportedDeps                  bazel.LabelListAttribute
+	deps                      bazel.LabelListAttribute
+	implementationDeps        bazel.LabelListAttribute
+	dynamicDeps               bazel.LabelListAttribute
+	implementationDynamicDeps bazel.LabelListAttribute
+	wholeArchiveDeps          bazel.LabelListAttribute
+	systemDynamicDeps         bazel.LabelListAttribute
+
 	useLibcrt                     bazel.BoolAttribute
 	linkopts                      bazel.StringListAttribute
 	versionScript                 bazel.LabelAttribute
@@ -355,12 +394,16 @@
 // bp2BuildParseLinkerProps parses the linker properties of a module, including
 // configurable attribute values.
 func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) linkerAttributes {
+
 	var headerDeps bazel.LabelListAttribute
-	var staticDeps bazel.LabelListAttribute
-	var exportedDeps bazel.LabelListAttribute
+	var implementationHeaderDeps bazel.LabelListAttribute
+	var deps bazel.LabelListAttribute
+	var implementationDeps bazel.LabelListAttribute
 	var dynamicDeps bazel.LabelListAttribute
+	var implementationDynamicDeps bazel.LabelListAttribute
 	var wholeArchiveDeps bazel.LabelListAttribute
 	systemSharedDeps := bazel.LabelListAttribute{ForceSpecifyEmptyList: true}
+
 	var linkopts bazel.StringListAttribute
 	var versionScript bazel.LabelAttribute
 	var useLibcrt bazel.BoolAttribute
@@ -386,12 +429,16 @@
 	for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
 		for config, props := range configToProps {
 			if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
+
 				// Excludes to parallel Soong:
 				// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
 				staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
-				staticDeps.SetSelectValue(axis, config, bazelLabelForStaticDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
-				wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
-				wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+				staticDeps := partitionExportedAndImplementationsDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs, baseLinkerProps.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
+				deps.SetSelectValue(axis, config, staticDeps.export)
+				implementationDeps.SetSelectValue(axis, config, staticDeps.implementation)
+
+				wholeStaticLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
+				wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, baseLinkerProps.Exclude_static_libs))
 
 				systemSharedLibs := baseLinkerProps.System_shared_libs
 				// systemSharedLibs distinguishes between nil/empty list behavior:
@@ -403,12 +450,15 @@
 				systemSharedDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
 
 				sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
-				dynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
+				sharedDeps := partitionExportedAndImplementationsDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs, baseLinkerProps.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
+				dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
+				implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
 
 				headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
-				headerDeps.SetSelectValue(axis, config, bazelLabelForHeaderDeps(ctx, headerLibs))
-				exportedLibs := android.FirstUniqueStrings(baseLinkerProps.Export_header_lib_headers)
-				exportedDeps.SetSelectValue(axis, config, bazelLabelForHeaderDeps(ctx, exportedLibs))
+				hDeps := partitionExportedAndImplementationsDeps(ctx, headerLibs, baseLinkerProps.Export_header_lib_headers, bazelLabelForHeaderDeps)
+
+				headerDeps.SetSelectValue(axis, config, hDeps.export)
+				implementationHeaderDeps.SetSelectValue(axis, config, hDeps.implementation)
 
 				linkopts.SetSelectValue(axis, config, getBp2BuildLinkerFlags(baseLinkerProps))
 				if baseLinkerProps.Version_script != nil {
@@ -430,8 +480,8 @@
 
 	productVarToDepFields := map[string]productVarDep{
 		// product variables do not support exclude_shared_libs
-		"Shared_libs":       productVarDep{attribute: &dynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
-		"Static_libs":       productVarDep{"Exclude_static_libs", &staticDeps, bazelLabelForStaticDepsExcludes},
+		"Shared_libs":       productVarDep{attribute: &implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
+		"Static_libs":       productVarDep{"Exclude_static_libs", &implementationDeps, bazelLabelForStaticDepsExcludes},
 		"Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
 	}
 
@@ -471,21 +521,26 @@
 		}
 	}
 
-	staticDeps.ResolveExcludes()
+	headerDeps.Append(deps)
+	implementationHeaderDeps.Append(implementationDeps)
+
+	headerDeps.ResolveExcludes()
+	implementationHeaderDeps.ResolveExcludes()
 	dynamicDeps.ResolveExcludes()
+	implementationDynamicDeps.ResolveExcludes()
 	wholeArchiveDeps.ResolveExcludes()
 
-	headerDeps.Append(staticDeps)
-
 	return linkerAttributes{
-		deps:              headerDeps,
-		exportedDeps:      exportedDeps,
-		dynamicDeps:       dynamicDeps,
-		systemDynamicDeps: systemSharedDeps,
-		wholeArchiveDeps:  wholeArchiveDeps,
-		linkopts:          linkopts,
-		useLibcrt:         useLibcrt,
-		versionScript:     versionScript,
+		deps:                      headerDeps,
+		implementationDeps:        implementationHeaderDeps,
+		dynamicDeps:               dynamicDeps,
+		implementationDynamicDeps: implementationDynamicDeps,
+		wholeArchiveDeps:          wholeArchiveDeps,
+		systemDynamicDeps:         systemSharedDeps,
+
+		linkopts:      linkopts,
+		useLibcrt:     useLibcrt,
+		versionScript: versionScript,
 
 		// Strip properties
 		stripKeepSymbols:              stripKeepSymbols,
diff --git a/cc/library.go b/cc/library.go
index 8a572f9..9114f14 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -232,12 +232,15 @@
 	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
+	Hdrs bazel.LabelListAttribute
+
+	Deps                        bazel.LabelListAttribute
+	Implementation_deps         bazel.LabelListAttribute
+	Dynamic_deps                bazel.LabelListAttribute
+	Implementation_dynamic_deps bazel.LabelListAttribute
+	Whole_archive_deps          bazel.LabelListAttribute
+	System_dynamic_deps         bazel.LabelListAttribute
+
 	Export_includes        bazel.StringListAttribute
 	Export_system_includes bazel.StringListAttribute
 	Local_includes         bazel.StringListAttribute
@@ -306,18 +309,19 @@
 		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,
-		Export_includes:        exportedIncludes.Includes,
-		Export_system_includes: exportedIncludes.SystemIncludes,
-		Local_includes:         compilerAttrs.localIncludes,
-		Absolute_includes:      compilerAttrs.absoluteIncludes,
-		Linkopts:               linkerAttrs.linkopts,
-		Use_libcrt:             linkerAttrs.useLibcrt,
-		Rtti:                   compilerAttrs.rtti,
+		Implementation_deps:         linkerAttrs.implementationDeps,
+		Deps:                        linkerAttrs.deps,
+		Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
+		Dynamic_deps:                linkerAttrs.dynamicDeps,
+		Whole_archive_deps:          linkerAttrs.wholeArchiveDeps,
+		System_dynamic_deps:         linkerAttrs.systemDynamicDeps,
+		Export_includes:             exportedIncludes.Includes,
+		Export_system_includes:      exportedIncludes.SystemIncludes,
+		Local_includes:              compilerAttrs.localIncludes,
+		Absolute_includes:           compilerAttrs.absoluteIncludes,
+		Linkopts:                    linkerAttrs.linkopts,
+		Use_libcrt:                  linkerAttrs.useLibcrt,
+		Rtti:                        compilerAttrs.rtti,
 
 		Version_script: linkerAttrs.versionScript,
 
@@ -2349,9 +2353,11 @@
 	compilerAttrs.cSrcs.Append(libSharedOrStaticAttrs.Srcs_c)
 	compilerAttrs.asSrcs.Append(libSharedOrStaticAttrs.Srcs_as)
 	compilerAttrs.copts.Append(libSharedOrStaticAttrs.Copts)
-	linkerAttrs.exportedDeps.Append(libSharedOrStaticAttrs.Static_deps)
+
+	linkerAttrs.deps.Append(libSharedOrStaticAttrs.Deps)
+	linkerAttrs.implementationDeps.Append(libSharedOrStaticAttrs.Implementation_deps)
 	linkerAttrs.dynamicDeps.Append(libSharedOrStaticAttrs.Dynamic_deps)
-	linkerAttrs.wholeArchiveDeps.Append(libSharedOrStaticAttrs.Whole_archive_deps)
+	linkerAttrs.implementationDynamicDeps.Append(libSharedOrStaticAttrs.Implementation_dynamic_deps)
 	linkerAttrs.systemDynamicDeps.Append(libSharedOrStaticAttrs.System_dynamic_deps)
 
 	asFlags := compilerAttrs.asFlags
@@ -2360,16 +2366,24 @@
 		asFlags = bazel.MakeStringListAttribute(nil)
 	}
 
+	commonAttrs := staticOrSharedAttributes{
+		Srcs:    compilerAttrs.srcs,
+		Srcs_c:  compilerAttrs.cSrcs,
+		Srcs_as: compilerAttrs.asSrcs,
+		Copts:   compilerAttrs.copts,
+
+		Deps:                        linkerAttrs.deps,
+		Implementation_deps:         linkerAttrs.implementationDeps,
+		Dynamic_deps:                linkerAttrs.dynamicDeps,
+		Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
+		Whole_archive_deps:          linkerAttrs.wholeArchiveDeps,
+		System_dynamic_deps:         linkerAttrs.systemDynamicDeps,
+	}
+
 	var attrs interface{}
 	if isStatic {
 		attrs = &bazelCcLibraryStaticAttributes{
-			Copts:               compilerAttrs.copts,
-			Srcs:                compilerAttrs.srcs,
-			Implementation_deps: linkerAttrs.deps,
-			Deps:                linkerAttrs.exportedDeps,
-			Whole_archive_deps:  linkerAttrs.wholeArchiveDeps,
-			Dynamic_deps:        linkerAttrs.dynamicDeps,
-			System_dynamic_deps: linkerAttrs.systemDynamicDeps,
+			staticOrSharedAttributes: commonAttrs,
 
 			Linkopts:               linkerAttrs.linkopts,
 			Use_libcrt:             linkerAttrs.useLibcrt,
@@ -2380,24 +2394,13 @@
 			Absolute_includes:      compilerAttrs.absoluteIncludes,
 
 			Cppflags:   compilerAttrs.cppFlags,
-			Srcs_c:     compilerAttrs.cSrcs,
 			Conlyflags: compilerAttrs.conlyFlags,
-			Srcs_as:    compilerAttrs.asSrcs,
 			Asflags:    asFlags,
 		}
 	} else {
 		attrs = &bazelCcLibrarySharedAttributes{
-			Srcs:    compilerAttrs.srcs,
-			Srcs_c:  compilerAttrs.cSrcs,
-			Srcs_as: compilerAttrs.asSrcs,
+			staticOrSharedAttributes: commonAttrs,
 
-			Implementation_deps: linkerAttrs.deps,
-			Deps:                linkerAttrs.exportedDeps,
-			Whole_archive_deps:  linkerAttrs.wholeArchiveDeps,
-			Dynamic_deps:        linkerAttrs.dynamicDeps,
-			System_dynamic_deps: linkerAttrs.systemDynamicDeps,
-
-			Copts:      compilerAttrs.copts,
 			Cppflags:   compilerAttrs.cppFlags,
 			Conlyflags: compilerAttrs.conlyFlags,
 			Asflags:    asFlags,
@@ -2432,16 +2435,12 @@
 
 // TODO(b/199902614): Can this be factored to share with the other Attributes?
 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
-	Use_libcrt             bazel.BoolAttribute
-	Rtti                   bazel.BoolAttribute
+	staticOrSharedAttributes
+
+	Linkopts   bazel.StringListAttribute
+	Use_libcrt bazel.BoolAttribute
+	Rtti       bazel.BoolAttribute
+
 	Export_includes        bazel.StringListAttribute
 	Export_system_includes bazel.StringListAttribute
 	Local_includes         bazel.StringListAttribute
@@ -2449,9 +2448,7 @@
 	Hdrs                   bazel.LabelListAttribute
 
 	Cppflags   bazel.StringListAttribute
-	Srcs_c     bazel.LabelListAttribute
 	Conlyflags bazel.StringListAttribute
-	Srcs_as    bazel.LabelListAttribute
 	Asflags    bazel.StringListAttribute
 }
 
@@ -2461,29 +2458,21 @@
 
 // TODO(b/199902614): Can this be factored to share with the other Attributes?
 type bazelCcLibrarySharedAttributes struct {
-	Srcs    bazel.LabelListAttribute
-	Srcs_c  bazel.LabelListAttribute
-	Srcs_as bazel.LabelListAttribute
-
-	Implementation_deps bazel.LabelListAttribute
-	Deps                bazel.LabelListAttribute
-	Whole_archive_deps  bazel.LabelListAttribute
-	Dynamic_deps        bazel.LabelListAttribute
-	System_dynamic_deps bazel.LabelListAttribute
+	staticOrSharedAttributes
 
 	Linkopts   bazel.StringListAttribute
 	Use_libcrt bazel.BoolAttribute
 	Rtti       bazel.BoolAttribute
-	Strip      stripAttributes
 
 	Export_includes        bazel.StringListAttribute
 	Export_system_includes bazel.StringListAttribute
 	Local_includes         bazel.StringListAttribute
 	Absolute_includes      bazel.StringListAttribute
 	Hdrs                   bazel.LabelListAttribute
-	Version_script         bazel.LabelAttribute
 
-	Copts      bazel.StringListAttribute
+	Strip          stripAttributes
+	Version_script bazel.LabelAttribute
+
 	Cppflags   bazel.StringListAttribute
 	Conlyflags bazel.StringListAttribute
 	Asflags    bazel.StringListAttribute
diff --git a/cc/library_headers.go b/cc/library_headers.go
index b335035..f88b801 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -135,8 +135,8 @@
 	attrs := &bazelCcLibraryHeadersAttributes{
 		Export_includes:        exportedIncludes.Includes,
 		Export_system_includes: exportedIncludes.SystemIncludes,
-		Implementation_deps:    linkerAttrs.deps,
-		Deps:                   linkerAttrs.exportedDeps,
+		Implementation_deps:    linkerAttrs.implementationDeps,
+		Deps:                   linkerAttrs.deps,
 		System_dynamic_deps:    linkerAttrs.systemDynamicDeps,
 	}