Merge "Implement API surface import with APEX stub"
This commit is contained in:
commit
8972e4d6bb
6 changed files with 520 additions and 265 deletions
|
@ -9788,30 +9788,85 @@ func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
|
|||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
native_shared_libs: ["libbaz"],
|
||||
binaries: ["binfoo"],
|
||||
min_sdk_version: "29",
|
||||
}
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
}
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libc"],
|
||||
cc_binary {
|
||||
name: "binfoo",
|
||||
shared_libs: ["libbar", "libbaz", "libqux",],
|
||||
apex_available: ["myapex"],
|
||||
min_sdk_version: "29",
|
||||
recovery_available: false,
|
||||
}
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["libbar.cc"],
|
||||
stubs: {
|
||||
symbol_file: "libbar.map.txt",
|
||||
versions: [
|
||||
"29",
|
||||
],
|
||||
},
|
||||
}
|
||||
cc_library {
|
||||
name: "libbaz",
|
||||
srcs: ["libbaz.cc"],
|
||||
apex_available: ["myapex"],
|
||||
min_sdk_version: "29",
|
||||
stubs: {
|
||||
symbol_file: "libbaz.map.txt",
|
||||
versions: [
|
||||
"29",
|
||||
],
|
||||
},
|
||||
}
|
||||
cc_api_library {
|
||||
name: "libc",
|
||||
src: "libc.so",
|
||||
name: "libbar",
|
||||
src: "libbar_stub.so",
|
||||
min_sdk_version: "29",
|
||||
recovery_available: true,
|
||||
variants: ["apex.29"],
|
||||
}
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "apex",
|
||||
version: "29",
|
||||
src: "libbar_apex_29.so",
|
||||
}
|
||||
cc_api_library {
|
||||
name: "libbaz",
|
||||
src: "libbaz_stub.so",
|
||||
min_sdk_version: "29",
|
||||
variants: ["apex.29"],
|
||||
}
|
||||
cc_api_variant {
|
||||
name: "libbaz",
|
||||
variant: "apex",
|
||||
version: "29",
|
||||
src: "libbaz_apex_29.so",
|
||||
}
|
||||
cc_api_library {
|
||||
name: "libqux",
|
||||
src: "libqux_stub.so",
|
||||
min_sdk_version: "29",
|
||||
variants: ["apex.29"],
|
||||
}
|
||||
cc_api_variant {
|
||||
name: "libqux",
|
||||
variant: "apex",
|
||||
version: "29",
|
||||
src: "libqux_apex_29.so",
|
||||
}
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libc",
|
||||
apex_shared_libs: [
|
||||
"libbar",
|
||||
"libbaz",
|
||||
"libqux",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
result := testApex(t, bp)
|
||||
|
@ -9827,17 +9882,107 @@ func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
|
|||
return found
|
||||
}
|
||||
|
||||
libfooApexVariant := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex29").Module()
|
||||
libcApexVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared_apex29").Module()
|
||||
// Library defines stubs and cc_api_library should be used with cc_api_library
|
||||
binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Module()
|
||||
libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(libfooApexVariant, libcApexVariant))
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
|
||||
android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))
|
||||
|
||||
// libfoo core variant should be buildable in the same inner tree since
|
||||
// certain mcombo files might build system and apexes in the same inner tree
|
||||
// libfoo core variant should link against source libc
|
||||
libfooCoreVariant := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libcCoreVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
android.AssertBoolEquals(t, "core variant should link against source libc", true, hasDep(libfooCoreVariant, libcCoreVariant))
|
||||
binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Rule("ld").Args["libFlags"]
|
||||
android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")
|
||||
|
||||
// Library defined in the same APEX should be linked with original definition instead of cc_api_library
|
||||
libbazApexVariant := result.ModuleForTests("libbaz", "android_arm64_armv8-a_shared_apex29").Module()
|
||||
libbazApiImportCoreVariant := result.ModuleForTests("libbaz.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even from same APEX", true, hasDep(binfooApexVariant, libbazApiImportCoreVariant))
|
||||
android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbazApexVariant))
|
||||
|
||||
android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbaz.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbaz.apiimport.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbaz.apex.29.apiimport.so")
|
||||
|
||||
// cc_api_library defined without original library should be linked with cc_api_library
|
||||
libquxApiImportApexVariant := result.ModuleForTests("libqux.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even original library definition does not exist", true, hasDep(binfooApexVariant, libquxApiImportApexVariant))
|
||||
android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libqux.apex.29.apiimport.so")
|
||||
}
|
||||
|
||||
func TestPlatformBinaryBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
|
||||
bp := `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libbar"],
|
||||
min_sdk_version: "29",
|
||||
}
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
}
|
||||
cc_binary {
|
||||
name: "binfoo",
|
||||
shared_libs: ["libbar"],
|
||||
recovery_available: false,
|
||||
}
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["libbar.cc"],
|
||||
apex_available: ["myapex"],
|
||||
min_sdk_version: "29",
|
||||
stubs: {
|
||||
symbol_file: "libbar.map.txt",
|
||||
versions: [
|
||||
"29",
|
||||
],
|
||||
},
|
||||
}
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar_stub.so",
|
||||
variants: ["apex.29"],
|
||||
}
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "apex",
|
||||
version: "29",
|
||||
src: "libbar_apex_29.so",
|
||||
}
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
apex_shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
result := testApex(t, bp)
|
||||
|
||||
hasDep := func(m android.Module, wantDep android.Module) bool {
|
||||
t.Helper()
|
||||
var found bool
|
||||
result.VisitDirectDeps(m, func(dep blueprint.Module) {
|
||||
if dep == wantDep {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
// Library defines stubs and cc_api_library should be used with cc_api_library
|
||||
binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Module()
|
||||
libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
|
||||
android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))
|
||||
|
||||
binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
|
||||
android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
|
||||
android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")
|
||||
}
|
||||
|
||||
func TestTrimmedApex(t *testing.T) {
|
||||
|
|
231
cc/cc.go
231
cc/cc.go
|
@ -2416,6 +2416,27 @@ func rewriteLibsForApiImports(c LinkableInterface, libs []string, replaceList ma
|
|||
return nonVariantLibs, variantLibs
|
||||
}
|
||||
|
||||
func (c *Module) shouldUseApiSurface() bool {
|
||||
if c.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
|
||||
if GetImageVariantType(c) == vendorImageVariant || GetImageVariantType(c) == productImageVariant {
|
||||
// LLNDK Variant
|
||||
return true
|
||||
}
|
||||
|
||||
if c.Properties.IsSdkVariant {
|
||||
// NDK Variant
|
||||
return true
|
||||
}
|
||||
|
||||
if c.isImportedApiLibrary() {
|
||||
// API Library should depend on API headers
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
if !c.Enabled() {
|
||||
return
|
||||
|
@ -2435,7 +2456,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
apiNdkLibs := []string{}
|
||||
apiLateNdkLibs := []string{}
|
||||
|
||||
if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
|
||||
if c.shouldUseApiSurface() {
|
||||
deps.SharedLibs, apiNdkLibs = rewriteLibsForApiImports(c, deps.SharedLibs, apiImportInfo.SharedLibs, ctx.Config())
|
||||
deps.LateSharedLibs, apiLateNdkLibs = rewriteLibsForApiImports(c, deps.LateSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
|
||||
deps.SystemSharedLibs, _ = rewriteLibsForApiImports(c, deps.SystemSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
|
||||
|
@ -2466,7 +2487,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
}
|
||||
|
||||
// Check header lib replacement from API surface first, and then check again with VSDK
|
||||
if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
|
||||
if c.shouldUseApiSurface() {
|
||||
lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
|
||||
}
|
||||
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
|
||||
|
@ -2550,12 +2571,22 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
}
|
||||
|
||||
name, version := StubsLibNameAndVersion(lib)
|
||||
if apiLibraryName, ok := apiImportInfo.SharedLibs[name]; ok && !ctx.OtherModuleExists(name) {
|
||||
name = apiLibraryName
|
||||
}
|
||||
sharedLibNames = append(sharedLibNames, name)
|
||||
|
||||
variations := []blueprint.Variation{
|
||||
{Mutator: "link", Variation: "shared"},
|
||||
}
|
||||
AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
|
||||
|
||||
if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
|
||||
AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
|
||||
}
|
||||
|
||||
if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
|
||||
AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, apiLibraryName, version, false)
|
||||
}
|
||||
}
|
||||
|
||||
for _, lib := range deps.LateStaticLibs {
|
||||
|
@ -2898,10 +2929,58 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||
c.apexSdkVersion = findApexSdkVersion(ctx, apexInfo)
|
||||
|
||||
skipModuleList := map[string]bool{}
|
||||
|
||||
var apiImportInfo multitree.ApiImportInfo
|
||||
hasApiImportInfo := false
|
||||
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
if dep.Name() == "api_imports" {
|
||||
apiImportInfo = ctx.OtherModuleProvider(dep, multitree.ApiImportsProvider).(multitree.ApiImportInfo)
|
||||
hasApiImportInfo = true
|
||||
}
|
||||
})
|
||||
|
||||
if hasApiImportInfo {
|
||||
targetStubModuleList := map[string]string{}
|
||||
targetOrigModuleList := map[string]string{}
|
||||
|
||||
// Search for dependency which both original module and API imported library with APEX stub exists
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
depName := ctx.OtherModuleName(dep)
|
||||
if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
|
||||
targetStubModuleList[apiLibrary] = depName
|
||||
}
|
||||
})
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
depName := ctx.OtherModuleName(dep)
|
||||
if origLibrary, ok := targetStubModuleList[depName]; ok {
|
||||
targetOrigModuleList[origLibrary] = depName
|
||||
}
|
||||
})
|
||||
|
||||
// Decide which library should be used between original and API imported library
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
depName := ctx.OtherModuleName(dep)
|
||||
if apiLibrary, ok := targetOrigModuleList[depName]; ok {
|
||||
if shouldUseStubForApex(ctx, dep) {
|
||||
skipModuleList[depName] = true
|
||||
} else {
|
||||
skipModuleList[apiLibrary] = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||
depName := ctx.OtherModuleName(dep)
|
||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||
|
||||
if _, ok := skipModuleList[depName]; ok {
|
||||
// skip this module because original module or API imported module matching with this should be used instead.
|
||||
return
|
||||
}
|
||||
|
||||
if depTag == android.DarwinUniversalVariantTag {
|
||||
depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile()
|
||||
return
|
||||
|
@ -3237,21 +3316,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
return depPaths
|
||||
}
|
||||
|
||||
// ChooseStubOrImpl determines whether a given dependency should be redirected to the stub variant
|
||||
// of the dependency or not, and returns the SharedLibraryInfo and FlagExporterInfo for the right
|
||||
// dependency. The stub variant is selected when the dependency crosses a boundary where each side
|
||||
// has different level of updatability. For example, if a library foo in an APEX depends on a
|
||||
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
|
||||
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
|
||||
// same APEX as foo, the non-stub variant of bar is used.
|
||||
func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
|
||||
func shouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
|
||||
depName := ctx.OtherModuleName(dep)
|
||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||
libDepTag, ok := depTag.(libraryDependencyTag)
|
||||
if !ok || !libDepTag.shared() {
|
||||
panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
|
||||
}
|
||||
|
||||
thisModule, ok := ctx.Module().(android.ApexModule)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("Not an APEX module: %q", ctx.ModuleName()))
|
||||
|
@ -3266,62 +3332,93 @@ func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibr
|
|||
bootstrap = linkable.Bootstrap()
|
||||
}
|
||||
|
||||
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||
|
||||
useStubs := false
|
||||
|
||||
if lib := moduleLibraryInterface(dep); lib.buildStubs() && useVndk { // LLNDK
|
||||
if !apexInfo.IsForPlatform() {
|
||||
// For platform libraries, use current version of LLNDK
|
||||
// If this is for use_vendor apex we will apply the same rules
|
||||
// of apex sdk enforcement below to choose right version.
|
||||
useStubs = true
|
||||
}
|
||||
} else if apexInfo.IsForPlatform() || apexInfo.UsePlatformApis {
|
||||
// If not building for APEX or the containing APEX allows the use of
|
||||
// platform APIs, use stubs only when it is from an APEX (and not from
|
||||
// platform) However, for host, ramdisk, vendor_ramdisk, recovery or
|
||||
// bootstrap modules, always link to non-stub variant
|
||||
isNotInPlatform := dep.(android.ApexModule).NotInPlatform()
|
||||
|
||||
isApexImportedApiLibrary := false
|
||||
|
||||
if cc, ok := dep.(*Module); ok {
|
||||
if apiLibrary, ok := cc.linker.(*apiLibraryDecorator); ok {
|
||||
if apiLibrary.hasApexStubs() {
|
||||
isApexImportedApiLibrary = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useStubs = (isNotInPlatform || isApexImportedApiLibrary) && !bootstrap
|
||||
|
||||
if useStubs {
|
||||
// Another exception: if this module is a test for an APEX, then
|
||||
// it is linked with the non-stub variant of a module in the APEX
|
||||
// as if this is part of the APEX.
|
||||
testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
|
||||
for _, apexContents := range testFor.ApexContents {
|
||||
if apexContents.DirectlyInApex(depName) {
|
||||
useStubs = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if useStubs {
|
||||
// Yet another exception: If this module and the dependency are
|
||||
// available to the same APEXes then skip stubs between their
|
||||
// platform variants. This complements the test_for case above,
|
||||
// which avoids the stubs on a direct APEX library dependency, by
|
||||
// avoiding stubs for indirect test dependencies as well.
|
||||
//
|
||||
// TODO(b/183882457): This doesn't work if the two libraries have
|
||||
// only partially overlapping apex_available. For that test_for
|
||||
// modules would need to be split into APEX variants and resolved
|
||||
// separately for each APEX they have access to.
|
||||
if !isApexImportedApiLibrary && android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
|
||||
useStubs = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If building for APEX, use stubs when the parent is in any APEX that
|
||||
// the child is not in.
|
||||
useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
|
||||
}
|
||||
|
||||
return useStubs
|
||||
}
|
||||
|
||||
// ChooseStubOrImpl determines whether a given dependency should be redirected to the stub variant
|
||||
// of the dependency or not, and returns the SharedLibraryInfo and FlagExporterInfo for the right
|
||||
// dependency. The stub variant is selected when the dependency crosses a boundary where each side
|
||||
// has different level of updatability. For example, if a library foo in an APEX depends on a
|
||||
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
|
||||
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
|
||||
// same APEX as foo, the non-stub variant of bar is used.
|
||||
func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
|
||||
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||
libDepTag, ok := depTag.(libraryDependencyTag)
|
||||
if !ok || !libDepTag.shared() {
|
||||
panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
|
||||
}
|
||||
|
||||
sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
|
||||
depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
|
||||
sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)
|
||||
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||
|
||||
if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
|
||||
useStubs := false
|
||||
|
||||
if lib := moduleLibraryInterface(dep); lib.buildStubs() && useVndk { // LLNDK
|
||||
if !apexInfo.IsForPlatform() {
|
||||
// For platform libraries, use current version of LLNDK
|
||||
// If this is for use_vendor apex we will apply the same rules
|
||||
// of apex sdk enforcement below to choose right version.
|
||||
useStubs = true
|
||||
}
|
||||
} else if apexInfo.IsForPlatform() || apexInfo.UsePlatformApis {
|
||||
// If not building for APEX or the containing APEX allows the use of
|
||||
// platform APIs, use stubs only when it is from an APEX (and not from
|
||||
// platform) However, for host, ramdisk, vendor_ramdisk, recovery or
|
||||
// bootstrap modules, always link to non-stub variant
|
||||
useStubs = dep.(android.ApexModule).NotInPlatform() && !bootstrap
|
||||
if useStubs {
|
||||
// Another exception: if this module is a test for an APEX, then
|
||||
// it is linked with the non-stub variant of a module in the APEX
|
||||
// as if this is part of the APEX.
|
||||
testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
|
||||
for _, apexContents := range testFor.ApexContents {
|
||||
if apexContents.DirectlyInApex(depName) {
|
||||
useStubs = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if useStubs {
|
||||
// Yet another exception: If this module and the dependency are
|
||||
// available to the same APEXes then skip stubs between their
|
||||
// platform variants. This complements the test_for case above,
|
||||
// which avoids the stubs on a direct APEX library dependency, by
|
||||
// avoiding stubs for indirect test dependencies as well.
|
||||
//
|
||||
// TODO(b/183882457): This doesn't work if the two libraries have
|
||||
// only partially overlapping apex_available. For that test_for
|
||||
// modules would need to be split into APEX variants and resolved
|
||||
// separately for each APEX they have access to.
|
||||
if android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
|
||||
useStubs = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If building for APEX, use stubs when the parent is in any APEX that
|
||||
// the child is not in.
|
||||
useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
|
||||
}
|
||||
|
||||
// when to use (unspecified) stubs, use the latest one.
|
||||
if useStubs {
|
||||
if shouldUseStubForApex(ctx, dep) {
|
||||
stubs := sharedLibraryStubsInfo.SharedStubLibraries
|
||||
toUse := stubs[len(stubs)-1]
|
||||
sharedLibraryInfo = toUse.SharedLibraryInfo
|
||||
|
|
|
@ -23,7 +23,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
|
||||
ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
|
||||
stubVariantRegex = regexp.MustCompile("apex\\.([a-zA-Z0-9]+)")
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -60,6 +61,12 @@ func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
|
|||
variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
|
||||
ctx.AddDependency(m, nil, variantName)
|
||||
}
|
||||
} else if m.IsStubs() {
|
||||
targetVariant := "apex." + m.StubsVersion()
|
||||
if inList(targetVariant, apiLibrary.properties.Variants) {
|
||||
variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
|
||||
ctx.AddDependency(m, nil, variantName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,15 +160,15 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
|
|||
in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
|
||||
}
|
||||
|
||||
// LLNDK variant
|
||||
if m.UseVndk() && d.hasLLNDKStubs() {
|
||||
apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
|
||||
libName := m.BaseModuleName() + multitree.GetApiImportSuffix()
|
||||
|
||||
load_cc_variant := func(apiVariantModule string) {
|
||||
var mod android.Module
|
||||
|
||||
ctx.VisitDirectDeps(func(depMod android.Module) {
|
||||
if depMod.Name() == apiVariantModule {
|
||||
mod = depMod
|
||||
libName = apiVariantModule
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -184,37 +191,17 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m.UseVndk() && d.hasLLNDKStubs() {
|
||||
// LLNDK variant
|
||||
load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "llndk", ""))
|
||||
} else if m.IsSdkVariant() {
|
||||
// NDK Variant
|
||||
apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion())
|
||||
|
||||
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 NDK properties to cc_api_library module
|
||||
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
|
||||
d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
|
||||
variantMod.exportProperties.Export_include_dirs...)
|
||||
|
||||
// Export headers as system include dirs if specified. Mostly for libc
|
||||
if 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
|
||||
}
|
||||
}
|
||||
}
|
||||
load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion()))
|
||||
} else if m.IsStubs() {
|
||||
// APEX Variant
|
||||
load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "apex", m.StubsVersion()))
|
||||
}
|
||||
|
||||
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
|
||||
|
@ -237,20 +224,58 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
|
|||
d.libraryDecorator.flagExporter.setProvider(ctx)
|
||||
|
||||
d.unstrippedOutputFile = in
|
||||
libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
|
||||
libName += flags.Toolchain.ShlibSuffix()
|
||||
|
||||
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
||||
d.tocFile = android.OptionalPathForPath(tocFile)
|
||||
TransformSharedObjectToToc(ctx, in, tocFile)
|
||||
|
||||
outputFile := android.PathForModuleOut(ctx, libName)
|
||||
|
||||
// TODO(b/270485584) This copies with a new name, just to avoid conflict with prebuilts.
|
||||
// We can just use original input if there is any way to avoid name conflict without copy.
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Cp,
|
||||
Description: "API surface imported library",
|
||||
Input: in,
|
||||
Output: outputFile,
|
||||
Args: map[string]string{
|
||||
"cpFlags": "-L",
|
||||
},
|
||||
})
|
||||
|
||||
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
|
||||
SharedLibrary: in,
|
||||
SharedLibrary: outputFile,
|
||||
Target: ctx.Target(),
|
||||
|
||||
TableOfContents: d.tocFile,
|
||||
})
|
||||
|
||||
return in
|
||||
d.shareStubs(ctx)
|
||||
|
||||
return outputFile
|
||||
}
|
||||
|
||||
// Share additional information about stub libraries with provider
|
||||
func (d *apiLibraryDecorator) shareStubs(ctx ModuleContext) {
|
||||
stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
|
||||
if len(stubs) > 0 {
|
||||
var stubsInfo []SharedStubLibrary
|
||||
for _, stub := range stubs {
|
||||
stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
|
||||
flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
|
||||
stubsInfo = append(stubsInfo, SharedStubLibrary{
|
||||
Version: moduleLibraryInterface(stub).stubsVersion(),
|
||||
SharedLibraryInfo: stubInfo,
|
||||
FlagExporterInfo: flagInfo,
|
||||
})
|
||||
}
|
||||
ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
|
||||
SharedStubLibraries: stubsInfo,
|
||||
|
||||
IsLLNDK: ctx.IsLlndk(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) availableFor(what string) bool {
|
||||
|
@ -258,6 +283,19 @@ func (d *apiLibraryDecorator) availableFor(what string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) hasApexStubs() bool {
|
||||
for _, variant := range d.properties.Variants {
|
||||
if strings.HasPrefix(variant, "apex") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) hasStubsVariants() bool {
|
||||
return d.hasApexStubs()
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
|
||||
m, ok := ctx.Module().(*Module)
|
||||
|
||||
|
@ -265,14 +303,8 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st
|
|||
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.IsSdkVariant() {
|
||||
// TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
|
||||
if d.hasNDKStubs() {
|
||||
|
@ -280,6 +312,17 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st
|
|||
}
|
||||
}
|
||||
|
||||
if d.hasLLNDKStubs() && m.UseVndk() {
|
||||
// LLNDK libraries only need a single stubs variant.
|
||||
return []string{android.FutureApiLevel.String()}
|
||||
}
|
||||
|
||||
stubsVersions := d.getStubVersions()
|
||||
|
||||
if len(stubsVersions) != 0 {
|
||||
return stubsVersions
|
||||
}
|
||||
|
||||
if m.MinSdkVersion() == "" {
|
||||
return nil
|
||||
}
|
||||
|
@ -319,6 +362,18 @@ func (d *apiLibraryDecorator) getNdkVersions() []string {
|
|||
return ndkVersions
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) getStubVersions() []string {
|
||||
stubVersions := []string{}
|
||||
|
||||
for _, variant := range d.properties.Variants {
|
||||
if match := stubVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
|
||||
stubVersions = append(stubVersions, match[1])
|
||||
}
|
||||
}
|
||||
|
||||
return stubVersions
|
||||
}
|
||||
|
||||
// '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.
|
||||
|
@ -433,7 +488,7 @@ func BuildApiVariantName(baseName string, variant string, version string) string
|
|||
// Implement ImageInterface to generate image variants
|
||||
func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
|
||||
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
|
||||
return String(v.properties.Variant) == "ndk"
|
||||
return inList(String(v.properties.Variant), []string{"ndk", "apex"})
|
||||
}
|
||||
func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
|
||||
func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
|
||||
|
|
|
@ -41,6 +41,7 @@ func TestApiLibraryReplacesExistingModule(t *testing.T) {
|
|||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
vendor_available: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
|
@ -49,6 +50,7 @@ func TestApiLibraryReplacesExistingModule(t *testing.T) {
|
|||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
vendor_available: true,
|
||||
src: "libbar.so",
|
||||
}
|
||||
|
||||
|
@ -57,7 +59,6 @@ func TestApiLibraryReplacesExistingModule(t *testing.T) {
|
|||
shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -67,8 +68,14 @@ func TestApiLibraryReplacesExistingModule(t *testing.T) {
|
|||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbar))
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
android.AssertBoolEquals(t, "original library should be linked with non-stub variant", true, hasDirectDependency(t, ctx, libfoo, libbar))
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be not linked with non-stub variant", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
|
||||
libfooVendor := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
libbarApiImportVendor := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfooVendor, libbar))
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfooVendor, libbarApiImportVendor))
|
||||
}
|
||||
|
||||
func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
|
||||
|
@ -76,11 +83,13 @@ func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
|
|||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
vendor: true,
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar.so",
|
||||
vendor_available: true,
|
||||
}
|
||||
|
||||
api_imports {
|
||||
|
@ -88,14 +97,13 @@ func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
|
|||
shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
}
|
||||
|
@ -105,143 +113,36 @@ func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
|
|||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
vendor_available: true,
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
vendor_available: true,
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar.so",
|
||||
vendor_available: true,
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
libbar := ctx.ModuleForTests("libbar", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
}
|
||||
|
||||
func TestApiHeaderReplacesExistingModule(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
header_libs: ["libfoo_headers"],
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libfoo",
|
||||
header_libs: ["libfoo_headers"],
|
||||
src: "libfoo.so",
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libfoo_headers",
|
||||
}
|
||||
|
||||
cc_api_headers {
|
||||
name: "libfoo_headers",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libfoo",
|
||||
],
|
||||
header_libs: [
|
||||
"libfoo_headers",
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libfooApiImport := ctx.ModuleForTests("libfoo.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
|
||||
libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original header should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeader))
|
||||
android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
|
||||
android.AssertBoolEquals(t, "original header should not be used for library imported from API surface", false, hasDirectDependency(t, ctx, libfooApiImport, libfooHeader))
|
||||
android.AssertBoolEquals(t, "Header from API surface should be used for library imported from API surface", true, hasDirectDependency(t, ctx, libfooApiImport, libfooHeaderApiImport))
|
||||
}
|
||||
|
||||
func TestApiHeadersDoNotRequireOriginalModule(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
header_libs: ["libfoo_headers"],
|
||||
}
|
||||
|
||||
cc_api_headers {
|
||||
name: "libfoo_headers",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libfoo",
|
||||
],
|
||||
header_libs: [
|
||||
"libfoo_headers",
|
||||
],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
|
||||
}
|
||||
|
||||
func TestApiHeadersShouldNotReplaceWithoutApiImport(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
header_libs: ["libfoo_headers"],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libfoo_headers",
|
||||
}
|
||||
|
||||
cc_api_headers {
|
||||
name: "libfoo_headers",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libfoo",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
|
||||
libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
|
||||
android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
|
||||
}
|
||||
|
||||
func TestExportDirFromStubLibrary(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
|
@ -330,7 +231,7 @@ func TestApiLibraryWithLlndkVariant(t *testing.T) {
|
|||
android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
|
||||
|
||||
binFooLibFlags := 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", binFooLibFlags, "libbar_llndk.so")
|
||||
android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar.llndk.apiimport.so")
|
||||
|
||||
binFooCFlags := 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", binFooCFlags, "-Ilibbar_llndk_include")
|
||||
|
@ -354,6 +255,17 @@ func TestApiLibraryWithNdkVariant(t *testing.T) {
|
|||
stl: "c++_shared",
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "binqux",
|
||||
srcs: ["binfoo.cc"],
|
||||
shared_libs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["libbar.cc"],
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
// TODO(b/244244438) Remove src property once all variants are implemented.
|
||||
|
@ -417,10 +329,14 @@ func TestApiLibraryWithNdkVariant(t *testing.T) {
|
|||
android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
|
||||
|
||||
binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
|
||||
android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar_ndk_29.so")
|
||||
android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar.ndk.29.apiimport.so")
|
||||
|
||||
binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
|
||||
android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
|
||||
|
||||
binQux := ctx.ModuleForTests("binqux", "android_arm64_armv8-a").Module()
|
||||
android.AssertBoolEquals(t, "NDK Stub library from API surface should not be linked with nonSdk binary", false,
|
||||
(hasDirectDependency(t, ctx, binQux, libbarApiImportv30) || hasDirectDependency(t, ctx, binQux, libbarApiImportv29)))
|
||||
}
|
||||
|
||||
func TestApiLibraryWithMultipleVariants(t *testing.T) {
|
||||
|
@ -440,6 +356,11 @@ func TestApiLibraryWithMultipleVariants(t *testing.T) {
|
|||
shared_libs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["libbar.cc"],
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
// TODO(b/244244438) Remove src property once all variants are implemented.
|
||||
|
@ -450,6 +371,9 @@ func TestApiLibraryWithMultipleVariants(t *testing.T) {
|
|||
"ndk.29",
|
||||
"ndk.30",
|
||||
"ndk.current",
|
||||
"apex.29",
|
||||
"apex.30",
|
||||
"apex.current",
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -477,6 +401,30 @@ func TestApiLibraryWithMultipleVariants(t *testing.T) {
|
|||
export_include_dirs: ["libbar_ndk_current_include"]
|
||||
}
|
||||
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "apex",
|
||||
version: "29",
|
||||
src: "libbar_apex_29.so",
|
||||
export_include_dirs: ["libbar_apex_29_include"]
|
||||
}
|
||||
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "apex",
|
||||
version: "30",
|
||||
src: "libbar_apex_30.so",
|
||||
export_include_dirs: ["libbar_apex_30_include"]
|
||||
}
|
||||
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "apex",
|
||||
version: "current",
|
||||
src: "libbar_apex_current.so",
|
||||
export_include_dirs: ["libbar_apex_current_include"]
|
||||
}
|
||||
|
||||
cc_api_variant {
|
||||
name: "libbar",
|
||||
variant: "llndk",
|
||||
|
@ -489,7 +437,9 @@ func TestApiLibraryWithMultipleVariants(t *testing.T) {
|
|||
shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
header_libs: [],
|
||||
apex_shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
}
|
||||
`
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
|
23
cc/sdk.go
23
cc/sdk.go
|
@ -62,21 +62,26 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
|
|||
} else if isCcModule && ccModule.isImportedApiLibrary() {
|
||||
apiLibrary, _ := ccModule.linker.(*apiLibraryDecorator)
|
||||
if apiLibrary.hasNDKStubs() && ccModule.canUseSdk() {
|
||||
variations := []string{"sdk"}
|
||||
if apiLibrary.hasApexStubs() {
|
||||
variations = append(variations, "")
|
||||
}
|
||||
// Handle cc_api_library module with NDK stubs and variants only which can use SDK
|
||||
modules := ctx.CreateVariations("", "sdk")
|
||||
|
||||
modules := ctx.CreateVariations(variations...)
|
||||
// Mark the SDK variant.
|
||||
modules[1].(*Module).Properties.IsSdkVariant = true
|
||||
// SDK variant is not supposed to be installed
|
||||
modules[1].(*Module).Properties.PreventInstall = true
|
||||
|
||||
modules[0].(*Module).Properties.IsSdkVariant = true
|
||||
if ctx.Config().UnbundledBuildApps() {
|
||||
// For an unbundled apps build, hide the platform variant from Make.
|
||||
modules[0].(*Module).Properties.HideFromMake = true
|
||||
if apiLibrary.hasApexStubs() {
|
||||
// For an unbundled apps build, hide the platform variant from Make.
|
||||
modules[1].(*Module).Properties.HideFromMake = true
|
||||
modules[1].(*Module).Properties.PreventInstall = true
|
||||
}
|
||||
} else {
|
||||
// For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
|
||||
// exposed to Make.
|
||||
modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
|
||||
modules[0].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
|
||||
// SDK variant is not supposed to be installed
|
||||
modules[0].(*Module).Properties.PreventInstall = true
|
||||
}
|
||||
} else {
|
||||
ccModule.Properties.Sdk_version = nil
|
||||
|
|
|
@ -40,8 +40,9 @@ type ApiImports struct {
|
|||
}
|
||||
|
||||
type apiImportsProperties struct {
|
||||
Shared_libs []string // List of C shared libraries from API surfaces
|
||||
Header_libs []string // List of C header libraries from API surfaces
|
||||
Shared_libs []string // List of C shared libraries from API surfaces
|
||||
Header_libs []string // List of C header libraries from API surfaces
|
||||
Apex_shared_libs []string // List of C shared libraries with APEX stubs
|
||||
}
|
||||
|
||||
// 'api_imports' is a module which describes modules available from API surfaces.
|
||||
|
@ -60,7 +61,7 @@ func (imports *ApiImports) GenerateAndroidBuildActions(ctx android.ModuleContext
|
|||
}
|
||||
|
||||
type ApiImportInfo struct {
|
||||
SharedLibs, HeaderLibs map[string]string
|
||||
SharedLibs, HeaderLibs, ApexSharedLibs map[string]string
|
||||
}
|
||||
|
||||
var ApiImportsProvider = blueprint.NewMutatorProvider(ApiImportInfo{}, "deps")
|
||||
|
@ -78,10 +79,12 @@ func (imports *ApiImports) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|||
|
||||
sharedLibs := generateNameMapWithSuffix(imports.properties.Shared_libs)
|
||||
headerLibs := generateNameMapWithSuffix(imports.properties.Header_libs)
|
||||
apexSharedLibs := generateNameMapWithSuffix(imports.properties.Apex_shared_libs)
|
||||
|
||||
ctx.SetProvider(ApiImportsProvider, ApiImportInfo{
|
||||
SharedLibs: sharedLibs,
|
||||
HeaderLibs: headerLibs,
|
||||
SharedLibs: sharedLibs,
|
||||
HeaderLibs: headerLibs,
|
||||
ApexSharedLibs: apexSharedLibs,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue