Abstract sdk_version string using sdkSpec type
The value format that sdk_version (and min_sdk_version, etc.) can have has consistently evolved and is quite complicated. Furthermore, with the Mainline module effort, we are expected to have more sdk_versions like 'module-app-current', 'module-lib-current', etc. The goal of this change is to abstract the various sdk versions, which are currently represented in string and is parsed in various places, into a type called sdkSpec, so that adding new sdk veresions becomes easier than before. The sdk_version string is now parsed in only one place 'SdkSpecFrom', in which it is converted into the sdkSpec struct. The struct type provides several methods that again converts sdkSpec into context-specific information such as the effective version number, etc. Bug: 146757305 Bug: 147879031 Test: m Change-Id: I252f3706544f00ea71c61c23460f07561dd28ab0
This commit is contained in:
parent
cf0bba7a30
commit
6a927c4e6a
|
@ -33,7 +33,8 @@ import (
|
|||
|
||||
var Bool = proptools.Bool
|
||||
var String = proptools.String
|
||||
var FutureApiLevel = 10000
|
||||
|
||||
const FutureApiLevel = 10000
|
||||
|
||||
// The configuration file name
|
||||
const configFileName = "soong.config"
|
||||
|
|
15
java/aar.go
15
java/aar.go
|
@ -177,7 +177,10 @@ func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
|
|||
linkDeps = append(linkDeps, assetFiles...)
|
||||
|
||||
// SDK version flags
|
||||
minSdkVersion := sdkVersionOrDefault(ctx, sdkContext.minSdkVersion())
|
||||
minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
|
||||
}
|
||||
|
||||
linkFlags = append(linkFlags, "--min-sdk-version "+minSdkVersion)
|
||||
linkFlags = append(linkFlags, "--target-sdk-version "+minSdkVersion)
|
||||
|
@ -524,22 +527,22 @@ type AARImport struct {
|
|||
exportedStaticPackages android.Paths
|
||||
}
|
||||
|
||||
func (a *AARImport) sdkVersion() string {
|
||||
return String(a.properties.Sdk_version)
|
||||
func (a *AARImport) sdkVersion() sdkSpec {
|
||||
return sdkSpecFrom(String(a.properties.Sdk_version))
|
||||
}
|
||||
|
||||
func (a *AARImport) systemModules() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *AARImport) minSdkVersion() string {
|
||||
func (a *AARImport) minSdkVersion() sdkSpec {
|
||||
if a.properties.Min_sdk_version != nil {
|
||||
return *a.properties.Min_sdk_version
|
||||
return sdkSpecFrom(*a.properties.Min_sdk_version)
|
||||
}
|
||||
return a.sdkVersion()
|
||||
}
|
||||
|
||||
func (a *AARImport) targetSdkVersion() string {
|
||||
func (a *AARImport) targetSdkVersion() sdkSpec {
|
||||
return a.sdkVersion()
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
|
|||
if isLibrary {
|
||||
args = append(args, "--library")
|
||||
} else {
|
||||
minSdkVersion, err := sdkVersionToNumber(ctx, sdkContext.minSdkVersion())
|
||||
minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersion(ctx)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
|
||||
}
|
||||
|
@ -92,15 +92,28 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
|
|||
}
|
||||
|
||||
var deps android.Paths
|
||||
targetSdkVersion := sdkVersionOrDefault(ctx, sdkContext.targetSdkVersion())
|
||||
minSdkVersion := sdkVersionOrDefault(ctx, sdkContext.minSdkVersion())
|
||||
if (UseApiFingerprint(ctx, sdkContext.targetSdkVersion()) ||
|
||||
UseApiFingerprint(ctx, sdkContext.minSdkVersion())) {
|
||||
apiFingerprint := ApiFingerprintPath(ctx)
|
||||
deps = append(deps, apiFingerprint)
|
||||
targetSdkVersion, err := sdkContext.targetSdkVersion().effectiveVersionString(ctx)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
|
||||
}
|
||||
if UseApiFingerprint(ctx, targetSdkVersion) {
|
||||
targetSdkVersion += fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
|
||||
deps = append(deps, ApiFingerprintPath(ctx))
|
||||
}
|
||||
|
||||
minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
|
||||
}
|
||||
if UseApiFingerprint(ctx, minSdkVersion) {
|
||||
minSdkVersion += fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
|
||||
deps = append(deps, ApiFingerprintPath(ctx))
|
||||
}
|
||||
|
||||
fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
|
||||
}
|
||||
ctx.Build(pctx, android.BuildParams{
|
||||
Rule: manifestFixerRule,
|
||||
Description: "fix manifest",
|
||||
|
|
|
@ -93,7 +93,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
if len(library.dexpreopter.builtInstalled) > 0 {
|
||||
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
|
||||
}
|
||||
entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion())
|
||||
entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion().raw)
|
||||
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
|
||||
entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
|
||||
|
||||
|
@ -174,7 +174,7 @@ func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
|
||||
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
|
||||
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
|
||||
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion())
|
||||
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw)
|
||||
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
|
||||
},
|
||||
},
|
||||
|
@ -223,7 +223,7 @@ func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
|
||||
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
|
||||
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
|
||||
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion())
|
||||
entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw)
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
|
14
java/app.go
14
java/app.go
|
@ -164,7 +164,7 @@ type Certificate struct {
|
|||
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
a.Module.deps(ctx)
|
||||
|
||||
if String(a.appProperties.Stl) == "c++_shared" && a.sdkVersion() == "" {
|
||||
if String(a.appProperties.Stl) == "c++_shared" && !a.sdkVersion().specified() {
|
||||
ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
// Returns true if the native libraries should be stored in the APK uncompressed and the
|
||||
// extractNativeLibs application flag should be set to false in the manifest.
|
||||
func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
|
||||
minSdkVersion, err := sdkVersionToNumber(ctx, a.minSdkVersion())
|
||||
minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx)
|
||||
if err != nil {
|
||||
ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
|
||||
}
|
||||
|
@ -1273,22 +1273,22 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
|
|||
ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile)
|
||||
}
|
||||
|
||||
func (r *RuntimeResourceOverlay) sdkVersion() string {
|
||||
return String(r.properties.Sdk_version)
|
||||
func (r *RuntimeResourceOverlay) sdkVersion() sdkSpec {
|
||||
return sdkSpecFrom(String(r.properties.Sdk_version))
|
||||
}
|
||||
|
||||
func (r *RuntimeResourceOverlay) systemModules() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *RuntimeResourceOverlay) minSdkVersion() string {
|
||||
func (r *RuntimeResourceOverlay) minSdkVersion() sdkSpec {
|
||||
if r.properties.Min_sdk_version != nil {
|
||||
return *r.properties.Min_sdk_version
|
||||
return sdkSpecFrom(*r.properties.Min_sdk_version)
|
||||
}
|
||||
return r.sdkVersion()
|
||||
}
|
||||
|
||||
func (r *RuntimeResourceOverlay) targetSdkVersion() string {
|
||||
func (r *RuntimeResourceOverlay) targetSdkVersion() sdkSpec {
|
||||
return r.sdkVersion()
|
||||
}
|
||||
|
||||
|
|
|
@ -73,12 +73,12 @@ func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
|
|||
"--verbose")
|
||||
}
|
||||
|
||||
minSdkVersion, err := sdkVersionToNumberAsString(ctx, j.minSdkVersion())
|
||||
minSdkVersion, err := j.minSdkVersion().effectiveVersion(ctx)
|
||||
if err != nil {
|
||||
ctx.PropertyErrorf("min_sdk_version", "%s", err)
|
||||
}
|
||||
|
||||
flags = append(flags, "--min-api "+minSdkVersion)
|
||||
flags = append(flags, "--min-api "+minSdkVersion.asNumberString())
|
||||
return flags
|
||||
}
|
||||
|
||||
|
|
|
@ -424,19 +424,19 @@ func JavadocHostFactory() android.Module {
|
|||
|
||||
var _ android.OutputFileProducer = (*Javadoc)(nil)
|
||||
|
||||
func (j *Javadoc) sdkVersion() string {
|
||||
return String(j.properties.Sdk_version)
|
||||
func (j *Javadoc) sdkVersion() sdkSpec {
|
||||
return sdkSpecFrom(String(j.properties.Sdk_version))
|
||||
}
|
||||
|
||||
func (j *Javadoc) systemModules() string {
|
||||
return proptools.String(j.properties.System_modules)
|
||||
}
|
||||
|
||||
func (j *Javadoc) minSdkVersion() string {
|
||||
func (j *Javadoc) minSdkVersion() sdkSpec {
|
||||
return j.sdkVersion()
|
||||
}
|
||||
|
||||
func (j *Javadoc) targetSdkVersion() string {
|
||||
func (j *Javadoc) targetSdkVersion() sdkSpec {
|
||||
return j.sdkVersion()
|
||||
}
|
||||
|
||||
|
|
64
java/java.go
64
java/java.go
|
@ -90,7 +90,7 @@ func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
|
|||
if j.SocSpecific() || j.DeviceSpecific() ||
|
||||
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
|
||||
if sc, ok := ctx.Module().(sdkContext); ok {
|
||||
if sc.sdkVersion() == "" {
|
||||
if !sc.sdkVersion().specified() {
|
||||
ctx.PropertyErrorf("sdk_version",
|
||||
"sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
|
||||
}
|
||||
|
@ -101,12 +101,11 @@ func (j *Module) checkSdkVersion(ctx android.ModuleContext) {
|
|||
func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
|
||||
if sc, ok := ctx.Module().(sdkContext); ok {
|
||||
usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
|
||||
if usePlatformAPI != (sc.sdkVersion() == "") {
|
||||
if usePlatformAPI {
|
||||
ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
|
||||
} else {
|
||||
ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
|
||||
}
|
||||
sdkVersionSpecified := sc.sdkVersion().specified()
|
||||
if usePlatformAPI && sdkVersionSpecified {
|
||||
ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
|
||||
} else if !usePlatformAPI && !sdkVersionSpecified {
|
||||
ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -455,8 +454,8 @@ type Dependency interface {
|
|||
}
|
||||
|
||||
type SdkLibraryDependency interface {
|
||||
SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths
|
||||
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths
|
||||
SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
|
||||
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
|
||||
}
|
||||
|
||||
type xref interface {
|
||||
|
@ -557,24 +556,24 @@ func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
|
|||
ctx.Config().UnbundledBuild())
|
||||
}
|
||||
|
||||
func (j *Module) sdkVersion() string {
|
||||
return String(j.deviceProperties.Sdk_version)
|
||||
func (j *Module) sdkVersion() sdkSpec {
|
||||
return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
|
||||
}
|
||||
|
||||
func (j *Module) systemModules() string {
|
||||
return proptools.String(j.deviceProperties.System_modules)
|
||||
}
|
||||
|
||||
func (j *Module) minSdkVersion() string {
|
||||
func (j *Module) minSdkVersion() sdkSpec {
|
||||
if j.deviceProperties.Min_sdk_version != nil {
|
||||
return *j.deviceProperties.Min_sdk_version
|
||||
return sdkSpecFrom(*j.deviceProperties.Min_sdk_version)
|
||||
}
|
||||
return j.sdkVersion()
|
||||
}
|
||||
|
||||
func (j *Module) targetSdkVersion() string {
|
||||
func (j *Module) targetSdkVersion() sdkSpec {
|
||||
if j.deviceProperties.Target_sdk_version != nil {
|
||||
return *j.deviceProperties.Target_sdk_version
|
||||
return sdkSpecFrom(*j.deviceProperties.Target_sdk_version)
|
||||
}
|
||||
return j.sdkVersion()
|
||||
}
|
||||
|
@ -780,26 +779,25 @@ func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
|
|||
name == "stub-annotations" || name == "private-stub-annotations-jar" ||
|
||||
name == "core-lambda-stubs" || name == "core-generated-annotation-stubs":
|
||||
return javaCore, true
|
||||
case ver == "core_current":
|
||||
case ver.kind == sdkCore:
|
||||
return javaCore, false
|
||||
case name == "android_system_stubs_current":
|
||||
return javaSystem, true
|
||||
case strings.HasPrefix(ver, "system_"):
|
||||
case ver.kind == sdkSystem:
|
||||
return javaSystem, false
|
||||
case name == "android_test_stubs_current":
|
||||
return javaSystem, true
|
||||
case strings.HasPrefix(ver, "test_"):
|
||||
case ver.kind == sdkTest:
|
||||
return javaPlatform, false
|
||||
case name == "android_stubs_current":
|
||||
return javaSdk, true
|
||||
case ver == "current":
|
||||
case ver.kind == sdkPublic:
|
||||
return javaSdk, false
|
||||
case ver == "" || ver == "none" || ver == "core_platform":
|
||||
case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
|
||||
return javaPlatform, false
|
||||
case !ver.valid():
|
||||
panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
|
||||
default:
|
||||
if _, err := strconv.Atoi(ver); err != nil {
|
||||
panic(fmt.Errorf("expected sdk_version to be a number, got %q", ver))
|
||||
}
|
||||
return javaSdk, false
|
||||
}
|
||||
}
|
||||
|
@ -996,19 +994,7 @@ func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) {
|
|||
}
|
||||
|
||||
func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion {
|
||||
v := sdkContext.sdkVersion()
|
||||
// For PDK builds, use the latest SDK version instead of "current"
|
||||
if ctx.Config().IsPdkBuild() &&
|
||||
(v == "" || v == "none" || v == "core_platform" || v == "current") {
|
||||
sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
|
||||
latestSdkVersion := 0
|
||||
if len(sdkVersions) > 0 {
|
||||
latestSdkVersion = sdkVersions[len(sdkVersions)-1]
|
||||
}
|
||||
v = strconv.Itoa(latestSdkVersion)
|
||||
}
|
||||
|
||||
sdk, err := sdkVersionToNumber(ctx, v)
|
||||
sdk, err := sdkContext.sdkVersion().effectiveVersion(ctx)
|
||||
if err != nil {
|
||||
ctx.PropertyErrorf("sdk_version", "%s", err)
|
||||
}
|
||||
|
@ -2297,11 +2283,11 @@ type Import struct {
|
|||
exportedSdkLibs []string
|
||||
}
|
||||
|
||||
func (j *Import) sdkVersion() string {
|
||||
return String(j.properties.Sdk_version)
|
||||
func (j *Import) sdkVersion() sdkSpec {
|
||||
return sdkSpecFrom(String(j.properties.Sdk_version))
|
||||
}
|
||||
|
||||
func (j *Import) minSdkVersion() string {
|
||||
func (j *Import) minSdkVersion() sdkSpec {
|
||||
return j.sdkVersion()
|
||||
}
|
||||
|
||||
|
|
325
java/sdk.go
325
java/sdk.go
|
@ -38,14 +38,16 @@ var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
|
|||
var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
|
||||
|
||||
type sdkContext interface {
|
||||
// sdkVersion returns the sdk_version property of the current module, or an empty string if it is not set.
|
||||
sdkVersion() string
|
||||
// sdkVersion returns sdkSpec that corresponds to the sdk_version property of the current module
|
||||
sdkVersion() sdkSpec
|
||||
// systemModules returns the system_modules property of the current module, or an empty string if it is not set.
|
||||
systemModules() string
|
||||
// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
|
||||
minSdkVersion() string
|
||||
// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
|
||||
targetSdkVersion() string
|
||||
// minSdkVersion returns sdkSpec that corresponds to the min_sdk_version property of the current module,
|
||||
// or from sdk_version if it is not set.
|
||||
minSdkVersion() sdkSpec
|
||||
// targetSdkVersion returns the sdkSpec that corresponds to the target_sdk_version property of the current module,
|
||||
// or from sdk_version if it is not set.
|
||||
targetSdkVersion() sdkSpec
|
||||
}
|
||||
|
||||
func UseApiFingerprint(ctx android.BaseModuleContext, v string) bool {
|
||||
|
@ -58,79 +60,236 @@ func UseApiFingerprint(ctx android.BaseModuleContext, v string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func sdkVersionOrDefault(ctx android.BaseModuleContext, v string) string {
|
||||
var sdkVersion string
|
||||
switch v {
|
||||
case "", "none", "current", "test_current", "system_current", "core_current", "core_platform":
|
||||
sdkVersion = ctx.Config().DefaultAppTargetSdk()
|
||||
// sdkKind represents a particular category of an SDK spec like public, system, test, etc.
|
||||
type sdkKind int
|
||||
|
||||
const (
|
||||
sdkInvalid sdkKind = iota
|
||||
sdkNone
|
||||
sdkCore
|
||||
sdkCorePlatform
|
||||
sdkPublic
|
||||
sdkSystem
|
||||
sdkTest
|
||||
sdkPrivate
|
||||
)
|
||||
|
||||
// String returns the string representation of this sdkKind
|
||||
func (k sdkKind) String() string {
|
||||
switch k {
|
||||
case sdkPrivate:
|
||||
return "private"
|
||||
case sdkNone:
|
||||
return "none"
|
||||
case sdkPublic:
|
||||
return "public"
|
||||
case sdkSystem:
|
||||
return "system"
|
||||
case sdkTest:
|
||||
return "test"
|
||||
case sdkCore:
|
||||
return "core"
|
||||
case sdkCorePlatform:
|
||||
return "core_platform"
|
||||
default:
|
||||
sdkVersion = v
|
||||
return "invalid"
|
||||
}
|
||||
if UseApiFingerprint(ctx, sdkVersion) {
|
||||
apiFingerprint := ApiFingerprintPath(ctx)
|
||||
sdkVersion += fmt.Sprintf(".$$(cat %s)", apiFingerprint.String())
|
||||
}
|
||||
return sdkVersion
|
||||
}
|
||||
|
||||
// Returns a sdk version as a number. For modules targeting an unreleased SDK (meaning it does not yet have a number)
|
||||
// it returns android.FutureApiLevel (10000).
|
||||
func sdkVersionToNumber(ctx android.EarlyModuleContext, v string) (int, error) {
|
||||
switch v {
|
||||
case "", "none", "current", "test_current", "system_current", "core_current", "core_platform":
|
||||
return ctx.Config().DefaultAppTargetSdkInt(), nil
|
||||
default:
|
||||
n := android.GetNumericSdkVersion(v)
|
||||
if i, err := strconv.Atoi(n); err != nil {
|
||||
return -1, fmt.Errorf("invalid sdk version %q", n)
|
||||
} else {
|
||||
return i, nil
|
||||
// sdkVersion represents a specific version number of an SDK spec of a particular kind
|
||||
type sdkVersion int
|
||||
|
||||
const (
|
||||
// special version number for a not-yet-frozen SDK
|
||||
sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevel)
|
||||
// special version number to be used for SDK specs where version number doesn't
|
||||
// make sense, e.g. "none", "", etc.
|
||||
sdkVersionNone sdkVersion = sdkVersion(0)
|
||||
)
|
||||
|
||||
// isCurrent checks if the sdkVersion refers to the not-yet-published version of an sdkKind
|
||||
func (v sdkVersion) isCurrent() bool {
|
||||
return v == sdkVersionCurrent
|
||||
}
|
||||
|
||||
// isNumbered checks if the sdkVersion refers to the published (a.k.a numbered) version of an sdkKind
|
||||
func (v sdkVersion) isNumbered() bool {
|
||||
return !v.isCurrent() && v != sdkVersionNone
|
||||
}
|
||||
|
||||
// String returns the string representation of this sdkVersion.
|
||||
func (v sdkVersion) String() string {
|
||||
if v.isCurrent() {
|
||||
return "current"
|
||||
} else if v.isNumbered() {
|
||||
return strconv.Itoa(int(v))
|
||||
}
|
||||
return "(no version)"
|
||||
}
|
||||
|
||||
// asNumberString directly converts the numeric value of this sdk version as a string.
|
||||
// When isNumbered() is true, this method is the same as String(). However, for sdkVersionCurrent
|
||||
// and sdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"),
|
||||
// respectively.
|
||||
func (v sdkVersion) asNumberString() string {
|
||||
return strconv.Itoa(int(v))
|
||||
}
|
||||
|
||||
// sdkSpec represents the kind and the version of an SDK for a module to build against
|
||||
type sdkSpec struct {
|
||||
kind sdkKind
|
||||
version sdkVersion
|
||||
raw string
|
||||
}
|
||||
|
||||
// valid checks if this sdkSpec is well-formed. Note however that true doesn't mean that the
|
||||
// specified SDK actually exists.
|
||||
func (s sdkSpec) valid() bool {
|
||||
return s.kind != sdkInvalid
|
||||
}
|
||||
|
||||
// specified checks if this sdkSpec is well-formed and is not "".
|
||||
func (s sdkSpec) specified() bool {
|
||||
return s.valid() && s.kind != sdkPrivate
|
||||
}
|
||||
|
||||
// prebuiltSdkAvailableForUnbundledBuilt tells whether this sdkSpec can have a prebuilt SDK
|
||||
// that can be used for unbundled builds.
|
||||
func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool {
|
||||
// "", "none", and "core_platform" are not available for unbundled build
|
||||
// as we don't/can't have prebuilt stub for the versions
|
||||
return s.kind != sdkPrivate && s.kind != sdkNone && s.kind != sdkCorePlatform
|
||||
}
|
||||
|
||||
// forPdkBuild converts this sdkSpec into another sdkSpec that is for the PDK builds.
|
||||
func (s sdkSpec) forPdkBuild(ctx android.EarlyModuleContext) sdkSpec {
|
||||
// For PDK builds, use the latest SDK version instead of "current" or ""
|
||||
if s.kind == sdkPrivate || s.kind == sdkPublic {
|
||||
kind := s.kind
|
||||
if kind == sdkPrivate {
|
||||
// We don't have prebuilt SDK for private APIs, so use the public SDK
|
||||
// instead. This looks odd, but that's how it has been done.
|
||||
// TODO(b/148271073): investigate the need for this.
|
||||
kind = sdkPublic
|
||||
}
|
||||
version := sdkVersion(LatestSdkVersionInt(ctx))
|
||||
return sdkSpec{kind, version, s.raw}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func sdkVersionToNumberAsString(ctx android.EarlyModuleContext, v string) (string, error) {
|
||||
n, err := sdkVersionToNumber(ctx, v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
// usePrebuilt determines whether prebuilt SDK should be used for this sdkSpec with the given context.
|
||||
func (s sdkSpec) usePrebuilt(ctx android.EarlyModuleContext) bool {
|
||||
if s.version.isCurrent() {
|
||||
// "current" can be built from source and be from prebuilt SDK
|
||||
return ctx.Config().UnbundledBuildUsePrebuiltSdks()
|
||||
} else if s.version.isNumbered() {
|
||||
// sanity check
|
||||
if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest {
|
||||
panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind))
|
||||
return false
|
||||
}
|
||||
// numbered SDKs are always from prebuilt
|
||||
return true
|
||||
}
|
||||
// "", "none", "core_platform" fall here
|
||||
return false
|
||||
}
|
||||
|
||||
// effectiveVersion converts an sdkSpec into the concrete sdkVersion that the module
|
||||
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
|
||||
// it returns android.FutureApiLevel(10000).
|
||||
func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, error) {
|
||||
if !s.valid() {
|
||||
return s.version, fmt.Errorf("invalid sdk version %q", s.raw)
|
||||
}
|
||||
if ctx.Config().IsPdkBuild() {
|
||||
s = s.forPdkBuild(ctx)
|
||||
}
|
||||
if s.version.isNumbered() {
|
||||
return s.version, nil
|
||||
}
|
||||
return sdkVersion(ctx.Config().DefaultAppTargetSdkInt()), nil
|
||||
}
|
||||
|
||||
// effectiveVersionString converts an sdkSpec into the concrete version string that the module
|
||||
// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
|
||||
// it returns the codename (P, Q, R, etc.)
|
||||
func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, error) {
|
||||
ver, err := s.effectiveVersion(ctx)
|
||||
if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdkInt() {
|
||||
return ctx.Config().DefaultAppTargetSdk(), nil
|
||||
}
|
||||
return ver.String(), err
|
||||
}
|
||||
|
||||
func sdkSpecFrom(str string) sdkSpec {
|
||||
switch str {
|
||||
// special cases first
|
||||
case "":
|
||||
return sdkSpec{sdkPrivate, sdkVersionNone, str}
|
||||
case "none":
|
||||
return sdkSpec{sdkNone, sdkVersionNone, str}
|
||||
case "core_platform":
|
||||
return sdkSpec{sdkCorePlatform, sdkVersionNone, str}
|
||||
default:
|
||||
// the syntax is [kind_]version
|
||||
sep := strings.LastIndex(str, "_")
|
||||
|
||||
var kindString string
|
||||
if sep == 0 {
|
||||
return sdkSpec{sdkInvalid, sdkVersionNone, str}
|
||||
} else if sep == -1 {
|
||||
kindString = ""
|
||||
} else {
|
||||
kindString = str[0:sep]
|
||||
}
|
||||
versionString := str[sep+1 : len(str)]
|
||||
|
||||
var kind sdkKind
|
||||
switch kindString {
|
||||
case "":
|
||||
kind = sdkPublic
|
||||
case "core":
|
||||
kind = sdkCore
|
||||
case "system":
|
||||
kind = sdkSystem
|
||||
case "test":
|
||||
kind = sdkTest
|
||||
default:
|
||||
return sdkSpec{sdkInvalid, sdkVersionNone, str}
|
||||
}
|
||||
|
||||
var version sdkVersion
|
||||
if versionString == "current" {
|
||||
version = sdkVersionCurrent
|
||||
} else if i, err := strconv.Atoi(versionString); err == nil {
|
||||
version = sdkVersion(i)
|
||||
} else {
|
||||
return sdkSpec{sdkInvalid, sdkVersionNone, str}
|
||||
}
|
||||
|
||||
return sdkSpec{kind, version, str}
|
||||
}
|
||||
return strconv.Itoa(n), nil
|
||||
}
|
||||
|
||||
func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep {
|
||||
v := sdkContext.sdkVersion()
|
||||
|
||||
// For PDK builds, use the latest SDK version instead of "current"
|
||||
if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
|
||||
sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
|
||||
latestSdkVersion := 0
|
||||
if len(sdkVersions) > 0 {
|
||||
latestSdkVersion = sdkVersions[len(sdkVersions)-1]
|
||||
}
|
||||
v = strconv.Itoa(latestSdkVersion)
|
||||
}
|
||||
|
||||
numericSdkVersion, err := sdkVersionToNumber(ctx, v)
|
||||
if err != nil {
|
||||
ctx.PropertyErrorf("sdk_version", "%s", err)
|
||||
sdkVersion := sdkContext.sdkVersion()
|
||||
if !sdkVersion.valid() {
|
||||
ctx.PropertyErrorf("sdk_version", "invalid version %q", sdkVersion.raw)
|
||||
return sdkDep{}
|
||||
}
|
||||
|
||||
toPrebuilt := func(sdk string) sdkDep {
|
||||
var api, v string
|
||||
if strings.Contains(sdk, "_") {
|
||||
t := strings.Split(sdk, "_")
|
||||
api = t[0]
|
||||
v = t[1]
|
||||
} else {
|
||||
api = "public"
|
||||
v = sdk
|
||||
}
|
||||
dir := filepath.Join("prebuilts", "sdk", v, api)
|
||||
if ctx.Config().IsPdkBuild() {
|
||||
sdkVersion = sdkVersion.forPdkBuild(ctx)
|
||||
}
|
||||
|
||||
if sdkVersion.usePrebuilt(ctx) {
|
||||
dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), sdkVersion.kind.String())
|
||||
jar := filepath.Join(dir, "android.jar")
|
||||
// There's no aidl for other SDKs yet.
|
||||
// TODO(77525052): Add aidl files for other SDKs too.
|
||||
public_dir := filepath.Join("prebuilts", "sdk", v, "public")
|
||||
public_dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), "public")
|
||||
aidl := filepath.Join(public_dir, "framework.aidl")
|
||||
jarPath := android.ExistentPathForSource(ctx, jar)
|
||||
aidlPath := android.ExistentPathForSource(ctx, aidl)
|
||||
|
@ -139,17 +298,17 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
|
|||
if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
|
||||
return sdkDep{
|
||||
invalidVersion: true,
|
||||
bootclasspath: []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
|
||||
bootclasspath: []string{fmt.Sprintf("sdk_%s_%s_android", sdkVersion.kind, sdkVersion.version.String())},
|
||||
}
|
||||
}
|
||||
|
||||
if !jarPath.Valid() {
|
||||
ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdk, jar)
|
||||
ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.raw, jar)
|
||||
return sdkDep{}
|
||||
}
|
||||
|
||||
if !aidlPath.Valid() {
|
||||
ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdk, aidl)
|
||||
ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.raw, aidl)
|
||||
return sdkDep{}
|
||||
}
|
||||
|
||||
|
@ -173,31 +332,26 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
|
|||
|
||||
// Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
|
||||
// or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
|
||||
if strings.HasPrefix(v, "system_") && numericSdkVersion != android.FutureApiLevel {
|
||||
if sdkVersion.kind == sdkSystem && sdkVersion.version.isNumbered() {
|
||||
allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
|
||||
if ctx.DeviceSpecific() || ctx.SocSpecific() {
|
||||
if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
|
||||
allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
|
||||
}
|
||||
}
|
||||
if len(allowed_versions) > 0 && !android.InList(strconv.Itoa(numericSdkVersion), allowed_versions) {
|
||||
if len(allowed_versions) > 0 && !android.InList(sdkVersion.version.String(), allowed_versions) {
|
||||
ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
|
||||
v, allowed_versions)
|
||||
sdkVersion.raw, allowed_versions)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Config().UnbundledBuildUsePrebuiltSdks() &&
|
||||
v != "" && v != "none" && v != "core_platform" {
|
||||
return toPrebuilt(v)
|
||||
}
|
||||
|
||||
switch v {
|
||||
case "":
|
||||
switch sdkVersion.kind {
|
||||
case sdkPrivate:
|
||||
return sdkDep{
|
||||
useDefaultLibs: true,
|
||||
frameworkResModule: "framework-res",
|
||||
}
|
||||
case "none":
|
||||
case sdkNone:
|
||||
systemModules := sdkContext.systemModules()
|
||||
if systemModules == "" {
|
||||
ctx.PropertyErrorf("sdk_version",
|
||||
|
@ -214,22 +368,22 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep
|
|||
systemModules: systemModules,
|
||||
bootclasspath: []string{systemModules},
|
||||
}
|
||||
case "core_platform":
|
||||
case sdkCorePlatform:
|
||||
return sdkDep{
|
||||
useDefaultLibs: true,
|
||||
frameworkResModule: "framework-res",
|
||||
noFrameworksLibs: true,
|
||||
}
|
||||
case "current":
|
||||
case sdkPublic:
|
||||
return toModule("android_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
|
||||
case "system_current":
|
||||
case sdkSystem:
|
||||
return toModule("android_system_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
|
||||
case "test_current":
|
||||
case sdkTest:
|
||||
return toModule("android_test_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
|
||||
case "core_current":
|
||||
case sdkCore:
|
||||
return toModule("core.current.stubs", "", nil)
|
||||
default:
|
||||
return toPrebuilt(v)
|
||||
panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,6 +416,15 @@ func (sdkPreSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|||
ctx.Config().Once(sdkVersionsKey, func() interface{} { return sdkVersions })
|
||||
}
|
||||
|
||||
func LatestSdkVersionInt(ctx android.EarlyModuleContext) int {
|
||||
sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
|
||||
latestSdkVersion := 0
|
||||
if len(sdkVersions) > 0 {
|
||||
latestSdkVersion = sdkVersions[len(sdkVersions)-1]
|
||||
}
|
||||
return latestSdkVersion
|
||||
}
|
||||
|
||||
func sdkSingletonFactory() android.Singleton {
|
||||
return sdkSingleton{}
|
||||
}
|
||||
|
|
|
@ -650,27 +650,27 @@ func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
|
|||
mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
|
||||
}
|
||||
|
||||
func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
|
||||
var api, v string
|
||||
if sdkVersion == "" || sdkVersion == "none" {
|
||||
api = "system"
|
||||
v = "current"
|
||||
} else if strings.Contains(sdkVersion, "_") {
|
||||
t := strings.Split(sdkVersion, "_")
|
||||
api = t[0]
|
||||
v = t[1]
|
||||
func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, s sdkSpec) android.Paths {
|
||||
var ver sdkVersion
|
||||
var kind sdkKind
|
||||
if s.usePrebuilt(ctx) {
|
||||
ver = s.version
|
||||
kind = s.kind
|
||||
} else {
|
||||
api = "public"
|
||||
v = sdkVersion
|
||||
// We don't have prebuilt SDK for the specific sdkVersion.
|
||||
// Instead of breaking the build, fallback to use "system_current"
|
||||
ver = sdkVersionCurrent
|
||||
kind = sdkSystem
|
||||
}
|
||||
dir := filepath.Join("prebuilts", "sdk", v, api)
|
||||
|
||||
dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
|
||||
jar := filepath.Join(dir, module.BaseModuleName()+".jar")
|
||||
jarPath := android.ExistentPathForSource(ctx, jar)
|
||||
if !jarPath.Valid() {
|
||||
if ctx.Config().AllowMissingDependencies() {
|
||||
return android.Paths{android.PathForSource(ctx, jar)}
|
||||
} else {
|
||||
ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", sdkVersion, jar)
|
||||
ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.raw, jar)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -678,32 +678,34 @@ func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, sdkVersion
|
|||
}
|
||||
|
||||
// to satisfy SdkLibraryDependency interface
|
||||
func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
|
||||
func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
|
||||
// This module is just a wrapper for the stubs.
|
||||
if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
|
||||
return module.PrebuiltJars(ctx, sdkVersion)
|
||||
} else {
|
||||
if strings.HasPrefix(sdkVersion, "system_") {
|
||||
switch sdkVersion.kind {
|
||||
case sdkSystem:
|
||||
return module.systemApiStubsPath
|
||||
} else if sdkVersion == "" {
|
||||
case sdkPrivate:
|
||||
return module.Library.HeaderJars()
|
||||
} else {
|
||||
default:
|
||||
return module.publicApiStubsPath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// to satisfy SdkLibraryDependency interface
|
||||
func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
|
||||
func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
|
||||
// This module is just a wrapper for the stubs.
|
||||
if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
|
||||
return module.PrebuiltJars(ctx, sdkVersion)
|
||||
} else {
|
||||
if strings.HasPrefix(sdkVersion, "system_") {
|
||||
switch sdkVersion.kind {
|
||||
case sdkSystem:
|
||||
return module.systemApiStubsImplPath
|
||||
} else if sdkVersion == "" {
|
||||
case sdkPrivate:
|
||||
return module.Library.ImplementationJars()
|
||||
} else {
|
||||
default:
|
||||
return module.publicApiStubsImplPath
|
||||
}
|
||||
}
|
||||
|
@ -923,13 +925,13 @@ func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
|
|||
}
|
||||
|
||||
// to satisfy SdkLibraryDependency interface
|
||||
func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
|
||||
func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
|
||||
// This module is just a wrapper for the prebuilt stubs.
|
||||
return module.stubsPath
|
||||
}
|
||||
|
||||
// to satisfy SdkLibraryDependency interface
|
||||
func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion string) android.Paths {
|
||||
func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
|
||||
// This module is just a wrapper for the stubs.
|
||||
return module.stubsPath
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue