122 lines
3.5 KiB
Python
122 lines
3.5 KiB
Python
|
|
"""Copyright (C) 2022 The Android Open Source Project
|
||
|
|
|
||
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
|
you may not use this file except in compliance with the License.
|
||
|
|
You may obtain a copy of the License at
|
||
|
|
|
||
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
|
||
|
|
Unless required by applicable law or agreed to in writing, software
|
||
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
|
See the License for the specific language governing permissions and
|
||
|
|
limitations under the License.
|
||
|
|
"""
|
||
|
|
|
||
|
|
load("@bazel_skylib//lib:paths.bzl", "paths")
|
||
|
|
|
||
|
|
"""Build rule for converting `.l` or `.ll` to C or C++ sources with Flex.
|
||
|
|
|
||
|
|
Uses flex (and m4 under the hood) to convert .l and .ll source files into
|
||
|
|
.c and .cc files. Does not support .lex or .lpp extensions
|
||
|
|
|
||
|
|
Examples
|
||
|
|
--------
|
||
|
|
|
||
|
|
This is a simple example.
|
||
|
|
```
|
||
|
|
genlex(
|
||
|
|
name = "html_lex",
|
||
|
|
src = "html.l",
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
This example uses some options for flex.
|
||
|
|
```
|
||
|
|
genlex(
|
||
|
|
name = "rules_l",
|
||
|
|
src = "rules.l",
|
||
|
|
lexopts = ["-d", "-v"],
|
||
|
|
)
|
||
|
|
```
|
||
|
|
"""
|
||
|
|
|
||
|
|
def _genlex_impl(ctx):
|
||
|
|
"""Implementation for genlex rule."""
|
||
|
|
|
||
|
|
# TODO(b/190006308): When fixed, l and ll sources can coexist. Remove this.
|
||
|
|
exts = [f.extension for f in ctx.files.srcs]
|
||
|
|
contains_l = False
|
||
|
|
contains_ll = False
|
||
|
|
for ext in exts:
|
||
|
|
if ext == "l":
|
||
|
|
contains_l = True
|
||
|
|
if ext == "ll":
|
||
|
|
contains_ll = True
|
||
|
|
if contains_l and contains_ll:
|
||
|
|
fail(
|
||
|
|
"srcs contains both .l and .ll files. Please use separate targets.",
|
||
|
|
)
|
||
|
|
|
||
|
|
outputs = []
|
||
|
|
for src_file in ctx.files.srcs:
|
||
|
|
args = ctx.actions.args()
|
||
|
|
output_filename = ""
|
||
|
|
|
||
|
|
src_ext = src_file.extension
|
||
|
|
split_filename = src_file.basename.partition(".")
|
||
|
|
filename_without_ext = split_filename[0]
|
||
|
|
|
||
|
|
if src_ext == "l":
|
||
|
|
output_filename = paths.replace_extension(filename_without_ext, ".c")
|
||
|
|
elif src_ext == "ll":
|
||
|
|
output_filename = paths.replace_extension(filename_without_ext, ".cc")
|
||
|
|
output_file = ctx.actions.declare_file(output_filename)
|
||
|
|
outputs.append(output_file)
|
||
|
|
args.add("-o", output_file.path)
|
||
|
|
|
||
|
|
args.add_all(ctx.attr.lexopts)
|
||
|
|
args.add(src_file)
|
||
|
|
|
||
|
|
ctx.actions.run(
|
||
|
|
executable = ctx.executable._flex,
|
||
|
|
env = {
|
||
|
|
"M4": ctx.executable._m4.path,
|
||
|
|
},
|
||
|
|
arguments = [args],
|
||
|
|
inputs = [src_file],
|
||
|
|
tools = [ctx.executable._m4],
|
||
|
|
outputs = [output_file],
|
||
|
|
mnemonic = "Flex",
|
||
|
|
progress_message = "Generating %s from %s" % (
|
||
|
|
output_filename,
|
||
|
|
src_file.short_path,
|
||
|
|
),
|
||
|
|
)
|
||
|
|
return [DefaultInfo(files = depset(outputs))]
|
||
|
|
|
||
|
|
genlex = rule(
|
||
|
|
implementation = _genlex_impl,
|
||
|
|
doc = "Generate C/C++-language sources from a lex file using Flex.",
|
||
|
|
attrs = {
|
||
|
|
"srcs": attr.label_list(
|
||
|
|
mandatory = True,
|
||
|
|
allow_files = [".l", ".ll"],
|
||
|
|
doc = "The lex source file for this rule",
|
||
|
|
),
|
||
|
|
"lexopts": attr.string_list(
|
||
|
|
doc = "A list of options to be added to the flex command line.",
|
||
|
|
),
|
||
|
|
"_flex": attr.label(
|
||
|
|
default = "//prebuilts/build-tools:flex",
|
||
|
|
executable = True,
|
||
|
|
cfg = "exec",
|
||
|
|
),
|
||
|
|
"_m4": attr.label(
|
||
|
|
default = "//prebuilts/build-tools:m4",
|
||
|
|
executable = True,
|
||
|
|
cfg = "exec",
|
||
|
|
),
|
||
|
|
},
|
||
|
|
)
|