Merge "Apex: support codenames for min_sdk_version" into rvc-dev

This commit is contained in:
Jooyung Han 2020-04-05 00:14:37 +00:00 committed by Android (Google) Code Review
commit 95148f607e
6 changed files with 135 additions and 19 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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 {

View file

@ -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
} }

View file

@ -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)
}

View file

@ -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