From 63acae9af1d5d7e35f461d091ba3dae478df08f3 Mon Sep 17 00:00:00 2001 From: Spandan Das Date: Thu, 14 Sep 2023 22:34:34 +0000 Subject: [PATCH 1/2] bp2build converter for ndk_library ndk_libary will be converted to a cc_stub_suite target. Its api_surface attribute will be publicapi The headers corresponding to this stub target will be added in a followup bug (tracked in b/300504837) Bug: 298085502 Test: Added a unit test Change-Id: If9745083b18e0bcf5ecb89229a0f709b949d401c --- bp2build/cc_library_conversion_test.go | 36 +++++++++++++++++++++++++ cc/cc.go | 2 ++ cc/ndk_library.go | 37 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 3957ff767..76dc5904b 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -65,6 +65,7 @@ func registerCcLibraryModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory) ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory) + ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory) } func TestCcLibrarySimple(t *testing.T) { @@ -5131,3 +5132,38 @@ cc_library { } runCcLibraryTestCase(t, tc) } + +func TestNdkLibraryConversion(t *testing.T) { + tc := Bp2buildTestCase{ + Description: "ndk_library conversion", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: ` +cc_library { + name: "libfoo", + bazel_module: { bp2build_available: false }, +} +ndk_library { + name: "libfoo", + first_version: "29", + symbol_file: "libfoo.map.txt", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_stub_suite", "libfoo.ndk_stub_libs", AttrNameToString{ + "api_surface": `"publicapi"`, + "soname": `"libfoo.so"`, + "source_library_label": `"//:libfoo"`, + "symbol_file": `"libfoo.map.txt"`, + "versions": `[ + "29", + "30", + "S", + "Tiramisu", + "current", + ]`, + }), + }, + } + runCcLibraryTestCase(t, tc) +} diff --git a/cc/cc.go b/cc/cc.go index 8d79df24b..e28d056f8 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -4255,6 +4255,8 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } case ndkPrebuiltStl: ndkPrebuiltStlBp2build(ctx, c) + case ndkLibrary: + ndkLibraryBp2build(ctx, c) default: ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") } diff --git a/cc/ndk_library.go b/cc/ndk_library.go index b201dd88a..bb40b4509 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -581,3 +581,40 @@ func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel. } return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix) } + +func ndkLibraryBp2build(ctx android.TopDownMutatorContext, c *Module) { + ndk, _ := c.linker.(*stubDecorator) + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_stub_suite", + Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl", + } + sourceLibraryName := strings.TrimSuffix(c.Name(), ".ndk") + fromApiLevel, err := android.ApiLevelFromUser(ctx, proptools.String(ndk.properties.First_version)) + if err != nil { + ctx.PropertyErrorf("first_version", "error converting first_version %v", proptools.String(ndk.properties.First_version)) + } + symbolFileLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(ndk.properties.Symbol_file)) + attrs := &bazelCcStubSuiteAttributes{ + // TODO - b/300504837 Add ndk headers + Symbol_file: proptools.StringPtr(symbolFileLabel.Label), + Soname: proptools.StringPtr(sourceLibraryName + ".so"), + Api_surface: proptools.StringPtr(android.PublicApi.String()), + } + if sourceLibrary, exists := ctx.ModuleFromName(sourceLibraryName); exists { + // the source library might not exist in minimal/unbuildable branches like kernel-build-tools. + // check for its existence + attrs.Source_library_label = proptools.StringPtr(c.GetBazelLabel(ctx, sourceLibrary)) + } + if ctx.Config().RawPlatformSdkVersion() != nil { + // This is a hack to populate `versions` only on branches that set a platform_sdk_version + // This prevents errors on branches such as kernel-build-tools + // This hack is acceptable since we are not required to support NDK Bazel builds on those branches + attrs.Versions = bazel.MakeStringListAttribute(ndkLibraryVersions(ctx, fromApiLevel)) + } + + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{Name: c.Name() + "_stub_libs"}, + attrs, + ) +} From 1f65f9e9bd7bf22c668d2f61a14c60bdcb79dde7 Mon Sep 17 00:00:00 2001 From: Spandan Das Date: Fri, 15 Sep 2023 01:08:23 +0000 Subject: [PATCH 2/2] Stub/Impl selection for sdk variants If a dependency has ndk stubs, then the sdk variant of the library should link against the ndk stub variant and not the impl/apex_stubs variant Unlike module-libapi, the depdendency does not go through an @api_surfaces external repo indirection. This indirection was created to support Multi-tree, and will likely be removed in the future Test: Added a unit test Bug: 298085502 Change-Id: Ie081e153fa586b6c22db0b8e42f91149fd8e5d9b --- bazel/configurability.go | 2 + bp2build/cc_library_shared_conversion_test.go | 60 +++++++++++++++++++ cc/bp2build.go | 27 +++++++++ 3 files changed, 89 insertions(+) diff --git a/bazel/configurability.go b/bazel/configurability.go index 1fe844219..a28432c01 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -71,6 +71,7 @@ const ( AndroidAndInApex = "android-in_apex" AndroidPlatform = "system" + Unbundled_app = "unbundled_app" InApex = "in_apex" NonApex = "non_apex" @@ -207,6 +208,7 @@ var ( osAndInApexMap = map[string]string{ AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex", AndroidPlatform: "//build/bazel/rules/apex:system", + Unbundled_app: "//build/bazel/rules/apex:unbundled_app", OsDarwin: "//build/bazel/platforms/os:darwin", OsLinux: "//build/bazel/platforms/os:linux_glibc", osLinuxMusl: "//build/bazel/platforms/os:linux_musl", diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 921e6e30b..b3dd6b177 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -32,6 +32,7 @@ func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory) ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) ctx.RegisterModuleType("cc_library", cc.LibraryFactory) + ctx.RegisterModuleType("ndk_library", cc.NdkLibraryFactory) } func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) { @@ -1593,3 +1594,62 @@ cc_library_shared{ ]`, })}}) } + +func TestCcLibrarySdkVariantUsesStubs(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared stubs", + ModuleTypeUnderTest: "cc_library_shared", + ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "libUsesSdk", + sdk_version: "current", + shared_libs: [ + "libNoStubs", + "libHasApexStubs", + "libHasApexAndNdkStubs", + ] +} +cc_library_shared { + name: "libNoStubs", + bazel_module: { bp2build_available: false }, +} +cc_library_shared { + name: "libHasApexStubs", + stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, + bazel_module: { bp2build_available: false }, + apex_available: ["apex_a"], +} +cc_library_shared { + name: "libHasApexAndNdkStubs", + stubs: { symbol_file: "b.map.txt", versions: ["28", "29", "current"] }, + bazel_module: { bp2build_available: false }, + apex_available: ["apex_b"], +} +ndk_library { + name: "libHasApexAndNdkStubs", + bazel_module: { bp2build_available: false }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "libUsesSdk", AttrNameToString{ + "implementation_dynamic_deps": `[":libNoStubs"] + select({ + "//build/bazel/rules/apex:system": [ + "@api_surfaces//module-libapi/current:libHasApexStubs", + "@api_surfaces//module-libapi/current:libHasApexAndNdkStubs", + ], + "//build/bazel/rules/apex:unbundled_app": [ + ":libHasApexStubs", + "//.:libHasApexAndNdkStubs.ndk_stub_libs", + ], + "//conditions:default": [ + ":libHasApexStubs", + ":libHasApexAndNdkStubs", + ], + })`, + "local_includes": `["."]`, + "sdk_version": `"current"`, + }), + }, + }) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index ce8c96d0c..aacc0884b 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -1578,6 +1578,12 @@ func useStubOrImplInApexWithName(ssi stubSelectionInfo) { } } +// hasNdkStubs returns true for libfoo if there exists a libfoo.ndk of type ndk_library +func hasNdkStubs(ctx android.BazelConversionPathContext, c *Module) bool { + mod, exists := ctx.ModuleFromName(c.Name() + ndkLibrarySuffix) + return exists && ctx.OtherModuleType(mod) == "ndk_library" +} + func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) { @@ -1638,6 +1644,27 @@ func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.C useStubOrImplInApexWithName(ssi) } } + + // If the library has an sdk variant, create additional selects to build this variant against the ndk + // The config setting for this variant will be //build/bazel/rules/apex:unbundled_app + if c, ok := ctx.Module().(*Module); ok && c.Properties.Sdk_version != nil { + for _, l := range dynamicLibs.Includes { + dep, _ := ctx.ModuleFromName(l.OriginalModuleName) + label := l // use the implementation by default + if depC, ok := dep.(*Module); ok && hasNdkStubs(ctx, depC) { + // If the dependency has ndk stubs, build against the ndk stubs + // https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=2642-2643;drc=e12d252e22dd8afa654325790d3298a0d67bd9d6;bpv=1;bpt=0 + ndkLibModule, _ := ctx.ModuleFromName(dep.Name() + ndkLibrarySuffix) + label = bazel.Label{ + Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs", + } + } + // add the ndk lib label to this axis + existingValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app") + existingValue.Append(bazel.MakeLabelList([]bazel.Label{label})) + dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue)) + } + } } func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {