• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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