diff --git a/bazel/configurability.go b/bazel/configurability.go index d01877dd5..29299e9b9 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -69,8 +69,8 @@ const ( productVariableBazelPackage = "//build/bazel/product_variables" - AndroidAndInApex = "android-in_apex" - AndroidAndNonApex = "android-non_apex" + AndroidAndInApex = "android-in_apex" + AndroidPlatform = "system" InApex = "in_apex" NonApex = "non_apex" @@ -202,7 +202,7 @@ var ( osAndInApexMap = map[string]string{ AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex", - AndroidAndNonApex: "//build/bazel/rules/apex:android-non_apex", + AndroidPlatform: "//build/bazel/rules/apex:system", osDarwin: "//build/bazel/platforms/os:darwin", osLinux: "//build/bazel/platforms/os:linux_glibc", osLinuxMusl: "//build/bazel/platforms/os:linux_musl", diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index e198a11b8..e127fd542 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -1941,7 +1941,7 @@ func TestPrettyPrintSelectMapEqualValues(t *testing.T) { libFooImplLabel := bazel.Label{ Label: ":libfoo.impl", } - lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.MakeLabelList([]bazel.Label{libFooImplLabel})) + lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList([]bazel.Label{libFooImplLabel})) lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{libFooImplLabel})) actual, _ := prettyPrintAttribute(lla, 0) android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual) diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 6d5fd7ec9..1b681efb0 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -3042,7 +3042,8 @@ cc_library { }`, ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{ "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"], + "//build/bazel/rules/apex:foo": ["@api_surfaces//module-libapi/current:barlib"], + "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:barlib"], "//conditions:default": [":barlib"], })`, "local_includes": `["."]`, @@ -3096,7 +3097,11 @@ cc_library { "//build/bazel/platforms/os:linux_glibc": [":quxlib"], "//build/bazel/platforms/os:linux_musl": [":quxlib"], "//build/bazel/platforms/os:windows": [":quxlib"], - "//build/bazel/rules/apex:android-in_apex": [ + "//build/bazel/rules/apex:foo": [ + "@api_surfaces//module-libapi/current:barlib", + "@api_surfaces//module-libapi/current:quxlib", + ], + "//build/bazel/rules/apex:system": [ "@api_surfaces//module-libapi/current:barlib", "@api_surfaces//module-libapi/current:quxlib", ], @@ -4139,44 +4144,34 @@ cc_library { name: "barlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, bazel_module: { bp2build_available: false }, + apex_available: ["//apex_available:platform",], } cc_library { name: "bazlib", stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] }, bazel_module: { bp2build_available: false }, + apex_available: ["//apex_available:platform",], } cc_library { name: "foo", shared_libs: ["barlib", "bazlib"], export_shared_lib_headers: ["bazlib"], apex_available: [ - "apex_available:platform", + "//apex_available:platform", ], }`, ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ - "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"], - "//conditions:default": [":barlib"], - })`, - "dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:bazlib"], - "//conditions:default": [":bazlib"], - })`, - "local_includes": `["."]`, - "tags": `["apex_available=apex_available:platform"]`, + "implementation_dynamic_deps": `[":barlib"]`, + "dynamic_deps": `[":bazlib"]`, + "local_includes": `["."]`, + "tags": `["apex_available=//apex_available:platform"]`, }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"], - "//conditions:default": [":barlib"], - })`, - "dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:bazlib"], - "//conditions:default": [":bazlib"], - })`, - "local_includes": `["."]`, - "tags": `["apex_available=apex_available:platform"]`, + "implementation_dynamic_deps": `[":barlib"]`, + "dynamic_deps": `[":bazlib"]`, + "local_includes": `["."]`, + "tags": `["apex_available=//apex_available:platform"]`, }), }, }) diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 47dff8a57..2ee9c99f9 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -609,7 +609,8 @@ cc_library_shared { ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"], + "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"], + "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"], "//conditions:default": [":a"], })`, "tags": `["apex_available=apex_b"]`, @@ -618,6 +619,64 @@ cc_library_shared { }) } +// Tests that library in apexfoo links against stubs of platform_lib and otherapex_lib +func TestCcLibrarySharedStubs_UseStubsFromMultipleApiDomains(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared stubs", + ModuleTypeUnderTest: "cc_library_shared", + ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "libplatform_stable", + stubs: { symbol_file: "libplatform_stable.map.txt", versions: ["28", "29", "current"] }, + apex_available: ["//apex_available:platform"], + bazel_module: { bp2build_available: false }, + include_build_directory: false, +} +cc_library_shared { + name: "libapexfoo_stable", + stubs: { symbol_file: "libapexfoo_stable.map.txt", versions: ["28", "29", "current"] }, + apex_available: ["apexfoo"], + bazel_module: { bp2build_available: false }, + include_build_directory: false, +} +cc_library_shared { + name: "libutils", + shared_libs: ["libplatform_stable", "libapexfoo_stable",], + apex_available: ["//apex_available:platform", "apexfoo", "apexbar"], + include_build_directory: false, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "libutils", AttrNameToString{ + "implementation_dynamic_deps": `select({ + "//build/bazel/rules/apex:apexbar": [ + "@api_surfaces//module-libapi/current:libplatform_stable", + "@api_surfaces//module-libapi/current:libapexfoo_stable", + ], + "//build/bazel/rules/apex:apexfoo": [ + "@api_surfaces//module-libapi/current:libplatform_stable", + ":libapexfoo_stable", + ], + "//build/bazel/rules/apex:system": [ + "@api_surfaces//module-libapi/current:libplatform_stable", + "@api_surfaces//module-libapi/current:libapexfoo_stable", + ], + "//conditions:default": [ + ":libplatform_stable", + ":libapexfoo_stable", + ], + })`, + "tags": `[ + "apex_available=//apex_available:platform", + "apex_available=apexfoo", + "apex_available=apexbar", + ]`, + }), + }, + }) +} + func TestCcLibrarySharedStubs_IgnorePlatformAvailable(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ Description: "cc_library_shared stubs", @@ -641,7 +700,8 @@ cc_library_shared { ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"], + "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"], + "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"], "//conditions:default": [":a"], })`, "tags": `[ @@ -653,6 +713,34 @@ cc_library_shared { }) } +func TestCcLibraryDoesNotDropStubDepIfNoVariationAcrossAxis(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library depeends on impl for all configurations", + ModuleTypeUnderTest: "cc_library_shared", + ModuleTypeUnderTestFactory: cc.LibrarySharedFactory, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "a", + stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] }, + bazel_module: { bp2build_available: false }, + apex_available: ["//apex_available:platform"], +} +cc_library_shared { + name: "b", + shared_libs: [":a"], + include_build_directory: false, + apex_available: ["//apex_available:platform"], +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ + "implementation_dynamic_deps": `[":a"]`, + "tags": `["apex_available=//apex_available:platform"]`, + }), + }, + }) +} + func TestCcLibrarySharedStubs_MultipleApexAvailable(t *testing.T) { runCcLibrarySharedTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library_shared", @@ -682,7 +770,7 @@ cc_library_shared { ExpectedBazelTargets: []string{ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"], + "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"], "//conditions:default": [":a"], })`, "tags": `[ diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index 948801486..2705aafe5 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -1504,6 +1504,7 @@ cc_library { versions: ["current"], }, bazel_module: { bp2build_available: false }, + apex_available: ["com.android.runtime"], } cc_library_static { @@ -1561,7 +1562,8 @@ cc_library_static { }), MakeBazelTarget("cc_library_static", "keep_with_stubs", AttrNameToString{ "implementation_dynamic_deps": `select({ - "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:libm"], + "//build/bazel/rules/apex:foo": ["@api_surfaces//module-libapi/current:libm"], + "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:libm"], "//conditions:default": [":libm"], })`, "system_dynamic_deps": `[]`, diff --git a/cc/bp2build.go b/cc/bp2build.go index ca8d60902..c42a7e8ba 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -1269,7 +1269,7 @@ func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName strin func inApexConfigSetting(apexAvailable string) string { if apexAvailable == android.AvailableToPlatform { - return bazel.AndroidAndNonApex + return bazel.AndroidPlatform } if apexAvailable == android.AvailableToAnyApex { return bazel.AndroidAndInApex @@ -1278,58 +1278,99 @@ func inApexConfigSetting(apexAvailable string) string { return "//build/bazel/rules/apex:" + apiDomain } +// Inputs to stub vs impl selection. +type stubSelectionInfo struct { + // Label of the implementation library (e.g. //bionic/libc:libc) + impl bazel.Label + // Axis containing the implementation library + axis bazel.ConfigurationAxis + // Axis key containing the implementation library + config string + // API domain of the apex + // For test apexes (test_com.android.foo), this will be the source apex (com.android.foo) + apiDomain string + // List of dep labels + dynamicDeps *bazel.LabelListAttribute + // Boolean value for determining if the dep is in the same api domain + // If false, the label will be rewritten to to the stub label + sameApiDomain bool +} + +func useStubOrImplInApexWithName(ssi stubSelectionInfo) { + lib := ssi.impl + if !ssi.sameApiDomain { + lib = bazel.Label{ + Label: apiSurfaceModuleLibCurrentPackage + strings.TrimPrefix(lib.OriginalModuleName, ":"), + } + } + // Create a select statement specific to this apex + inApexSelectValue := ssi.dynamicDeps.SelectValue(bazel.OsAndInApexAxis, inApexConfigSetting(ssi.apiDomain)) + (&inApexSelectValue).Append(bazel.MakeLabelList([]bazel.Label{lib})) + ssi.dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, inApexConfigSetting(ssi.apiDomain), bazel.FirstUniqueBazelLabelList(inApexSelectValue)) + // Delete the library from the common config for this apex + implDynamicDeps := ssi.dynamicDeps.SelectValue(ssi.axis, ssi.config) + implDynamicDeps = bazel.SubtractBazelLabelList(implDynamicDeps, bazel.MakeLabelList([]bazel.Label{ssi.impl})) + ssi.dynamicDeps.SetSelectValue(ssi.axis, ssi.config, implDynamicDeps) + if ssi.axis == bazel.NoConfigAxis { + // Set defaults. Defaults (i.e. host) should use impl and not stubs. + defaultSelectValue := ssi.dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey) + (&defaultSelectValue).Append(bazel.MakeLabelList([]bazel.Label{ssi.impl})) + ssi.dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue)) + } +} + func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) { - depsWithStubs := []bazel.Label{} - for _, l := range dynamicLibs.Includes { - dep, _ := ctx.ModuleFromName(l.OriginalModuleName) - if d, ok := dep.(*Module); ok && d.HasStubsVariants() { - depApexAvailable := d.ApexAvailable() - if !availableToSameApexes(apexAvailable, depApexAvailable) { - depsWithStubs = append(depsWithStubs, l) - } - } - } - if len(depsWithStubs) > 0 { - implDynamicDeps := bazel.SubtractBazelLabelList(dynamicLibs, bazel.MakeLabelList(depsWithStubs)) - dynamicDeps.SetSelectValue(axis, config, implDynamicDeps) - - stubLibLabels := []bazel.Label{} - for _, l := range depsWithStubs { - stubLabelInApiSurfaces := bazel.Label{ - Label: apiSurfaceModuleLibCurrentPackage + strings.TrimPrefix(l.OriginalModuleName, ":"), - } - stubLibLabels = append(stubLibLabels, stubLabelInApiSurfaces) - } - inApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex) - nonApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex) - defaultSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey) - nonApexDeps := depsWithStubs - if buildNonApexWithStubs { - nonApexDeps = stubLibLabels - } - if axis == bazel.NoConfigAxis { - (&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels)) - (&nonApexSelectValue).Append(bazel.MakeLabelList(nonApexDeps)) - (&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs)) - dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue)) - dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue)) - dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue)) - } else if config == bazel.OsAndroid { - (&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels)) - (&nonApexSelectValue).Append(bazel.MakeLabelList(nonApexDeps)) - dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue)) - dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue)) - } - } - // Create a config_setting for each apex_available. // This will be used to select impl of a dep if dep is available to the same apex. for _, aa := range apexAvailable { createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa) } + apiDomainForSelects := []string{} + for _, apex := range apexAvailable { + apiDomainForSelects = append(apiDomainForSelects, GetApiDomain(apex)) + } + // Always emit a select statement for the platform variant. + // This ensures that b build //foo --config=android works + // Soong always creates a platform variant even when the library might not be available to platform. + if !android.InList(android.AvailableToPlatform, apiDomainForSelects) { + apiDomainForSelects = append(apiDomainForSelects, android.AvailableToPlatform) + } + apiDomainForSelects = android.SortedUniqueStrings(apiDomainForSelects) + + // Create a select for each apex this library could be included in. + for _, l := range dynamicLibs.Includes { + dep, _ := ctx.ModuleFromName(l.OriginalModuleName) + if c, ok := dep.(*Module); !ok || !c.HasStubsVariants() { + continue + } + // TODO (b/280339069): Decrease the verbosity of the generated BUILD files + for _, apiDomain := range apiDomainForSelects { + var sameApiDomain bool + if apiDomain == android.AvailableToPlatform { + // Platform variants in Soong use equality of apex_available for stub/impl selection. + // https://cs.android.com/android/_/android/platform/build/soong/+/316b0158fe57ee7764235923e7c6f3d530da39c6:cc/cc.go;l=3393-3404;drc=176271a426496fa2688efe2b40d5c74340c63375;bpv=1;bpt=0 + // One of the factors behind this design choice is cc_test + // Tests only have a platform variant, and using equality of apex_available ensures + // that tests of an apex library gets its implementation and not stubs. + // TODO (b/280343104): Discuss if we can drop this special handling for platform variants. + sameApiDomain = availableToSameApexes(apexAvailable, dep.(*Module).ApexAvailable()) + } else { + sameApiDomain = android.InList(apiDomain, dep.(*Module).ApexAvailable()) + } + ssi := stubSelectionInfo{ + impl: l, + axis: axis, + config: config, + apiDomain: apiDomain, + dynamicDeps: dynamicDeps, + sameApiDomain: sameApiDomain, + } + useStubOrImplInApexWithName(ssi) + } + } } func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { @@ -1424,7 +1465,6 @@ func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) { la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove) la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, toRemove) - la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, toRemove) stubsToRemove := make([]bazel.Label, 0, len(la.usedSystemDynamicDepAsDynamicDep)) for _, lib := range toRemove.Includes { stubLabelInApiSurfaces := bazel.Label{ @@ -1432,7 +1472,12 @@ func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) { } stubsToRemove = append(stubsToRemove, stubLabelInApiSurfaces) } - la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.MakeLabelList(stubsToRemove)) + // system libraries (e.g. libc, libm, libdl) belong the com.android.runtime api domain + // dedupe the stubs of these libraries from the other api domains (platform, other_apexes...) + for _, aa := range ctx.Module().(*Module).ApexAvailable() { + la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, inApexConfigSetting(aa), bazel.MakeLabelList(stubsToRemove)) + } + la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList(stubsToRemove)) } la.deps.ResolveExcludes()