• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Description:
2#   BUILD rules for generating flatbuffer files in various languages.
3
4"""
5Rules for building C++ flatbuffers with Bazel.
6"""
7
8load("@rules_cc//cc:defs.bzl", "cc_library")
9
10flatc_path = "@com_github_google_flatbuffers//:flatc"
11
12DEFAULT_INCLUDE_PATHS = [
13    "./",
14    "$(GENDIR)",
15    "$(BINDIR)",
16]
17
18DEFAULT_FLATC_ARGS = [
19    "--gen-object-api",
20    "--gen-compare",
21    "--no-includes",
22    "--gen-mutable",
23    "--reflect-names",
24    "--cpp-ptr-type flatbuffers::unique_ptr",
25]
26
27def flatbuffer_library_public(
28        name,
29        srcs,
30        outs,
31        language_flag,
32        out_prefix = "",
33        includes = [],
34        include_paths = DEFAULT_INCLUDE_PATHS,
35        flatc_args = DEFAULT_FLATC_ARGS,
36        reflection_name = "",
37        reflection_visibility = None,
38        compatible_with = None,
39        restricted_to = None,
40        output_to_bindir = False):
41    """Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
42
43    Args:
44      name: Rule name.
45      srcs: Source .fbs files. Sent in order to the compiler.
46      outs: Output files from flatc.
47      language_flag: Target language flag. One of [-c, -j, -js].
48      out_prefix: Prepend this path to the front of all generated files except on
49          single source targets. Usually is a directory name.
50      includes: Optional, list of filegroups of schemas that the srcs depend on.
51      include_paths: Optional, list of paths the includes files can be found in.
52      flatc_args: Optional, list of additional arguments to pass to flatc.
53      reflection_name: Optional, if set this will generate the flatbuffer
54        reflection binaries for the schemas.
55      reflection_visibility: The visibility of the generated reflection Fileset.
56      output_to_bindir: Passed to genrule for output to bin directory.
57      compatible_with: Optional, The list of environments this rule can be
58        built for, in addition to default-supported environments.
59      restricted_to: Optional, The list of environments this rule can be built
60        for, instead of default-supported environments.
61      output_to_bindir: Passed to genrule for output to bin directory.
62
63
64    This rule creates a filegroup(name) with all generated source files, and
65    optionally a Fileset([reflection_name]) with all generated reflection
66    binaries.
67    """
68    include_paths_cmd = ["-I %s" % (s) for s in include_paths]
69
70    # '$(@D)' when given a single source target will give the appropriate
71    # directory. Appending 'out_prefix' is only necessary when given a build
72    # target with multiple sources.
73    output_directory = (
74        ("-o $(@D)/%s" % (out_prefix)) if len(srcs) > 1 else ("-o $(@D)")
75    )
76    genrule_cmd = " ".join([
77        "SRCS=($(SRCS));",
78        "for f in $${SRCS[@]:0:%s}; do" % len(srcs),
79        "$(location %s)" % (flatc_path),
80        " ".join(include_paths_cmd),
81        " ".join(flatc_args),
82        language_flag,
83        output_directory,
84        "$$f;",
85        "done",
86    ])
87    native.genrule(
88        name = name,
89        srcs = srcs + includes,
90        outs = outs,
91        output_to_bindir = output_to_bindir,
92        tools = [flatc_path],
93        cmd = genrule_cmd,
94        compatible_with = compatible_with,
95        restricted_to = restricted_to,
96        message = "Generating flatbuffer files for %s:" % (name),
97    )
98    if reflection_name:
99        reflection_genrule_cmd = " ".join([
100            "SRCS=($(SRCS));",
101            "for f in $${SRCS[@]:0:%s}; do" % len(srcs),
102            "$(location %s)" % (flatc_path),
103            "-b --schema",
104            " ".join(flatc_args),
105            " ".join(include_paths_cmd),
106            language_flag,
107            output_directory,
108            "$$f;",
109            "done",
110        ])
111        reflection_outs = [
112            (out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
113            for s in srcs
114        ]
115        native.genrule(
116            name = "%s_srcs" % reflection_name,
117            srcs = srcs + includes,
118            outs = reflection_outs,
119            output_to_bindir = output_to_bindir,
120            tools = [flatc_path],
121            compatible_with = compatible_with,
122            restricted_to = restricted_to,
123            cmd = reflection_genrule_cmd,
124            message = "Generating flatbuffer reflection binary for %s:" % (name),
125        )
126        native.filegroup(
127            name = "%s_out" % reflection_name,
128            srcs = reflection_outs,
129            visibility = reflection_visibility,
130            compatible_with = compatible_with,
131            restricted_to = restricted_to,
132        )
133
134def flatbuffer_cc_library(
135        name,
136        srcs,
137        srcs_filegroup_name = "",
138        out_prefix = "",
139        includes = [],
140        include_paths = DEFAULT_INCLUDE_PATHS,
141        flatc_args = DEFAULT_FLATC_ARGS,
142        visibility = None,
143        compatible_with = None,
144        restricted_to = None,
145        srcs_filegroup_visibility = None,
146        gen_reflections = False):
147    '''A cc_library with the generated reader/writers for the given flatbuffer definitions.
148
149    Args:
150      name: Rule name.
151      srcs: Source .fbs files. Sent in order to the compiler.
152      srcs_filegroup_name: Name of the output filegroup that holds srcs. Pass this
153          filegroup into the `includes` parameter of any other
154          flatbuffer_cc_library that depends on this one's schemas.
155      out_prefix: Prepend this path to the front of all generated files. Usually
156          is a directory name.
157      includes: Optional, list of filegroups of schemas that the srcs depend on.
158          ** SEE REMARKS BELOW **
159      include_paths: Optional, list of paths the includes files can be found in.
160      flatc_args: Optional list of additional arguments to pass to flatc
161          (e.g. --gen-mutable).
162      visibility: The visibility of the generated cc_library. By default, use the
163          default visibility of the project.
164      srcs_filegroup_visibility: The visibility of the generated srcs filegroup.
165          By default, use the value of the visibility parameter above.
166      gen_reflections: Optional, if true this will generate the flatbuffer
167        reflection binaries for the schemas.
168      compatible_with: Optional, The list of environments this rule can be built
169        for, in addition to default-supported environments.
170      restricted_to: Optional, The list of environments this rule can be built
171        for, instead of default-supported environments.
172
173    This produces:
174      filegroup([name]_srcs): all generated .h files.
175      filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
176          Other flatbuffer_cc_library's can pass this in for their `includes`
177          parameter, if they depend on the schemas in this library.
178      Fileset([name]_reflection): (Optional) all generated reflection binaries.
179      cc_library([name]): library with sources and flatbuffers deps.
180
181    Remarks:
182      ** Because the genrule used to call flatc does not have any trivial way of
183        computing the output list of files transitively generated by includes and
184        --gen-includes (the default) being defined for flatc, the --gen-includes
185        flag will not work as expected. The way around this is to add a dependency
186        to the flatbuffer_cc_library defined alongside the flatc included Fileset.
187        For example you might define:
188
189        flatbuffer_cc_library(
190            name = "my_fbs",
191            srcs = [ "schemas/foo.fbs" ],
192            includes = [ "//third_party/bazz:bazz_fbs_includes" ],
193        )
194
195        In which foo.fbs includes a few files from the Fileset defined at
196        //third_party/bazz:bazz_fbs_includes. When compiling the library that
197        includes foo_generated.h, and therefore has my_fbs as a dependency, it
198        will fail to find any of the bazz *_generated.h files unless you also
199        add bazz's flatbuffer_cc_library to your own dependency list, e.g.:
200
201        cc_library(
202            name = "my_lib",
203            deps = [
204                ":my_fbs",
205                "//third_party/bazz:bazz_fbs"
206            ],
207        )
208
209        Happy dependent Flatbuffering!
210    '''
211    output_headers = [
212        (out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
213        for s in srcs
214    ]
215    reflection_name = "%s_reflection" % name if gen_reflections else ""
216
217    srcs_lib = "%s_srcs" % (name)
218    flatbuffer_library_public(
219        name = srcs_lib,
220        srcs = srcs,
221        outs = output_headers,
222        language_flag = "-c",
223        out_prefix = out_prefix,
224        includes = includes,
225        include_paths = include_paths,
226        flatc_args = flatc_args,
227        compatible_with = compatible_with,
228        restricted_to = restricted_to,
229        reflection_name = reflection_name,
230        reflection_visibility = visibility,
231    )
232    cc_library(
233        name = name,
234        hdrs = [
235            ":" + srcs_lib,
236        ],
237        srcs = [
238            ":" + srcs_lib,
239        ],
240        features = [
241            "-parse_headers",
242        ],
243        deps = [
244            "@com_github_google_flatbuffers//:runtime_cc",
245        ],
246        includes = [],
247        compatible_with = compatible_with,
248        restricted_to = restricted_to,
249        linkstatic = 1,
250        visibility = visibility,
251    )
252
253    # A filegroup for the `srcs`. That is, all the schema files for this
254    # Flatbuffer set.
255    native.filegroup(
256        name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
257        srcs = srcs,
258        compatible_with = compatible_with,
259        restricted_to = restricted_to,
260        visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
261    )
262