-
Notifications
You must be signed in to change notification settings - Fork 4
/
CMakeLists.txt
471 lines (346 loc) · 15.6 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
# Note: COMMAND_EXPAND_LISTS is keyword is only available with CMake version >= 3.8
cmake_minimum_required(VERSION 3.8)
# ------------------------------- project settings --------------------------------------
# project() must be before checks, see https://stackoverflow.com/a/26437667/10904212
set(PROJECT_NAME "flextool")
set(FLEXTOOL_LIB_NAME ${PROJECT_NAME})
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/parse_version_file.cmake)
project(${PROJECT_NAME}
VERSION ${PROJECT_VERSION}
LANGUAGES CXX C)
# sets cmake_build_type_tolower, PROJECT_SOURCE_DIR, etc.
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/global_constants.cmake)
# ------------------------- External CMake includes ----------------------------
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_externals.cmake)
# ------------------------------- Options --------------------------------------
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Options.cmake)
# --------------------------- conan configuration ------------------------------
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/fetch_cmake_utils.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/fetch_conan_auto_install.cmake)
option(CONAN_AUTO_INSTALL
"Let CMake call conan install automatically"
OFF
)
if (CONAN_AUTO_INSTALL)
set(CONAN_PROFILE
"clang"
CACHE STRING "Conan profile to use during installation")
if (NOT cmake_build_type_tolower MATCHES "debug" )
set(conan_build_type "Release")
else()
set(conan_build_type "Debug")
endif()
# No --build=missing cause llvm requires long build
# You can use `EXTRA_CONAN_AUTO_INSTALL_OPTIONS` like so:
# cmake .. -DCONAN_AUTO_INSTALL=ON -DEXTRA_CONAN_AUTO_INSTALL_OPTIONS="--build missing" -DCMAKE_BUILD_TYPE=Debug
conan_auto_install(
CONAN_OPTIONS "--profile=${CONAN_PROFILE} -s build_type=${conan_build_type} -s cling_conan:build_type=Release -s llvm_tools:build_type=Release -o openssl:shared=True ${EXTRA_CONAN_AUTO_INSTALL_OPTIONS}"
#FORCE
)
endif()
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR}/)
include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake)
include(${CMAKE_CURRENT_BINARY_DIR}/conan_paths.cmake OPTIONAL)
conan_basic_setup(
# prevent conan_basic_setup from resetting cmake variables
TARGETS
KEEP_RPATHS
# see https://github.com/conan-io/conan/issues/6012
NO_OUTPUT_DIRS
)
else()
message (FATAL_ERROR "must use conan")
endif()
# ------------------------------- settings --------------------------------------
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
# Generate clang compilation database
# see https://stackoverflow.com/a/31086619/10904212
#set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(cmake_platform_detection REQUIRED)
# populates variables with TRUE or FALSE:
# PLATFORM_MOBILE | PLATFORM_WEB | PLATFORM_DESKTOP
# | TARGET_EMSCRIPTEN | TARGET_LINUX | TARGET_WINDOWS | TARGET_MACOS
# | TARGET_IOS | TARGET_ANDROID
run_cmake_platform_detection() # from cmake_platform_detection
find_package(cmake_build_options REQUIRED)
# set default cmake build type if CMAKE_BUILD_TYPE not set
setup_default_build_type(RELEASE) # from cmake_build_options
# Limits possible values of CMAKE_BUILD_TYPE
# Also populates variables with TRUE or FALSE:
# RELEASE_BUILD | DEBUG_BUILD | PROFILE_BUILD
# | MINSIZEREL_BUILD | RELWITHDEBINFO_BUILD | COVERAGE_BUILD
# | DOCS_BUILD | TEST_BUILD
setup_cmake_build_options(RELEASE DEBUG) # from cmake_build_options
message(STATUS
"Compiler ${CMAKE_CXX_COMPILER}, version: ${CMAKE_CXX_COMPILER_VERSION}")
# CMAKE_BUILD_TYPE must be not empty
check_cmake_build_type_selected() # from Utils.cmake
# beautify compiler output
enable_colored_diagnostics() # from Utils.cmake
# log cmake vars
print_cmake_system_info() # from Utils.cmake
# limit to known platforms
check_supported_os() # from Utils.cmake
find_package(cmake_helper_utils REQUIRED)
# prefer ASCII for folder names
force_latin_paths() # from cmake_helper_utils (conan package)
# out dirs (CMAKE_*_OUTPUT_DIRECTORY) must be not empty
validate_out_dirs() # from cmake_helper_utils (conan package)
# In-source builds not allowed
validate_out_source_build(WARNING) # from cmake_helper_utils (conan package)
if(ENABLE_MSAN OR ENABLE_TSAN OR ENABLE_ASAN OR ENABLE_UBSAN)
find_package(cmake_sanitizers REQUIRED)
endif()
if(ENABLE_MSAN)
add_msan_flags()
endif(ENABLE_MSAN)
if(ENABLE_TSAN)
add_tsan_flags()
endif(ENABLE_TSAN)
if(ENABLE_ASAN)
add_asan_flags()
endif(ENABLE_ASAN)
if(ENABLE_UBSAN)
add_ubsan_flags()
endif(ENABLE_UBSAN)
if(COMPILE_WITH_LLVM_TOOLS)
# force change CMAKE_*_COMPILER and CMAKE_LINKER to clang from conan
compile_with_llvm_tools() # from cmake_helper_utils (conan package)
endif(COMPILE_WITH_LLVM_TOOLS)
# Keep symbols for JIT resolution
set(LLVM_NO_DEAD_STRIP 1)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/PlatformChecks.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CommonOptions.cmake)
# ------------------------------- thirdparty_libs --------------------------------------
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_thirdparty_libs.cmake)
# ------------------------------- source files --------------------------------------
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ProjectFiles.cmake)
add_library(${FLEXTOOL_LIB_NAME}-test-includes INTERFACE)
set(VERSION_HEADER_LOCATION
${flextool_include_DIR}/version.hpp)
configure_file_if_changed(
INPUT ${flextool_include_DIR}/version.hpp.in
OUTPUT ${VERSION_HEADER_LOCATION}
TMP_FILE ${CMAKE_CURRENT_BINARY_DIR}/generated_version_hpp.tmp)
set_source_files_properties(${PROJECT_BINARY_DIR}/version.hpp
PROPERTIES GENERATED 1)
# -------------------------------- Executable ------------------------------------
# Executable target definition. CMake-build-system documentation:
# https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html
add_executable(${FLEXTOOL_LIB_NAME}
${flextool_SOURCES} # from ProjectFiles.cmake
${flextool_src_DIR}/main.cc
${VERSION_HEADER_LOCATION}
)
# Alias target for the executable to be used outside of the project. Command:
# https://cmake.org/cmake/help/latest/command/add_executable.html
add_executable(flextool::exe
ALIAS ${FLEXTOOL_LIB_NAME})
# -------------------------------- link_libraries ------------------------------------
target_link_libraries(${FLEXTOOL_LIB_NAME} PUBLIC
-lncurses
-ltinfo
${USED_3DPARTY_LIBS}
${USED_SYSTEM_LIBS}
)
target_link_libraries( ${FLEXTOOL_LIB_NAME} PRIVATE
CONAN_PKG::entt
chromium_icu::chromium_icu-static
)
if(ENABLE_CLING)
find_package(Cling REQUIRED)
list(APPEND CLING_DEFINITIONS CLING_IS_ON=1)
target_link_libraries(${FLEXTOOL_LIB_NAME} PUBLIC
CONAN_PKG::cling_conan
)
if(MSVC)
set_target_properties(${FLEXTOOL_LIB_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1)
set_property(
TARGET ${FLEXTOOL_LIB_NAME}
APPEND_STRING
PROPERTY LINK_FLAGS
"/EXPORT:?setValueNoAlloc@internal@runtime@cling@@YAXPEAX00D_K@Z
/EXPORT:?setValueNoAlloc@internal@runtime@cling@@YAXPEAX00DM@Z
/EXPORT:cling_runtime_internal_throwIfInvalidPointer")
endif()
endif(ENABLE_CLING)
# -------------------------------- Includes ------------------------------------
# $<INSTALL_INTERFACE:...> is exported using install(EXPORT)
# $<BUILD_INTERFACE:...> is exported using export(), or when the target is used by another target in the same buildsystem
macro(add_relative_include_dir TARGET VISIBILITY_BUILD VISIBILITY_INSTALL NEW_ELEM)
target_include_directories(${TARGET}
${VISIBILITY_BUILD} "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${NEW_ELEM}>"
${VISIBILITY_INSTALL} "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}/${NEW_ELEM}>"
)
target_include_directories( ${FLEXTOOL_LIB_NAME}-test-includes SYSTEM INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/${NEW_ELEM} )
endmacro(add_relative_include_dir)
#add_relative_include_dir(${FLEXTOOL_LIB_NAME} PRIVATE PRIVATE "include/flextool")
add_relative_include_dir(${FLEXTOOL_LIB_NAME} PUBLIC PUBLIC "include")
# ---------------------------------- Build options -------------------------------------
# startup target for MS Visual Studio IDE
set_vs_startup_project(${FLEXTOOL_LIB_NAME}) # from Utils.cmake
if(TARGET_EMSCRIPTEN)
# use PROPERTY CXX_STANDARD 17
else()
target_compile_features(${FLEXTOOL_LIB_NAME}
PUBLIC cxx_auto_type
PRIVATE cxx_variadic_templates)
endif()
# being a cross-platform target, we enforce standards conformance on MSVC
target_compile_options(${FLEXTOOL_LIB_NAME}
PUBLIC "$<$<BOOL:${MSVC}>:/permissive->")
# without rtti you will get error:
# ERROR: boost::bad_any_cast: failed conversion using boost::any_cast
target_compile_options(${FLEXTOOL_LIB_NAME} PRIVATE
-frtti)
set(DEBUG_LIBRARY_SUFFIX "")
set_target_properties(${FLEXTOOL_LIB_NAME}
PROPERTIES
# ENABLE_EXPORTS for -rdynamic
# i.e. export symbols from the executables
# required for plugin system
# see https://stackoverflow.com/a/8626922
ENABLE_EXPORTS ON
POSITION_INDEPENDENT_CODE ON
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" # TODO: /lib
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" # TODO: /lib
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" # TODO: /bin
ENABLE_EXPORTS 1
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CMAKE_CXX_STANDARD_REQUIRED ON
)
# bin dirs used by https://docs.conan.io/en/latest/developing_packages/workspaces.html
list(APPEND CMAKE_PROGRAM_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PROGRAM_PATH ${CMAKE_CURRENT_BINARY_DIR})
# POSITION_INDEPENDENT_CODE for -fPIC
set_property(TARGET ${FLEXTOOL_LIB_NAME}
PROPERTY POSITION_INDEPENDENT_CODE ON)
# ---------------------------------- compile_definitions -------------------------------------
# see https://cmake.org/cmake/help/v3.0/module/TestBigEndian.html
test_big_endian(${FLEXTOOL_LIB_NAME}_IS_BIG_ENDIAN)
if(${${FLEXTOOL_LIB_NAME}_IS_BIG_ENDIAN})
list(APPEND flextool_PUBLIC_DEFINES
IS_BIG_ENDIAN=1)
endif()
if(ENABLE_CLING)
target_compile_definitions(${FLEXTOOL_LIB_NAME} PRIVATE CLING_IS_ON=1)
endif(ENABLE_CLING)
target_compile_definitions(${FLEXTOOL_LIB_NAME} PRIVATE
${flextool_PRIVATE_DEFINES}
# https://stackoverflow.com/a/30877725
BOOST_SYSTEM_NO_DEPRECATED
BOOST_ERROR_CODE_HEADER_ONLY
# TODO: make program_options work without rtti (boost::bad_any_cast)
#BOOST_NO_RTTI
#BOOST_NO_TYPEID
# TODO
#BOOST_NO_EXCEPTIONS
BOOST_ASIO_STANDALONE=1
)
target_compile_definitions(${FLEXTOOL_LIB_NAME} PUBLIC
${flextool_PUBLIC_DEFINES}
${CLING_DEFINITIONS}
)
# TODO: DISABLE_DOCTEST
target_compile_definitions(${FLEXTOOL_LIB_NAME} PUBLIC
DISABLE_DOCTEST=1
)
# ---------------------------------- libfuzzer -------------------------------------
# TODO
# Optionally enable Clang's libfuzzer.
#if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND ${PROJECT_NAME}_ENABLE_LIBFUZZER)
# target_compile_options(${TARGET_NAME} PRIVATE "-fsanitize=fuzzer")
# target_compile_options(${TARGET_NAME} PRIVATE "-fsanitize-coverage=trace-cmp,trace-div,trace-gep")
#endif()
# ---------------------------------- resource dirs -------------------------------------
# remove old resources dir
#add_custom_command( TARGET ${FLEXTOOL_LIB_NAME} PRE_BUILD
# COMMAND ${CMAKE_COMMAND} -E remove_directory
# $<TARGET_FILE_DIR:${FLEXTOOL_LIB_NAME}>/resources )
# copy new resources
add_custom_command( TARGET ${FLEXTOOL_LIB_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/resources/
$<TARGET_FILE_DIR:${FLEXTOOL_LIB_NAME}>/resources )
# -------------------------------- Install -------------------------------------
# install and export steps
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Exports.cmake)
# It is always easier to navigate in an IDE when projects are organized in folders.
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
## ---------------------------- Link Time Optimization -------------------------------- ##
if(ENABLE_LTO)
# Check for LTO support (needs to be after project(...) )
find_lto(CXX)
# enable lto if available for non-debug configurations
target_enable_lto(${FLEXTOOL_LIB_NAME} optimized)
else(ENABLE_LTO)
if(cmake_build_type_tolower MATCHES "release" )
message(WARNING "Enable LTO in Release builds")
endif()
endif(ENABLE_LTO)
## ---------------------------- warning level -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_compile_warnings.cmake)
## ---------------------------- valgrind -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_valgrind.cmake)
## ---------------------------- cppcheck -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_cppcheck.cmake)
## ---------------------------- clang_tidy -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_clang_tidy.cmake)
## ---------------------------- cppclean -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_cppclean.cmake)
## ---------------------------- oclint -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_oclint.cmake)
## ---------------------------- iwyu -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_iwyu.cmake)
## ---------------------------- clang_format -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_clang_format.cmake)
## ---------------------------- uncrustify -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_uncrustify.cmake)
## ---------------------------- sanitizers -------------------------------- ##
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_sanitizers.cmake)
## ---------------------------- gold linker -------------------------------- ##
# add_gold_linker
if(USE_LD_GOLD)
add_gold_linker() # from cmake_helper_utils (conan package)
endif(USE_LD_GOLD)
## ---------------------------- ccache -------------------------------- ##
if(USE_CCACHE)
add_ccache()
target_ccache_summary(${FLEXTOOL_LIB_NAME}) # from cmake_helper_utils (conan package)
endif(USE_CCACHE)
## ---------------------------- coverage -------------------------------- ##
if(USE_COVERAGE)
add_coverage() # from cmake_helper_utils (conan package)
endif(USE_COVERAGE)
## ---------------------------- RULE_MESSAGES property -------------------------------- ##
# controls RULE_MESSAGES property
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_compile_log_level.cmake)
## ---------------------------- docs -------------------------------- ##
if(BUILD_DOXY_DOC)
add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/docs )
endif()
## ---------------------------- tests -------------------------------- ##
if(ENABLE_TESTS)
enable_testing()
message( "${PROJECT_NAME} testing enabled" )
add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
endif()
# --------------------------------- Benchmark ----------------------------------
# TODO: https://github.com/jar-git/cmake-template/blob/b7fbb0d465fbbfd0a0e80977d9563f042314bbb3/example_app/CMakeLists.txt#L70
# add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/bench)
## ---------------------------- Uninstall -------------------------------- ##
if(ENABLE_UNINSTALL)
# add `uninstall` cmake target
addinstallManifest() # from cmake_helper_utils (conan package)
endif()
## ---------------------------- various files -------------------------------- ##
# Create a dummy target to hold various files in the project root (for IDE)
if (CONAN_AUTO_INSTALL)
# NOTE: enable only when project is open in IDE
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_misc_files.cmake)
endif (CONAN_AUTO_INSTALL)