• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
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
15load("//build/bazel/rules/aidl:aidl_library.bzl", "aidl_library")
16load("//build/bazel/rules/cc:cc_aidl_library.bzl", "cc_aidl_library")
17load("//build/bazel/rules/java:java_aidl_library.bzl", "java_aidl_library")
18
19JAVA = "java"
20CPP = "cpp"
21NDK = "ndk"
22#TODO(b/246803961) Add support for rust backend
23
24def _hash_file(name, version):
25    return "aidl_api/{}/{}/.hash".format(name, version)
26
27def _check_versions_with_info(versions_with_info):
28    for version_with_info in versions_with_info:
29        for dep in version_with_info.get("deps", []):
30            parts = dep.split("-V")
31            if len(parts) < 2 or not parts[-1].isdigit():
32                fail("deps in versions_with_info must specify its version, but", dep)
33
34    versions = []
35
36    # ensure that all versions are ints
37    for info in versions_with_info:
38        version = info["version"]
39        if version.isdigit() == False:
40            fail("version %s is not an integer".format(version))
41
42        versions.append(int(version))
43
44    if versions != sorted(versions):
45        fail("versions should be sorted")
46
47    for i, v in enumerate(versions):
48        if i > 0:
49            if v == versions[i - 1]:
50                fail("duplicate version found:", v)
51        if v <= 0:
52            fail("all versions should be > 0, but found version:", v)
53
54def _create_latest_version_aliases(name, last_version_name, backend_configs, **kwargs):
55    latest_name = name + "-latest"
56    native.alias(
57        name = latest_name,
58        actual = ":" + last_version_name,
59        **kwargs
60    )
61    for lang in backend_configs.keys():
62        language_binding_name = last_version_name + "-" + lang
63        native.alias(
64            name = latest_name + "-" + lang,
65            actual = ":" + language_binding_name,
66            **kwargs
67        )
68
69def _versioned_name(name, version):
70    if version == "":
71        return name
72
73    return name + "-V" + version
74
75# https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=782-799;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9
76def _next_version(versions_with_info, unstable):
77    if unstable:
78        return ""
79
80    if versions_with_info == None or len(versions_with_info) == 0:
81        return "1"
82
83    return str(int(versions_with_info[-1]["version"]) + 1)
84
85def _is_config_enabled(config):
86    if config == None:
87        return False
88
89    for key in config:
90        if key not in ["enabled", "min_sdk_version", "tags"]:
91            fail("unknown property in aidl configuration: " + str(key))
92
93    return config.get("enabled", False) == True
94
95def aidl_interface(
96        name,
97        deps = [],
98        strip_import_prefix = "",
99        srcs = None,
100        flags = None,
101        java_config = None,
102        cpp_config = None,
103        ndk_config = None,
104        stability = None,
105        versions_with_info = [],
106        unstable = False,
107        tags = [],
108        # TODO(b/261208761): Support frozen attr
109        frozen = False,
110        **kwargs):
111    """aidl_interface creates a versioned aidl_libraries and language-specific *_aidl_libraries
112
113    This macro loops over the list of required versions and searches for all
114    *.aidl source files located under the path `aidl_api/<version label/`.
115    For each version, an `aidl_library` is created with the corresponding sources.
116    For each `aidl_library`, a language-binding library *_aidl_library is created
117    based on the values passed to the `backends` argument.
118
119    Arguments:
120        name:                   string, base name of generated targets: <module-name>-V<version number>-<language-type>
121        deps:                   List[AidlGenInfo], a list of other aidl_libraries that all versions of this interface depend on
122        strip_import_prefix:    str, a local directory to pass to the AIDL compiler to satisfy imports
123        srcs:                   List[file], a list of files to include in the development (unversioned) version of the aidl_interface
124        flags:                  List[string], a list of flags to pass to the AIDL compiler
125        java_config:            Dict{"enabled": bool}, config for java backend
126        cpp_config:             Dict{"enabled": bool, "min_sdk_version": string}, config for cpp backend
127        ndk_config:             Dict{"enabled": bool, "min_sdk_version": string}, config for ndk backend
128        stability:              string, stability promise of the interface. Currently, only supports "vintf"
129        backends:               List[string], a list of the languages to generate bindings for
130    """
131
132    # When versions_with_info is set, versions is no-op.
133    # TODO(b/244349745): Modify bp2build to skip convert versions if versions_with_info is set
134    if (len(versions_with_info) == 0 and srcs == None):
135        fail("must specify at least versions_with_info or srcs")
136
137    if len(versions_with_info) == 0:
138        if frozen == True:
139            fail("frozen cannot be set without versions_with_info attr being set")
140    elif unstable == True:
141        # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=872;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9
142        fail("cannot have versions for unstable interface")
143
144    aidl_flags = ["--structured"]
145    if flags != None:
146        aidl_flags.extend(flags)
147
148    enabled_backend_configs = {}
149    if _is_config_enabled(java_config):
150        enabled_backend_configs[JAVA] = java_config
151    if _is_config_enabled(cpp_config):
152        enabled_backend_configs[CPP] = cpp_config
153    if _is_config_enabled(ndk_config):
154        enabled_backend_configs[NDK] = ndk_config
155
156    if stability != None:
157        if unstable == True:
158            fail("stability must be unset when unstable is true")
159        if stability == "vintf":
160            aidl_flags.append("--stability=" + stability)
161
162            # TODO(b/245738285): Add support for vintf stability in java backend
163            if JAVA in enabled_backend_configs:
164                enabled_backend_configs.pop(JAVA)
165        else:
166            # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=329;drc=e88d9a9b14eafb064a234d555a5cd96de97ca9e2
167            # only vintf is allowed currently
168            fail("stability must be unset or \"vintf\"")
169
170    # next_version will be the last specified version + 1.
171    # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=791?q=system%2Ftools%2Faidl%2Fbuild%2Faidl_interface.go
172    next_version = None
173
174    if len(versions_with_info) > 0:
175        _check_versions_with_info(versions_with_info)
176        next_version = _next_version(versions_with_info, False)
177
178        for version_with_info in versions_with_info:
179            deps_for_version = version_with_info.get("deps", [])
180
181            create_aidl_binding_for_backends(
182                name = name,
183                version = version_with_info["version"],
184                deps = deps_for_version,
185                aidl_flags = aidl_flags,
186                backend_configs = enabled_backend_configs,
187                tags = tags,
188                **kwargs
189            )
190
191        _create_latest_version_aliases(
192            name,
193            _versioned_name(name, versions_with_info[-1]["version"]),
194            enabled_backend_configs,
195            tags = tags,
196            **kwargs
197        )
198    else:
199        next_version = _next_version(versions_with_info, unstable)
200
201    # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface.go;l=941;drc=5390d9a42f5e4f99ccb3a84068f554d948cb62b9
202    # Create aidl binding for next_version with srcs
203    if srcs and len(srcs) > 0:
204        create_aidl_binding_for_backends(
205            name = name,
206            version = next_version,
207            srcs = srcs,
208            strip_import_prefix = strip_import_prefix,
209            deps = deps,
210            aidl_flags = aidl_flags,
211            backend_configs = enabled_backend_configs,
212            tags = tags,
213            **kwargs
214        )
215
216def create_aidl_binding_for_backends(
217        name,
218        version = None,
219        srcs = None,
220        strip_import_prefix = "",
221        deps = None,
222        aidl_flags = [],
223        backend_configs = {},
224        tags = [],
225        **kwargs):
226    """
227    Create aidl_library target and corrending <backend>_aidl_library target for a given version
228
229    Arguments:
230        name:                   string, base name of the aidl interface
231        version:                string, version of the aidl interface
232        srcs:                   List[Label] list of unversioned AIDL srcs
233        strip_import_prefix     string, the prefix to strip the paths of the .aidl files in srcs
234        deps:                   List[AidlGenInfo], a list of other aidl_libraries that the version depends on
235                                the label of the targets have format <aidl-interface>-V<version_number>
236        aidl_flags:             List[string], a list of flags to pass to the AIDL compiler
237        backends:               List[string], a list of the languages to generate bindings for
238    """
239    aidl_library_name = _versioned_name(name, version)
240
241    # srcs is None when create_aidl_binding_for_backends is called with a
242    # frozen version specified via versions or versions_with_info.
243    # next_version being equal to "" means this is an unstable version and
244    # we should use srcs instead
245    if version != "":
246        aidl_flags = aidl_flags + ["--version=" + version]
247
248    hash_file = None
249
250    if srcs == None:
251        if version == "":
252            fail("need srcs for unversioned interface")
253        strip_import_prefix = "aidl_api/{}/{}".format(name, version)
254        srcs = native.glob([strip_import_prefix + "/**/*.aidl"])
255        hash_file = _hash_file(name, version)
256
257    aidl_library(
258        name = aidl_library_name,
259        deps = deps,
260        hash_file = hash_file,
261        version = version,
262        strip_import_prefix = strip_import_prefix,
263        srcs = srcs,
264        flags = aidl_flags,
265        # The language-specific backends will set more appropriate apex_available values.
266        tags = tags + ["apex_available=//apex_available:anyapex"],
267        **kwargs
268    )
269
270    for lang, config in backend_configs.items():
271        # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_gen_rule.go;l=207;drc=a858ae7039b876a30002a1130f24196915a859a4
272        min_sdk_version = "current"
273        if "min_sdk_version" in config:
274            min_sdk_version = config["min_sdk_version"]
275
276        if lang == JAVA:
277            java_aidl_library(
278                name = aidl_library_name + "-java",
279                deps = [":" + aidl_library_name],
280                tags = tags + config.get("tags", []),
281                # TODO(b/249276008): Pass min_sdk_version to java_aidl_library
282                **(kwargs | {"target_compatible_with": ["//build/bazel/platforms/os:android"]})
283            )
284        elif lang == CPP or lang == NDK:
285            dynamic_deps = []
286            cppflags = []
287
288            # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=564;drc=0517d97079d4b08f909e7f35edfa33b88fcc0d0e
289            if deps != None:
290                # For each aidl_library target label versioned_name, there's an
291                # associated cc_library_shared target with label versioned_name-<cpp|ndk>
292                dynamic_deps.extend(["{}-{}".format(dep, lang) for dep in deps])
293
294            # https://cs.android.com/android/platform/superproject/+/master:system/tools/aidl/build/aidl_interface_backends.go;l=111;drc=ef9f1352a1a8fec7bb134b1c713e13fc3ccee651
295            if lang == CPP:
296                dynamic_deps.extend([
297                    "//frameworks/native/libs/binder:libbinder",
298                    "//system/core/libutils:libutils",
299                ])
300            elif lang == NDK:
301                dynamic_deps = dynamic_deps + select({
302                    "//build/bazel/rules/apex:android-in_apex": ["//frameworks/native/libs/binder/ndk:libbinder_ndk_stub_libs_current"],
303                    "//conditions:default": ["//frameworks/native/libs/binder/ndk:libbinder_ndk"],
304                })
305
306                # https://source.corp.google.com/android/system/tools/aidl/build/aidl_interface_backends.go;l=120;rcl=18dd931bde35b502545b7a52987e2363042c151c
307                cppflags = ["-DBINDER_STABILITY_SUPPORT"]
308
309            if hasattr(kwargs, "tidy_checks_as_errors"):
310                fail("tidy_checks_as_errors cannot be overriden for aidl_interface cc_libraries")
311            tidy_checks_as_errors = [
312                "*",
313                "-clang-analyzer-deadcode.DeadStores",  # b/253079031
314                "-clang-analyzer-cplusplus.NewDeleteLeaks",  # b/253079031
315                "-clang-analyzer-optin.performance.Padding",  # b/253079031
316            ]
317
318            cc_aidl_library(
319                name = "{}-{}".format(aidl_library_name, lang),
320                make_shared = True,
321                cppflags = cppflags,
322                deps = [":" + aidl_library_name],
323                dynamic_deps = dynamic_deps,
324                lang = lang,
325                min_sdk_version = min_sdk_version,
326                tidy = "local",
327                tidy_checks_as_errors = tidy_checks_as_errors,
328                tidy_gen_header_filter = True,
329                tags = tags + config.get("tags", []),
330                **kwargs
331            )
332