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