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 elseif(TARGET flatbuffers::flatc) 63 set(FLATC_TARGET flatbuffers::flatc) 64 set(FLATC flatbuffers::flatc) 65 else() 66 set(FLATC_TARGET flatc) 67 set(FLATC flatc) 68 endif() 69 set(FLATC_SCHEMA_ARGS --gen-mutable) 70 if(FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS) 71 set(FLATC_SCHEMA_ARGS 72 ${FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS} 73 ${FLATC_SCHEMA_ARGS} 74 ) 75 endif() 76 77 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 78 79 set(schema_glob "*.fbs") 80 # Generate the include files parameters. 81 set(include_params "") 82 set(all_generated_files "") 83 foreach (include_dir ${schema_include_dirs}) 84 set(include_params -I ${include_dir} ${include_params}) 85 if (NOT ${copy_text_schemas_dir} STREQUAL "") 86 # Copy text schemas from dependent folders. 87 file(GLOB_RECURSE dependent_schemas ${include_dir}/${schema_glob}) 88 foreach (dependent_schema ${dependent_schemas}) 89 file(COPY ${dependent_schema} DESTINATION ${copy_text_schemas_dir}) 90 endforeach() 91 endif() 92 endforeach() 93 94 foreach(schema ${flatbuffers_schemas}) 95 get_filename_component(filename ${schema} NAME_WE) 96 # For each schema, do the things we requested. 97 if (NOT ${generated_includes_dir} STREQUAL "") 98 set(generated_include ${generated_includes_dir}/${filename}_generated.h) 99 add_custom_command( 100 OUTPUT ${generated_include} 101 COMMAND ${FLATC} ${FLATC_SCHEMA_ARGS} 102 -o ${generated_includes_dir} 103 ${include_params} 104 -c ${schema} 105 DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies} 106 WORKING_DIRECTORY "${working_dir}") 107 list(APPEND all_generated_files ${generated_include}) 108 endif() 109 110 if (NOT ${binary_schemas_dir} STREQUAL "") 111 set(binary_schema ${binary_schemas_dir}/${filename}.bfbs) 112 add_custom_command( 113 OUTPUT ${binary_schema} 114 COMMAND ${FLATC} -b --schema 115 -o ${binary_schemas_dir} 116 ${include_params} 117 ${schema} 118 DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies} 119 WORKING_DIRECTORY "${working_dir}") 120 list(APPEND all_generated_files ${binary_schema}) 121 endif() 122 123 if (NOT ${copy_text_schemas_dir} STREQUAL "") 124 file(COPY ${schema} DESTINATION ${copy_text_schemas_dir}) 125 endif() 126 endforeach() 127 128 # Create a custom target that depends on all the generated files. 129 # This is the target that you can depend on to trigger all these 130 # to be built. 131 add_custom_target(${custom_target_name} 132 DEPENDS ${all_generated_files} ${additional_dependencies}) 133 134 # Register the include directory we are using. 135 if (NOT ${generated_includes_dir} STREQUAL "") 136 include_directories(${generated_includes_dir}) 137 set_property(TARGET ${custom_target_name} 138 PROPERTY GENERATED_INCLUDES_DIR 139 ${generated_includes_dir}) 140 endif() 141 142 # Register the binary schemas dir we are using. 143 if (NOT ${binary_schemas_dir} STREQUAL "") 144 set_property(TARGET ${custom_target_name} 145 PROPERTY BINARY_SCHEMAS_DIR 146 ${binary_schemas_dir}) 147 endif() 148 149 # Register the text schema copy dir we are using. 150 if (NOT ${copy_text_schemas_dir} STREQUAL "") 151 set_property(TARGET ${custom_target_name} 152 PROPERTY COPY_TEXT_SCHEMAS_DIR 153 ${copy_text_schemas_dir}) 154 endif() 155endfunction() 156 157# Creates a target that can be linked against that generates flatbuffer headers. 158# 159# This function takes a target name and a list of schemas. You can also specify 160# other flagc flags using the FLAGS option to change the behavior of the flatc 161# tool. 162# 163# When the target_link_libraries is done within a different directory than 164# flatbuffers_generate_headers is called, then the target should also be dependent 165# the custom generation target called GENERATE_<TARGET>. 166# 167# Arguments: 168# TARGET: The name of the target to generate. 169# SCHEMAS: The list of schema files to generate code for. 170# BINARY_SCHEMAS_DIR: Optional. The directory in which to generate binary 171# schemas. Binary schemas will only be generated if a path is provided. 172# INCLUDE: Optional. Search for includes in the specified paths. (Use this 173# instead of "-I <path>" and the FLAGS option so that CMake is aware of 174# the directories that need to be searched). 175# INCLUDE_PREFIX: Optional. The directory in which to place the generated 176# files. Use this instead of the --include-prefix option. 177# FLAGS: Optional. A list of any additional flags that you would like to pass 178# to flatc. 179# 180# Example: 181# 182# flatbuffers_generate_headers( 183# TARGET my_generated_headers_target 184# INCLUDE_PREFIX ${MY_INCLUDE_PREFIX}" 185# SCHEMAS ${MY_SCHEMA_FILES} 186# BINARY_SCHEMAS_DIR "${MY_BINARY_SCHEMA_DIRECTORY}" 187# FLAGS --gen-object-api) 188# 189# target_link_libraries(MyExecutableTarget 190# PRIVATE my_generated_headers_target 191# ) 192# 193# Optional (only needed within different directory): 194# add_dependencies(app GENERATE_my_generated_headers_target) 195function(flatbuffers_generate_headers) 196 # Parse function arguments. 197 set(options) 198 set(one_value_args 199 "TARGET" 200 "INCLUDE_PREFIX" 201 "BINARY_SCHEMAS_DIR") 202 set(multi_value_args 203 "SCHEMAS" 204 "INCLUDE" 205 "FLAGS") 206 cmake_parse_arguments( 207 PARSE_ARGV 0 208 FLATBUFFERS_GENERATE_HEADERS 209 "${options}" 210 "${one_value_args}" 211 "${multi_value_args}") 212 213 # Test if including from FindFlatBuffers 214 if(FLATBUFFERS_FLATC_EXECUTABLE) 215 set(FLATC_TARGET "") 216 set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE}) 217 elseif(TARGET flatbuffers::flatc) 218 set(FLATC_TARGET flatbuffers::flatc) 219 set(FLATC flatbuffers::flatc) 220 else() 221 set(FLATC_TARGET flatc) 222 set(FLATC flatc) 223 endif() 224 225 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 226 227 # Generate the include files parameters. 228 set(include_params "") 229 foreach (include_dir ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE}) 230 set(include_params -I ${include_dir} ${include_params}) 231 endforeach() 232 233 # Create a directory to place the generated code. 234 set(generated_target_dir "${CMAKE_CURRENT_BINARY_DIR}/${FLATBUFFERS_GENERATE_HEADERS_TARGET}") 235 set(generated_include_dir "${generated_target_dir}") 236 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX} STREQUAL "") 237 set(generated_include_dir "${generated_include_dir}/${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}") 238 list(APPEND FLATBUFFERS_GENERATE_HEADERS_FLAGS 239 "--include-prefix" ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}) 240 endif() 241 242 set(generated_custom_commands) 243 244 # Create rules to generate the code for each schema. 245 foreach(schema ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 246 get_filename_component(filename ${schema} NAME_WE) 247 set(generated_include "${generated_include_dir}/${filename}_generated.h") 248 249 # Generate files for grpc if needed 250 set(generated_source_file) 251 if("${FLATBUFFERS_GENERATE_HEADERS_FLAGS}" MATCHES "--grpc") 252 # Check if schema file contain a rpc_service definition 253 file(STRINGS ${schema} has_grpc REGEX "rpc_service") 254 if(has_grpc) 255 list(APPEND generated_include "${generated_include_dir}/${filename}.grpc.fb.h") 256 set(generated_source_file "${generated_include_dir}/${filename}.grpc.fb.cc") 257 endif() 258 endif() 259 260 add_custom_command( 261 OUTPUT ${generated_include} ${generated_source_file} 262 COMMAND ${FLATC} ${FLATC_ARGS} 263 -o ${generated_include_dir} 264 ${include_params} 265 -c ${schema} 266 ${FLATBUFFERS_GENERATE_HEADERS_FLAGS} 267 DEPENDS ${FLATC_TARGET} ${schema} 268 WORKING_DIRECTORY "${working_dir}" 269 COMMENT "Building ${schema} flatbuffers...") 270 list(APPEND all_generated_header_files ${generated_include}) 271 list(APPEND all_generated_source_files ${generated_source_file}) 272 list(APPEND generated_custom_commands "${generated_include}" "${generated_source_file}") 273 274 # Geneate the binary flatbuffers schemas if instructed to. 275 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "") 276 set(binary_schema 277 "${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}/${filename}.bfbs") 278 add_custom_command( 279 OUTPUT ${binary_schema} 280 COMMAND ${FLATC} -b --schema 281 -o ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} 282 ${include_params} 283 ${schema} 284 DEPENDS ${FLATC_TARGET} ${schema} 285 WORKING_DIRECTORY "${working_dir}") 286 list(APPEND generated_custom_commands "${binary_schema}") 287 list(APPEND all_generated_binary_files ${binary_schema}) 288 endif() 289 endforeach() 290 291 # Create an additional target as add_custom_command scope is only within same directory (CMakeFile.txt) 292 set(generate_target GENERATE_${FLATBUFFERS_GENERATE_HEADERS_TARGET}) 293 add_custom_target(${generate_target} ALL 294 DEPENDS ${generated_custom_commands} 295 COMMENT "Generating flatbuffer target ${FLATBUFFERS_GENERATE_HEADERS_TARGET}") 296 297 # Set up interface library 298 add_library(${FLATBUFFERS_GENERATE_HEADERS_TARGET} INTERFACE) 299 target_sources( 300 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 301 INTERFACE 302 ${all_generated_header_files} 303 ${all_generated_binary_files} 304 ${all_generated_source_files} 305 ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 306 add_dependencies( 307 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 308 ${FLATC} 309 ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 310 target_include_directories( 311 ${FLATBUFFERS_GENERATE_HEADERS_TARGET} 312 INTERFACE ${generated_target_dir}) 313 314 # Organize file layout for IDEs. 315 source_group( 316 TREE "${generated_target_dir}" 317 PREFIX "Flatbuffers/Generated/Headers Files" 318 FILES ${all_generated_header_files}) 319 source_group( 320 TREE "${generated_target_dir}" 321 PREFIX "Flatbuffers/Generated/Source Files" 322 FILES ${all_generated_source_files}) 323 source_group( 324 TREE ${working_dir} 325 PREFIX "Flatbuffers/Schemas" 326 FILES ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS}) 327 if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "") 328 source_group( 329 TREE "${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}" 330 PREFIX "Flatbuffers/Generated/Binary Schemas" 331 FILES ${all_generated_binary_files}) 332 endif() 333endfunction() 334 335# Creates a target that can be linked against that generates flatbuffer binaries 336# from json files. 337# 338# This function takes a target name and a list of schemas and Json files. You 339# can also specify other flagc flags and options to change the behavior of the 340# flatc compiler. 341# 342# Adding this target to your executable ensurses that the flatbuffer binaries 343# are compiled before your executable is run. 344# 345# Arguments: 346# TARGET: The name of the target to generate. 347# JSON_FILES: The list of json files to compile to flatbuffers binaries. 348# SCHEMA: The flatbuffers schema of the Json files to be compiled. 349# INCLUDE: Optional. Search for includes in the specified paths. (Use this 350# instead of "-I <path>" and the FLAGS option so that CMake is aware of 351# the directories that need to be searched). 352# OUTPUT_DIR: The directly where the generated flatbuffers binaries should be 353# placed. 354# FLAGS: Optional. A list of any additional flags that you would like to pass 355# to flatc. 356# 357# Example: 358# 359# flatbuffers_generate_binary_files( 360# TARGET my_binary_data 361# SCHEMA "${MY_SCHEMA_DIR}/my_example_schema.fbs" 362# JSON_FILES ${MY_JSON_FILES} 363# OUTPUT_DIR "${MY_BINARY_DATA_DIRECTORY}" 364# FLAGS --strict-json) 365# 366# target_link_libraries(MyExecutableTarget 367# PRIVATE my_binary_data 368# ) 369function(flatbuffers_generate_binary_files) 370 # Parse function arguments. 371 set(options) 372 set(one_value_args 373 "TARGET" 374 "SCHEMA" 375 "OUTPUT_DIR") 376 set(multi_value_args 377 "JSON_FILES" 378 "INCLUDE" 379 "FLAGS") 380 cmake_parse_arguments( 381 PARSE_ARGV 0 382 FLATBUFFERS_GENERATE_BINARY_FILES 383 "${options}" 384 "${one_value_args}" 385 "${multi_value_args}") 386 387 # Test if including from FindFlatBuffers 388 if(FLATBUFFERS_FLATC_EXECUTABLE) 389 set(FLATC_TARGET "") 390 set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE}) 391 elseif(TARGET flatbuffers::flatc) 392 set(FLATC_TARGET flatbuffers::flatc) 393 set(FLATC flatbuffers::flatc) 394 else() 395 set(FLATC_TARGET flatc) 396 set(FLATC flatc) 397 endif() 398 399 set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}") 400 401 # Generate the include files parameters. 402 set(include_params "") 403 foreach (include_dir ${FLATBUFFERS_GENERATE_BINARY_FILES_INCLUDE}) 404 set(include_params -I ${include_dir} ${include_params}) 405 endforeach() 406 407 # Create rules to generate the flatbuffers binary for each json file. 408 foreach(json_file ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES}) 409 get_filename_component(filename ${json_file} NAME_WE) 410 set(generated_binary_file "${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR}/${filename}.bin") 411 add_custom_command( 412 OUTPUT ${generated_binary_file} 413 COMMAND ${FLATC} ${FLATC_ARGS} 414 -o ${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR} 415 ${include_params} 416 -b ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA} ${json_file} 417 ${FLATBUFFERS_GENERATE_BINARY_FILES_FLAGS} 418 DEPENDS ${FLATC_TARGET} ${json_file} 419 WORKING_DIRECTORY "${working_dir}" 420 COMMENT "Building ${json_file} binary flatbuffers...") 421 list(APPEND all_generated_binary_files ${generated_binary_file}) 422 endforeach() 423 424 # Set up interface library 425 add_library(${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} INTERFACE) 426 target_sources( 427 ${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} 428 INTERFACE 429 ${all_generated_binary_files} 430 ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES} 431 ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA}) 432 add_dependencies( 433 ${FLATBUFFERS_GENERATE_BINARY_FILES_TARGET} 434 ${FLATC}) 435 436 # Organize file layout for IDEs. 437 source_group( 438 TREE ${working_dir} 439 PREFIX "Flatbuffers/JSON Files" 440 FILES ${FLATBUFFERS_GENERATE_BINARY_FILES_JSON_FILES}) 441 source_group( 442 TREE ${working_dir} 443 PREFIX "Flatbuffers/Schemas" 444 FILES ${FLATBUFFERS_GENERATE_BINARY_FILES_SCHEMA}) 445 source_group( 446 TREE ${FLATBUFFERS_GENERATE_BINARY_FILES_OUTPUT_DIR} 447 PREFIX "Flatbuffers/Generated/Binary Files" 448 FILES ${all_generated_binary_files}) 449endfunction() 450