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/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,
 	}