"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then `shared_libs: ["libfoo"]` is linked to the version 11 of the stub. This requires the author of `libfoo` to manually update the property whenever a new version is introduced. Otherwise, clients are not able to use the newly added APIs because the latest stub is for an old version. This change eliminates the need for manual updating. "current" version is always implicitly added to `stubs.versions`. It is added even when nothing is set on the property, if `stubs.symbol_file` is set. i.e. ``` cc_library { name: "libfoo", stubs: { symbol_file: "libfoo.map.txt", // no versions: [...] needed }, } cc_library { name: "a_client", shared_libs: ["libfoo"], apex_available: ["myapex"], min_sdk_version: "29", } apex { name: "myapex", native_shared_libraries: ["a_client"], min_sdk_version: "29", } ``` `a_client` links to the "current" stub of `libfoo` that has all symbols shown in the map file. Note that, above doesn't mean that the client has unlimited access to APIs that are introduced even after the min_sdk_version of the client (29 in this example). The use of such APIs still has to be guarded with `__builtin_available` check. Bug: N/A Test: m Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
This commit is contained in:
parent
fdaa5f7164
commit
d4a3a137ed
|
@ -23,6 +23,7 @@ import (
|
|||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
@ -815,7 +816,7 @@ func TestApexWithStubs(t *testing.T) {
|
|||
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
|
||||
|
||||
// Ensure that mylib is linking with the latest version of stubs for mylib2
|
||||
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so")
|
||||
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
|
||||
// ... and not linking to the non-stub (impl) variant of mylib2
|
||||
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
|
||||
|
||||
|
@ -1293,15 +1294,15 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
|
|||
name: "unspecified version links to the latest",
|
||||
minSdkVersion: "",
|
||||
apexVariant: "apex10000",
|
||||
shouldLink: "30",
|
||||
shouldNotLink: []string{"29"},
|
||||
shouldLink: "current",
|
||||
shouldNotLink: []string{"29", "30"},
|
||||
},
|
||||
{
|
||||
name: "always use the latest",
|
||||
minSdkVersion: "min_sdk_version: \"29\",",
|
||||
apexVariant: "apex29",
|
||||
shouldLink: "30",
|
||||
shouldNotLink: []string{"29"},
|
||||
shouldLink: "current",
|
||||
shouldNotLink: []string{"29", "30"},
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
|
@ -1368,7 +1369,11 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
|
|||
}
|
||||
|
||||
mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
|
||||
ensureContains(t, mylibCFlags, "__LIBBAR_API__="+tc.shouldLink)
|
||||
ver := tc.shouldLink
|
||||
if tc.shouldLink == "current" {
|
||||
ver = strconv.Itoa(android.FutureApiLevelInt)
|
||||
}
|
||||
ensureContains(t, mylibCFlags, "__LIBBAR_API__="+ver)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1430,12 +1435,12 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
|
|||
|
||||
// For dependency to libc
|
||||
// Ensure that mylib is linking with the latest version of stubs
|
||||
ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29/libc.so")
|
||||
ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
|
||||
// ... and not linking to the non-stub (impl) variant
|
||||
ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so")
|
||||
// ... Cflags from stub is correctly exported to mylib
|
||||
ensureContains(t, mylibCFlags, "__LIBC_API__=29")
|
||||
ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
|
||||
ensureContains(t, mylibCFlags, "__LIBC_API__=10000")
|
||||
ensureContains(t, mylibSharedCFlags, "__LIBC_API__=10000")
|
||||
|
||||
// For dependency to libm
|
||||
// Ensure that mylib is linking with the non-stub (impl) variant
|
||||
|
@ -1541,12 +1546,14 @@ func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T)
|
|||
}
|
||||
// platform liba is linked to non-stub version
|
||||
expectLink("liba", "shared", "libz", "shared")
|
||||
// liba in myapex is linked to #30
|
||||
expectLink("liba", "shared_apex29", "libz", "shared_30")
|
||||
// liba in myapex is linked to current
|
||||
expectLink("liba", "shared_apex29", "libz", "shared_current")
|
||||
expectNoLink("liba", "shared_apex29", "libz", "shared_30")
|
||||
expectNoLink("liba", "shared_apex29", "libz", "shared_28")
|
||||
expectNoLink("liba", "shared_apex29", "libz", "shared")
|
||||
// liba in otherapex is linked to #30
|
||||
expectLink("liba", "shared_apex30", "libz", "shared_30")
|
||||
// liba in otherapex is linked to current
|
||||
expectLink("liba", "shared_apex30", "libz", "shared_current")
|
||||
expectNoLink("liba", "shared_apex30", "libz", "shared_30")
|
||||
expectNoLink("liba", "shared_apex30", "libz", "shared_28")
|
||||
expectNoLink("liba", "shared_apex30", "libz", "shared")
|
||||
}
|
||||
|
@ -1597,7 +1604,8 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
|
|||
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
|
||||
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||
}
|
||||
expectLink("libx", "shared_apex10000", "libz", "shared_R")
|
||||
expectLink("libx", "shared_apex10000", "libz", "shared_current")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared_R")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared")
|
||||
}
|
||||
|
@ -1643,8 +1651,9 @@ func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
|
|||
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
|
||||
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||
}
|
||||
expectLink("libx", "shared_apex10000", "libz", "shared_2")
|
||||
expectLink("libx", "shared_apex10000", "libz", "shared_current")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared_2")
|
||||
expectNoLink("libx", "shared_apex10000", "libz", "shared")
|
||||
}
|
||||
|
||||
|
@ -1691,7 +1700,8 @@ func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
|
|||
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
|
||||
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||
}
|
||||
expectLink("libz", "shared", "libx", "shared_2")
|
||||
expectLink("libz", "shared", "libx", "shared_current")
|
||||
expectNoLink("libz", "shared", "libx", "shared_2")
|
||||
expectNoLink("libz", "shared", "libz", "shared_1")
|
||||
expectNoLink("libz", "shared", "libz", "shared")
|
||||
}
|
||||
|
@ -1738,7 +1748,7 @@ func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
|
|||
libFlags := ld.Args["libFlags"]
|
||||
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||
}
|
||||
expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_30")
|
||||
expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current")
|
||||
}
|
||||
|
||||
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
|
||||
|
@ -2086,7 +2096,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion
|
|||
private_key: "testkey.pem",
|
||||
}
|
||||
|
||||
// mylib in myapex will link to mylib2#30
|
||||
// mylib in myapex will link to mylib2#current
|
||||
// mylib in otherapex will link to mylib2(non-stub) in otherapex as well
|
||||
cc_library {
|
||||
name: "mylib",
|
||||
|
@ -2120,7 +2130,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion
|
|||
libFlags := ld.Args["libFlags"]
|
||||
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||
}
|
||||
expectLink("mylib", "shared_apex29", "mylib2", "shared_30")
|
||||
expectLink("mylib", "shared_apex29", "mylib2", "shared_current")
|
||||
expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
|
||||
}
|
||||
|
||||
|
@ -2188,10 +2198,10 @@ func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
|
|||
}
|
||||
`, withSAsActiveCodeNames)
|
||||
|
||||
// ensure libfoo is linked with "S" version of libbar stub
|
||||
// ensure libfoo is linked with current version of libbar stub
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
|
||||
libFlags := libfoo.Rule("ld").Args["libFlags"]
|
||||
ensureContains(t, libFlags, "android_arm64_armv8-a_shared_T/libbar.so")
|
||||
ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so")
|
||||
}
|
||||
|
||||
func TestFilesInSubDir(t *testing.T) {
|
||||
|
@ -7386,7 +7396,7 @@ func TestPrebuiltStubLibDep(t *testing.T) {
|
|||
t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries)
|
||||
}
|
||||
cflags := entry.mkEntries.EntryMap["LOCAL_EXPORT_CFLAGS"]
|
||||
expected := "-D__STUBLIB_API__=1"
|
||||
expected := "-D__STUBLIB_API__=10000"
|
||||
if !android.InList(expected, cflags) {
|
||||
t.Errorf("LOCAL_EXPORT_CFLAGS expected to have %q, but got %q", expected, cflags)
|
||||
}
|
||||
|
|
|
@ -2679,9 +2679,11 @@ func TestLlndkLibrary(t *testing.T) {
|
|||
expected := []string{
|
||||
"android_vendor.VER_arm64_armv8-a_shared_1",
|
||||
"android_vendor.VER_arm64_armv8-a_shared_2",
|
||||
"android_vendor.VER_arm64_armv8-a_shared_current",
|
||||
"android_vendor.VER_arm64_armv8-a_shared",
|
||||
"android_vendor.VER_arm_armv7-a-neon_shared_1",
|
||||
"android_vendor.VER_arm_armv7-a-neon_shared_2",
|
||||
"android_vendor.VER_arm_armv7-a-neon_shared_current",
|
||||
"android_vendor.VER_arm_armv7-a-neon_shared",
|
||||
}
|
||||
checkEquals(t, "variants for llndk stubs", expected, actual)
|
||||
|
@ -3181,10 +3183,12 @@ func TestVersionedStubs(t *testing.T) {
|
|||
"android_arm64_armv8-a_shared_1",
|
||||
"android_arm64_armv8-a_shared_2",
|
||||
"android_arm64_armv8-a_shared_3",
|
||||
"android_arm64_armv8-a_shared_current",
|
||||
"android_arm_armv7-a-neon_shared",
|
||||
"android_arm_armv7-a-neon_shared_1",
|
||||
"android_arm_armv7-a-neon_shared_2",
|
||||
"android_arm_armv7-a-neon_shared_3",
|
||||
"android_arm_armv7-a-neon_shared_current",
|
||||
}
|
||||
variantsMismatch := false
|
||||
if len(variants) != len(expectedVariants) {
|
||||
|
|
|
@ -64,7 +64,8 @@ type LibraryProperties struct {
|
|||
// symbols that are exported for stubs variant of this library.
|
||||
Symbol_file *string `android:"path"`
|
||||
|
||||
// List versions to generate stubs libs for.
|
||||
// List versions to generate stubs libs for. The version name "current" is always
|
||||
// implicitly added.
|
||||
Versions []string
|
||||
}
|
||||
|
||||
|
@ -170,6 +171,8 @@ type LibraryMutatedProperties struct {
|
|||
|
||||
// This variant is a stubs lib
|
||||
BuildStubs bool `blueprint:"mutated"`
|
||||
// This variant is the latest version
|
||||
IsLatestVersion bool `blueprint:"mutated"`
|
||||
// Version of the stubs lib
|
||||
StubsVersion string `blueprint:"mutated"`
|
||||
// List of all stubs versions associated with an implementation lib
|
||||
|
@ -777,7 +780,7 @@ type libraryInterface interface {
|
|||
|
||||
type versionedInterface interface {
|
||||
buildStubs() bool
|
||||
setBuildStubs()
|
||||
setBuildStubs(isLatest bool)
|
||||
hasStubsVariants() bool
|
||||
setStubsVersion(string)
|
||||
stubsVersion() string
|
||||
|
@ -1495,7 +1498,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) {
|
|||
if ctx.isVndk() && !ctx.IsVndkExt() {
|
||||
return
|
||||
}
|
||||
} else if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.directlyInAnyApex() {
|
||||
} else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() {
|
||||
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
|
||||
// The original path becomes a symlink to the corresponding file in the
|
||||
// runtime APEX.
|
||||
|
@ -1611,11 +1614,29 @@ func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *strin
|
|||
}
|
||||
|
||||
func (library *libraryDecorator) hasStubsVariants() bool {
|
||||
return len(library.Properties.Stubs.Versions) > 0
|
||||
// Just having stubs.symbol_file is enough to create a stub variant. In that case
|
||||
// the stub for the future API level is created.
|
||||
return library.Properties.Stubs.Symbol_file != nil ||
|
||||
len(library.Properties.Stubs.Versions) > 0
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
|
||||
return library.Properties.Stubs.Versions
|
||||
if !library.hasStubsVariants() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Future API level is implicitly added if there isn't
|
||||
vers := library.Properties.Stubs.Versions
|
||||
if inList(android.FutureApiLevel.String(), vers) {
|
||||
return vers
|
||||
}
|
||||
// In some cases, people use the raw value "10000" in the versions property.
|
||||
// We shouldn't add the future API level in that case, otherwise there will
|
||||
// be two identical versions.
|
||||
if inList(strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()), vers) {
|
||||
return vers
|
||||
}
|
||||
return append(vers, android.FutureApiLevel.String())
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) setStubsVersion(version string) {
|
||||
|
@ -1626,8 +1647,9 @@ func (library *libraryDecorator) stubsVersion() string {
|
|||
return library.MutatedProperties.StubsVersion
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) setBuildStubs() {
|
||||
func (library *libraryDecorator) setBuildStubs(isLatest bool) {
|
||||
library.MutatedProperties.BuildStubs = true
|
||||
library.MutatedProperties.IsLatestVersion = isLatest
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) setAllStubsVersions(versions []string) {
|
||||
|
@ -1639,8 +1661,7 @@ func (library *libraryDecorator) allStubsVersions() []string {
|
|||
}
|
||||
|
||||
func (library *libraryDecorator) isLatestStubVersion() bool {
|
||||
versions := library.Properties.Stubs.Versions
|
||||
return versions[len(versions)-1] == library.stubsVersion()
|
||||
return library.MutatedProperties.IsLatestVersion
|
||||
}
|
||||
|
||||
func (library *libraryDecorator) availableFor(what string) bool {
|
||||
|
@ -1883,7 +1904,8 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str
|
|||
c.stl = nil
|
||||
c.Properties.PreventInstall = true
|
||||
lib := moduleLibraryInterface(m)
|
||||
lib.setBuildStubs()
|
||||
isLatest := i == (len(versions) - 1)
|
||||
lib.setBuildStubs(isLatest)
|
||||
|
||||
if variants[i] != "" {
|
||||
// A non-LLNDK stubs module is hidden from make and has a dependency from the
|
||||
|
|
|
@ -2397,6 +2397,7 @@ cc_prebuilt_library_shared {
|
|||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"current",
|
||||
],
|
||||
},
|
||||
arch: {
|
||||
|
@ -2451,6 +2452,7 @@ cc_prebuilt_library_shared {
|
|||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"current",
|
||||
],
|
||||
},
|
||||
target: {
|
||||
|
@ -2490,6 +2492,7 @@ cc_prebuilt_library_shared {
|
|||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"current",
|
||||
],
|
||||
},
|
||||
target: {
|
||||
|
|
Loading…
Reference in New Issue