diff --git a/android/api_domain.go b/android/api_domain.go index 787665475..0993e3d84 100644 --- a/android/api_domain.go +++ b/android/api_domain.go @@ -73,9 +73,9 @@ func ApiDomainFactory() Module { func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) { for _, cc := range a.properties.Cc_api_contributions { // Use FarVariationDependencies since the variants of api_domain is a subset of the variants of the dependency cc module - // Creating a dependency on the first variant is ok since this is a no-op in Soong + // Creating a dependency on the first variant that matches (os,arch) is ok since this is a no-op in Soong // The primary function of this dependency is to create a connected graph in the corresponding bp2build workspace - ctx.AddFarVariationDependencies([]blueprint.Variation{}, nil, cc) + ctx.AddFarVariationDependencies(ctx.Target().Variations(), nil, cc) } } diff --git a/android/module.go b/android/module.go index 68d9f8e75..c099e6d15 100644 --- a/android/module.go +++ b/android/module.go @@ -915,9 +915,16 @@ type commonProperties struct { type CommonAttributes struct { // Soong nameProperties -> Bazel name Name string + // Data mapped from: Required Data bazel.LabelListAttribute + // SkipData is neither a Soong nor Bazel target attribute + // If true, this will not fill the data attribute automatically + // This is useful for Soong modules that have 1:many Bazel targets + // Some of the generated Bazel targets might not have a data attribute + SkipData *bool + Tags bazel.StringListAttribute Applicable_licenses bazel.LabelListAttribute @@ -1305,7 +1312,12 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator platformEnabledAttribute.Add(&l) } - attrs.Data.Append(required) + if !proptools.Bool(attrs.SkipData) { + attrs.Data.Append(required) + } + // SkipData is not an attribute of any Bazel target + // Set this to nil so that it does not appear in the generated build file + attrs.SkipData = nil moduleEnableConstraints := bazel.LabelListAttribute{} moduleEnableConstraints.Append(platformEnabledAttribute) diff --git a/bazel/properties.go b/bazel/properties.go index c329e4197..823cda8b2 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -73,6 +73,17 @@ func MakeLabelList(labels []Label) LabelList { } } +// MakeLabelListFromTargetNames creates a LabelList from unqualified target names +// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets +func MakeLabelListFromTargetNames(targetNames []string) LabelList { + labels := []Label{} + for _, name := range targetNames { + label := Label{Label: ":" + name} + labels = append(labels, label) + } + return MakeLabelList(labels) +} + func (ll *LabelList) Equals(other LabelList) bool { if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) { return false @@ -1178,6 +1189,11 @@ type StringListAttribute struct { ConfigurableValues configurableStringLists } +// IsEmpty returns true if the attribute has no values under any configuration. +func (sla StringListAttribute) IsEmpty() bool { + return len(sla.Value) == 0 && !sla.HasConfigurableValues() +} + type configurableStringLists map[ConfigurationAxis]stringListSelectValues func (csl configurableStringLists) Append(other configurableStringLists) { diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index d4461b6ab..0d6d5b87e 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -2743,6 +2743,205 @@ cc_library { ) } +func TestCcApiContributionsWithHdrs(t *testing.T) { + bp := ` + cc_library { + name: "libfoo", + stubs: { symbol_file: "libfoo.map.txt", versions: ["28", "29", "current"] }, + llndk: { symbol_file: "libfoo.map.txt", override_export_include_dirs: ["dir2"]}, + export_include_dirs: ["dir1"], + } + ` + expectedBazelTargets := []string{ + MakeBazelTarget( + "cc_api_library_headers", + "libfoo.systemapi.headers", + AttrNameToString{ + "export_includes": `["dir1"]`, + }), + MakeBazelTarget( + "cc_api_library_headers", + "libfoo.vendorapi.headers", + AttrNameToString{ + "export_includes": `["dir2"]`, + }), + MakeBazelTarget( + "cc_api_contribution", + "libfoo.contribution", + AttrNameToString{ + "api": `"libfoo.map.txt"`, + "library_name": `"libfoo"`, + "api_surfaces": `[ + "systemapi", + "vendorapi", + ]`, + "hdrs": `[ + ":libfoo.systemapi.headers", + ":libfoo.vendorapi.headers", + ]`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: bp, + Description: "cc API contributions to systemapi and vendorapi", + ExpectedBazelTargets: expectedBazelTargets, + }) +} + +func TestCcApiSurfaceCombinations(t *testing.T) { + testCases := []struct { + bp string + expectedApi string + expectedApiSurfaces string + description string + }{ + { + bp: ` + cc_library { + name: "a", + stubs: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `["systemapi"]`, + description: "Library that contributes to systemapi", + }, + { + bp: ` + cc_library { + name: "a", + llndk: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `["vendorapi"]`, + description: "Library that contributes to vendorapi", + }, + { + bp: ` + cc_library { + name: "a", + llndk: {symbol_file: "a.map.txt"}, + stubs: {symbol_file: "a.map.txt"}, + }`, + expectedApi: `"a.map.txt"`, + expectedApiSurfaces: `[ + "systemapi", + "vendorapi", + ]`, + description: "Library that contributes to systemapi and vendorapi", + }, + } + for _, testCase := range testCases { + expectedBazelTargets := []string{ + MakeBazelTarget( + "cc_api_contribution", + "a.contribution", + AttrNameToString{ + "library_name": `"a"`, + "hdrs": `[]`, + "api": testCase.expectedApi, + "api_surfaces": testCase.expectedApiSurfaces, + }, + ), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: testCase.bp, + Description: testCase.description, + ExpectedBazelTargets: expectedBazelTargets, + }) + } +} + +// llndk struct property in Soong provides users with several options to configure the exported include dirs +// Test the generated bazel targets for the different configurations +func TestCcVendorApiHeaders(t *testing.T) { + testCases := []struct { + bp string + expectedIncludes string + expectedSystemIncludes string + description string + }{ + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + export_headers_as_system: true, + }, + } + `, + expectedIncludes: "", + expectedSystemIncludes: `[ + "base_system_include", + "include", + ]`, + description: "Headers are exported as system to API surface", + }, + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + override_export_include_dirs: ["llndk_include"], + }, + } + `, + expectedIncludes: `["llndk_include"]`, + expectedSystemIncludes: `["base_system_include"]`, + description: "Non-system Headers are ovverriden before export to API surface", + }, + { + bp: ` + cc_library { + name: "a", + export_include_dirs: ["include"], + export_system_include_dirs: ["base_system_include"], + llndk: { + symbol_file: "a.map.txt", + override_export_include_dirs: ["llndk_include"], + export_headers_as_system: true, + }, + } + `, + expectedIncludes: "", // includes are set to nil + expectedSystemIncludes: `[ + "base_system_include", + "llndk_include", + ]`, + description: "System Headers are extended before export to API surface", + }, + } + for _, testCase := range testCases { + attrs := AttrNameToString{} + if testCase.expectedIncludes != "" { + attrs["export_includes"] = testCase.expectedIncludes + } + if testCase.expectedSystemIncludes != "" { + attrs["export_system_includes"] = testCase.expectedSystemIncludes + } + + expectedBazelTargets := []string{ + MakeBazelTarget("cc_api_library_headers", "a.vendorapi.headers", attrs), + // Create a target for cc_api_contribution target + MakeBazelTarget("cc_api_contribution", "a.contribution", AttrNameToString{ + "api": `"a.map.txt"`, + "api_surfaces": `["vendorapi"]`, + "hdrs": `[":a.vendorapi.headers"]`, + "library_name": `"a"`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{ + Blueprint: testCase.bp, + ExpectedBazelTargets: expectedBazelTargets, + }) + } +} + func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "stub target generation of the same lib across configs should not result in duplicates", diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 5fa7cac5e..7d9db6fe2 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -123,6 +123,69 @@ cc_library_headers { }) } +func TestCcApiHeaders(t *testing.T) { + fs := map[string]string{ + "bar/Android.bp": `cc_library_headers { name: "bar_headers", }`, + } + bp := ` + cc_library_headers { + name: "foo_headers", + export_include_dirs: ["dir1", "dir2"], + export_header_lib_headers: ["bar_headers"], + + arch: { + arm: { + export_include_dirs: ["dir_arm"], + }, + x86: { + export_include_dirs: ["dir_x86"], + }, + }, + + target: { + android: { + export_include_dirs: ["dir1", "dir_android"], + }, + windows: { + export_include_dirs: ["dir_windows"], + }, + } + } + ` + expectedBazelTargets := []string{ + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{ + "export_includes": `["dir_arm"]`, + "arch": `"arm"`, + }), + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{ + "export_includes": `["dir_x86"]`, + "arch": `"x86"`, + }), + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{ + "export_includes": `["dir_android"]`, // common includes are deduped + }), + // Windows headers are not exported + MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{ + "export_includes": `[ + "dir1", + "dir2", + ]`, + "deps": `[ + "//bar:bar_headers.contribution", + ":foo_headers.contribution.arm", + ":foo_headers.contribution.x86", + ":foo_headers.contribution.androidos", + ]`, + }), + } + RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{ + Blueprint: bp, + Description: "Header library contributions to API surfaces", + ExpectedBazelTargets: expectedBazelTargets, + Filesystem: fs, + }) +} + func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) { runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ Description: "cc_library_headers test with os-specific header_libs props", diff --git a/cc/cc.go b/cc/cc.go index d4eaa5364..d173cc1b6 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -3751,7 +3751,18 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { var _ android.ApiProvider = (*Module)(nil) func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { + if c.IsPrebuilt() { + return + } switch c.typ() { + case fullLibrary: + apiContributionBp2Build(ctx, c) + case sharedLibrary: + apiContributionBp2Build(ctx, c) + case headerLibrary: + // Aggressively generate api targets for all header modules + // This is necessary since the header module does not know if it is a dep of API surface stub library + apiLibraryHeadersBp2Build(ctx, c) case ndkLibrary: ndkLibraryBp2build(ctx, c) } diff --git a/cc/library.go b/cc/library.go index 13a7a3eb1..4c09403ec 100644 --- a/cc/library.go +++ b/cc/library.go @@ -30,6 +30,7 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/pathtools" + "github.com/google/blueprint/proptools" ) // LibraryProperties is a collection of properties shared by cc library rules/cc. @@ -466,6 +467,147 @@ func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module } } +func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) { + apiSurfaces := make([]string, 0) + apiHeaders := make([]string, 0) + // systemapi (non-null `stubs` property) + if module.HasStubsVariants() { + apiSurfaces = append(apiSurfaces, android.SystemApi.String()) + apiIncludes := getSystemApiIncludes(ctx, module) + if !apiIncludes.isEmpty() { + createApiHeaderTarget(ctx, apiIncludes) + apiHeaders = append(apiHeaders, apiIncludes.name) + } + } + // vendorapi (non-null `llndk` property) + if module.HasLlndkStubs() { + apiSurfaces = append(apiSurfaces, android.VendorApi.String()) + apiIncludes := getVendorApiIncludes(ctx, module) + if !apiIncludes.isEmpty() { + createApiHeaderTarget(ctx, apiIncludes) + apiHeaders = append(apiHeaders, apiIncludes.name) + } + } + // create a target only if this module contributes to an api surface + // TODO: Currently this does not distinguish systemapi-only headers and vendrorapi-only headers + // TODO: Update so that systemapi-only headers do not get exported to vendorapi (and vice-versa) + if len(apiSurfaces) > 0 { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_api_contribution", + Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", + } + attrs := &bazelCcApiContributionAttributes{ + Library_name: module.Name(), + Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces), + Api: apiLabelAttribute(ctx, module), + Hdrs: bazel.MakeLabelListAttribute( + bazel.MakeLabelListFromTargetNames(apiHeaders), + ), + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{ + Name: android.ApiContributionTargetName(module.Name()), + SkipData: proptools.BoolPtr(true), + }, + attrs, + ) + } +} + +// Native apis are versioned in a single .map.txt for all api surfaces +// Pick any one of the .map.txt files +func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute { + var apiFile *string + linker := module.linker.(*libraryDecorator) + if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil { + apiFile = llndkApi + } else if systemApi := linker.Properties.Stubs.Symbol_file; systemApi != nil { + apiFile = systemApi + } else { + ctx.ModuleErrorf("API surface library does not have any API file") + } + apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label + return *bazel.MakeLabelAttribute(apiLabel) +} + +// wrapper struct to flatten the arch and os specific export_include_dirs +// flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.) +type bazelCcApiLibraryHeadersAttributes struct { + bazelCcLibraryHeadersAttributes + + Arch *string +} + +func (a *bazelCcApiLibraryHeadersAttributes) isEmpty() bool { + return a.Export_includes.IsEmpty() && + a.Export_system_includes.IsEmpty() && + a.Deps.IsEmpty() +} + +type apiIncludes struct { + name string // name of the Bazel target in the generated bp2build workspace + attrs bazelCcApiLibraryHeadersAttributes +} + +func (includes *apiIncludes) isEmpty() bool { + return includes.attrs.isEmpty() +} + +func (includes *apiIncludes) addDep(name string) { + l := bazel.Label{Label: ":" + name} + ll := bazel.MakeLabelList([]bazel.Label{l}) + lla := bazel.MakeLabelListAttribute(ll) + includes.attrs.Deps.Append(lla) +} + +func getSystemApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes { + flagProps := c.library.(*libraryDecorator).flagExporter.Properties + linkProps := c.library.(*libraryDecorator).baseLinker.Properties + includes := android.FirstUniqueStrings(flagProps.Export_include_dirs) + systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs) + headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers) + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)), + } + + return apiIncludes{ + name: c.Name() + ".systemapi.headers", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + }, + } +} + +func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes { + baseProps := c.library.(*libraryDecorator).flagExporter.Properties + llndkProps := c.library.(*libraryDecorator).Properties.Llndk + includes := baseProps.Export_include_dirs + systemIncludes := baseProps.Export_system_include_dirs + // LLNDK can override the base includes + if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil { + includes = llndkIncludes + } + if proptools.Bool(llndkProps.Export_headers_as_system) { + systemIncludes = append(systemIncludes, includes...) + includes = nil + } + + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)), + } + return apiIncludes{ + name: c.Name() + ".vendorapi.headers", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + }, + } +} + // cc_library creates both static and/or shared libraries for a device and/or // host. By default, a cc_library has a single variant that targets the device. // Specifying `host_supported: true` also creates a library that targets the diff --git a/cc/library_headers.go b/cc/library_headers.go index a683f58df..1c4f35403 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -15,6 +15,8 @@ package cc import ( + "github.com/google/blueprint/proptools" + "android/soong/android" "android/soong/bazel" "android/soong/bazel/cquery" @@ -145,3 +147,118 @@ func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) } + +// Append .contribution suffix to input labels +func apiBazelTargets(ll bazel.LabelList) bazel.LabelList { + labels := make([]bazel.Label, 0) + for _, l := range ll.Includes { + labels = append(labels, bazel.Label{ + Label: android.ApiContributionTargetName(l.Label), + }) + } + return bazel.MakeLabelList(labels) +} + +func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { + // cc_api_library_headers have a 1:1 mapping to arch/no-arch + // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps + + // arch-agnostic includes + apiIncludes := getSystemApiIncludes(ctx, module) + // arch and os specific includes + archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module) + for _, arch := range allArches { // sorted iteration + archApiInclude := archApiIncludes[arch] + if !archApiInclude.isEmpty() { + createApiHeaderTarget(ctx, archApiInclude) + apiIncludes.addDep(archApiInclude.name) + } + } + // os==android includes + if !androidOsIncludes.isEmpty() { + createApiHeaderTarget(ctx, androidOsIncludes) + apiIncludes.addDep(androidOsIncludes.name) + } + + if !apiIncludes.isEmpty() { + // override the name from .systemapi.headers --> .contribution + apiIncludes.name = android.ApiContributionTargetName(module.Name()) + createApiHeaderTarget(ctx, apiIncludes) + } +} + +func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_api_library_headers", + Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{ + Name: includes.name, + SkipData: proptools.BoolPtr(true), + }, + &includes.attrs, + ) +} + +var ( + allArches = []string{"arm", "arm64", "x86", "x86_64"} +) + +type archApiIncludes map[string]apiIncludes + +func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) { + baseProps := bp2BuildParseBaseProps(ctx, module) + i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes) + archRet := archApiIncludes{} + for _, arch := range allArches { + includes := i.Includes.SelectValue( + bazel.ArchConfigurationAxis, + arch) + systemIncludes := i.SystemIncludes.SelectValue( + bazel.ArchConfigurationAxis, + arch) + deps := baseProps.deps.SelectValue( + bazel.ArchConfigurationAxis, + arch) + attrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute(includes), + Export_system_includes: bazel.MakeStringListAttribute(systemIncludes), + } + apiDeps := apiBazelTargets(deps) + if !apiDeps.IsEmpty() { + attrs.Deps = bazel.MakeLabelListAttribute(apiDeps) + } + apiIncludes := apiIncludes{ + name: android.ApiContributionTargetName(module.Name()) + "." + arch, + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: attrs, + Arch: proptools.StringPtr(arch), + }, + } + archRet[arch] = apiIncludes + } + + // apiIncludes for os == Android + androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid) + androidOsAttrs := bazelCcLibraryHeadersAttributes{ + Export_includes: bazel.MakeStringListAttribute( + i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), + ), + Export_system_includes: bazel.MakeStringListAttribute( + i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid), + ), + } + androidOsApiDeps := apiBazelTargets(androidOsDeps) + if !androidOsApiDeps.IsEmpty() { + androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps) + } + osRet := apiIncludes{ + name: android.ApiContributionTargetName(module.Name()) + ".androidos", + attrs: bazelCcApiLibraryHeadersAttributes{ + bazelCcLibraryHeadersAttributes: androidOsAttrs, + }, + } + return archRet, osRet +} diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 06ded3f8e..49a919eea 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -581,12 +581,12 @@ type bazelCcApiContributionAttributes struct { } // Names of the cc_api_header targets in the bp2build workspace -func (s *stubDecorator) apiHeaderLabels(ctx android.TopDownMutatorContext) bazel.LabelList { +func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList { addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string { label := android.BazelModuleLabel(ctx, module) return android.ApiContributionTargetName(label) } - return android.BazelLabelForModuleDepsWithFn(ctx, s.properties.Export_header_libs, addSuffix) + return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix) } func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) { @@ -604,7 +604,7 @@ func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) { apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label attrs.Api = *bazel.MakeLabelAttribute(apiLabel) } - apiHeaders := stubLibrary.apiHeaderLabels(ctx) + apiHeaders := apiHeaderLabels(ctx, stubLibrary.properties.Export_header_libs) attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders) apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName()) ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs)