Merge "Apex: support codenames for min_sdk_version" into rvc-dev
This commit is contained in:
commit
95148f607e
6 changed files with 135 additions and 19 deletions
|
@ -16,6 +16,7 @@ package android
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -84,14 +85,19 @@ func getApiLevelsMap(config Config) map[string]int {
|
||||||
// Converts an API level string into its numeric form.
|
// Converts an API level string into its numeric form.
|
||||||
// * Codenames are decoded.
|
// * Codenames are decoded.
|
||||||
// * Numeric API levels are simply converted.
|
// * Numeric API levels are simply converted.
|
||||||
// * "minimum" and "current" are not currently handled since the former is
|
// * "current" is mapped to FutureApiLevel(10000)
|
||||||
// NDK specific and the latter has inconsistent meaning.
|
// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go)
|
||||||
func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
|
func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
|
||||||
num, ok := getApiLevelsMap(ctx.Config())[apiLevel]
|
if apiLevel == "current" {
|
||||||
if ok {
|
return FutureApiLevel, nil
|
||||||
|
}
|
||||||
|
if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok {
|
||||||
return num, nil
|
return num, nil
|
||||||
}
|
}
|
||||||
return strconv.Atoi(apiLevel)
|
if num, err := strconv.Atoi(apiLevel); err == nil {
|
||||||
|
return num, nil
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("SDK version should be one of \"current\", <number> or <codename>: %q", apiLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
|
||||||
|
|
12
apex/apex.go
12
apex/apex.go
|
@ -19,7 +19,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
@ -1995,14 +1994,11 @@ func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
|
||||||
|
|
||||||
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
|
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
|
||||||
ver := proptools.StringDefault(a.properties.Min_sdk_version, "current")
|
ver := proptools.StringDefault(a.properties.Min_sdk_version, "current")
|
||||||
if ver != "current" {
|
intVer, err := android.ApiStrToNum(ctx, ver)
|
||||||
minSdkVersion, err := strconv.Atoi(ver)
|
if err != nil {
|
||||||
if err != nil {
|
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
|
||||||
ctx.PropertyErrorf("min_sdk_version", "should be \"current\" or <number>, but %q", ver)
|
|
||||||
}
|
|
||||||
return minSdkVersion
|
|
||||||
}
|
}
|
||||||
return android.FutureApiLevel
|
return intVer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that the dependencies are marked as available for this APEX
|
// Ensures that the dependencies are marked as available for this APEX
|
||||||
|
|
|
@ -1106,6 +1106,60 @@ func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
|
||||||
expectNoLink("liba", "shared_otherapex", "libz", "shared")
|
expectNoLink("liba", "shared_otherapex", "libz", "shared")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
|
||||||
|
ctx, _ := testApex(t, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["libx"],
|
||||||
|
min_sdk_version: "R",
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libx",
|
||||||
|
shared_libs: ["libz"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
apex_available: [ "myapex" ],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libz",
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
stubs: {
|
||||||
|
versions: ["29", "R"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`, func(fs map[string][]byte, config android.Config) {
|
||||||
|
config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
|
||||||
|
})
|
||||||
|
|
||||||
|
expectLink := func(from, from_variant, to, to_variant string) {
|
||||||
|
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
|
||||||
|
ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
|
||||||
|
}
|
||||||
|
expectNoLink := func(from, from_variant, to, to_variant string) {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
// 9000 is quite a magic number.
|
||||||
|
// Finalized SDK codenames are mapped as P(28), Q(29), ...
|
||||||
|
// And, codenames which are not finalized yet(active_codenames + future_codenames) are numbered from 9000, 9001, ...
|
||||||
|
// to distinguish them from finalized and future_api(10000)
|
||||||
|
// In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000
|
||||||
|
// (refer android/api_levels.go)
|
||||||
|
expectLink("libx", "shared_myapex", "libz", "shared_9000")
|
||||||
|
expectNoLink("libx", "shared_myapex", "libz", "shared_29")
|
||||||
|
expectNoLink("libx", "shared_myapex", "libz", "shared")
|
||||||
|
}
|
||||||
|
|
||||||
func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
|
func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
|
||||||
ctx, _ := testApex(t, `
|
ctx, _ := testApex(t, `
|
||||||
apex {
|
apex {
|
||||||
|
@ -1296,11 +1350,11 @@ func TestInvalidMinSdkVersion(t *testing.T) {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
testApexError(t, `"myapex" .*: min_sdk_version: should be "current" or <number>`, `
|
testApexError(t, `"myapex" .*: min_sdk_version: SDK version should be .*`, `
|
||||||
apex {
|
apex {
|
||||||
name: "myapex",
|
name: "myapex",
|
||||||
key: "myapex.key",
|
key: "myapex.key",
|
||||||
min_sdk_version: "R",
|
min_sdk_version: "abc",
|
||||||
}
|
}
|
||||||
|
|
||||||
apex_key {
|
apex_key {
|
||||||
|
|
|
@ -1455,18 +1455,22 @@ func LatestStubsVersionFor(config android.Config, name string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkVersions(ctx android.BaseModuleContext, versions []string) {
|
func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
|
||||||
numVersions := make([]int, len(versions))
|
numVersions := make([]int, len(versions))
|
||||||
for i, v := range versions {
|
for i, v := range versions {
|
||||||
numVer, err := strconv.Atoi(v)
|
numVer, err := android.ApiStrToNum(ctx, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.PropertyErrorf("versions", "%q is not a number", v)
|
ctx.PropertyErrorf("versions", "%s", err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
numVersions[i] = numVer
|
numVersions[i] = numVer
|
||||||
}
|
}
|
||||||
if !sort.IsSorted(sort.IntSlice(numVersions)) {
|
if !sort.IsSorted(sort.IntSlice(numVersions)) {
|
||||||
ctx.PropertyErrorf("versions", "not sorted: %v", versions)
|
ctx.PropertyErrorf("versions", "not sorted: %v", versions)
|
||||||
}
|
}
|
||||||
|
for i, v := range numVersions {
|
||||||
|
versions[i] = strconv.Itoa(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
|
func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
|
||||||
|
@ -1488,7 +1492,7 @@ func VersionMutator(mctx android.BottomUpMutatorContext) {
|
||||||
if library, ok := mctx.Module().(LinkableInterface); ok && !library.InRecovery() {
|
if library, ok := mctx.Module().(LinkableInterface); ok && !library.InRecovery() {
|
||||||
if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
|
if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 {
|
||||||
versions := library.StubsVersions()
|
versions := library.StubsVersions()
|
||||||
checkVersions(mctx, versions)
|
normalizeVersions(mctx, versions)
|
||||||
if mctx.Failed() {
|
if mctx.Failed() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ package cc
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLibraryReuse(t *testing.T) {
|
func TestLibraryReuse(t *testing.T) {
|
||||||
|
@ -186,3 +188,55 @@ func TestLibraryReuse(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStubsVersions(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
cc_library {
|
||||||
|
name: "libfoo",
|
||||||
|
srcs: ["foo.c"],
|
||||||
|
stubs: {
|
||||||
|
versions: ["29", "R", "10000"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`
|
||||||
|
config := TestConfig(buildDir, android.Android, nil, bp, nil)
|
||||||
|
config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
|
||||||
|
ctx := testCcWithConfig(t, config)
|
||||||
|
|
||||||
|
variants := ctx.ModuleVariantsForTests("libfoo")
|
||||||
|
for _, expectedVer := range []string{"29", "9000", "10000"} {
|
||||||
|
expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer
|
||||||
|
if !inList(expectedVariant, variants) {
|
||||||
|
t.Errorf("missing expected variant: %q", expectedVariant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStubsVersions_NotSorted(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
cc_library {
|
||||||
|
name: "libfoo",
|
||||||
|
srcs: ["foo.c"],
|
||||||
|
stubs: {
|
||||||
|
versions: ["29", "10000", "R"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`
|
||||||
|
config := TestConfig(buildDir, android.Android, nil, bp, nil)
|
||||||
|
config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
|
||||||
|
testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStubsVersions_ParseError(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
cc_library {
|
||||||
|
name: "libfoo",
|
||||||
|
srcs: ["foo.c"],
|
||||||
|
stubs: {
|
||||||
|
versions: ["29", "10000", "X"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
testCcError(t, `"libfoo" .*: versions: SDK version should be`, bp)
|
||||||
|
}
|
||||||
|
|
|
@ -96,6 +96,8 @@ type libraryProperties struct {
|
||||||
Unversioned_until *string
|
Unversioned_until *string
|
||||||
|
|
||||||
// Private property for use by the mutator that splits per-API level.
|
// Private property for use by the mutator that splits per-API level.
|
||||||
|
// can be one of <number:sdk_version> or <codename> or "current"
|
||||||
|
// passed to "gen_stub_libs.py" as it is
|
||||||
ApiLevel string `blueprint:"mutated"`
|
ApiLevel string `blueprint:"mutated"`
|
||||||
|
|
||||||
// True if this API is not yet ready to be shipped in the NDK. It will be
|
// True if this API is not yet ready to be shipped in the NDK. It will be
|
||||||
|
|
Loading…
Reference in a new issue