diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index bf3a6b5c6..6a3b3c82c 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -149,6 +149,7 @@ sharedLibraries = [] rootSharedLibraries = [] shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo" +stubs_tag = "//build/bazel/rules/cc:cc_stub_library.bzl%CcStubInfo" unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo" unstripped = "" @@ -160,6 +161,8 @@ if shared_info_tag in p: unstripped = path if unstripped_tag in p: unstripped = p[unstripped_tag].unstripped.path +elif stubs_tag in p: + rootSharedLibraries.extend([f.path for f in target.files.to_list()]) else: for linker_input in linker_inputs: for library in linker_input.libraries: diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 29316ab1e..f5d62c692 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -1291,3 +1291,66 @@ cc_library_shared{ }, }) } + +func TestCcLibrarySharedStubsDessertVersionConversion(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared converts dessert codename versions to numerical versions", + Blueprint: ` +cc_library_shared { + name: "a", + include_build_directory: false, + stubs: { + symbol_file: "a.map.txt", + versions: [ + "Q", + "R", + "31", + ], + }, +} +cc_library_shared { + name: "b", + include_build_directory: false, + stubs: { + symbol_file: "b.map.txt", + versions: [ + "Q", + "R", + "31", + "current", + ], + }, +} +`, + ExpectedBazelTargets: []string{ + makeCcStubSuiteTargets("a", AttrNameToString{ + "soname": `"a.so"`, + "source_library_label": `"//:a"`, + "stubs_symbol_file": `"a.map.txt"`, + "stubs_versions": `[ + "29", + "30", + "31", + "current", + ]`, + }), + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "stubs_symbol_file": `"a.map.txt"`, + }), + makeCcStubSuiteTargets("b", AttrNameToString{ + "soname": `"b.so"`, + "source_library_label": `"//:b"`, + "stubs_symbol_file": `"b.map.txt"`, + "stubs_versions": `[ + "29", + "30", + "31", + "current", + ]`, + }), + MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ + "stubs_symbol_file": `"b.map.txt"`, + }), + }, + }) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 96c478966..4e3953253 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -772,8 +772,13 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) if libraryProps, ok := archVariantLibraryProperties[axis][cfg].(*LibraryProperties); ok { if axis == bazel.NoConfigAxis { - compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file - compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, libraryProps.Stubs.Versions) + if libraryProps.Stubs.Symbol_file != nil { + compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file + versions := android.CopyOf(libraryProps.Stubs.Versions) + normalizeVersions(ctx, versions) + versions = addCurrentVersionIfNotPresent(versions) + compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, versions) + } } if suffix := libraryProps.Suffix; suffix != nil { compilerAttrs.suffix.SetSelectValue(axis, cfg, suffix) diff --git a/cc/cc.go b/cc/cc.go index 82cfe9079..c1a1020ad 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1976,6 +1976,17 @@ func (c *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) { c.maybeInstall(mctx, apexInfo) } +func moduleContextFromAndroidModuleContext(actx android.ModuleContext, c *Module) ModuleContext { + ctx := &moduleContext{ + ModuleContext: actx, + moduleContextImpl: moduleContextImpl{ + mod: c, + }, + } + ctx.ctx = ctx + return ctx +} + func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // Handle the case of a test module split by `test_per_src` mutator. // @@ -1995,13 +2006,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { c.makeLinkType = GetMakeLinkType(actx, c) - ctx := &moduleContext{ - ModuleContext: actx, - moduleContextImpl: moduleContextImpl{ - mod: c, - }, - } - ctx.ctx = ctx + ctx := moduleContextFromAndroidModuleContext(actx, c) deps := c.depsToPaths(ctx) if ctx.Failed() { diff --git a/cc/cc_test.go b/cc/cc_test.go index 830de40c0..ebe543eaf 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -3685,6 +3685,133 @@ func TestStubsForLibraryInMultipleApexes(t *testing.T) { } } +func TestMixedBuildUsesStubs(t *testing.T) { + // TODO(b/275313114): Test exposes non-determinism which should be corrected and the test + // reenabled. + t.Skip() + t.Parallel() + bp := ` + cc_library_shared { + name: "libFoo", + bazel_module: { label: "//:libFoo" }, + srcs: ["foo.c"], + stubs: { + symbol_file: "foo.map.txt", + versions: ["current"], + }, + apex_available: ["bar", "a1"], + } + + cc_library_shared { + name: "libBar", + srcs: ["bar.c"], + shared_libs: ["libFoo"], + apex_available: ["a1"], + } + + cc_library_shared { + name: "libA1", + srcs: ["a1.c"], + shared_libs: ["libFoo"], + apex_available: ["a1"], + } + + cc_library_shared { + name: "libBarA1", + srcs: ["bara1.c"], + shared_libs: ["libFoo"], + apex_available: ["bar", "a1"], + } + + cc_library_shared { + name: "libAnyApex", + srcs: ["anyApex.c"], + shared_libs: ["libFoo"], + apex_available: ["//apex_available:anyapex"], + } + + cc_library_shared { + name: "libBaz", + srcs: ["baz.c"], + shared_libs: ["libFoo"], + apex_available: ["baz"], + } + + cc_library_shared { + name: "libQux", + srcs: ["qux.c"], + shared_libs: ["libFoo"], + apex_available: ["qux", "bar"], + }` + + result := android.GroupFixturePreparers( + prepareForCcTest, + android.FixtureModifyConfig(func(config android.Config) { + config.BazelContext = android.MockBazelContext{ + OutputBaseDir: "out/bazel", + LabelToCcInfo: map[string]cquery.CcInfo{ + "//:libFoo": { + RootDynamicLibraries: []string{"libFoo.so"}, + }, + "//:libFoo_stub_libs-current": { + RootDynamicLibraries: []string{"libFoo_stub_libs-current.so"}, + }, + }, + } + }), + ).RunTestWithBp(t, bp) + ctx := result.TestContext + + variants := ctx.ModuleVariantsForTests("libFoo") + expectedVariants := []string{ + "android_arm64_armv8-a_shared", + "android_arm64_armv8-a_shared_current", + "android_arm_armv7-a-neon_shared", + "android_arm_armv7-a-neon_shared_current", + } + variantsMismatch := false + if len(variants) != len(expectedVariants) { + variantsMismatch = true + } else { + for _, v := range expectedVariants { + if !inList(v, variants) { + variantsMismatch = false + } + } + } + if variantsMismatch { + t.Errorf("variants of libFoo expected:\n") + for _, v := range expectedVariants { + t.Errorf("%q\n", v) + } + t.Errorf(", but got:\n") + for _, v := range variants { + t.Errorf("%q\n", v) + } + } + + linkAgainstFoo := []string{"libBarA1"} + linkAgainstFooStubs := []string{"libBar", "libA1", "libBaz", "libQux", "libAnyApex"} + + libFooPath := "out/bazel/execroot/__main__/libFoo.so" + for _, lib := range linkAgainstFoo { + libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld") + libFlags := libLinkRule.Args["libFlags"] + if !strings.Contains(libFlags, libFooPath) { + t.Errorf("%q: %q is not found in %q", lib, libFooPath, libFlags) + } + } + + libFooStubPath := "out/bazel/execroot/__main__/libFoo_stub_libs-current.so" + for _, lib := range linkAgainstFooStubs { + libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld") + libFlags := libLinkRule.Args["libFlags"] + if !strings.Contains(libFlags, libFooStubPath) { + t.Errorf("%q: %q is not found in %q", lib, libFooStubPath, libFlags) + } + } +} + func TestVersioningMacro(t *testing.T) { t.Parallel() for _, tc := range []struct{ moduleName, expected string }{ diff --git a/cc/library.go b/cc/library.go index 1daeeffc2..ee09389ca 100644 --- a/cc/library.go +++ b/cc/library.go @@ -936,9 +936,17 @@ func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx androi func (handler *ccLibraryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) { bazelCtx := ctx.Config().BazelContext bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx))) + if v := handler.module.library.stubsVersion(); v != "" { + stubsLabel := label + "_stub_libs-" + v + bazelCtx.QueueBazelRequest(stubsLabel, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx))) + } } func (handler *ccLibraryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) { + if v := handler.module.library.stubsVersion(); v != "" { + // if we are a stubs variant, just use the Bazel stubs target + label = label + "_stub_libs-" + v + } bazelCtx := ctx.Config().BazelContext ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx))) if err != nil { @@ -967,6 +975,9 @@ func (handler *ccLibraryBazelHandler) ProcessBazelQueryResponse(ctx android.Modu } handler.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo) + + cctx := moduleContextFromAndroidModuleContext(ctx, handler.module) + addStubDependencyProviders(cctx) } func (library *libraryDecorator) setFlagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) { @@ -1792,6 +1803,12 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, Target: ctx.Target(), }) + addStubDependencyProviders(ctx) + + return unstrippedOutputFile +} + +func addStubDependencyProviders(ctx ModuleContext) { stubs := ctx.GetDirectDepsWithTag(stubImplDepTag) if len(stubs) > 0 { var stubsInfo []SharedStubLibrary @@ -1806,12 +1823,9 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, } ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{ SharedStubLibraries: stubsInfo, - - IsLLNDK: ctx.IsLlndk(), + IsLLNDK: ctx.IsLlndk(), }) } - - return unstrippedOutputFile } func (library *libraryDecorator) unstrippedOutputFilePath() android.Path { @@ -2397,7 +2411,10 @@ func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) [ } // Future API level is implicitly added if there isn't - vers := library.Properties.Stubs.Versions + return addCurrentVersionIfNotPresent(library.Properties.Stubs.Versions) +} + +func addCurrentVersionIfNotPresent(vers []string) []string { if inList(android.FutureApiLevel.String(), vers) { return vers } @@ -2662,7 +2679,7 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { // normalizeVersions modifies `versions` in place, so that each raw version // string becomes its normalized canonical form. // Validates that the versions in `versions` are specified in least to greatest order. -func normalizeVersions(ctx android.BaseModuleContext, versions []string) { +func normalizeVersions(ctx android.BazelConversionPathContext, versions []string) { var previous android.ApiLevel for i, v := range versions { ver, err := android.ApiLevelFromUser(ctx, v)