xref: /aosp_15_r20/build/bazel/rules/common/api.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker#
3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*7594170eSAndroid Build Coastguard Worker#
7*7594170eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*7594170eSAndroid Build Coastguard Worker#
9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Worker# limitations under the License.
14*7594170eSAndroid Build Coastguard Worker
15*7594170eSAndroid Build Coastguard Worker# An API level, can be a finalized (numbered) API, a preview (codenamed) API, or
16*7594170eSAndroid Build Coastguard Worker# the future API level (10000). Can be parsed from a string with
17*7594170eSAndroid Build Coastguard Worker# parse_api_level_with_version.
18*7594170eSAndroid Build Coastguard Worker
19*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:dicts.bzl", "dicts")
20*7594170eSAndroid Build Coastguard Workerload("@soong_injection//api_levels:platform_versions.bzl", "platform_versions")
21*7594170eSAndroid Build Coastguard Workerload(":api_constants.bzl", "api_levels_released_versions")
22*7594170eSAndroid Build Coastguard Worker
23*7594170eSAndroid Build Coastguard Worker_NONE_API_LEVEL_INT = -1
24*7594170eSAndroid Build Coastguard Worker_PREVIEW_API_LEVEL_BASE = 9000  # Base constant for preview API levels.
25*7594170eSAndroid Build Coastguard Worker_FUTURE_API_LEVEL_INT = 10000  # API Level associated with an arbitrary future release
26*7594170eSAndroid Build Coastguard Worker
27*7594170eSAndroid Build Coastguard Worker# Dict of unfinalized codenames to a placeholder preview API int.
28*7594170eSAndroid Build Coastguard Workerdef _preview_codenames_to_ints(platform_sdk_variables):
29*7594170eSAndroid Build Coastguard Worker    return {
30*7594170eSAndroid Build Coastguard Worker        codename: _PREVIEW_API_LEVEL_BASE + i
31*7594170eSAndroid Build Coastguard Worker        for i, codename in enumerate(platform_sdk_variables.platform_version_active_codenames)
32*7594170eSAndroid Build Coastguard Worker    }
33*7594170eSAndroid Build Coastguard Worker
34*7594170eSAndroid Build Coastguard Worker# Returns true if a string or int version is in preview (not finalized).
35*7594170eSAndroid Build Coastguard Workerdef _is_preview(version, platform_sdk_variables):
36*7594170eSAndroid Build Coastguard Worker    preview_codenames_to_ints = _preview_codenames_to_ints(platform_sdk_variables)
37*7594170eSAndroid Build Coastguard Worker    if type(version) == "string" and version.isdigit():
38*7594170eSAndroid Build Coastguard Worker        # normalize int types internally
39*7594170eSAndroid Build Coastguard Worker        version = int(version)
40*7594170eSAndroid Build Coastguard Worker
41*7594170eSAndroid Build Coastguard Worker    # Future / current / none is considered as a preview.
42*7594170eSAndroid Build Coastguard Worker    if version in ("current", "(no version)", _FUTURE_API_LEVEL_INT, _NONE_API_LEVEL_INT):
43*7594170eSAndroid Build Coastguard Worker        return True
44*7594170eSAndroid Build Coastguard Worker
45*7594170eSAndroid Build Coastguard Worker    # api can be either the codename or the int level (9000+)
46*7594170eSAndroid Build Coastguard Worker    return version in preview_codenames_to_ints or version in preview_codenames_to_ints.values()
47*7594170eSAndroid Build Coastguard Worker
48*7594170eSAndroid Build Coastguard Worker# Return 10000 for unfinalized versions, otherwise return unchanged.
49*7594170eSAndroid Build Coastguard Workerdef _final_or_future(version, platform_sdk_variables):
50*7594170eSAndroid Build Coastguard Worker    if _is_preview(version = version, platform_sdk_variables = platform_sdk_variables):
51*7594170eSAndroid Build Coastguard Worker        return _FUTURE_API_LEVEL_INT
52*7594170eSAndroid Build Coastguard Worker    else:
53*7594170eSAndroid Build Coastguard Worker        return version
54*7594170eSAndroid Build Coastguard Worker
55*7594170eSAndroid Build Coastguard Workerdef _api_levels_with_previews(platform_sdk_variables):
56*7594170eSAndroid Build Coastguard Worker    return dicts.add(
57*7594170eSAndroid Build Coastguard Worker        api_levels_released_versions,
58*7594170eSAndroid Build Coastguard Worker        _preview_codenames_to_ints(platform_sdk_variables),
59*7594170eSAndroid Build Coastguard Worker    )
60*7594170eSAndroid Build Coastguard Worker
61*7594170eSAndroid Build Coastguard Worker# @unused
62*7594170eSAndroid Build Coastguard Workerdef _api_levels_with_final_codenames(platform_sdk_variables):
63*7594170eSAndroid Build Coastguard Worker    if platform_sdk_variables.platform_sdk_final and platform_sdk_variables.platform_sdk_version:
64*7594170eSAndroid Build Coastguard Worker        return api_levels_released_versions
65*7594170eSAndroid Build Coastguard Worker    return dicts.add(
66*7594170eSAndroid Build Coastguard Worker        api_levels_released_versions,
67*7594170eSAndroid Build Coastguard Worker        {"current": _final_or_future(
68*7594170eSAndroid Build Coastguard Worker            version = platform_sdk_variables.platform_sdk_version,
69*7594170eSAndroid Build Coastguard Worker            platform_sdk_variables = platform_sdk_variables,
70*7594170eSAndroid Build Coastguard Worker        )},
71*7594170eSAndroid Build Coastguard Worker    )
72*7594170eSAndroid Build Coastguard Worker
73*7594170eSAndroid Build Coastguard Worker# parse_api_level_from_version is a Starlark implementation of ApiLevelFromUser
74*7594170eSAndroid Build Coastguard Worker# at https://cs.android.com/android/platform/superproject/+/master:build/soong/android/api_levels.go;l=221-250;drc=5095a6c4b484f34d5c4f55a855d6174e00fb7f5e
75*7594170eSAndroid Build Coastguard Workerdef _parse_api_level_from_version(version, platform_sdk_variables):
76*7594170eSAndroid Build Coastguard Worker    """converts the given string `version` to an api level
77*7594170eSAndroid Build Coastguard Worker
78*7594170eSAndroid Build Coastguard Worker    Args:
79*7594170eSAndroid Build Coastguard Worker        version: must be non-empty. Inputs that are not "current", known
80*7594170eSAndroid Build Coastguard Worker        previews, finalized codenames, or convertible to an integer will return
81*7594170eSAndroid Build Coastguard Worker        an error.
82*7594170eSAndroid Build Coastguard Worker
83*7594170eSAndroid Build Coastguard Worker    Returns: The api level as an int.
84*7594170eSAndroid Build Coastguard Worker    """
85*7594170eSAndroid Build Coastguard Worker    if version == "":
86*7594170eSAndroid Build Coastguard Worker        fail("API level string must be non-empty")
87*7594170eSAndroid Build Coastguard Worker
88*7594170eSAndroid Build Coastguard Worker    if version == "current":
89*7594170eSAndroid Build Coastguard Worker        return _FUTURE_API_LEVEL_INT
90*7594170eSAndroid Build Coastguard Worker
91*7594170eSAndroid Build Coastguard Worker    if _is_preview(version = version, platform_sdk_variables = platform_sdk_variables):
92*7594170eSAndroid Build Coastguard Worker        return _preview_codenames_to_ints(platform_sdk_variables).get(version) or int(version)
93*7594170eSAndroid Build Coastguard Worker
94*7594170eSAndroid Build Coastguard Worker    # Not preview nor current.
95*7594170eSAndroid Build Coastguard Worker    #
96*7594170eSAndroid Build Coastguard Worker    # If the level is the codename of an API level that has been finalized, this
97*7594170eSAndroid Build Coastguard Worker    # function returns the API level number associated with that API level. If
98*7594170eSAndroid Build Coastguard Worker    # the input is *not* a finalized codename, the input is returned unmodified.
99*7594170eSAndroid Build Coastguard Worker    canonical_level = api_levels_released_versions.get(version)
100*7594170eSAndroid Build Coastguard Worker    if not canonical_level:
101*7594170eSAndroid Build Coastguard Worker        if not version.isdigit():
102*7594170eSAndroid Build Coastguard Worker            fail("version %s could not be parsed as integer and is not a recognized codename" % version)
103*7594170eSAndroid Build Coastguard Worker        return int(version)
104*7594170eSAndroid Build Coastguard Worker    return canonical_level
105*7594170eSAndroid Build Coastguard Worker
106*7594170eSAndroid Build Coastguard Workerdef _default_app_target_sdk_string(platform_sdk_variables):
107*7594170eSAndroid Build Coastguard Worker    if platform_sdk_variables.platform_sdk_final:
108*7594170eSAndroid Build Coastguard Worker        return str(platform_sdk_variables.platform_sdk_version)
109*7594170eSAndroid Build Coastguard Worker
110*7594170eSAndroid Build Coastguard Worker    if not platform_sdk_variables.platform_sdk_codename:
111*7594170eSAndroid Build Coastguard Worker        # soong returns NoneApiLevel here value: "(no version)", number: -1, isPreview: true
112*7594170eSAndroid Build Coastguard Worker        #
113*7594170eSAndroid Build Coastguard Worker        # fail fast instead of returning an arbitrary value.
114*7594170eSAndroid Build Coastguard Worker        fail("Platform_sdk_codename must be set.")
115*7594170eSAndroid Build Coastguard Worker
116*7594170eSAndroid Build Coastguard Worker    if platform_sdk_variables.platform_sdk_codename == "REL":
117*7594170eSAndroid Build Coastguard Worker        fail("Platform_sdk_codename should not be REL when Platform_sdk_final is false")
118*7594170eSAndroid Build Coastguard Worker
119*7594170eSAndroid Build Coastguard Worker    return platform_sdk_variables.platform_sdk_codename
120*7594170eSAndroid Build Coastguard Worker
121*7594170eSAndroid Build Coastguard Worker# Starlark implementation of DefaultAppTargetSDK from build/soong/android/config.go
122*7594170eSAndroid Build Coastguard Worker# https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;l=875-889;drc=b0dc477ef740ec959548fe5517bd92ac4ea0325c
123*7594170eSAndroid Build Coastguard Worker# check what you want returned for codename == "" case before using
124*7594170eSAndroid Build Coastguard Workerdef _default_app_target_sdk(platform_sdk_variables):
125*7594170eSAndroid Build Coastguard Worker    """default_app_target_sdk returns the API level that platform apps are targeting.
126*7594170eSAndroid Build Coastguard Worker       This converts a codename to the exact ApiLevel it represents.
127*7594170eSAndroid Build Coastguard Worker    """
128*7594170eSAndroid Build Coastguard Worker    return _parse_api_level_from_version(
129*7594170eSAndroid Build Coastguard Worker        version = _default_app_target_sdk_string(platform_sdk_variables),
130*7594170eSAndroid Build Coastguard Worker        platform_sdk_variables = platform_sdk_variables,
131*7594170eSAndroid Build Coastguard Worker    )
132*7594170eSAndroid Build Coastguard Worker
133*7594170eSAndroid Build Coastguard Worker# Starlark implementation of EffectiveVersionString from build/soong/android/api_levels.go
134*7594170eSAndroid Build Coastguard Worker# EffectiveVersionString converts an api level string into the concrete version string that the module
135*7594170eSAndroid Build Coastguard Worker# should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
136*7594170eSAndroid Build Coastguard Worker# it returns the codename (P, Q, R, etc.)
137*7594170eSAndroid Build Coastguard Workerdef _effective_version_string(
138*7594170eSAndroid Build Coastguard Worker        version,
139*7594170eSAndroid Build Coastguard Worker        platform_sdk_variables):
140*7594170eSAndroid Build Coastguard Worker    if not _is_preview(version, platform_sdk_variables):
141*7594170eSAndroid Build Coastguard Worker        return version
142*7594170eSAndroid Build Coastguard Worker    default_app_target_sdk_string = _default_app_target_sdk_string(platform_sdk_variables)
143*7594170eSAndroid Build Coastguard Worker    if not _is_preview(default_app_target_sdk_string, platform_sdk_variables):
144*7594170eSAndroid Build Coastguard Worker        return default_app_target_sdk_string
145*7594170eSAndroid Build Coastguard Worker    if version in platform_sdk_variables.platform_version_active_codenames:
146*7594170eSAndroid Build Coastguard Worker        return version
147*7594170eSAndroid Build Coastguard Worker    return default_app_target_sdk_string
148*7594170eSAndroid Build Coastguard Worker
149*7594170eSAndroid Build Coastguard Workerdef api_from_product(platform_sdk_variables):
150*7594170eSAndroid Build Coastguard Worker    """Provides api level-related utility functions from platform variables.
151*7594170eSAndroid Build Coastguard Worker
152*7594170eSAndroid Build Coastguard Worker    Args:
153*7594170eSAndroid Build Coastguard Worker        platform_sdk_variables: a struct that must provides the 4
154*7594170eSAndroid Build Coastguard Worker          product variables: platform_sdk_final (boolean),
155*7594170eSAndroid Build Coastguard Worker          platform_sdk_version (int), platform_sdk_codename (string),
156*7594170eSAndroid Build Coastguard Worker          platform_version_active_codenames (string list)
157*7594170eSAndroid Build Coastguard Worker
158*7594170eSAndroid Build Coastguard Worker    Returns: A struct containing utility functions and constants
159*7594170eSAndroid Build Coastguard Worker        around api levels, e.g. for parsing them from user input and for
160*7594170eSAndroid Build Coastguard Worker        overriding them based on defaults and the input product variables.
161*7594170eSAndroid Build Coastguard Worker    """
162*7594170eSAndroid Build Coastguard Worker    return struct(
163*7594170eSAndroid Build Coastguard Worker        NONE_API_LEVEL = _NONE_API_LEVEL_INT,
164*7594170eSAndroid Build Coastguard Worker        FUTURE_API_LEVEL = _FUTURE_API_LEVEL_INT,
165*7594170eSAndroid Build Coastguard Worker        is_preview = lambda version: _is_preview(
166*7594170eSAndroid Build Coastguard Worker            version = version,
167*7594170eSAndroid Build Coastguard Worker            platform_sdk_variables = platform_sdk_variables,
168*7594170eSAndroid Build Coastguard Worker        ),
169*7594170eSAndroid Build Coastguard Worker        final_or_future = lambda version: _final_or_future(
170*7594170eSAndroid Build Coastguard Worker            version = version,
171*7594170eSAndroid Build Coastguard Worker            platform_sdk_variables = platform_sdk_variables,
172*7594170eSAndroid Build Coastguard Worker        ),
173*7594170eSAndroid Build Coastguard Worker        default_app_target_sdk_string = lambda: _default_app_target_sdk_string(platform_sdk_variables),
174*7594170eSAndroid Build Coastguard Worker        default_app_target_sdk = lambda: _default_app_target_sdk(platform_sdk_variables),
175*7594170eSAndroid Build Coastguard Worker        parse_api_level_from_version = lambda version: _parse_api_level_from_version(
176*7594170eSAndroid Build Coastguard Worker            version = version,
177*7594170eSAndroid Build Coastguard Worker            platform_sdk_variables = platform_sdk_variables,
178*7594170eSAndroid Build Coastguard Worker        ),
179*7594170eSAndroid Build Coastguard Worker        api_levels = _api_levels_with_previews(platform_sdk_variables),
180*7594170eSAndroid Build Coastguard Worker        effective_version_string = lambda version: _effective_version_string(
181*7594170eSAndroid Build Coastguard Worker            version = version,
182*7594170eSAndroid Build Coastguard Worker            platform_sdk_variables = platform_sdk_variables,
183*7594170eSAndroid Build Coastguard Worker        ),
184*7594170eSAndroid Build Coastguard Worker    )
185*7594170eSAndroid Build Coastguard Worker
186*7594170eSAndroid Build Coastguard Worker# TODO(b/300428335): access these variables in a transition friendly way.
187*7594170eSAndroid Build Coastguard Workerapi = api_from_product(platform_versions)
188