1# Copyright 2015 Google Inc. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# General function to create FlatBuffer build rules for the given list of 16# schemas. 17# 18# flatbuffers_schemas: A list of flatbuffer schema files to process. 19# 20# schema_include_dirs: A list of schema file include directories, which will be 21# passed to flatc via the -I parameter. 22# 23# custom_target_name: The generated files will be added as dependencies for a 24# new custom target with this name. You should add that target as a dependency 25# for your main target to ensure these files are built. You can also retrieve 26# various properties from this target, such as GENERATED_INCLUDES_DIR, 27# BINARY_SCHEMAS_DIR, and COPY_TEXT_SCHEMAS_DIR. 28# 29# additional_dependencies: A list of additional dependencies that you'd like 30# all generated files to depend on. Pass in a blank string if you have none. 31# 32# generated_includes_dir: Where to generate the C++ header files for these 33# schemas. The generated includes directory will automatically be added to 34# CMake's include directories, and will be where generated header files are 35# placed. This parameter is optional; pass in empty string if you don't want to 36# generate include files for these schemas. 37# 38# binary_schemas_dir: If you specify an optional binary schema directory, binary 39# schemas will be generated for these schemas as well, and placed into the given 40# directory. 41# 42# copy_text_schemas_dir: If you want all text schemas (including schemas from 43# all schema include directories) copied into a directory (for example, if you 44# need them within your project to build JSON files), you can specify that 45# folder here. All text schemas will be copied to that folder. 46# 47# IMPORTANT: Make sure you quote all list arguments you pass to this function! 48# Otherwise CMake will only pass in the first element. 49# Example: build_flatbuffers("${fb_files}" "${include_dirs}" target_name ...) 50function(build_flatbuffers flatbuffers_schemas 51 schema_include_dirs 52 custom_target_name 53 additional_dependencies 54 generated_includes_dir 55 binary_schemas_dir 56 copy_text_schemas_dir) 57 58 # Test if including from FindFlatBuffers 59 if(FLATBUFFERS_FLATC_EXECUTABLE) 60 set(FLATC_TARGET "") 61 set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE}) 62 else() 63 set(FLATC_TARGET flatc) 64 set(FLATC flatc) 65 endif() 66 set(FLATC_SCHEMA_ARGS --gen-mutable) 67 if(FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS) 68 set(FLATC_SCHEMA_ARGS 69 ${FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS} 70 ${FLATC_SCHEMA_ARGS} 71 ) 72 endif() 73 74 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 75 76 set(schema_glob "*.fbs") 77 # Generate the include files parameters. 78 set(include_params "") 79 set(all_generated_files "") 80 foreach (include_dir ${schema_include_dirs}) 81 set(include_params -I ${include_dir} ${include_params}) 82 if (NOT ${copy_text_schemas_dir} STREQUAL "") 83 # Copy text schemas from dependent folders. 84 file(GLOB_RECURSE dependent_schemas ${include_dir}/${schema_glob}) 85 foreach (dependent_schema ${dependent_schemas}) 86 file(COPY ${dependent_schema} DESTINATION ${copy_text_schemas_dir}) 87 endforeach() 88 endif() 89 endforeach() 90 91 foreach(schema ${flatbuffers_schemas}) 92 get_filename_component(filename ${schema} NAME_WE) 93 # For each schema, do the things we requested. 94 if (NOT ${generated_includes_dir} STREQUAL "") 95 set(generated_include ${generated_includes_dir}/${filename}_generated.h) 96 add_custom_command( 97 OUTPUT ${generated_include} 98 COMMAND ${FLATC} ${FLATC_SCHEMA_ARGS} 99 -o ${generated_includes_dir} 100 ${include_params} 101 -c ${schema} 102 DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies} 103 WORKING_DIRECTORY "${working_dir}") 104 list(APPEND all_generated_files ${generated_include}) 105 endif() 106 107 if (NOT ${binary_schemas_dir} STREQUAL "") 108 set(binary_schema ${binary_schemas_dir}/${filename}.bfbs) 109 add_custom_command( 110 OUTPUT ${binary_schema} 111 COMMAND ${FLATC} -b --schema 112 -o ${binary_schemas_dir} 113 ${include_params} 114 ${schema} 115 DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies} 116 WORKING_DIRECTORY "${working_dir}") 117 list(APPEND all_generated_files ${binary_schema}) 118 endif() 119 120 if (NOT ${copy_text_schemas_dir} STREQUAL "") 121 file(COPY ${schema} DESTINATION ${copy_text_schemas_dir}) 122 endif() 123 endforeach() 124 125 # Create a custom target that depends on all the generated files. 126 # This is the target that you can depend on to trigger all these 127 # to be built. 128 add_custom_target(${custom_target_name} 129 DEPENDS ${all_generated_files} ${additional_dependencies}) 130 131 # Register the include directory we are using. 132 if (NOT ${generated_includes_dir} STREQUAL "") 133 include_directories(${generated_includes_dir}) 134 set_property(TARGET ${custom_target_name} 135 PROPERTY GENERATED_INCLUDES_DIR 136 ${generated_includes_dir}) 137 endif() 138 139 # Register the binary schemas dir we are using. 140 if (NOT ${binary_schemas_dir} STREQUAL "") 141 set_property(TARGET ${custom_target_name} 142 PROPERTY BINARY_SCHEMAS_DIR 143 ${binary_schemas_dir}) 144 endif() 145 146 # Register the text schema copy dir we are using. 147 if (NOT ${copy_text_schemas_dir} STREQUAL "") 148 set_property(TARGET ${custom_target_name} 149 PROPERTY COPY_TEXT_SCHEMAS_DIR 150 ${copy_text_schemas_dir}) 151 endif() 152endfunction() 153 154# Creates a target that can be linked against that generates flatbuffer headers. 155# 156# This function takes a target name and a list of schemas. You can also specify 157# other flagc flags using the FLAGS option to change the behavior of the flatc 158# tool. 159# 160# Arguments: 161# TARGET: The name of the target to generate. 162# SCHEMAS: The list of schema files to generate code for. 163# BINARY_SCHEMAS_DIR: Optional. The directory in which to generate binary 164# schemas. Binary schemas will only be generated if a path is provided. 165# INCLUDE: Optional. Search for includes in the specified paths. (Use this 166# instead of "-I <path>" and the FLAGS option so that CMake is aware of 167# the directories that need to be searched). 168# INCLUDE_PREFIX: Optional. The directory in which to place the generated 169# files. Use this instead of the --include-prefix option. 170# FLAGS: Optional. A list of any additional flags that you would like to pass 171# to flatc. 172# 173# Example: 174# 175# flatbuffers_generate_headers( 176# TARGET my_generated_headers_target 177# INCLUDE_PREFIX ${MY_INCLUDE_PREFIX}" 178# SCHEMAS ${MY_SCHEMA_FILES} 179# BINARY_SCHEMAS_DIR "${MY_BINARY_SCHEMA_DIRECTORY}" 180# FLAGS --gen-object-api) 181# 182# target_link_libraries(MyExecutableTarget 183# PRIVATE my_generated_headers_target 184# ) 185function(flatbuffers_generate_headers) 186 # Parse function arguments. 187 set(options) 188 set(one_value_args 189 "TARGET" 190 "INCLUDE_PREFIX" 191 "BINARY_SCHEMAS_DIR") 192 set(multi_value_args 193 "SCHEMAS" 194 "INCLUDE" 195 "FLAGS") 196 cmake_parse_arguments( 197 PARSE_ARGV 0 198 FLATBUFFERS_GENERATE_HEADERS 199 "${options}" 200 "${one_value_args}" 201 "${multi_value_args}") 202 203 # Test if including from FindFlatBuffers 204 if(FLATBUFFERS_FLATC_EXECUTABLE) 205 set(FLATC_TARGET "") 206 set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE}) 207 else() 208 set(FLATC_TARGET flatc) 209 set(FLATC flatc) 210 endif() 211 212 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 213 214 # Generate the include files parameters. 215 set(include_params "") 216 foreach (include_dir ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE}) 217 set(include_params -I ${include_dir} ${include_params}) 218 endforeach() 219 220 # Create a directory to place the generated code. 221 set(generated_target_dir "${CMAKE_CURRENT_BINARY_DIR}/${FLATBUFFERS_GENERATE_HEADERS_TARGET}") 222 set(generated_include_dir "${generated_target_dir}") 223 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX} STREQUAL "") 224 set(generated_include_dir "${generated_include_dir}/${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}") 225 list(APPEND FLATBUFFERS_GENERATE_HEADERS_FLAGS 226 "--include-prefix" ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}) 227 endif() 228 229 # Create rules to generate the code for each schema. 230 foreach(schema ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 231 get_filename_component(filename ${schema} NAME_WE) 232 set(generated_include "${generated_include_dir}/${filename}_generated.h") 233 234 # Generate files for grpc if needed 235 set(generated_source_file) 236 if("${FLATBUFFERS_GENERATE_HEADERS_FLAGS}" MATCHES "--grpc") 237 # Check if schema file contain a rpc_service definition 238 file(STRINGS ${schema} has_grpc REGEX "rpc_service") 239 if(has_grpc) 240 list(APPEND generated_include "${generated_include_dir}/${filename}.grpc.fb.h") 241 set(generated_source_file "${generated_include_dir}/${filename}.grpc.fb.cc") 242 endif() 243 endif() 244 245 add_custom_command( 246 OUTPUT ${generated_include} ${generated_source_file} 247 COMMAND ${FLATC} ${FLATC_ARGS} 248 -o ${generated_include_dir} 249 ${include_params} 250 -c ${schema} 251 ${FLATBUFFERS_GENERATE_HEADERS_FLAGS} 252 DEPENDS ${FLATC_TARGET} ${schema} 253 WORKING_DIRECTORY "${working_dir}" 254 COMMENT "Building ${schema} flatbuffers...") 255 list(APPEND all_generated_header_files ${generated_include}) 256 list(APPEND all_generated_source_files ${generated_source_file}) 257 258 # Geneate the binary flatbuffers schemas if instructed to. 259 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "") 260 set(binary_schema 261 "${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}/${filename}.bfbs") 262 add_custom_command( 263 OUTPUT ${binary_schema} 264 COMMAND ${FLATC} -b --schema 265 -o ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} 266 ${include_params} 267 ${schema} 268 DEPENDS ${FLATC_TARGET} ${schema} 269 WORKING_DIRECTORY "${working_dir}") 270 list(APPEND all_generated_binary_files ${binary_schema}) 271 endif() 272 endforeach() 273 274 # Set up interface library 275 add_library(${FLATBUFFERS_GENERATE_HEADERS_TARGET} INTERFACE) 276 target_sources( 277 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 278 INTERFACE 279 ${all_generated_header_files} 280 ${all_generated_binary_files} 281 ${all_generated_source_files} 282 ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 283 add_dependencies( 284 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 285 ${FLATC} 286 ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 287 target_include_directories( 288 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 289 INTERFACE ${generated_target_dir}) 290 291 # Organize file layout for IDEs. 292 source_group( 293 TREE "${generated_target_dir}" 294 PREFIX "Flatbuffers/Generated/Headers Files" 295 FILES ${all_generated_header_files}) 296 source_group( 297 TREE "${generated_target_dir}" 298 PREFIX "Flatbuffers/Generated/Source Files" 299 FILES ${all_generated_source_files}) 300 source_group( 301 TREE ${working_dir} 302 PREFIX "Flatbuffers/Schemas" 303 FILES ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 304 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "") 305 source_group( 306 TREE "${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}" 307 PREFIX "Flatbuffers/Generated/Binary Schemas" 308 FILES ${all_generated_binary_files}) 309 endif() 310endfunction() 311 312# Creates a target that can be linked against that generates flatbuffer binaries 313# from json files. 314# 315# This function takes a target name and a list of schemas and Json files. You 316# can also specify other flagc flags and options to change the behavior of the 317# flatc compiler. 318# 319# Adding this target to your executable ensurses that the flatbuffer binaries 320# are compiled before your executable is run. 321# 322# Arguments: 323# TARGET: The name of the target to generate. 324# JSON_FILES: The list of json files to compile to flatbuffers binaries. 325# SCHEMA: The flatbuffers schema of the Json files to be compiled. 326# INCLUDE: Optional. Search for includes in the specified paths. (Use this 327# instead of "-I <path>" and the FLAGS option so that CMake is aware of 328# the directories that need to be searched). 329# OUTPUT_DIR: The directly where the generated flatbuffers binaries should be 330# placed. 331# FLAGS: Optional. A list of any additional flags that you would like to pass 332# to flatc. 333# 334# Example: 335# 336# flatbuffers_generate_binary_files( 337# TARGET my_binary_data 338# SCHEMA "${MY_SCHEMA_DIR}/my_example_schema.fbs" 339# JSON_FILES ${MY_JSON_FILES} 340# OUTPUT_DIR "${MY_BINARY_DATA_DIRECTORY}" 341# FLAGS --strict-json) 342# 343# target_link_libraries(MyExecutableTarget 344# PRIVATE my_binary_data 345# ) 346function(flatbuffers_generate_binary_files) 347 # Parse function arguments. 348 set(options) 349 set(one_value_args 350 "TARGET" 351 "SCHEMA" 352 "OUTPUT_DIR") 353 set(multi_value_args 354 "JSON_FILES" 355 "INCLUDE" 356 "FLAGS") 357 cmake_parse_arguments( 358 PARSE_ARGV 0 359 FLATBUFFERS_GENERATE_BINARY_FILES 360 "${options}" 361 "${one_value_args}" 362 "${multi_value_args}") 363 364 # Test if including from FindFlatBuffers 365 if(FLATBUFFERS_FLATC_EXECUTABLE) 366 set(FLATC_TARGET "") 367 set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE}) 368 else() 369 set(FLATC_TARGET flatc) 370 set(FLATC flatc) 371 endif() 372 373 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 374 375 # Generate the include files parameters. 376 set(include_params "") 377 foreach (include_dir ${FLATBUFFERS_GENERATE_BINARY_FILES_INCLUDE}) 378 set(include_params -I ${include_dir} ${include_params}) 379 endforeach() 380 381 # Create rules to generate the flatbuffers binary for each json file. 382 foreach(json_file ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES}) 383 get_filename_component(filename ${json_file} NAME_WE) 384 set(generated_binary_file "${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR}/${filename}.bin") 385 add_custom_command( 386 OUTPUT ${generated_binary_file} 387 COMMAND ${FLATC} ${FLATC_ARGS} 388 -o ${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR} 389 ${include_params} 390 -b ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA} ${json_file} 391 ${FLATBUFFERS_GENERATE_BINARY_FILES_FLAGS} 392 DEPENDS ${FLATC_TARGET} ${json_file} 393 WORKING_DIRECTORY "${working_dir}" 394 COMMENT "Building ${json_file} binary flatbuffers...") 395 list(APPEND all_generated_binary_files ${generated_binary_file}) 396 endforeach() 397 398 # Set up interface library 399 add_library(${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} INTERFACE) 400 target_sources( 401 ${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} 402 INTERFACE 403 ${all_generated_binary_files} 404 ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES} 405 ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA}) 406 add_dependencies( 407 ${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} 408 ${FLATC}) 409 410 # Organize file layout for IDEs. 411 source_group( 412 TREE ${working_dir} 413 PREFIX "Flatbuffers/JSON Files" 414 FILES ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES}) 415 source_group( 416 TREE ${working_dir} 417 PREFIX "Flatbuffers/Schemas" 418 FILES ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA}) 419 source_group( 420 TREE ${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR} 421 PREFIX "Flatbuffers/Generated/Binary Files" 422 FILES ${all_generated_binary_files}) 423endfunction() 424