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
This commit is contained in:
2
cc/cc.go
2
cc/cc.go
@@ -2540,6 +2540,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||||||
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
|
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateImportedLibraryDependency(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BeginMutator(ctx android.BottomUpMutatorContext) {
|
func BeginMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
@@ -2597,11 +2597,12 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str
|
|||||||
m := mctx.Module().(*Module)
|
m := mctx.Module().(*Module)
|
||||||
isLLNDK := m.IsLlndk()
|
isLLNDK := m.IsLlndk()
|
||||||
isVendorPublicLibrary := m.IsVendorPublicLibrary()
|
isVendorPublicLibrary := m.IsVendorPublicLibrary()
|
||||||
|
isImportedApiLibrary := m.isImportedApiLibrary()
|
||||||
|
|
||||||
modules := mctx.CreateLocalVariations(variants...)
|
modules := mctx.CreateLocalVariations(variants...)
|
||||||
for i, m := range modules {
|
for i, m := range modules {
|
||||||
|
|
||||||
if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
|
if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
|
||||||
// A stubs or LLNDK stubs variant.
|
// A stubs or LLNDK stubs variant.
|
||||||
c := m.(*Module)
|
c := m.(*Module)
|
||||||
c.sanitize = nil
|
c.sanitize = nil
|
||||||
|
@@ -15,6 +15,10 @@
|
|||||||
package cc
|
package cc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/multitree"
|
"android/soong/multitree"
|
||||||
)
|
)
|
||||||
@@ -26,6 +30,30 @@ func init() {
|
|||||||
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
|
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
|
||||||
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
|
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
|
||||||
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
|
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
|
// 'cc_api_library' is a module type which is from the exported API surface
|
||||||
@@ -34,6 +62,7 @@ func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
|
|||||||
// map file.
|
// map file.
|
||||||
type apiLibraryProperties struct {
|
type apiLibraryProperties struct {
|
||||||
Src *string `android:"arch_variant"`
|
Src *string `android:"arch_variant"`
|
||||||
|
Variants []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiLibraryDecorator struct {
|
type apiLibraryDecorator struct {
|
||||||
@@ -55,11 +84,9 @@ func CcApiLibraryFactory() android.Module {
|
|||||||
module.compiler = nil
|
module.compiler = nil
|
||||||
module.linker = apiLibraryDecorator
|
module.linker = apiLibraryDecorator
|
||||||
module.installer = nil
|
module.installer = nil
|
||||||
|
module.library = apiLibraryDecorator
|
||||||
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
|
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
|
// Prevent default system libs (libc, libm, and libdl) from being linked
|
||||||
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
|
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
|
||||||
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
|
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
|
||||||
@@ -91,13 +118,46 @@ func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
|
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
|
||||||
|
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
|
// Export headers as system include dirs if specified. Mostly for libc
|
||||||
if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
|
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 = append(
|
||||||
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
|
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
|
||||||
d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
|
d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
|
||||||
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
|
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
|
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
|
||||||
d.exportIncludes(ctx)
|
d.exportIncludes(ctx)
|
||||||
@@ -107,13 +167,10 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
|
|||||||
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
|
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
|
||||||
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
|
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
|
||||||
|
|
||||||
if d.properties.Src == nil {
|
if in == nil {
|
||||||
ctx.PropertyErrorf("src", "src is a required property")
|
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)
|
// 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.
|
// 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
|
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
|
// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
|
||||||
// header libraries. The module will replace any dependencies to existing
|
// header libraries. The module will replace any dependencies to existing
|
||||||
// original header libraries.
|
// original header libraries.
|
||||||
@@ -165,9 +259,6 @@ func CcApiHeadersFactory() android.Module {
|
|||||||
module.linker = apiHeadersDecorator
|
module.linker = apiHeadersDecorator
|
||||||
module.installer = nil
|
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
|
// Prevent default system libs (libc, libm, and libdl) from being linked
|
||||||
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
|
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
|
||||||
apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
|
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.
|
// Stub from API surface should be available for any APEX.
|
||||||
return true
|
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) {
|
||||||
|
}
|
||||||
|
@@ -284,3 +284,54 @@ func TestExportDirFromStubLibrary(t *testing.T) {
|
|||||||
// These header files are required for compiling the other API domain (vendor in this case)
|
// 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")
|
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")
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user