sdk_version.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // Copyright 2021 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package android
  15. import (
  16. "fmt"
  17. "strconv"
  18. "strings"
  19. )
  20. type SdkContext interface {
  21. // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
  22. SdkVersion(ctx EarlyModuleContext) SdkSpec
  23. // SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
  24. SystemModules() string
  25. // MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
  26. // or from sdk_version if it is not set.
  27. MinSdkVersion(ctx EarlyModuleContext) ApiLevel
  28. // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
  29. // uses-permission tags if it is set.
  30. ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
  31. // TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
  32. // or from sdk_version if it is not set.
  33. TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
  34. }
  35. // SdkKind represents a particular category of an SDK spec like public, system, test, etc.
  36. type SdkKind int
  37. const (
  38. SdkInvalid SdkKind = iota
  39. SdkNone
  40. SdkCore
  41. SdkCorePlatform
  42. SdkIntraCore // API surface provided by one core module to another
  43. SdkPublic
  44. SdkSystem
  45. SdkTest
  46. SdkModule
  47. SdkSystemServer
  48. SdkPrivate
  49. SdkToolchain // API surface provided by ART to compile other API domains
  50. )
  51. // String returns the string representation of this SdkKind
  52. func (k SdkKind) String() string {
  53. switch k {
  54. case SdkPrivate:
  55. return "private"
  56. case SdkNone:
  57. return "none"
  58. case SdkPublic:
  59. return "public"
  60. case SdkSystem:
  61. return "system"
  62. case SdkTest:
  63. return "test"
  64. case SdkCore:
  65. return "core"
  66. case SdkCorePlatform:
  67. return "core_platform"
  68. case SdkIntraCore:
  69. return "intracore"
  70. case SdkModule:
  71. return "module-lib"
  72. case SdkSystemServer:
  73. return "system-server"
  74. case SdkToolchain:
  75. return "toolchain"
  76. default:
  77. return "invalid"
  78. }
  79. }
  80. // JavaLibraryName returns the soong module containing the Java APIs of that API surface.
  81. func (k SdkKind) JavaLibraryName(c Config) string {
  82. name := k.defaultJavaLibraryName()
  83. return JavaLibraryNameFromText(c, name)
  84. }
  85. // JavaLibraryNameFromText returns the name of .txt equivalent of a java_library, but does
  86. // not check if either module exists.
  87. // TODO: Return .txt (single-tree or multi-tree equivalents) based on config
  88. func JavaLibraryNameFromText(c Config, name string) string {
  89. // This returns the default for now.
  90. // TODO: Implement this
  91. return name
  92. }
  93. func (k SdkKind) defaultJavaLibraryName() string {
  94. switch k {
  95. case SdkPublic:
  96. return "android_stubs_current"
  97. case SdkSystem:
  98. return "android_system_stubs_current"
  99. case SdkTest:
  100. return "android_test_stubs_current"
  101. case SdkCore:
  102. return "core.current.stubs"
  103. case SdkModule:
  104. return "android_module_lib_stubs_current"
  105. case SdkSystemServer:
  106. return "android_system_server_stubs_current"
  107. default:
  108. panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
  109. }
  110. }
  111. // SdkSpec represents the kind and the version of an SDK for a module to build against
  112. type SdkSpec struct {
  113. Kind SdkKind
  114. ApiLevel ApiLevel
  115. Raw string
  116. }
  117. func (s SdkSpec) String() string {
  118. return fmt.Sprintf("%s_%s", s.Kind, s.ApiLevel)
  119. }
  120. // Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
  121. // specified SDK actually exists.
  122. func (s SdkSpec) Valid() bool {
  123. return s.Kind != SdkInvalid
  124. }
  125. // Specified checks if this SdkSpec is well-formed and is not "".
  126. func (s SdkSpec) Specified() bool {
  127. return s.Valid() && s.Kind != SdkPrivate
  128. }
  129. // whether the API surface is managed and versioned, i.e. has .txt file that
  130. // get frozen on SDK freeze and changes get reviewed by API council.
  131. func (s SdkSpec) Stable() bool {
  132. if !s.Specified() {
  133. return false
  134. }
  135. switch s.Kind {
  136. case SdkNone:
  137. // there is nothing to manage and version in this case; de facto stable API.
  138. return true
  139. case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
  140. return true
  141. case SdkCorePlatform, SdkTest, SdkPrivate:
  142. return false
  143. default:
  144. panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
  145. }
  146. return false
  147. }
  148. // PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
  149. // that can be used for unbundled builds.
  150. func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
  151. // "", "none", and "core_platform" are not available for unbundled build
  152. // as we don't/can't have prebuilt stub for the versions
  153. return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
  154. }
  155. func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
  156. // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
  157. // use it instead of "current" for the vendor partition.
  158. currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
  159. if currentSdkVersion == "current" {
  160. return s
  161. }
  162. if s.Kind == SdkPublic || s.Kind == SdkSystem {
  163. if s.ApiLevel.IsCurrent() {
  164. if i, err := strconv.Atoi(currentSdkVersion); err == nil {
  165. apiLevel := uncheckedFinalApiLevel(i)
  166. return SdkSpec{s.Kind, apiLevel, s.Raw}
  167. }
  168. panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
  169. }
  170. }
  171. return s
  172. }
  173. // UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
  174. func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
  175. switch s {
  176. case SdkSpecNone, SdkSpecCorePlatform, SdkSpecPrivate:
  177. return false
  178. }
  179. if s.ApiLevel.IsCurrent() {
  180. // "current" can be built from source and be from prebuilt SDK
  181. return ctx.Config().AlwaysUsePrebuiltSdks()
  182. } else if !s.ApiLevel.IsPreview() {
  183. // validation check
  184. if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
  185. panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
  186. return false
  187. }
  188. // numbered SDKs are always from prebuilt
  189. return true
  190. }
  191. return false
  192. }
  193. // EffectiveVersion converts an SdkSpec into the concrete ApiLevel that the module should use. For
  194. // modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
  195. // FutureApiLevel(10000).
  196. func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
  197. if !s.Valid() {
  198. return s.ApiLevel, fmt.Errorf("invalid sdk version %q", s.Raw)
  199. }
  200. if ctx.DeviceSpecific() || ctx.SocSpecific() {
  201. s = s.ForVendorPartition(ctx)
  202. }
  203. return s.ApiLevel.EffectiveVersion(ctx)
  204. }
  205. // EffectiveVersionString converts an SdkSpec into the concrete version string that the module
  206. // should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
  207. // it returns the codename (P, Q, R, etc.)
  208. func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
  209. if !s.Valid() {
  210. return s.ApiLevel.String(), fmt.Errorf("invalid sdk version %q", s.Raw)
  211. }
  212. if ctx.DeviceSpecific() || ctx.SocSpecific() {
  213. s = s.ForVendorPartition(ctx)
  214. }
  215. return s.ApiLevel.EffectiveVersionString(ctx)
  216. }
  217. var (
  218. SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
  219. SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
  220. SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
  221. )
  222. func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
  223. return SdkSpecFromWithConfig(ctx.Config(), str)
  224. }
  225. func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
  226. switch str {
  227. // special cases first
  228. case "":
  229. return SdkSpecPrivate
  230. case "none":
  231. return SdkSpecNone
  232. case "core_platform":
  233. return SdkSpecCorePlatform
  234. default:
  235. // the syntax is [kind_]version
  236. sep := strings.LastIndex(str, "_")
  237. var kindString string
  238. if sep == 0 {
  239. return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
  240. } else if sep == -1 {
  241. kindString = ""
  242. } else {
  243. kindString = str[0:sep]
  244. }
  245. versionString := str[sep+1 : len(str)]
  246. var kind SdkKind
  247. switch kindString {
  248. case "":
  249. kind = SdkPublic
  250. case "core":
  251. kind = SdkCore
  252. case "system":
  253. kind = SdkSystem
  254. case "test":
  255. kind = SdkTest
  256. case "module":
  257. kind = SdkModule
  258. case "system_server":
  259. kind = SdkSystemServer
  260. default:
  261. return SdkSpec{SdkInvalid, NoneApiLevel, str}
  262. }
  263. apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
  264. if err != nil {
  265. return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
  266. }
  267. return SdkSpec{kind, apiLevel, str}
  268. }
  269. }
  270. func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
  271. // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
  272. // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
  273. // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
  274. if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
  275. return true
  276. }
  277. allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
  278. if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
  279. systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
  280. if len(systemSdkVersions) > 0 {
  281. allowedVersions = systemSdkVersions
  282. }
  283. }
  284. if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
  285. ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
  286. s.Raw, allowedVersions)
  287. return false
  288. }
  289. return true
  290. }