CMakeLists.txt (10690B)
1 cmake_minimum_required(VERSION 3.2) 2 project(trompeloeil) 3 4 option(TROMPELOEIL_INSTALL_DOCS "Install documentation" ON) 5 6 include(GNUInstallDirs) 7 include(ExternalProject) 8 include(CMakePackageConfigHelpers) 9 include(CheckCXXCompilerFlag) 10 11 write_basic_package_version_file( 12 "${CMAKE_CURRENT_BINARY_DIR}/trompeloeil/trompeloeil-config-version.cmake" 13 VERSION 41 14 COMPATIBILITY AnyNewerVersion) 15 16 add_library(trompeloeil INTERFACE) 17 add_library(trompeloeil::trompeloeil ALIAS trompeloeil) 18 19 set(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 20 21 target_include_directories( 22 trompeloeil 23 INTERFACE 24 $<BUILD_INTERFACE:${INCLUDE_DIR}> 25 ) 26 27 target_include_directories( 28 trompeloeil 29 INTERFACE 30 $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include> 31 ) 32 33 set(MASTER_PROJECT OFF) 34 if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) 35 set(MASTER_PROJECT ON) 36 endif() 37 38 if (MASTER_PROJECT AND CMAKE_BUILD_TYPE MATCHES Debug) 39 40 if (${CXX_STANDARD}) 41 set(CMAKE_CXX_STANDARD ${CXX_STANDARD}) 42 else() 43 set(CMAKE_CXX_STANDARD 14) 44 endif() 45 set(CMAKE_CXX_STANDARD_REQUIRED YES) 46 set(CMAKE_CXX_EXTENSIONS OFF) 47 48 set(CATCH_DIR ${CMAKE_CURRENT_BINARY_DIR}/catch) 49 if(NOT EXISTS ${CATCH_DIR}/catch.hpp) 50 if (NOT EXISTS ${CATCH_DIR}) 51 make_directory(${CATCH_DIR}) 52 endif() 53 file( 54 DOWNLOAD 55 https://github.com/catchorg/Catch2/releases/download/v2.9.2/catch.hpp ${CATCH_DIR}/catch.hpp 56 STATUS 57 status 58 LOG 59 log 60 ) 61 list(GET status 0 status_code) 62 list(GET status 1 status_string) 63 64 if(NOT status_code EQUAL 0) 65 message(FATAL_ERROR "error downloading catch: ${status_string}" 66 "${log}") 67 endif() 68 endif() 69 70 # Assumptions: 71 # Clang and GNU compilers run on Linux or Linux-like platforms. 72 # MSVC compilers run on Windows platforms. 73 74 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") 75 76 set( 77 LIBCXX_PREFIX_PATH 78 "/usr/lib/llvm-8" 79 CACHE 80 PATH 81 "Path prefix to libc++" 82 ) 83 84 # Interpret CXX_STDLIB, if specified 85 if (NOT "${CXX_STDLIB}" STREQUAL "") 86 87 if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") 88 89 # Emulate -stdlib for g++ 90 if ("${CXX_STDLIB}" STREQUAL "libc++") 91 92 # Disable standard library and 93 # set include path to appropriate libc++ headers 94 string(CONCAT 95 LIBCXX_INCLUDE_PATH 96 "-isystem" 97 "${LIBCXX_PREFIX_PATH}" 98 "/include/c++/v1") 99 string(CONCAT 100 STDLIB_COMPILE_FLAGS 101 "-nostdinc++" 102 " " 103 "${LIBCXX_INCLUDE_PATH}") 104 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STDLIB_COMPILE_FLAGS}") 105 106 elseif ("${CXX_STDLIB}" STREQUAL "libstdc++") 107 108 # This is the default library for g++, nothing to do. 109 110 else() 111 112 # Unknown CXX_STDLIB option 113 message(FATAL_ERROR 114 "CXX_STDLIB only understands libc++ and libstdc++, not " 115 "'${CXX_STDLIB}'") 116 117 endif() 118 119 elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 120 121 if (("${CXX_STDLIB}" STREQUAL "libc++") OR 122 ("${CXX_STDLIB}" STREQUAL "libstdc++")) 123 124 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${CXX_STDLIB}") 125 126 else() 127 128 # Unknown CXX_STDLIB option 129 message(FATAL_ERROR 130 "CXX_STDLIB only understands libc++ and libstdc++, not " 131 "'${CXX_STDLIB}'") 132 133 endif() 134 135 else() 136 137 message(FATAL_ERROR 138 "Only g++ and Clang++ compilers support CXX_STDLIB") 139 140 endif() 141 142 endif() 143 144 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 145 string(CONCAT 146 WARN_FLAGS 147 "-Weverything" 148 " -Wno-c++98-compat-pedantic" 149 " -Wno-padded" 150 " -Wno-weak-vtables" 151 " -Wno-exit-time-destructors" 152 " -Wno-global-constructors") 153 154 # Disable for Catch2. 155 # See <https://github.com/catchorg/Catch2/issues/1456> 156 check_cxx_compiler_flag("-Wno-extra-semi-stmt" WARN_SEMI_STMT) 157 158 if (WARN_SEMI_STMT) 159 string(APPEND 160 WARN_FLAGS 161 " -Wno-extra-semi-stmt") 162 endif() 163 164 check_cxx_compiler_flag("-Wno-zero-as-null-pointer-constant" WARN_ZERO_NULL) 165 166 if (WARN_ZERO_NULL) 167 string(APPEND 168 WARN_FLAGS 169 " -Wno-zero-as-null-pointer-constant") 170 endif() 171 172 # Disable for Catch2. 173 # See <https://github.com/catchorg/Catch2/issues/578> 174 check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) 175 176 if (WARN_RESERVED_ID) 177 string(APPEND 178 WARN_FLAGS 179 " -Wno-reserved-identifier") 180 endif() 181 182 elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") 183 string(CONCAT 184 WARN_FLAGS 185 "-Wall" 186 " -Wextra" 187 " -pedantic" 188 " -Wshadow" 189 " -Wconversion") 190 check_cxx_compiler_flag("-Wnonnull" WARN_NONNULL) 191 192 if (WARN_NONNULL) 193 string(APPEND 194 WARN_FLAGS 195 " -Wnonnull") 196 endif() 197 endif() 198 199 set(WARN_FLAGS "${WARN_FLAGS} -Werror") 200 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARN_FLAGS}") 201 202 # Default sanitizer target properties. 203 set(TSAN "-fsanitize=undefined,thread") 204 set(SSAN "-fsanitize=undefined,address") 205 206 # Exceptions to sanitizer target properties based on compiler and compiler version. 207 if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 208 209 if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0")) 210 set(SSAN "-fsanitize=undefined,address -fsanitize-address-use-after-scope") 211 else() 212 set(SSAN "-fsanitize=undefined,address") 213 endif() 214 215 elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU") 216 217 if ((NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8")) AND 218 (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9")) 219 set(TSAN "-fsanitize=thread") 220 set(SSAN "-fsanitize=address") 221 endif() 222 223 endif() 224 225 endif() # Clang or GNU 226 227 if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") 228 229 add_compile_options(/W4) 230 add_compile_options(/bigobj) 231 add_compile_options(/EHsc) 232 233 check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG) 234 if(HAS_PERMISSIVE_FLAG) 235 add_compile_options(/permissive-) 236 endif() 237 238 endif() # MSVC 239 240 add_executable( 241 self_test 242 EXCLUDE_FROM_ALL 243 test/compiling_tests.cpp 244 test/compiling_tests_11.cpp 245 test/compiling_tests_14.cpp 246 include/catch2/trompeloeil.hpp) 247 248 target_include_directories( 249 self_test 250 PRIVATE 251 ${CATCH_DIR} 252 ) 253 254 if (SANITIZE AND NOT APPLE) 255 set_target_properties( 256 self_test 257 PROPERTIES 258 LINK_FLAGS 259 "${SSAN} -fuse-ld=gold" 260 COMPILE_FLAGS 261 ${SSAN} 262 ) 263 endif() 264 265 target_link_libraries( 266 self_test 267 PUBLIC 268 trompeloeil 269 ) 270 271 find_package(Threads REQUIRED) 272 273 add_executable( 274 thread_terror 275 EXCLUDE_FROM_ALL 276 test/thread_terror.cpp 277 ) 278 279 target_link_libraries( 280 thread_terror 281 PUBLIC 282 trompeloeil 283 Threads::Threads 284 ) 285 286 if (SANITIZE) 287 set_target_properties( 288 thread_terror 289 PROPERTIES 290 LINK_FLAGS 291 ${TSAN} 292 COMPILE_FLAGS 293 ${TSAN} 294 ) 295 endif() 296 297 add_executable( 298 custom_recursive_mutex 299 EXCLUDE_FROM_ALL 300 test/custom_recursive_mutex.cpp 301 ) 302 303 target_link_libraries( 304 custom_recursive_mutex 305 PUBLIC 306 trompeloeil 307 Threads::Threads 308 ) 309 310 if (SANITIZE AND NOT APPLE) 311 set_target_properties( 312 custom_recursive_mutex 313 PROPERTIES 314 LINK_FLAGS 315 "${SSAN} -fuse-ld=gold" 316 COMPILE_FLAGS 317 ${SSAN} 318 ) 319 endif() 320 321 # Linker support for CXX_STDLIB argument 322 if (NOT ("${CXX_STDLIB}" STREQUAL "")) 323 324 if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") 325 326 if ("${CXX_STDLIB}" STREQUAL "libc++") 327 328 set(LIBCXX_LIBRARY_PATH "${LIBCXX_PREFIX_PATH}/lib") 329 set(STDLIB_LINK_FLAGS 330 -nodefaultlibs 331 -L${LIBCXX_LIBRARY_PATH} 332 -Wl,-rpath,${LIBCXX_LIBRARY_PATH} 333 ) 334 set(STDLIB_LINK_LIBRARIES 335 "-lc++" 336 "-lc++abi" 337 "-lm" 338 "-lc" 339 "-lgcc_s" 340 "-lgcc" 341 ) 342 343 set_target_properties( 344 self_test 345 PROPERTIES 346 LINK_FLAGS 347 ${STDLIB_LINK_FLAGS} 348 ) 349 350 target_link_libraries( 351 self_test 352 PUBLIC 353 ${STDLIB_LINK_LIBRARIES} 354 ) 355 356 set_target_properties( 357 thread_terror 358 PROPERTIES 359 LINK_FLAGS 360 ${STDLIB_LINK_FLAGS} 361 ) 362 363 target_link_libraries( 364 thread_terror 365 PUBLIC 366 ${STDLIB_LINK_LIBRARIES} 367 ) 368 369 set_target_properties( 370 custom_recursive_mutex 371 PROPERTIES 372 LINK_FLAGS 373 ${STDLIB_LINK_FLAGS} 374 ) 375 376 target_link_libraries( 377 custom_recursive_mutex 378 PUBLIC 379 ${STDLIB_LINK_LIBRARIES} 380 ) 381 382 endif() 383 384 endif() 385 386 endif() 387 388 # Shameless hack to get target to work on Windows. 389 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") 390 391 add_custom_target( 392 run_self_test 393 COMMAND 394 ${CMAKE_CURRENT_BINARY_DIR}/self_test 395 DEPENDS 396 self_test 397 ) 398 399 else() 400 401 add_custom_target( 402 run_self_test 403 COMMAND 404 ${CMAKE_CURRENT_BINARY_DIR}/Debug/self_test 405 DEPENDS 406 self_test 407 ) 408 409 endif() 410 411 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") 412 413 add_custom_target( 414 run_coverage 415 COMMAND 416 kcov --skip-solibs --include-pattern=trompeloeil.hpp ./coverage ${CMAKE_CURRENT_BINARY_DIR}/self_test 417 DEPENDS 418 self_test 419 ) 420 421 endif() 422 423 endif() # MASTER_PROJECT AND CMAKE_BUILD_TYPE MATCHES Debug 424 425 install( 426 TARGETS 427 trompeloeil 428 EXPORT 429 trompeloeil-targets 430 INCLUDES DESTINATION 431 include 432 ) 433 434 install( 435 EXPORT 436 trompeloeil-targets 437 NAMESPACE 438 trompeloeil:: 439 DESTINATION 440 ${CMAKE_INSTALL_LIBDIR}/cmake/trompeloeil 441 ) 442 install( 443 FILES 444 trompeloeil-config.cmake 445 "${CMAKE_CURRENT_BINARY_DIR}/trompeloeil/trompeloeil-config-version.cmake" 446 DESTINATION 447 ${CMAKE_INSTALL_LIBDIR}/cmake/trompeloeil 448 COMPONENT 449 Devel 450 ) 451 452 install( 453 DIRECTORY 454 include/ 455 DESTINATION 456 ${CMAKE_INSTALL_INCLUDEDIR} 457 ) 458 459 if(TROMPELOEIL_INSTALL_DOCS) 460 install( 461 FILES 462 LICENSE_1_0.txt 463 DESTINATION 464 ${CMAKE_INSTALL_DOCDIR} 465 ) 466 467 install( 468 DIRECTORY 469 docs 470 DESTINATION 471 ${CMAKE_INSTALL_DOCDIR} 472 ) 473 endif()