xref: /aosp_15_r20/external/emboss/build_defs.bzl (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1*99e0aae7SDavid Rees# Copyright 2019 Google LLC
2*99e0aae7SDavid Rees#
3*99e0aae7SDavid Rees# Licensed under the Apache License, Version 2.0 (the "License");
4*99e0aae7SDavid Rees# you may not use this file except in compliance with the License.
5*99e0aae7SDavid Rees# You may obtain a copy of the License at
6*99e0aae7SDavid Rees#
7*99e0aae7SDavid Rees#     https://www.apache.org/licenses/LICENSE-2.0
8*99e0aae7SDavid Rees#
9*99e0aae7SDavid Rees# Unless required by applicable law or agreed to in writing, software
10*99e0aae7SDavid Rees# distributed under the License is distributed on an "AS IS" BASIS,
11*99e0aae7SDavid Rees# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*99e0aae7SDavid Rees# See the License for the specific language governing permissions and
13*99e0aae7SDavid Rees# limitations under the License.
14*99e0aae7SDavid Rees
15*99e0aae7SDavid Rees# -*- mode: python; -*-
16*99e0aae7SDavid Rees# vim:set ft=blazebuild:
17*99e0aae7SDavid Rees"""Build defs for Emboss.
18*99e0aae7SDavid Rees
19*99e0aae7SDavid ReesThis file exports emboss_library, which creates an Emboss library, and
20*99e0aae7SDavid Reescc_emboss_library, which creates a header file and can be used as a dep in a
21*99e0aae7SDavid Rees`cc_library`, `cc_binary`, or `cc_test` rule.
22*99e0aae7SDavid Rees
23*99e0aae7SDavid ReesThere is also a convenience macro, `emboss_cc_library()`, which creates an
24*99e0aae7SDavid Rees`emboss_library` and a `cc_emboss_library` based on it.
25*99e0aae7SDavid Rees"""
26*99e0aae7SDavid Rees
27*99e0aae7SDavid Reesload("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
28*99e0aae7SDavid Rees
29*99e0aae7SDavid Reesdef emboss_cc_library(name, srcs, deps = [], visibility = None, import_dirs = [], enable_enum_traits = True, **kwargs):
30*99e0aae7SDavid Rees    """Constructs a C++ library from an .emb file."""
31*99e0aae7SDavid Rees    if len(srcs) != 1:
32*99e0aae7SDavid Rees        fail(
33*99e0aae7SDavid Rees            "Must specify exactly one Emboss source file for emboss_cc_library.",
34*99e0aae7SDavid Rees            "srcs",
35*99e0aae7SDavid Rees        )
36*99e0aae7SDavid Rees
37*99e0aae7SDavid Rees    emboss_library(
38*99e0aae7SDavid Rees        name = name + "_ir",
39*99e0aae7SDavid Rees        srcs = srcs,
40*99e0aae7SDavid Rees        deps = [dep + "_ir" for dep in deps],
41*99e0aae7SDavid Rees        import_dirs = import_dirs,
42*99e0aae7SDavid Rees        **kwargs
43*99e0aae7SDavid Rees    )
44*99e0aae7SDavid Rees
45*99e0aae7SDavid Rees    cc_emboss_library(
46*99e0aae7SDavid Rees        name = name,
47*99e0aae7SDavid Rees        deps = [":" + name + "_ir"],
48*99e0aae7SDavid Rees        visibility = visibility,
49*99e0aae7SDavid Rees        enable_enum_traits = enable_enum_traits,
50*99e0aae7SDavid Rees        **kwargs
51*99e0aae7SDavid Rees    )
52*99e0aae7SDavid Rees
53*99e0aae7SDavid Rees# Full Starlark rules for emboss_library and cc_emboss_library.
54*99e0aae7SDavid Rees#
55*99e0aae7SDavid Rees# This implementation is loosely based on the proto_library and
56*99e0aae7SDavid Rees# cc_proto_library rules that are included with Bazel.
57*99e0aae7SDavid Rees
58*99e0aae7SDavid ReesEmbossInfo = provider(
59*99e0aae7SDavid Rees    doc = "Encapsulates information provided by a `emboss_library.`",
60*99e0aae7SDavid Rees    fields = {
61*99e0aae7SDavid Rees        "direct_source": "(File) The `.emb` source files from the `srcs`" +
62*99e0aae7SDavid Rees                         " attribute.",
63*99e0aae7SDavid Rees        "transitive_sources": "(depset[File]) The `.emb` files from `srcs` " +
64*99e0aae7SDavid Rees                              "and all `deps`.",
65*99e0aae7SDavid Rees        "transitive_roots": "(list[str]) The root paths for all " +
66*99e0aae7SDavid Rees                            "transitive_sources.",
67*99e0aae7SDavid Rees        "direct_ir": "(list[File]) The `.emb.ir` files generated from the " +
68*99e0aae7SDavid Rees                     "`srcs`.",
69*99e0aae7SDavid Rees        "transitive_ir": "(depset[File]) The `.emb.ir` files generated from " +
70*99e0aae7SDavid Rees                         "transitive_srcs.",
71*99e0aae7SDavid Rees    },
72*99e0aae7SDavid Rees)
73*99e0aae7SDavid Rees
74*99e0aae7SDavid Reesdef _emboss_library_impl(ctx):
75*99e0aae7SDavid Rees    deps = [dep[EmbossInfo] for dep in ctx.attr.deps]
76*99e0aae7SDavid Rees    outs = []
77*99e0aae7SDavid Rees    if len(ctx.attr.srcs) != 1:
78*99e0aae7SDavid Rees        fail("`srcs` attribute must contain exactly one label.", attr = "srcs")
79*99e0aae7SDavid Rees    src = ctx.files.srcs[0]
80*99e0aae7SDavid Rees    out = ctx.actions.declare_file(src.basename + ".ir", sibling = src)
81*99e0aae7SDavid Rees    outs.append(out)
82*99e0aae7SDavid Rees    inputs = depset(
83*99e0aae7SDavid Rees        direct = [src],
84*99e0aae7SDavid Rees        transitive = [dep.transitive_sources for dep in deps],
85*99e0aae7SDavid Rees    )
86*99e0aae7SDavid Rees
87*99e0aae7SDavid Rees    # If the file is in an external repo, we want to use the path to that repo
88*99e0aae7SDavid Rees    # as the root (e.g. ./external/my-repo) so that import paths are resolved
89*99e0aae7SDavid Rees    # relative to the external repo root.
90*99e0aae7SDavid Rees    fixed_src_root = src.root.path
91*99e0aae7SDavid Rees    if src.path.startswith("external/"):
92*99e0aae7SDavid Rees        path_segments = src.path.split("/")[:2]
93*99e0aae7SDavid Rees        fixed_src_root = "/".join(path_segments)
94*99e0aae7SDavid Rees
95*99e0aae7SDavid Rees    transitive_roots = depset(
96*99e0aae7SDavid Rees        direct = [fixed_src_root],
97*99e0aae7SDavid Rees        transitive = [dep.transitive_roots for dep in deps],
98*99e0aae7SDavid Rees    )
99*99e0aae7SDavid Rees
100*99e0aae7SDavid Rees    imports = ["--import-dir=" + root for root in transitive_roots.to_list()]
101*99e0aae7SDavid Rees    imports_arg = ["--import-dir=" + impt.path for impt in ctx.files.import_dirs]
102*99e0aae7SDavid Rees    ctx.actions.run(
103*99e0aae7SDavid Rees        inputs = inputs.to_list(),
104*99e0aae7SDavid Rees        outputs = [out],
105*99e0aae7SDavid Rees        arguments = [src.path, "--output-file=" + out.path] + imports + imports_arg,
106*99e0aae7SDavid Rees        executable = ctx.executable._emboss_compiler,
107*99e0aae7SDavid Rees    )
108*99e0aae7SDavid Rees    transitive_sources = depset(
109*99e0aae7SDavid Rees        direct = [src],
110*99e0aae7SDavid Rees        transitive = [dep.transitive_sources for dep in deps],
111*99e0aae7SDavid Rees    )
112*99e0aae7SDavid Rees    transitive_ir = depset(
113*99e0aae7SDavid Rees        direct = outs,
114*99e0aae7SDavid Rees        transitive = [dep.transitive_ir for dep in deps],
115*99e0aae7SDavid Rees    )
116*99e0aae7SDavid Rees    return [
117*99e0aae7SDavid Rees        EmbossInfo(
118*99e0aae7SDavid Rees            direct_source = src,
119*99e0aae7SDavid Rees            transitive_sources = transitive_sources,
120*99e0aae7SDavid Rees            transitive_roots = transitive_roots,
121*99e0aae7SDavid Rees            direct_ir = outs,
122*99e0aae7SDavid Rees            transitive_ir = transitive_ir,
123*99e0aae7SDavid Rees        ),
124*99e0aae7SDavid Rees        DefaultInfo(
125*99e0aae7SDavid Rees            files = depset(outs),
126*99e0aae7SDavid Rees        ),
127*99e0aae7SDavid Rees    ]
128*99e0aae7SDavid Rees
129*99e0aae7SDavid Reesemboss_library = rule(
130*99e0aae7SDavid Rees    _emboss_library_impl,
131*99e0aae7SDavid Rees    attrs = {
132*99e0aae7SDavid Rees        "srcs": attr.label_list(
133*99e0aae7SDavid Rees            allow_files = [".emb"],
134*99e0aae7SDavid Rees        ),
135*99e0aae7SDavid Rees        "deps": attr.label_list(
136*99e0aae7SDavid Rees            providers = [EmbossInfo],
137*99e0aae7SDavid Rees        ),
138*99e0aae7SDavid Rees        "import_dirs": attr.label_list(
139*99e0aae7SDavid Rees            allow_files = True,
140*99e0aae7SDavid Rees        ),
141*99e0aae7SDavid Rees        "licenses": attr.license() if hasattr(attr, "license") else attr.string_list(),
142*99e0aae7SDavid Rees        "_emboss_compiler": attr.label(
143*99e0aae7SDavid Rees            executable = True,
144*99e0aae7SDavid Rees            cfg = "exec",
145*99e0aae7SDavid Rees            allow_files = True,
146*99e0aae7SDavid Rees            default = Label(
147*99e0aae7SDavid Rees                "@com_google_emboss//compiler/front_end:emboss_front_end",
148*99e0aae7SDavid Rees            ),
149*99e0aae7SDavid Rees        ),
150*99e0aae7SDavid Rees    },
151*99e0aae7SDavid Rees    provides = [EmbossInfo],
152*99e0aae7SDavid Rees)
153*99e0aae7SDavid Rees
154*99e0aae7SDavid ReesEmbossCcHeaderInfo = provider(
155*99e0aae7SDavid Rees    fields = {
156*99e0aae7SDavid Rees        "headers": "(list[File]) The `.emb.h` headers from this rule.",
157*99e0aae7SDavid Rees        "transitive_headers": "(list[File]) The `.emb.h` headers from this " +
158*99e0aae7SDavid Rees                              "rule and all dependencies.",
159*99e0aae7SDavid Rees    },
160*99e0aae7SDavid Rees    doc = "Provide cc emboss headers.",
161*99e0aae7SDavid Rees)
162*99e0aae7SDavid Rees
163*99e0aae7SDavid Reesdef _cc_emboss_aspect_impl(target, ctx):
164*99e0aae7SDavid Rees    cc_toolchain = find_cpp_toolchain(ctx, mandatory = True)
165*99e0aae7SDavid Rees    emboss_cc_compiler = ctx.executable._emboss_cc_compiler
166*99e0aae7SDavid Rees    emboss_info = target[EmbossInfo]
167*99e0aae7SDavid Rees    feature_configuration = cc_common.configure_features(
168*99e0aae7SDavid Rees        ctx = ctx,
169*99e0aae7SDavid Rees        cc_toolchain = cc_toolchain,
170*99e0aae7SDavid Rees        requested_features = list(ctx.features),
171*99e0aae7SDavid Rees        unsupported_features = list(ctx.disabled_features),
172*99e0aae7SDavid Rees    )
173*99e0aae7SDavid Rees    src = target[EmbossInfo].direct_source
174*99e0aae7SDavid Rees    headers = [ ctx.actions.declare_file( src.basename + ".h", sibling = src) ]
175*99e0aae7SDavid Rees    args = ctx.actions.args()
176*99e0aae7SDavid Rees    args.add("--input-file")
177*99e0aae7SDavid Rees    args.add_all(emboss_info.direct_ir)
178*99e0aae7SDavid Rees    args.add("--output-file")
179*99e0aae7SDavid Rees    args.add_all(headers)
180*99e0aae7SDavid Rees    if not ctx.attr.enable_enum_traits:
181*99e0aae7SDavid Rees      args.add("--no-cc-enum-traits")
182*99e0aae7SDavid Rees    ctx.actions.run(
183*99e0aae7SDavid Rees        executable = emboss_cc_compiler,
184*99e0aae7SDavid Rees        arguments = [args],
185*99e0aae7SDavid Rees        inputs = emboss_info.direct_ir,
186*99e0aae7SDavid Rees        outputs = headers,
187*99e0aae7SDavid Rees    )
188*99e0aae7SDavid Rees    runtime_cc_info = ctx.attr._emboss_cc_runtime[CcInfo]
189*99e0aae7SDavid Rees    transitive_headers = depset(
190*99e0aae7SDavid Rees        direct = headers,
191*99e0aae7SDavid Rees        transitive = [
192*99e0aae7SDavid Rees                         dep[EmbossCcHeaderInfo].transitive_headers
193*99e0aae7SDavid Rees                         for dep in ctx.rule.attr.deps
194*99e0aae7SDavid Rees                     ],
195*99e0aae7SDavid Rees    )
196*99e0aae7SDavid Rees    (cc_compilation_context, cc_compilation_outputs) = cc_common.compile(
197*99e0aae7SDavid Rees        name = ctx.label.name,
198*99e0aae7SDavid Rees        actions = ctx.actions,
199*99e0aae7SDavid Rees        feature_configuration = feature_configuration,
200*99e0aae7SDavid Rees        cc_toolchain = cc_toolchain,
201*99e0aae7SDavid Rees        public_hdrs = headers,
202*99e0aae7SDavid Rees        private_hdrs = transitive_headers.to_list(),
203*99e0aae7SDavid Rees        compilation_contexts = [runtime_cc_info.compilation_context],
204*99e0aae7SDavid Rees    )
205*99e0aae7SDavid Rees    return [
206*99e0aae7SDavid Rees        CcInfo(compilation_context = cc_compilation_context),
207*99e0aae7SDavid Rees        EmbossCcHeaderInfo(
208*99e0aae7SDavid Rees            headers = depset(headers),
209*99e0aae7SDavid Rees            transitive_headers = transitive_headers,
210*99e0aae7SDavid Rees        ),
211*99e0aae7SDavid Rees    ]
212*99e0aae7SDavid Rees
213*99e0aae7SDavid Rees_cc_emboss_aspect = aspect(
214*99e0aae7SDavid Rees    implementation = _cc_emboss_aspect_impl,
215*99e0aae7SDavid Rees    attr_aspects = ["deps"],
216*99e0aae7SDavid Rees    fragments = ["cpp"],
217*99e0aae7SDavid Rees    required_providers = [EmbossInfo],
218*99e0aae7SDavid Rees    attrs = {
219*99e0aae7SDavid Rees        "_cc_toolchain": attr.label(
220*99e0aae7SDavid Rees            default = "@bazel_tools//tools/cpp:current_cc_toolchain",
221*99e0aae7SDavid Rees        ),
222*99e0aae7SDavid Rees        "_emboss_cc_compiler": attr.label(
223*99e0aae7SDavid Rees            executable = True,
224*99e0aae7SDavid Rees            cfg = "exec",
225*99e0aae7SDavid Rees            default = "@com_google_emboss//compiler/back_end/cpp:emboss_codegen_cpp",
226*99e0aae7SDavid Rees        ),
227*99e0aae7SDavid Rees        "_emboss_cc_runtime": attr.label(
228*99e0aae7SDavid Rees            default = "@com_google_emboss//runtime/cpp:cpp_utils",
229*99e0aae7SDavid Rees        ),
230*99e0aae7SDavid Rees        "enable_enum_traits": attr.bool(
231*99e0aae7SDavid Rees            default = True,
232*99e0aae7SDavid Rees        ),
233*99e0aae7SDavid Rees    },
234*99e0aae7SDavid Rees    toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
235*99e0aae7SDavid Rees)
236*99e0aae7SDavid Rees
237*99e0aae7SDavid Reesdef _cc_emboss_library_impl(ctx):
238*99e0aae7SDavid Rees    if len(ctx.attr.deps) != 1:
239*99e0aae7SDavid Rees        fail("`deps` attribute must contain exactly one label.", attr = "deps")
240*99e0aae7SDavid Rees    dep = ctx.attr.deps[0]
241*99e0aae7SDavid Rees    return [
242*99e0aae7SDavid Rees        dep[CcInfo],
243*99e0aae7SDavid Rees        dep[EmbossInfo],
244*99e0aae7SDavid Rees        DefaultInfo(files = dep[EmbossCcHeaderInfo].headers),
245*99e0aae7SDavid Rees    ]
246*99e0aae7SDavid Rees
247*99e0aae7SDavid Reescc_emboss_library = rule(
248*99e0aae7SDavid Rees    implementation = _cc_emboss_library_impl,
249*99e0aae7SDavid Rees    attrs = {
250*99e0aae7SDavid Rees        "deps": attr.label_list(
251*99e0aae7SDavid Rees            aspects = [_cc_emboss_aspect],
252*99e0aae7SDavid Rees            allow_rules = ["emboss_library"],
253*99e0aae7SDavid Rees            allow_files = False,
254*99e0aae7SDavid Rees        ),
255*99e0aae7SDavid Rees        "enable_enum_traits": attr.bool(
256*99e0aae7SDavid Rees            default = True,
257*99e0aae7SDavid Rees        ),
258*99e0aae7SDavid Rees    },
259*99e0aae7SDavid Rees    provides = [CcInfo, EmbossInfo],
260*99e0aae7SDavid Rees)
261