Add Bazel rules for Rust flatbuffers
This required exposing things as a provider to properly build up the
file structure, so I refactored the other languages instead of
duplicating the functionality.
logger_test's sha1s changed because we're generating the .fbs files in
the host configuration now so their paths are different.
Change-Id: Idd60c6360efacfa1e5a5b8658a9d5770f37b02c6
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/aos/BUILD b/aos/BUILD
index b04bb3d..2bd0ec8 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -396,7 +396,7 @@
],
data = [
"//aos/events:pingpong_config",
- "//aos/events:pong.bfbs",
+ "//aos/events:pong_fbs_reflection_out",
"//aos/testdata:test_configs",
],
target_compatible_with = ["@platforms//os:linux"],
diff --git a/aos/events/logging/logger_test.cc b/aos/events/logging/logger_test.cc
index bb5b41e..5f265e2 100644
--- a/aos/events/logging/logger_test.cc
+++ b/aos/events/logging/logger_test.cc
@@ -3482,9 +3482,9 @@
}
constexpr std::string_view kCombinedConfigSha1(
- "158a244107a7dc637fc5934ac161cb9e6c26195930fd8f82bb351c3ad7cce349");
+ "bcc66bc13a90a4a268649744e244129c5d024f5abd67587dcfbd7158d8abfc44");
constexpr std::string_view kSplitConfigSha1(
- "c73aa7913a9e116ee0a793d8280fac170b7eeea8e7350f45c6ac5bfc4ab018e1");
+ "d97e998164a6f1bf078aad77ef127329728ac9198a13a5ab8d5f30d84a932662");
INSTANTIATE_TEST_SUITE_P(
All, MultinodeLoggerTest,
diff --git a/third_party/flatbuffers/build_defs.bzl b/third_party/flatbuffers/build_defs.bzl
index 7eaa4d3..c3e2bb0 100644
--- a/third_party/flatbuffers/build_defs.bzl
+++ b/third_party/flatbuffers/build_defs.bzl
@@ -6,6 +6,8 @@
"""
load("@io_bazel_rules_go//go:def.bzl", "go_library")
+load("@rules_rust//rust:defs.bzl", "rust_library")
+load("@rules_rust//rust:rust_common.bzl", "CrateInfo")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("@npm//@bazel/typescript:index.bzl", "ts_project")
load("@rules_cc//cc:defs.bzl", "cc_library")
@@ -14,9 +16,6 @@
DEFAULT_INCLUDE_PATHS = [
"./",
- "$(GENDIR)",
- "$(BINDIR)",
- "$(execpath @com_github_google_flatbuffers//:flatc).runfiles/com_github_google_flatbuffers",
]
DEFAULT_FLATC_ARGS = [
@@ -28,7 +27,8 @@
"--require-explicit-ids",
"--gen-mutable",
"--reflect-names",
- "--cpp-ptr-type flatbuffers::unique_ptr",
+ "--cpp-ptr-type",
+ "flatbuffers::unique_ptr",
"--force-empty",
"--scoped-enums",
"--gen-name-strings",
@@ -40,6 +40,11 @@
"--require-explicit-ids",
]
+DEFAULT_FLATC_RUST_ARGS = [
+ "--gen-object-api",
+ "--require-explicit-ids",
+]
+
DEFAULT_FLATC_TS_ARGS = [
"--gen-object-api",
"--gen-mutable",
@@ -49,12 +54,80 @@
"--keep-prefix",
]
+"""Contains information about a set of flatbuffers which have their code for
+reading/writing generated in a single library-style rule.
+
+Fields:
+ srcs: [File], the .fbs source files
+"""
+FlatbufferLibraryInfo = provider()
+
+def _flatbuffer_library_compile_impl(ctx):
+ outs = []
+ commands = []
+ for src in ctx.files.srcs:
+ if ctx.attr.tables_for_filenames:
+ out_dir = None
+ for table in ctx.attr.tables_for_filenames:
+ out = ctx.actions.declare_file(ctx.attr.out_prefix + table + ctx.attr.output_suffix)
+ this_out_dir = "/".join(out.dirname.split("/")[:-(len(ctx.attr.out_prefix.split("/")) - 1)])
+ if out_dir:
+ if this_out_dir != out_dir:
+ fail("Trying to write to multiple directories")
+ else:
+ out_dir = this_out_dir
+ outs.append(out)
+ else:
+ out = ctx.actions.declare_file(ctx.attr.out_prefix + src.basename.replace(".fbs", "") + ctx.attr.output_suffix)
+ outs.append(out)
+ out_dir = out.dirname
+ arguments = [ctx.executable._flatc.path]
+ for path in ctx.attr.include_paths:
+ for subpath in ["", ctx.bin_dir.path + "/"]:
+ arguments.append("-I")
+ arguments.append(subpath + path)
+ arguments.append("-I")
+ arguments.append("%s.runfiles/com_github_google_flatbuffers" % ctx.executable._flatc.path)
+ arguments.extend(ctx.attr.flatc_args)
+ arguments.extend(ctx.attr.language_flags)
+ arguments.extend([
+ "-o",
+ out_dir,
+ ])
+ arguments.append(src.path)
+ commands.append(arguments)
+ ctx.actions.run_shell(
+ outputs = outs,
+ inputs = ctx.files.srcs + ctx.files.includes,
+ tools = [ctx.executable._flatc],
+ command = " && ".join([" ".join(arguments) for arguments in commands]),
+ mnemonic = "Flatc",
+ progress_message = "Generating flatbuffer files for %{input}:",
+ )
+ return [DefaultInfo(files = depset(outs), runfiles = ctx.runfiles(files = outs)), FlatbufferLibraryInfo(srcs = ctx.files.srcs)]
+
+_flatbuffer_library_compile = rule(
+ implementation = _flatbuffer_library_compile_impl,
+ attrs = {
+ "srcs": attr.label_list(mandatory = True, allow_files = True),
+ "output_suffix": attr.string(mandatory = True),
+ "tables_for_filenames": attr.string_list(mandatory = False),
+ "language_flags": attr.string_list(mandatory = True),
+ "includes": attr.label_list(default = [], allow_files = True),
+ "include_paths": attr.string_list(default = []),
+ "flatc_args": attr.string_list(default = []),
+ "out_prefix": attr.string(default = ""),
+ "_flatc": attr.label(executable = True, cfg = "exec", default = Label(flatc_path)),
+ },
+)
+
def flatbuffer_library_public(
name,
srcs,
- outs,
+ output_suffix,
language_flag,
out_prefix = "",
+ tables_for_filenames = None,
includes = [],
include_paths = DEFAULT_INCLUDE_PATHS,
flatc_args = DEFAULT_FLATC_ARGS,
@@ -63,14 +136,15 @@
compatible_with = None,
restricted_to = None,
target_compatible_with = None,
- output_to_bindir = False):
+ output_to_bindir = False,
+ visibility = None):
"""Generates code files for reading/writing the given flatbuffers in the
requested language using the public compiler.
Args:
name: Rule name.
srcs: Source .fbs files. Sent in order to the compiler.
- outs: Output files from flatc.
+ output_suffix: Suffix for 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.
@@ -94,73 +168,36 @@
optionally a Fileset([reflection_name]) with all generated reflection
binaries.
"""
- 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([
- "SRCS=($(SRCS));",
- "for f in $${SRCS[@]:0:%s}; do" % len(srcs),
- "$(location %s)" % (flatc_path),
- " ".join(include_paths_cmd),
- " ".join(flatc_args),
- language_flag,
- output_directory,
- "$$f;",
- "done",
- ])
- native.genrule(
+ _flatbuffer_library_compile(
name = name,
- srcs = srcs + includes,
- outs = outs,
- output_to_bindir = output_to_bindir,
- tools = [flatc_path],
- cmd = genrule_cmd,
+ srcs = srcs,
+ output_suffix = output_suffix,
+ language_flags = [language_flag],
+ includes = includes,
+ include_paths = include_paths,
+ flatc_args = flatc_args,
+ out_prefix = out_prefix,
+ tables_for_filenames = tables_for_filenames,
compatible_with = compatible_with,
target_compatible_with = target_compatible_with,
restricted_to = restricted_to,
- message = "Generating flatbuffer files for %s:" % (name),
+ visibility = visibility,
)
+
if reflection_name:
- reflection_genrule_cmd = " ".join([
- "SRCS=($(SRCS));",
- "for f in $${SRCS[@]:0:%s}; do" % len(srcs),
- "$(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 + includes,
- outs = reflection_outs,
- output_to_bindir = output_to_bindir,
- tools = [flatc_path],
- compatible_with = compatible_with,
- restricted_to = restricted_to,
- target_compatible_with = target_compatible_with,
- cmd = reflection_genrule_cmd,
- message = "Generating flatbuffer reflection binary for %s:" % (name),
- visibility = reflection_visibility,
- )
- native.filegroup(
+ _flatbuffer_library_compile(
name = "%s_out" % reflection_name,
- srcs = reflection_outs,
- visibility = reflection_visibility,
+ srcs = srcs,
+ output_suffix = ".bfbs",
+ language_flags = ["-b", "--schema"],
+ includes = includes,
+ include_paths = include_paths,
+ flatc_args = flatc_args,
+ out_prefix = out_prefix,
compatible_with = compatible_with,
+ target_compatible_with = target_compatible_with,
restricted_to = restricted_to,
+ visibility = reflection_visibility,
)
def flatbuffer_cc_library(
@@ -220,10 +257,6 @@
Fileset([name]_reflection): (Optional) all generated reflection binaries.
cc_library([name]): library with sources and flatbuffers deps.
"""
- output_headers = [
- (out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1].split(":")[-1])
- for s in srcs
- ]
if deps and includes:
# There is no inherent reason we couldn't support both, but this discourages
# use of includes without good reason.
@@ -236,7 +269,7 @@
flatbuffer_library_public(
name = srcs_lib,
srcs = srcs,
- outs = output_headers,
+ output_suffix = "_generated.h",
language_flag = "-c",
out_prefix = out_prefix,
includes = includes,
@@ -309,23 +342,27 @@
been parsed. As such, we just force the user to manually specify
things.
"""
- python_files = ["%s/%s.py" % (namespace.replace(".", "/"), table) for table in tables]
srcs_lib = "%s_srcs" % (name)
+ if not tables:
+ fail("Must specify the list of tables")
flatbuffer_library_public(
name = srcs_lib,
srcs = srcs,
- outs = python_files,
+ output_suffix = ".py",
+ out_prefix = namespace.replace(".", "/") + "/",
+ tables_for_filenames = tables,
language_flag = "--python",
includes = includes,
include_paths = include_paths,
flatc_args = flatc_args,
compatible_with = compatible_with,
target_compatible_with = target_compatible_with,
+ visibility = ["//visibility:private"],
)
native.py_library(
name = name,
- srcs = python_files,
+ srcs = [srcs_lib],
visibility = visibility,
compatible_with = compatible_with,
target_compatible_with = target_compatible_with,
@@ -345,23 +382,23 @@
visibility = None,
srcs_filegroup_visibility = None):
srcs_lib = "%s_srcs" % (name)
- outs = ["%s_generated.go" % (s.replace(".fbs", "").split("/")[-1]) for s in srcs]
flatc_args = flatc_args + ["--go-namespace", importpath.split("/")[-1]]
flatbuffer_library_public(
name = srcs_lib,
srcs = srcs,
- outs = outs,
+ output_suffix = "_generated.go",
language_flag = "--go",
includes = includes,
include_paths = include_paths,
flatc_args = flatc_args,
compatible_with = compatible_with,
target_compatible_with = target_compatible_with,
+ visibility = ["//visibility:private"],
)
go_library(
name = name,
- srcs = outs,
+ srcs = [srcs_lib],
deps = ["@com_github_google_flatbuffers//go"],
importpath = importpath,
visibility = visibility,
@@ -369,6 +406,93 @@
target_compatible_with = target_compatible_with,
)
+def _flatbuffer_rust_lib_gen_impl(ctx):
+ # TODO(Brian): I think this needs changes to properly handle multiple .fbs files in a rule.
+ uses = []
+ for (dep, dep_srcs) in zip(ctx.attr.deps, ctx.attr.dep_srcs):
+ for dep_src in dep_srcs[FlatbufferLibraryInfo].srcs:
+ uses.append((dep[CrateInfo].name, dep_src.basename.replace(".fbs", "_generated")))
+ lib_rs_content = "\n".join(
+ [
+ "// Automatically generated by the Flatbuffers Bazel rules. Do not modify",
+ "#![allow(unused_imports)]",
+ ] + ["use %s as %s;" % (crate, use_as) for (crate, use_as) in uses] +
+ ["include!(\"%s\");" % src.basename for src in ctx.files.srcs_lib],
+ )
+ output = ctx.actions.declare_file(ctx.attr.name + "_lib.rs")
+ ctx.actions.write(
+ output = output,
+ content = lib_rs_content,
+ )
+ return [DefaultInfo(files = depset([output]))]
+
+"""Generates a lib.rs for a flatbuffer_rust_library.
+
+flatc generates individual .rs files for us. It can also generate a top-level mod.rs to be included
+in a crate, but that is laid out to include all flatbuffers files in a project. That's not a good
+fit for Bazel rules and monorepos, so we generate an alternative that imports all dependencies under
+their expected names."""
+_flatbuffer_rust_lib_gen = rule(
+ implementation = _flatbuffer_rust_lib_gen_impl,
+ attrs = {
+ "srcs_lib": attr.label(mandatory = True, doc = "The generated srcs for this rule"),
+ "dep_srcs": attr.label_list(mandatory = True, providers = [FlatbufferLibraryInfo], doc = "The _srcs rules for all our direct dependencies"),
+ "deps": attr.label_list(mandatory = True, providers = [CrateInfo]),
+ },
+)
+
+def flatbuffer_rust_library(
+ name,
+ srcs,
+ compatible_with = None,
+ target_compatible_with = None,
+ deps = [],
+ include_paths = DEFAULT_INCLUDE_PATHS,
+ flatc_args = DEFAULT_FLATC_RUST_ARGS,
+ include_reflection = True,
+ crate_name = None,
+ visibility = None,
+ srcs_filegroup_visibility = None):
+ includes = [d + "_includes" for d in deps]
+ srcs_lib = "%s_srcs" % (name)
+ lib_gen = "%s_lib_gen" % (name)
+ deps = list(deps)
+ if include_reflection:
+ deps.append("@com_github_google_flatbuffers//reflection:reflection_rust_fbs")
+
+ flatbuffer_library_public(
+ name = srcs_lib,
+ srcs = srcs,
+ language_flag = "--rust",
+ output_suffix = "_generated.rs",
+ includes = includes,
+ include_paths = include_paths,
+ flatc_args = flatc_args,
+ compatible_with = compatible_with,
+ target_compatible_with = target_compatible_with,
+ visibility = visibility,
+ )
+ _flatbuffer_rust_lib_gen(
+ name = lib_gen,
+ deps = deps,
+ dep_srcs = [dep + "_srcs" for dep in deps],
+ srcs_lib = srcs_lib,
+ visibility = ["//visibility:private"],
+ compatible_with = compatible_with,
+ target_compatible_with = target_compatible_with,
+ )
+ rust_library(
+ name = name,
+ srcs = [srcs_lib, lib_gen],
+ crate_root = lib_gen,
+ crate_name = crate_name,
+ deps = ["@com_github_google_flatbuffers//rust"] + deps,
+ edition = "2018",
+ visibility = visibility,
+ compatible_with = compatible_with,
+ target_compatible_with = target_compatible_with,
+ )
+
def flatbuffer_ts_library(
name,
srcs,
@@ -411,13 +535,12 @@
# third_party/.
# TODO(james): There absolutely are better ways to do this, but this was the quick and dirty
# one....
- pre_outs = ["%s_pregenerated.ts" % (s.replace(".fbs", "").split("/")[-1]) for s in srcs]
outs = ["%s_generated.ts" % (s.replace(".fbs", "").split("/")[-1]) for s in srcs]
includes = [d + "_includes" for d in deps]
flatbuffer_library_public(
name = srcs_lib,
srcs = srcs,
- outs = pre_outs,
+ output_suffix = "_pregenerated.ts",
language_flag = "--ts",
includes = includes,
include_paths = include_paths,
@@ -435,8 +558,8 @@
"done",
])
native.genrule(
- name = name + "_reimporter",
- srcs = pre_outs,
+ name = name + "_reimporter.ts",
+ srcs = [srcs_lib],
outs = outs,
cmd = genrule_cmd,
)
diff --git a/third_party/flatbuffers/reflection/BUILD.bazel b/third_party/flatbuffers/reflection/BUILD.bazel
index aa421db..9b08734 100644
--- a/third_party/flatbuffers/reflection/BUILD.bazel
+++ b/third_party/flatbuffers/reflection/BUILD.bazel
@@ -1,4 +1,4 @@
-load("//:build_defs.bzl", "flatbuffer_ts_library")
+load("//:build_defs.bzl", "flatbuffer_rust_library", "flatbuffer_ts_library")
filegroup(
name = "reflection_fbs_schema",
@@ -13,3 +13,11 @@
include_reflection = False,
visibility = ["//visibility:public"],
)
+
+flatbuffer_rust_library(
+ name = "reflection_rust_fbs",
+ srcs = ["reflection.fbs"],
+ crate_name = "flatbuffers_reflection",
+ include_reflection = False,
+ visibility = ["//visibility:public"],
+)
diff --git a/third_party/flatbuffers/rust/BUILD.bazel b/third_party/flatbuffers/rust/BUILD.bazel
new file mode 100644
index 0000000..246f5a0
--- /dev/null
+++ b/third_party/flatbuffers/rust/BUILD.bazel
@@ -0,0 +1,16 @@
+load("@rules_rust//rust:defs.bzl", "rust_library")
+
+rust_library(
+ name = "rust",
+ srcs = glob(["flatbuffers/**/*.rs"]),
+ crate_name = "flatbuffers",
+ crate_root = "flatbuffers/src/lib.rs",
+ edition = "2018",
+ version = "2.1.1",
+ visibility = ["//visibility:public"],
+ deps = [
+ "@//third_party/cargo:bitflags",
+ "@//third_party/cargo:smallvec",
+ "@//third_party/cargo:thiserror",
+ ],
+)
diff --git a/third_party/flatbuffers/src/idl_gen_rust.cpp b/third_party/flatbuffers/src/idl_gen_rust.cpp
index 17853a0..b15cdf5 100644
--- a/third_party/flatbuffers/src/idl_gen_rust.cpp
+++ b/third_party/flatbuffers/src/idl_gen_rust.cpp
@@ -366,6 +366,7 @@
if (symbol.generated) continue;
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
+ code_ += "#![allow(unused_imports)]";
code_ += "extern crate flatbuffers;";
code_ += "use std::mem;";
code_ += "use std::cmp::Ordering;";