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