CcApiLibrary Variants for LLNDK
Define CcApiLibrary Variants for LLNDK. Each variant will be defined as
below.
cc_api_variant {
name: "libc",
variant: "llndk",
arch: {
x86_64: {
src: "libs/x86_64/libc.so",
},
...
},
}
And CcApiLibrary will be marked to use this variant as below.
cc_api_library {
name: "libc",
...
variants: [
"llndk",
...
]
}
Soong will replace source of libc cc_api_library as src from
cc_api_variant during build time.
Bug: 244244438
Test: cf vendor build succeeded with LLNDK variants
Change-Id: I317ed1f558beb1f82f9f2d70811fa8f765bcad2b
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 760d36a..2fb21a3 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -15,6 +15,10 @@
package cc
import (
+ "strings"
+
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/multitree"
)
@@ -26,6 +30,30 @@
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 @@
// 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 @@
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) 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 @@
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 @@
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 @@
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 @@
// 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) {
+}