Merge "CcApiLibrary Variants for LLNDK"

This commit is contained in:
Treehugger Robot
2022-11-09 02:36:26 +00:00
committed by Gerrit Code Review
5 changed files with 255 additions and 20 deletions

View File

@@ -2540,6 +2540,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
}
}
updateImportedLibraryDependency(ctx)
}
func BeginMutator(ctx android.BottomUpMutatorContext) {

View File

@@ -2597,11 +2597,12 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str
m := mctx.Module().(*Module)
isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary()
isImportedApiLibrary := m.isImportedApiLibrary()
modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
// A stubs or LLNDK stubs variant.
c := m.(*Module)
c.sanitize = nil

View File

@@ -15,6 +15,10 @@
package cc
import (
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/multitree"
)
@@ -26,6 +30,30 @@ func init() {
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
}
func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
m, ok := ctx.Module().(*Module)
if !ok {
return
}
apiLibrary, ok := m.linker.(*apiLibraryDecorator)
if !ok {
return
}
if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
// Add LLNDK dependencies
for _, variant := range apiLibrary.properties.Variants {
if variant == "llndk" {
variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
ctx.AddDependency(m, nil, variantName)
break
}
}
}
}
// 'cc_api_library' is a module type which is from the exported API surface
@@ -33,7 +61,8 @@ func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
// offer a link to the module that generates shared library object from the
// map file.
type apiLibraryProperties struct {
Src *string `android:"arch_variant"`
Src *string `android:"arch_variant"`
Variants []string
}
type apiLibraryDecorator struct {
@@ -55,11 +84,9 @@ func CcApiLibraryFactory() android.Module {
module.compiler = nil
module.linker = apiLibraryDecorator
module.installer = nil
module.library = apiLibraryDecorator
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
// Mark module as stub, so APEX would not include this stub in the package.
module.library.setBuildStubs(true)
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -91,12 +118,45 @@ func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
}
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
// Export headers as system include dirs if specified. Mostly for libc
if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
m, _ := ctx.Module().(*Module)
var in android.Path
if src := proptools.String(d.properties.Src); src != "" {
in = android.PathForModuleSrc(ctx, src)
}
// LLNDK variant
if m.UseVndk() && d.hasLLNDKStubs() {
apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
var mod android.Module
ctx.VisitDirectDeps(func(depMod android.Module) {
if depMod.Name() == apiVariantModule {
mod = depMod
}
})
if mod != nil {
variantMod, ok := mod.(*CcApiVariant)
if ok {
in = variantMod.Src()
// Copy LLDNK properties to cc_api_library module
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
variantMod.exportProperties.Export_headers...)
// Export headers as system include dirs if specified. Mostly for libc
if proptools.Bool(variantMod.exportProperties.Export_headers_as_system) {
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
}
}
}
}
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
@@ -107,13 +167,10 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
if d.properties.Src == nil {
ctx.PropertyErrorf("src", "src is a required property")
if in == nil {
ctx.PropertyErrorf("src", "Unable to locate source property")
return nil
}
// Skip the existence check of the stub prebuilt file.
// The file is not guaranteed to exist during Soong analysis.
// Build orchestrator will be responsible for creating a connected ninja graph.
in := android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), *d.properties.Src)
// Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
// The .so file itself has an order-only dependency on the headers contributed by this library.
@@ -143,6 +200,43 @@ func (d *apiLibraryDecorator) availableFor(what string) bool {
return true
}
func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
m, ok := ctx.Module().(*Module)
if !ok {
return nil
}
if d.hasLLNDKStubs() && m.UseVndk() {
// LLNDK libraries only need a single stubs variant.
return []string{android.FutureApiLevel.String()}
}
// TODO(b/244244438) Create more version information for NDK and APEX variations
// NDK variants
if m.MinSdkVersion() == "" {
return nil
}
firstVersion, err := nativeApiLevelFromUser(ctx,
m.MinSdkVersion())
if err != nil {
return nil
}
return ndkLibraryVersions(ctx, firstVersion)
}
func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
for _, variant := range d.properties.Variants {
if strings.Contains(variant, "llndk") {
return true
}
}
return false
}
// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
// header libraries. The module will replace any dependencies to existing
// original header libraries.
@@ -165,9 +259,6 @@ func CcApiHeadersFactory() android.Module {
module.linker = apiHeadersDecorator
module.installer = nil
// Mark module as stub, so APEX would not include this stub in the package.
module.library.setBuildStubs(true)
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -189,3 +280,91 @@ func (d *apiHeadersDecorator) availableFor(what string) bool {
// Stub from API surface should be available for any APEX.
return true
}
type ccApiexportProperties struct {
Src *string `android:"arch_variant"`
Variant *string
Version *string
}
type variantExporterProperties struct {
// Header directory or library to export
Export_headers []string
// Export all headers as system include
Export_headers_as_system *bool
}
type CcApiVariant struct {
android.ModuleBase
properties ccApiexportProperties
exportProperties variantExporterProperties
src android.Path
}
var _ android.Module = (*CcApiVariant)(nil)
var _ android.ImageInterface = (*CcApiVariant)(nil)
func CcApiVariantFactory() android.Module {
module := &CcApiVariant{}
module.AddProperties(&module.properties)
module.AddProperties(&module.exportProperties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
return module
}
func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// No need to build
if proptools.String(v.properties.Src) == "" {
ctx.PropertyErrorf("src", "src is a required property")
}
// Skip the existence check of the stub prebuilt file.
// The file is not guaranteed to exist during Soong analysis.
// Build orchestrator will be responsible for creating a connected ninja graph.
v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), proptools.String(v.properties.Src))
}
func (v *CcApiVariant) Name() string {
version := proptools.String(v.properties.Version)
return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
}
func (v *CcApiVariant) Src() android.Path {
return v.src
}
func BuildApiVariantName(baseName string, variant string, version string) string {
names := []string{baseName, variant}
if version != "" {
names = append(names, version)
}
return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
}
// Implement ImageInterface to generate image variants
func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
var variations []string
platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
if proptools.String(v.properties.Variant) == "llndk" {
variations = append(variations, VendorVariationPrefix+platformVndkVersion)
variations = append(variations, ProductVariationPrefix+platformVndkVersion)
}
return variations
}
func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}

View File

@@ -284,3 +284,54 @@ func TestExportDirFromStubLibrary(t *testing.T) {
// These header files are required for compiling the other API domain (vendor in this case)
android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
}
func TestApiLibraryWithLlndkVariant(t *testing.T) {
bp := `
cc_binary {
name: "binfoo",
vendor: true,
srcs: ["binfoo.cc"],
shared_libs: ["libbar"],
}
cc_api_library {
name: "libbar",
// TODO(b/244244438) Remove src property once all variants are implemented.
src: "libbar.so",
vendor_available: true,
variants: [
"llndk",
],
}
cc_api_variant {
name: "libbar",
variant: "llndk",
src: "libbar_llndk.so",
export_headers: ["libbar_llndk_include"]
}
api_imports {
name: "api_imports",
shared_libs: [
"libbar",
],
header_libs: [],
}
`
ctx := prepareForCcTest.RunTestWithBp(t, bp)
libfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
libFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", libFooLibFlags, "libbar_llndk.so")
libFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", libFooCFlags, "-Ilibbar_llndk_include")
}

View File

@@ -78,5 +78,7 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
}
case *snapshotModule:
ctx.CreateVariations("")
case *CcApiVariant:
ctx.CreateVariations("")
}
}