The last sed command used for adding the import statement and the '\n' was working as intended on Linux, but was failing on macOS, due to the difference in sed behavior between GNU and BSD. Fixed the issue by using an actual newline character with $'\n', which correctly works on both platforms. Fixes https://github.com/tensorflow/tensorflow/issues/39756 PiperOrigin-RevId: 313691192 Change-Id: I96e5544c03641bae05753e8f7d1346c8aa1c0f6e
612 lines
21 KiB
Python
612 lines
21 KiB
Python
"""BUILD rules for generating flatbuffer files."""
|
|
|
|
load("@build_bazel_rules_android//android:rules.bzl", "android_library")
|
|
|
|
flatc_path = "@flatbuffers//:flatc"
|
|
zip_files = "//tensorflow/lite/tools:zip_files"
|
|
|
|
DEFAULT_INCLUDE_PATHS = [
|
|
"./",
|
|
"$(GENDIR)",
|
|
"$(BINDIR)",
|
|
]
|
|
|
|
DEFAULT_FLATC_ARGS = [
|
|
"--no-union-value-namespacing",
|
|
"--gen-object-api",
|
|
]
|
|
|
|
def flatbuffer_library_public(
|
|
name,
|
|
srcs,
|
|
outs,
|
|
language_flag,
|
|
out_prefix = "",
|
|
includes = [],
|
|
include_paths = [],
|
|
flatc_args = DEFAULT_FLATC_ARGS,
|
|
reflection_name = "",
|
|
reflection_visibility = None,
|
|
output_to_bindir = False):
|
|
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
|
|
|
|
Outs:
|
|
filegroup(name): all generated source files.
|
|
Fileset([reflection_name]): (Optional) all generated reflection binaries.
|
|
|
|
Args:
|
|
name: Rule name.
|
|
srcs: Source .fbs files. Sent in order to the compiler.
|
|
outs: Output files from flatc.
|
|
language_flag: Target language flag. One of [-c, -j, -js].
|
|
out_prefix: Prepend this path to the front of all generated files except on
|
|
single source targets. Usually is a directory name.
|
|
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
|
include_paths: Optional, list of paths the includes files can be found in.
|
|
flatc_args: Optional, list of additional arguments to pass to flatc.
|
|
reflection_name: Optional, if set this will generate the flatbuffer
|
|
reflection binaries for the schemas.
|
|
reflection_visibility: The visibility of the generated reflection Fileset.
|
|
output_to_bindir: Passed to genrule for output to bin directory.
|
|
"""
|
|
include_paths_cmd = ["-I %s" % (s) for s in include_paths]
|
|
|
|
# '$(@D)' when given a single source target will give the appropriate
|
|
# directory. Appending 'out_prefix' is only necessary when given a build
|
|
# target with multiple sources.
|
|
output_directory = (
|
|
("-o $(@D)/%s" % (out_prefix)) if len(srcs) > 1 else ("-o $(@D)")
|
|
)
|
|
genrule_cmd = " ".join([
|
|
"for f in $(SRCS); do",
|
|
"$(location %s)" % (flatc_path),
|
|
" ".join(flatc_args),
|
|
" ".join(include_paths_cmd),
|
|
language_flag,
|
|
output_directory,
|
|
"$$f;",
|
|
"done",
|
|
])
|
|
native.genrule(
|
|
name = name,
|
|
srcs = srcs,
|
|
outs = outs,
|
|
output_to_bindir = output_to_bindir,
|
|
tools = includes + [flatc_path],
|
|
cmd = genrule_cmd,
|
|
message = "Generating flatbuffer files for %s:" % (name),
|
|
)
|
|
if reflection_name:
|
|
reflection_genrule_cmd = " ".join([
|
|
"for f in $(SRCS); do",
|
|
"$(location %s)" % (flatc_path),
|
|
"-b --schema",
|
|
" ".join(flatc_args),
|
|
" ".join(include_paths_cmd),
|
|
language_flag,
|
|
output_directory,
|
|
"$$f;",
|
|
"done",
|
|
])
|
|
reflection_outs = [
|
|
(out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
|
|
for s in srcs
|
|
]
|
|
native.genrule(
|
|
name = "%s_srcs" % reflection_name,
|
|
srcs = srcs,
|
|
outs = reflection_outs,
|
|
output_to_bindir = output_to_bindir,
|
|
tools = includes + [flatc_path],
|
|
cmd = reflection_genrule_cmd,
|
|
message = "Generating flatbuffer reflection binary for %s:" % (name),
|
|
)
|
|
# TODO(b/114456773): Make bazel rules proper and supported by flatbuffer
|
|
# Have to comment this since FilesetEntry is not supported in bazel
|
|
# skylark.
|
|
# native.Fileset(
|
|
# name = reflection_name,
|
|
# out = "%s_out" % reflection_name,
|
|
# entries = [
|
|
# native.FilesetEntry(files = reflection_outs),
|
|
# ],
|
|
# visibility = reflection_visibility,
|
|
# )
|
|
|
|
def flatbuffer_cc_library(
|
|
name,
|
|
srcs,
|
|
srcs_filegroup_name = "",
|
|
out_prefix = "",
|
|
includes = [],
|
|
include_paths = [],
|
|
flatc_args = DEFAULT_FLATC_ARGS,
|
|
visibility = None,
|
|
srcs_filegroup_visibility = None,
|
|
gen_reflections = False):
|
|
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
|
|
|
|
Outs:
|
|
filegroup([name]_srcs): all generated .h files.
|
|
filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
|
|
Other flatbuffer_cc_library's can pass this in for their `includes`
|
|
parameter, if they depend on the schemas in this library.
|
|
Fileset([name]_reflection): (Optional) all generated reflection binaries.
|
|
cc_library([name]): library with sources and flatbuffers deps.
|
|
|
|
Remarks:
|
|
** Because the genrule used to call flatc does not have any trivial way of
|
|
computing the output list of files transitively generated by includes and
|
|
--gen-includes (the default) being defined for flatc, the --gen-includes
|
|
flag will not work as expected. The way around this is to add a dependency
|
|
to the flatbuffer_cc_library defined alongside the flatc included Fileset.
|
|
For example you might define:
|
|
|
|
flatbuffer_cc_library(
|
|
name = "my_fbs",
|
|
srcs = [ "schemas/foo.fbs" ],
|
|
includes = [ "//third_party/bazz:bazz_fbs_includes" ],
|
|
)
|
|
|
|
In which foo.fbs includes a few files from the Fileset defined at
|
|
//third_party/bazz:bazz_fbs_includes. When compiling the library that
|
|
includes foo_generated.h, and therefore has my_fbs as a dependency, it
|
|
will fail to find any of the bazz *_generated.h files unless you also
|
|
add bazz's flatbuffer_cc_library to your own dependency list, e.g.:
|
|
|
|
cc_library(
|
|
name = "my_lib",
|
|
deps = [
|
|
":my_fbs",
|
|
"//third_party/bazz:bazz_fbs"
|
|
],
|
|
)
|
|
|
|
Happy dependent Flatbuffering!
|
|
|
|
Args:
|
|
name: Rule name.
|
|
srcs: Source .fbs files. Sent in order to the compiler.
|
|
srcs_filegroup_name: Name of the output filegroup that holds srcs. Pass this
|
|
filegroup into the `includes` parameter of any other
|
|
flatbuffer_cc_library that depends on this one's schemas.
|
|
out_prefix: Prepend this path to the front of all generated files. Usually
|
|
is a directory name.
|
|
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
|
** SEE REMARKS BELOW **
|
|
include_paths: Optional, list of paths the includes files can be found in.
|
|
flatc_args: Optional list of additional arguments to pass to flatc
|
|
(e.g. --gen-mutable).
|
|
visibility: The visibility of the generated cc_library. By default, use the
|
|
default visibility of the project.
|
|
srcs_filegroup_visibility: The visibility of the generated srcs filegroup.
|
|
By default, use the value of the visibility parameter above.
|
|
gen_reflections: Optional, if true this will generate the flatbuffer
|
|
reflection binaries for the schemas.
|
|
'''
|
|
output_headers = [
|
|
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
|
|
for s in srcs
|
|
]
|
|
reflection_name = "%s_reflection" % name if gen_reflections else ""
|
|
|
|
flatbuffer_library_public(
|
|
name = "%s_srcs" % (name),
|
|
srcs = srcs,
|
|
outs = output_headers,
|
|
language_flag = "-c",
|
|
out_prefix = out_prefix,
|
|
includes = includes,
|
|
include_paths = include_paths,
|
|
flatc_args = flatc_args,
|
|
reflection_name = reflection_name,
|
|
reflection_visibility = visibility,
|
|
)
|
|
native.cc_library(
|
|
name = name,
|
|
hdrs = output_headers,
|
|
srcs = output_headers,
|
|
features = [
|
|
"-parse_headers",
|
|
],
|
|
deps = [
|
|
"@flatbuffers//:runtime_cc",
|
|
],
|
|
includes = ["."],
|
|
linkstatic = 1,
|
|
visibility = visibility,
|
|
)
|
|
|
|
# A filegroup for the `srcs`. That is, all the schema files for this
|
|
# Flatbuffer set.
|
|
native.filegroup(
|
|
name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
|
|
srcs = srcs,
|
|
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
|
|
)
|
|
|
|
# Custom provider to track dependencies transitively.
|
|
FlatbufferInfo = provider(
|
|
fields = {
|
|
"transitive_srcs": "flatbuffer schema definitions.",
|
|
},
|
|
)
|
|
|
|
def _flatbuffer_schemas_aspect_impl(target, ctx):
|
|
_ignore = [target]
|
|
transitive_srcs = depset()
|
|
if hasattr(ctx.rule.attr, "deps"):
|
|
for dep in ctx.rule.attr.deps:
|
|
if FlatbufferInfo in dep:
|
|
transitive_srcs = depset(dep[FlatbufferInfo].transitive_srcs, transitive = [transitive_srcs])
|
|
if hasattr(ctx.rule.attr, "srcs"):
|
|
for src in ctx.rule.attr.srcs:
|
|
if FlatbufferInfo in src:
|
|
transitive_srcs = depset(src[FlatbufferInfo].transitive_srcs, transitive = [transitive_srcs])
|
|
for f in src.files:
|
|
if f.extension == "fbs":
|
|
transitive_srcs = depset([f], transitive = [transitive_srcs])
|
|
return [FlatbufferInfo(transitive_srcs = transitive_srcs)]
|
|
|
|
# An aspect that runs over all dependencies and transitively collects
|
|
# flatbuffer schema files.
|
|
_flatbuffer_schemas_aspect = aspect(
|
|
attr_aspects = [
|
|
"deps",
|
|
"srcs",
|
|
],
|
|
implementation = _flatbuffer_schemas_aspect_impl,
|
|
)
|
|
|
|
# Rule to invoke the flatbuffer compiler.
|
|
def _gen_flatbuffer_srcs_impl(ctx):
|
|
outputs = ctx.attr.outputs
|
|
include_paths = ctx.attr.include_paths
|
|
if ctx.attr.no_includes:
|
|
no_includes_statement = ["--no-includes"]
|
|
else:
|
|
no_includes_statement = []
|
|
|
|
# Need to generate all files in a directory.
|
|
if not outputs:
|
|
outputs = [ctx.actions.declare_directory("{}_all".format(ctx.attr.name))]
|
|
output_directory = outputs[0].path
|
|
else:
|
|
outputs = [ctx.actions.declare_file(output) for output in outputs]
|
|
output_directory = outputs[0].dirname
|
|
|
|
deps = depset(ctx.files.srcs + ctx.files.deps, transitive = [
|
|
dep[FlatbufferInfo].transitive_srcs
|
|
for dep in ctx.attr.deps
|
|
if FlatbufferInfo in dep
|
|
])
|
|
|
|
include_paths_cmd_line = []
|
|
for s in include_paths:
|
|
include_paths_cmd_line.extend(["-I", s])
|
|
|
|
for src in ctx.files.srcs:
|
|
ctx.actions.run(
|
|
inputs = deps,
|
|
outputs = outputs,
|
|
executable = ctx.executable._flatc,
|
|
arguments = [
|
|
ctx.attr.language_flag,
|
|
"-o",
|
|
output_directory,
|
|
# Allow for absolute imports and referencing of generated files.
|
|
"-I",
|
|
"./",
|
|
"-I",
|
|
ctx.genfiles_dir.path,
|
|
"-I",
|
|
ctx.bin_dir.path,
|
|
] + no_includes_statement +
|
|
include_paths_cmd_line + [
|
|
"--no-union-value-namespacing",
|
|
"--gen-object-api",
|
|
src.path,
|
|
],
|
|
progress_message = "Generating flatbuffer files for {}:".format(src),
|
|
)
|
|
return [
|
|
DefaultInfo(files = depset(outputs)),
|
|
]
|
|
|
|
_gen_flatbuffer_srcs = rule(
|
|
_gen_flatbuffer_srcs_impl,
|
|
attrs = {
|
|
"srcs": attr.label_list(
|
|
allow_files = [".fbs"],
|
|
mandatory = True,
|
|
),
|
|
"outputs": attr.string_list(
|
|
default = [],
|
|
mandatory = False,
|
|
),
|
|
"deps": attr.label_list(
|
|
default = [],
|
|
mandatory = False,
|
|
aspects = [_flatbuffer_schemas_aspect],
|
|
),
|
|
"include_paths": attr.string_list(
|
|
default = [],
|
|
mandatory = False,
|
|
),
|
|
"language_flag": attr.string(
|
|
mandatory = True,
|
|
),
|
|
"no_includes": attr.bool(
|
|
default = False,
|
|
mandatory = False,
|
|
),
|
|
"_flatc": attr.label(
|
|
default = Label("@flatbuffers//:flatc"),
|
|
executable = True,
|
|
cfg = "host",
|
|
),
|
|
},
|
|
output_to_genfiles = True,
|
|
)
|
|
|
|
def _concat_flatbuffer_py_srcs_impl(ctx):
|
|
# Merge all generated python files. The files are concatenated and the
|
|
# import statements are removed. Finally we import the flatbuffer runtime
|
|
# library.
|
|
ctx.actions.run_shell(
|
|
inputs = ctx.attr.deps[0].files,
|
|
outputs = [ctx.outputs.out],
|
|
command = (
|
|
"find '%s' -name '*.py' -exec cat {} + |" +
|
|
"sed '/import flatbuffers/d' |" +
|
|
"sed 's/from flatbuffers." +
|
|
"/from flatbuffers.python.flatbuffers./' |" +
|
|
"sed '1s/^/from flatbuffers.python " +
|
|
"import flatbuffers\\'$'\\n/' > %s"
|
|
) % (
|
|
ctx.attr.deps[0].files.to_list()[0].path,
|
|
ctx.outputs.out.path,
|
|
),
|
|
)
|
|
|
|
_concat_flatbuffer_py_srcs = rule(
|
|
_concat_flatbuffer_py_srcs_impl,
|
|
attrs = {
|
|
"deps": attr.label_list(mandatory = True),
|
|
},
|
|
output_to_genfiles = True,
|
|
outputs = {"out": "%{name}.py"},
|
|
)
|
|
|
|
def flatbuffer_py_library(
|
|
name,
|
|
srcs,
|
|
deps = [],
|
|
include_paths = []):
|
|
"""A py_library with the generated reader/writers for the given schema.
|
|
|
|
This rule assumes that the schema files define non-conflicting names, so that
|
|
they can be merged in a single file. This is e.g. the case if only a single
|
|
namespace is used.
|
|
The rule call the flatbuffer compiler for all schema files and merges the
|
|
generated python files into a single file that is wrapped in a py_library.
|
|
|
|
Args:
|
|
name: Rule name. (required)
|
|
srcs: List of source .fbs files. (required)
|
|
deps: List of dependencies.
|
|
include_paths: Optional, list of paths the includes files can be found in.
|
|
"""
|
|
all_srcs = "{}_srcs".format(name)
|
|
_gen_flatbuffer_srcs(
|
|
name = all_srcs,
|
|
srcs = srcs,
|
|
language_flag = "--python",
|
|
deps = deps,
|
|
include_paths = include_paths,
|
|
)
|
|
all_srcs_no_include = "{}_srcs_no_include".format(name)
|
|
_gen_flatbuffer_srcs(
|
|
name = all_srcs_no_include,
|
|
srcs = srcs,
|
|
language_flag = "--python",
|
|
deps = deps,
|
|
no_includes = True,
|
|
include_paths = include_paths,
|
|
)
|
|
concat_py_srcs = "{}_generated".format(name)
|
|
_concat_flatbuffer_py_srcs(
|
|
name = concat_py_srcs,
|
|
deps = [
|
|
":{}".format(all_srcs_no_include),
|
|
],
|
|
)
|
|
native.py_library(
|
|
name = name,
|
|
srcs = [
|
|
":{}".format(concat_py_srcs),
|
|
],
|
|
srcs_version = "PY2AND3",
|
|
deps = deps + [
|
|
"@flatbuffers//:runtime_py",
|
|
],
|
|
)
|
|
|
|
def flatbuffer_java_library(
|
|
name,
|
|
srcs,
|
|
custom_package = "",
|
|
package_prefix = "",
|
|
include_paths = DEFAULT_INCLUDE_PATHS,
|
|
flatc_args = DEFAULT_FLATC_ARGS,
|
|
visibility = None):
|
|
"""A java library with the generated reader/writers for the given flatbuffer definitions.
|
|
|
|
Args:
|
|
name: Rule name. (required)
|
|
srcs: List of source .fbs files including all includes. (required)
|
|
custom_package: Package name of generated Java files. If not specified
|
|
namespace in the schema files will be used. (optional)
|
|
package_prefix: like custom_package, but prefixes to the existing
|
|
namespace. (optional)
|
|
include_paths: List of paths that includes files can be found in. (optional)
|
|
flatc_args: List of additional arguments to pass to flatc. (optional)
|
|
visibility: Visibility setting for the java_library rule. (optional)
|
|
"""
|
|
out_srcjar = "java_%s_all.srcjar" % name
|
|
flatbuffer_java_srcjar(
|
|
name = "%s_srcjar" % name,
|
|
srcs = srcs,
|
|
out = out_srcjar,
|
|
custom_package = custom_package,
|
|
flatc_args = flatc_args,
|
|
include_paths = include_paths,
|
|
package_prefix = package_prefix,
|
|
)
|
|
|
|
native.filegroup(
|
|
name = "%s.srcjar" % name,
|
|
srcs = [out_srcjar],
|
|
)
|
|
|
|
native.java_library(
|
|
name = name,
|
|
srcs = [out_srcjar],
|
|
javacopts = ["-source 7 -target 7"],
|
|
deps = [
|
|
"@flatbuffers//:runtime_java",
|
|
],
|
|
visibility = visibility,
|
|
)
|
|
|
|
def flatbuffer_java_srcjar(
|
|
name,
|
|
srcs,
|
|
out,
|
|
custom_package = "",
|
|
package_prefix = "",
|
|
include_paths = DEFAULT_INCLUDE_PATHS,
|
|
flatc_args = DEFAULT_FLATC_ARGS):
|
|
"""Generate flatbuffer Java source files.
|
|
|
|
Args:
|
|
name: Rule name. (required)
|
|
srcs: List of source .fbs files including all includes. (required)
|
|
out: Output file name. (required)
|
|
custom_package: Package name of generated Java files. If not specified
|
|
namespace in the schema files will be used. (optional)
|
|
package_prefix: like custom_package, but prefixes to the existing
|
|
namespace. (optional)
|
|
include_paths: List of paths that includes files can be found in. (optional)
|
|
flatc_args: List of additional arguments to pass to flatc. (optional)
|
|
"""
|
|
command_fmt = """set -e
|
|
tmpdir=$(@D)
|
|
schemas=$$tmpdir/schemas
|
|
java_root=$$tmpdir/java
|
|
rm -rf $$schemas
|
|
rm -rf $$java_root
|
|
mkdir -p $$schemas
|
|
mkdir -p $$java_root
|
|
|
|
for src in $(SRCS); do
|
|
dest=$$schemas/$$src
|
|
rm -rf $$(dirname $$dest)
|
|
mkdir -p $$(dirname $$dest)
|
|
if [ -z "{custom_package}" ] && [ -z "{package_prefix}" ]; then
|
|
cp -f $$src $$dest
|
|
else
|
|
if [ -z "{package_prefix}" ]; then
|
|
sed -e "s/namespace\\s.*/namespace {custom_package};/" $$src > $$dest
|
|
else
|
|
sed -e "s/namespace \\([^;]\\+\\);/namespace {package_prefix}.\\1;/" $$src > $$dest
|
|
fi
|
|
fi
|
|
done
|
|
|
|
flatc_arg_I="-I $$tmpdir/schemas"
|
|
for include_path in {include_paths}; do
|
|
flatc_arg_I="$$flatc_arg_I -I $$schemas/$$include_path"
|
|
done
|
|
|
|
flatc_additional_args=
|
|
for arg in {flatc_args}; do
|
|
flatc_additional_args="$$flatc_additional_args $$arg"
|
|
done
|
|
|
|
for src in $(SRCS); do
|
|
$(location {flatc_path}) $$flatc_arg_I --java $$flatc_additional_args -o $$java_root $$schemas/$$src
|
|
done
|
|
|
|
$(location {zip_files}) -export_zip_path=$@ -file_directory=$$java_root
|
|
"""
|
|
genrule_cmd = command_fmt.format(
|
|
package_name = native.package_name(),
|
|
custom_package = custom_package,
|
|
package_prefix = package_prefix,
|
|
flatc_path = flatc_path,
|
|
zip_files = zip_files,
|
|
include_paths = " ".join(include_paths),
|
|
flatc_args = " ".join(flatc_args),
|
|
)
|
|
|
|
native.genrule(
|
|
name = name,
|
|
srcs = srcs,
|
|
outs = [out],
|
|
tools = [flatc_path, zip_files],
|
|
cmd = genrule_cmd,
|
|
)
|
|
|
|
def flatbuffer_android_library(
|
|
name,
|
|
srcs,
|
|
custom_package = "",
|
|
package_prefix = "",
|
|
include_paths = DEFAULT_INCLUDE_PATHS,
|
|
flatc_args = DEFAULT_FLATC_ARGS,
|
|
visibility = None):
|
|
"""An android_library with the generated reader/writers for the given flatbuffer definitions.
|
|
|
|
Args:
|
|
name: Rule name. (required)
|
|
srcs: List of source .fbs files including all includes. (required)
|
|
custom_package: Package name of generated Java files. If not specified
|
|
namespace in the schema files will be used. (optional)
|
|
package_prefix: like custom_package, but prefixes to the existing
|
|
namespace. (optional)
|
|
include_paths: List of paths that includes files can be found in. (optional)
|
|
flatc_args: List of additional arguments to pass to flatc. (optional)
|
|
visibility: Visibility setting for the android_library rule. (optional)
|
|
"""
|
|
out_srcjar = "android_%s_all.srcjar" % name
|
|
flatbuffer_java_srcjar(
|
|
name = "%s_srcjar" % name,
|
|
srcs = srcs,
|
|
out = out_srcjar,
|
|
custom_package = custom_package,
|
|
flatc_args = flatc_args,
|
|
include_paths = include_paths,
|
|
package_prefix = package_prefix,
|
|
)
|
|
|
|
native.filegroup(
|
|
name = "%s.srcjar" % name,
|
|
srcs = [out_srcjar],
|
|
)
|
|
|
|
# To support org.checkerframework.dataflow.qual.Pure.
|
|
checkerframework_annotations = [
|
|
"@org_checkerframework_qual",
|
|
] if "--java-checkerframework" in flatc_args else []
|
|
|
|
android_library(
|
|
name = name,
|
|
srcs = [out_srcjar],
|
|
javacopts = ["-source 7 -target 7"],
|
|
visibility = visibility,
|
|
deps = [
|
|
"@flatbuffers//:runtime_android",
|
|
] + checkerframework_annotations,
|
|
)
|