xref: /aosp_15_r20/build/bazel/rules/cc/flex.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker"""Copyright (C) 2022 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker
3*7594170eSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard WorkerYou 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 WorkerUnless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Workerlimitations under the License.
14*7594170eSAndroid Build Coastguard Worker"""
15*7594170eSAndroid Build Coastguard Worker
16*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:paths.bzl", "paths")
17*7594170eSAndroid Build Coastguard Worker
18*7594170eSAndroid Build Coastguard Worker"""Build rule for converting `.l` or `.ll` to C or C++ sources with Flex.
19*7594170eSAndroid Build Coastguard Worker
20*7594170eSAndroid Build Coastguard WorkerUses flex (and m4 under the hood) to convert .l and .ll source files into
21*7594170eSAndroid Build Coastguard Worker.c and .cc files. Does not support .lex or .lpp extensions
22*7594170eSAndroid Build Coastguard Worker
23*7594170eSAndroid Build Coastguard WorkerExamples
24*7594170eSAndroid Build Coastguard Worker--------
25*7594170eSAndroid Build Coastguard Worker
26*7594170eSAndroid Build Coastguard WorkerThis is a simple example.
27*7594170eSAndroid Build Coastguard Worker```
28*7594170eSAndroid Build Coastguard Workergenlex(
29*7594170eSAndroid Build Coastguard Worker    name = "html_lex",
30*7594170eSAndroid Build Coastguard Worker    src = "html.l",
31*7594170eSAndroid Build Coastguard Worker)
32*7594170eSAndroid Build Coastguard Worker```
33*7594170eSAndroid Build Coastguard Worker
34*7594170eSAndroid Build Coastguard WorkerThis example uses some options for flex.
35*7594170eSAndroid Build Coastguard Worker```
36*7594170eSAndroid Build Coastguard Workergenlex(
37*7594170eSAndroid Build Coastguard Worker    name = "rules_l",
38*7594170eSAndroid Build Coastguard Worker    src = "rules.l",
39*7594170eSAndroid Build Coastguard Worker    lexopts = ["-d", "-v"],
40*7594170eSAndroid Build Coastguard Worker)
41*7594170eSAndroid Build Coastguard Worker```
42*7594170eSAndroid Build Coastguard Worker"""
43*7594170eSAndroid Build Coastguard Worker
44*7594170eSAndroid Build Coastguard Workerdef _genlex_impl(ctx):
45*7594170eSAndroid Build Coastguard Worker    """Implementation for genlex rule."""
46*7594170eSAndroid Build Coastguard Worker
47*7594170eSAndroid Build Coastguard Worker    # TODO(b/190006308): When fixed, l and ll sources can coexist. Remove this.
48*7594170eSAndroid Build Coastguard Worker    exts = [f.extension for f in ctx.files.srcs]
49*7594170eSAndroid Build Coastguard Worker    contains_l = False
50*7594170eSAndroid Build Coastguard Worker    contains_ll = False
51*7594170eSAndroid Build Coastguard Worker    for ext in exts:
52*7594170eSAndroid Build Coastguard Worker        if ext == "l":
53*7594170eSAndroid Build Coastguard Worker            contains_l = True
54*7594170eSAndroid Build Coastguard Worker        if ext == "ll":
55*7594170eSAndroid Build Coastguard Worker            contains_ll = True
56*7594170eSAndroid Build Coastguard Worker    if contains_l and contains_ll:
57*7594170eSAndroid Build Coastguard Worker        fail(
58*7594170eSAndroid Build Coastguard Worker            "srcs contains both .l and .ll files. Please use separate targets.",
59*7594170eSAndroid Build Coastguard Worker        )
60*7594170eSAndroid Build Coastguard Worker
61*7594170eSAndroid Build Coastguard Worker    outputs = []
62*7594170eSAndroid Build Coastguard Worker    for src_file in ctx.files.srcs:
63*7594170eSAndroid Build Coastguard Worker        args = ctx.actions.args()
64*7594170eSAndroid Build Coastguard Worker        output_filename = ""
65*7594170eSAndroid Build Coastguard Worker
66*7594170eSAndroid Build Coastguard Worker        src_ext = src_file.extension
67*7594170eSAndroid Build Coastguard Worker        split_filename = src_file.basename.partition(".")
68*7594170eSAndroid Build Coastguard Worker        filename_without_ext = split_filename[0]
69*7594170eSAndroid Build Coastguard Worker
70*7594170eSAndroid Build Coastguard Worker        if src_ext == "l":
71*7594170eSAndroid Build Coastguard Worker            output_filename = paths.replace_extension(filename_without_ext, ".c")
72*7594170eSAndroid Build Coastguard Worker        elif src_ext == "ll":
73*7594170eSAndroid Build Coastguard Worker            output_filename = paths.replace_extension(filename_without_ext, ".cc")
74*7594170eSAndroid Build Coastguard Worker        output_file = ctx.actions.declare_file(output_filename)
75*7594170eSAndroid Build Coastguard Worker        outputs.append(output_file)
76*7594170eSAndroid Build Coastguard Worker        args.add("-o", output_file.path)
77*7594170eSAndroid Build Coastguard Worker
78*7594170eSAndroid Build Coastguard Worker        args.add_all(ctx.attr.lexopts)
79*7594170eSAndroid Build Coastguard Worker        args.add(src_file)
80*7594170eSAndroid Build Coastguard Worker
81*7594170eSAndroid Build Coastguard Worker        ctx.actions.run(
82*7594170eSAndroid Build Coastguard Worker            executable = ctx.executable._flex,
83*7594170eSAndroid Build Coastguard Worker            env = {
84*7594170eSAndroid Build Coastguard Worker                "M4": ctx.executable._m4.path,
85*7594170eSAndroid Build Coastguard Worker            },
86*7594170eSAndroid Build Coastguard Worker            arguments = [args],
87*7594170eSAndroid Build Coastguard Worker            inputs = [src_file],
88*7594170eSAndroid Build Coastguard Worker            tools = [ctx.executable._m4],
89*7594170eSAndroid Build Coastguard Worker            outputs = [output_file],
90*7594170eSAndroid Build Coastguard Worker            mnemonic = "Flex",
91*7594170eSAndroid Build Coastguard Worker            progress_message = "Generating %s from %s" % (
92*7594170eSAndroid Build Coastguard Worker                output_filename,
93*7594170eSAndroid Build Coastguard Worker                src_file.short_path,
94*7594170eSAndroid Build Coastguard Worker            ),
95*7594170eSAndroid Build Coastguard Worker        )
96*7594170eSAndroid Build Coastguard Worker    return [DefaultInfo(files = depset(outputs))]
97*7594170eSAndroid Build Coastguard Worker
98*7594170eSAndroid Build Coastguard Workergenlex = rule(
99*7594170eSAndroid Build Coastguard Worker    implementation = _genlex_impl,
100*7594170eSAndroid Build Coastguard Worker    doc = "Generate C/C++-language sources from a lex file using Flex.",
101*7594170eSAndroid Build Coastguard Worker    attrs = {
102*7594170eSAndroid Build Coastguard Worker        "srcs": attr.label_list(
103*7594170eSAndroid Build Coastguard Worker            mandatory = True,
104*7594170eSAndroid Build Coastguard Worker            allow_files = [".l", ".ll"],
105*7594170eSAndroid Build Coastguard Worker            doc = "The lex source file for this rule",
106*7594170eSAndroid Build Coastguard Worker        ),
107*7594170eSAndroid Build Coastguard Worker        "lexopts": attr.string_list(
108*7594170eSAndroid Build Coastguard Worker            doc = "A list of options to be added to the flex command line.",
109*7594170eSAndroid Build Coastguard Worker        ),
110*7594170eSAndroid Build Coastguard Worker        "_flex": attr.label(
111*7594170eSAndroid Build Coastguard Worker            default = "//prebuilts/build-tools:flex",
112*7594170eSAndroid Build Coastguard Worker            executable = True,
113*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
114*7594170eSAndroid Build Coastguard Worker        ),
115*7594170eSAndroid Build Coastguard Worker        "_m4": attr.label(
116*7594170eSAndroid Build Coastguard Worker            default = "//prebuilts/build-tools:m4",
117*7594170eSAndroid Build Coastguard Worker            executable = True,
118*7594170eSAndroid Build Coastguard Worker            cfg = "exec",
119*7594170eSAndroid Build Coastguard Worker        ),
120*7594170eSAndroid Build Coastguard Worker    },
121*7594170eSAndroid Build Coastguard Worker)
122