1cmake_minimum_required(VERSION 2.8)
2# generate compile_commands.json
3set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
4include(CheckCXXSymbolExists)
5
6project(FlatBuffers)
7
8# NOTE: Code coverage only works on Linux & OSX.
9option(FLATBUFFERS_CODE_COVERAGE "Enable the code coverage build option." OFF)
10option(FLATBUFFERS_BUILD_TESTS "Enable the build of tests and samples." ON)
11option(FLATBUFFERS_INSTALL "Enable the installation of targets." ON)
12option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library"
13       ON)
14option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
15       ON)
16option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
17option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
18option(FLATBUFFERS_BUILD_SHAREDLIB
19       "Enable the build of the flatbuffers shared library"
20       OFF)
21option(FLATBUFFERS_LIBCXX_WITH_CLANG "Force libc++ when using Clang" ON)
22# NOTE: Sanitizer check only works on Linux & OSX (gcc & llvm).
23option(FLATBUFFERS_CODE_SANITIZE
24      "Add '-fsanitize' flags to 'flattests' and 'flatc' targets."
25      OFF)
26option(FLATBUFFERS_PACKAGE_REDHAT
27       "Build an rpm using the 'package' target."
28       OFF)
29option(FLATBUFFERS_PACKAGE_DEBIAN
30       "Build an deb using the 'package' target."
31       OFF)
32
33if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
34    message(WARNING
35    "Cannot build tests without building the compiler. Tests will be disabled.")
36    set(FLATBUFFERS_BUILD_TESTS OFF)
37endif()
38
39if(DEFINED FLATBUFFERS_MAX_PARSING_DEPTH)
40  # Override the default recursion depth limit.
41  add_definitions(-DFLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH})
42  message(STATUS "FLATBUFFERS_MAX_PARSING_DEPTH: ${FLATBUFFERS_MAX_PARSING_DEPTH}")
43endif()
44
45# Auto-detect locale-narrow 'strtod_l' function.
46if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
47  if(MSVC)
48    check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
49  else()
50    check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
51  endif()
52endif()
53add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
54
55set(FlatBuffers_Library_SRCS
56  include/flatbuffers/code_generators.h
57  include/flatbuffers/base.h
58  include/flatbuffers/flatbuffers.h
59  include/flatbuffers/hash.h
60  include/flatbuffers/idl.h
61  include/flatbuffers/util.h
62  include/flatbuffers/reflection.h
63  include/flatbuffers/reflection_generated.h
64  include/flatbuffers/stl_emulation.h
65  include/flatbuffers/flexbuffers.h
66  include/flatbuffers/registry.h
67  include/flatbuffers/minireflect.h
68  src/code_generators.cpp
69  src/idl_parser.cpp
70  src/idl_gen_text.cpp
71  src/reflection.cpp
72  src/util.cpp
73)
74
75set(FlatBuffers_Compiler_SRCS
76  ${FlatBuffers_Library_SRCS}
77  src/idl_gen_cpp.cpp
78  src/idl_gen_dart.cpp
79  src/idl_gen_general.cpp
80  src/idl_gen_go.cpp
81  src/idl_gen_js_ts.cpp
82  src/idl_gen_php.cpp
83  src/idl_gen_python.cpp
84  src/idl_gen_lobster.cpp
85  src/idl_gen_lua.cpp
86  src/idl_gen_rust.cpp
87  src/idl_gen_fbs.cpp
88  src/idl_gen_grpc.cpp
89  src/idl_gen_json_schema.cpp
90  src/flatc.cpp
91  src/flatc_main.cpp
92  grpc/src/compiler/schema_interface.h
93  grpc/src/compiler/cpp_generator.h
94  grpc/src/compiler/cpp_generator.cc
95  grpc/src/compiler/go_generator.h
96  grpc/src/compiler/go_generator.cc
97  grpc/src/compiler/java_generator.h
98  grpc/src/compiler/java_generator.cc
99)
100
101set(FlatHash_SRCS
102  include/flatbuffers/hash.h
103  src/flathash.cpp
104)
105
106set(FlatBuffers_Tests_SRCS
107  ${FlatBuffers_Library_SRCS}
108  src/idl_gen_fbs.cpp
109  tests/test.cpp
110  tests/test_assert.h
111  tests/test_assert.cpp
112  tests/test_builder.h
113  tests/test_builder.cpp
114  # file generate by running compiler on tests/monster_test.fbs
115  ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
116)
117
118set(FlatBuffers_Sample_Binary_SRCS
119  include/flatbuffers/flatbuffers.h
120  samples/sample_binary.cpp
121  # file generated by running compiler on samples/monster.fbs
122  ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
123)
124
125set(FlatBuffers_Sample_Text_SRCS
126  ${FlatBuffers_Library_SRCS}
127  samples/sample_text.cpp
128  # file generated by running compiler on samples/monster.fbs
129  ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
130)
131
132set(FlatBuffers_Sample_BFBS_SRCS
133  ${FlatBuffers_Library_SRCS}
134  src/idl_gen_general.cpp
135  samples/sample_bfbs.cpp
136  # file generated by running compiler on samples/monster.fbs
137  ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
138)
139
140set(FlatBuffers_GRPCTest_SRCS
141  include/flatbuffers/flatbuffers.h
142  include/flatbuffers/grpc.h
143  tests/monster_test.grpc.fb.h
144  tests/test_assert.h
145  tests/test_builder.h
146  tests/monster_test.grpc.fb.cc
147  tests/test_assert.cpp
148  tests/test_builder.cpp
149  grpc/tests/grpctest.cpp
150  grpc/tests/message_builder_test.cpp
151  # file generated by running compiler on samples/monster.fbs
152  ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
153)
154
155# source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS})
156# source_group(Tests FILES ${FlatBuffers_Tests_SRCS})
157
158if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
159  # do not apply any global settings if the toolchain
160  # is being configured externally
161  message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
162elseif(APPLE)
163  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
164  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
165  set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
166elseif(CMAKE_COMPILER_IS_GNUCXX)
167  if(CYGWIN)
168    set(CMAKE_CXX_FLAGS
169      "${CMAKE_CXX_FLAGS} -std=gnu++11")
170  else(CYGWIN)
171    set(CMAKE_CXX_FLAGS
172      "${CMAKE_CXX_FLAGS} -std=c++0x")
173  endif(CYGWIN)
174  set(CMAKE_CXX_FLAGS
175    "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
176  set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
177  if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
178    if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
179      set(CMAKE_CXX_FLAGS
180        "${CMAKE_CXX_FLAGS} -faligned-new -Werror=implicit-fallthrough=2")
181    endif()
182    set(CMAKE_CXX_FLAGS
183      "${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
184  endif()
185
186  # Certain platforms such as ARM do not use signed chars by default
187  # which causes issues with certain bounds checks.
188  set(CMAKE_CXX_FLAGS
189    "${CMAKE_CXX_FLAGS} -fsigned-char")
190
191elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
192  set(CMAKE_CXX_FLAGS
193      "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
194  set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
195  if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
196    list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Wc++98-compat-extra-semi" "-Werror=unused-private-field") # enable warning
197  endif()
198  if(FLATBUFFERS_LIBCXX_WITH_CLANG)
199    if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
200      set(CMAKE_CXX_FLAGS
201          "${CMAKE_CXX_FLAGS} -stdlib=libc++")
202    endif()
203    if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
204            "${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
205      set(CMAKE_EXE_LINKER_FLAGS
206          "${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
207    endif()
208  endif()
209
210  # Certain platforms such as ARM do not use signed chars by default
211  # which causes issues with certain bounds checks.
212  set(CMAKE_CXX_FLAGS
213    "${CMAKE_CXX_FLAGS} -fsigned-char")
214
215elseif(MSVC)
216  # Visual Studio pedantic build settings
217  # warning C4512: assignment operator could not be generated
218  # warning C4316: object allocated on the heap may not be aligned
219  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX /wd4512 /wd4316")
220endif()
221
222if(FLATBUFFERS_CODE_COVERAGE)
223  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fprofile-arcs -ftest-coverage")
224  set(CMAKE_EXE_LINKER_FLAGS
225      "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
226endif()
227
228function(add_fsanitize_to_target _target _sanitizer)
229  # FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
230  # List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
231  if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
232    ((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
233  )
234    set(_sanitizer_flags "=address,undefined")
235    if(_sanitizer MATCHES "=.*")
236      # override default by user-defined sanitizer list
237      set(_sanitizer_flags ${_sanitizer})
238    endif()
239    target_compile_options(${_target} PRIVATE
240      -g -fsigned-char -fno-omit-frame-pointer
241      "-fsanitize${_sanitizer_flags}")
242    target_link_libraries(${_target} PRIVATE
243      "-fsanitize${_sanitizer_flags}")
244    set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
245    message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
246  endif()
247endfunction()
248
249if(BIICODE)
250  include(biicode/cmake/biicode.cmake)
251  return()
252endif()
253
254include_directories(include)
255include_directories(grpc)
256
257if(FLATBUFFERS_BUILD_FLATLIB)
258  add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
259  # CMake > 2.8.11: Attach header directory for when build via add_subdirectory().
260  target_include_directories(flatbuffers INTERFACE
261    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
262  target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
263endif()
264
265if(FLATBUFFERS_BUILD_FLATC)
266  add_executable(flatc ${FlatBuffers_Compiler_SRCS})
267  target_compile_options(flatc PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
268  if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
269    add_fsanitize_to_target(flatc ${FLATBUFFERS_CODE_SANITIZE})
270  endif()
271  if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
272    set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
273  endif()
274  if(MSVC)
275    # Make flatc.exe not depend on runtime dlls for easy distribution.
276    target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
277  endif()
278endif()
279
280if(FLATBUFFERS_BUILD_FLATHASH)
281  add_executable(flathash ${FlatHash_SRCS})
282endif()
283
284if(FLATBUFFERS_BUILD_SHAREDLIB)
285  add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
286
287  # Shared object version: "major.minor.micro"
288  # - micro updated every release when there is no API/ABI changes
289  # - minor updated when there are additions in API/ABI
290  # - major (ABI number) updated when there are changes in ABI (or removals)
291  set(FlatBuffers_Library_SONAME_MAJOR "1")
292  set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.10.0")
293  set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
294                        SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
295                        VERSION "${FlatBuffers_Library_SONAME_FULL}")
296endif()
297
298function(compile_flatbuffers_schema_to_cpp SRC_FBS)
299  get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
300  string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
301  add_custom_command(
302    OUTPUT ${GEN_HEADER}
303    COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
304            --gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
305            --cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
306            --reflect-names
307            -I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
308            "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
309    DEPENDS flatc)
310endfunction()
311
312function(compile_flatbuffers_schema_to_binary SRC_FBS)
313  get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
314  string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
315  add_custom_command(
316    OUTPUT ${GEN_BINARY_SCHEMA}
317    COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}"
318            "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
319    DEPENDS flatc)
320endfunction()
321
322if(FLATBUFFERS_BUILD_TESTS)
323  compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
324  include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
325  add_executable(flattests ${FlatBuffers_Tests_SRCS})
326  set_property(TARGET flattests
327    PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
328    FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
329  if(FLATBUFFERS_CODE_SANITIZE)
330    if(WIN32)
331      target_compile_definitions(flattests PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
332      message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to flattests")
333    else()
334      add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
335    endif()
336  endif()
337
338  compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
339  include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
340  add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
341  add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
342  add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
343endif()
344
345if(FLATBUFFERS_BUILD_GRPCTEST)
346  if(CMAKE_COMPILER_IS_GNUCXX)
347    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
348  endif()
349  if(NOT GRPC_INSTALL_PATH)
350    message(SEND_ERROR "GRPC_INSTALL_PATH variable is not defined. See grpc/README.md")
351  endif()
352  if(NOT PROTOBUF_DOWNLOAD_PATH)
353    message(SEND_ERROR "PROTOBUF_DOWNLOAD_PATH variable is not defined. See grpc/README.md")
354  endif()
355  INCLUDE_DIRECTORIES(${GRPC_INSTALL_PATH}/include)
356  INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
357  LINK_DIRECTORIES(${GRPC_INSTALL_PATH}/lib)
358  add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
359  target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
360endif()
361
362include(CMake/Version.cmake)
363
364if(FLATBUFFERS_INSTALL)
365  include(GNUInstallDirs)
366
367  install(DIRECTORY include/flatbuffers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
368
369  set(FB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/flatbuffers")
370
371  configure_file(CMake/FlatbuffersConfigVersion.cmake.in FlatbuffersConfigVersion.cmake @ONLY)
372  install(
373      FILES "CMake/FlatbuffersConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/FlatbuffersConfigVersion.cmake"
374      DESTINATION ${FB_CMAKE_DIR}
375  )
376
377  if(FLATBUFFERS_BUILD_FLATLIB)
378    if(CMAKE_VERSION VERSION_LESS 3.0)
379      install(
380        TARGETS flatbuffers EXPORT FlatbuffersTargets
381        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
382      )
383    else()
384      install(
385        TARGETS flatbuffers EXPORT FlatbuffersTargets
386        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
387        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
388      )
389    endif()
390
391    install(EXPORT FlatbuffersTargets
392      FILE FlatbuffersTargets.cmake
393      NAMESPACE flatbuffers::
394      DESTINATION ${FB_CMAKE_DIR}
395    )
396  endif()
397
398  if(FLATBUFFERS_BUILD_FLATC)
399    install(
400      TARGETS flatc EXPORT FlatcTargets
401      RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
402    )
403
404    install(
405      EXPORT FlatcTargets
406      FILE FlatcTargets.cmake
407      NAMESPACE flatbuffers::
408      DESTINATION ${FB_CMAKE_DIR}
409    )
410  endif()
411
412  if(FLATBUFFERS_BUILD_SHAREDLIB)
413    if(CMAKE_VERSION VERSION_LESS 3.0)
414      install(
415        TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
416        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
417        RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
418        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
419      )
420    else()
421      install(
422        TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
423        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
424        RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
425        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
426        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
427      )
428    endif()
429
430  install(
431      EXPORT FlatbuffersSharedTargets
432      FILE FlatbuffersSharedTargets.cmake
433      NAMESPACE flatbuffers::
434      DESTINATION ${FB_CMAKE_DIR}
435    )
436  endif()
437endif()
438
439if(FLATBUFFERS_BUILD_TESTS)
440  enable_testing()
441
442  file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
443       "${CMAKE_CURRENT_BINARY_DIR}")
444  add_test(NAME flattests COMMAND flattests)
445  if(FLATBUFFERS_BUILD_GRPCTEST)
446    add_test(NAME grpctest COMMAND grpctest)
447  endif()
448endif()
449
450include(CMake/BuildFlatBuffers.cmake)
451
452if(UNIX)
453    # Use of CPack only supported on Linux systems.
454    if(FLATBUFFERS_PACKAGE_DEBIAN)
455        include(CMake/PackageDebian.cmake)
456    endif()
457    if (FLATBUFFERS_PACKAGE_REDHAT)
458        include(CMake/PackageRedhat.cmake)
459    endif()
460    include(CPack)
461endif()
462