xref: /aosp_15_r20/build/bazel/rules/hidl_file_utils.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
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("@bazel_skylib//lib:paths.bzl", "paths")
16
17LANGUAGE_CC_HEADERS = "c++-headers"
18LANGUAGE_CC_SOURCES = "c++-sources"
19INTERFACE_HEADER_PREFIXES = ["I", "Bs", "BnHw", "BpHw", "IHw"]
20TYPE_HEADER_PREFIXES = ["", "hw"]
21
22def _generate_hidl_action(
23        hidl_info,
24        language,
25        ctx):
26    """ Utility function for generating code for the given language from HIDL interface."""
27
28    output_dir = paths.join(ctx.bin_dir.path, ctx.label.package)
29
30    args = ctx.actions.args()
31
32    args.add("-R")
33    args.add_all(["-p", "."])
34    args.add_all(["-o", output_dir])
35    args.add_all(["-L", language])
36    for root in hidl_info.transitive_roots.to_list():
37        args.add_all(["-r", root])
38
39    args.add(hidl_info.fq_name)
40
41    hidl_srcs = hidl_info.srcs.to_list()
42    inputs = depset(
43        direct = hidl_srcs,
44        # These are needed for hidl-gen to correctly generate the code.
45        transitive = [hidl_info.transitive_srcs, hidl_info.transitive_root_interface_files],
46    )
47
48    outputs = _generate_and_declare_output_files(
49        ctx,
50        hidl_info.fq_name,
51        language,
52        hidl_srcs,
53    )
54
55    ctx.actions.run(
56        inputs = inputs,
57        executable = ctx.executable._hidl_gen,
58        outputs = outputs,
59        arguments = [args],
60        mnemonic = "HidlGen" + _get_language_string(language),
61    )
62
63    return outputs
64
65def _get_language_string(language):
66    if language == LANGUAGE_CC_HEADERS:
67        return "CcHeader"
68    elif language == LANGUAGE_CC_SOURCES:
69        return "Cc"
70
71def _generate_and_declare_output_files(
72        ctx,
73        fq_name,
74        language,
75        hidl_srcs):
76    files = []
77
78    # Break FQ name such as [email protected] into
79    # android/hardware/neuralnetworks/1.3 which is the directory structure
80    # that hidl-gen uses to generate files.
81    parts = fq_name.split("@")
82    dirname = paths.join(parts[0].replace(".", "/"), parts[1])
83
84    for src in hidl_srcs:
85        filename = src.basename
86
87        # "I" prefix indicates that this file is a interface file, the rest are
88        # files that define types. Interface files and type files are treated
89        # differently when generating code using hidl-gen.
90        basename = filename.removeprefix("I").removesuffix(".hal")
91        interface = _is_interface(filename)
92        if language == LANGUAGE_CC_HEADERS:
93            if interface:
94                prefixes = INTERFACE_HEADER_PREFIXES
95            else:
96                prefixes = TYPE_HEADER_PREFIXES
97            for prefix in prefixes:
98                out_name = paths.join(dirname, prefix + basename + ".h")
99                declared = ctx.actions.declare_file(out_name)
100                files.append(declared)
101        elif language == LANGUAGE_CC_SOURCES:
102            if interface:
103                out_name = paths.join(dirname, basename + "All.cpp")
104            else:
105                out_name = paths.join(dirname, basename + ".cpp")
106            declared = ctx.actions.declare_file(out_name)
107            files.append(declared)
108
109    return files
110
111def _is_interface(filename):
112    if not filename.endswith(".hal"):
113        fail("HIDL source file must be a .hal file: %s" % filename)
114
115    return filename.startswith("I")
116
117hidl_file_utils = struct(
118    generate_hidl_action = _generate_hidl_action,
119)
120