1#################################################################################### 2# # 3# Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org> # 4# # 5# This file is part of RTTR (Run Time Type Reflection) # 6# License: MIT License # 7# # 8# Permission is hereby granted, free of charge, to any person obtaining # 9# a copy of this software and associated documentation files (the "Software"), # 10# to deal in the Software without restriction, including without limitation # 11# the rights to use, copy, modify, merge, publish, distribute, sublicense, # 12# and/or sell copies of the Software, and to permit persons to whom the # 13# Software is furnished to do so, subject to the following conditions: # 14# # 15# The above copyright notice and this permission notice shall be included in # 16# all copies or substantial portions of the Software. # 17# # 18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # 19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # 20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # 21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # 22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # 23# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # 24# SOFTWARE. # 25# # 26#################################################################################### 27 28#################################################################################### 29# Welcome to the CMake build system for RTTR. 30# This file contains several helper function to make the life easier with cmake. 31#################################################################################### 32 33#################################################################################### 34# create hierarchical source groups, useful for big VS-Projects 35# FILE_LIST <= a list of files with absolute path 36#################################################################################### 37function (createSrcGroups FILE_LIST ) 38 # we want to get the relative path from the 39 # current source dir 40 string(LENGTH ${CMAKE_CURRENT_SOURCE_DIR} curDirLen) 41 set(TMP_FILE_LIST ${${FILE_LIST}}) 42 43 foreach ( SOURCE ${TMP_FILE_LIST} ) 44 string(LENGTH ${SOURCE} fullPathLen) 45 math(EXPR RelPathLen ${fullPathLen}-${curDirLen}) 46 string(SUBSTRING ${SOURCE} ${curDirLen} ${RelPathLen} curStr) 47 48 string ( REGEX REPLACE "[\\/]" "\\\\" normPath ${curStr} ) 49 string ( REGEX MATCH "\\\\(.*)\\\\" ouput ${normPath} ) 50 if(NOT CMAKE_MATCH_1 STREQUAL "") 51 source_group ( ${CMAKE_MATCH_1} FILES ${SOURCE} ) 52 endif() 53 endforeach() 54endfunction() 55 56#################################################################################### 57# Create a UnityFile. This is a file which inlcudes all other source files. 58# This is usefull, when you want a fast rebuild. 59# _UNITY_FILE <= The name of the UnityFile 60# _SRC_FILES <= The list of source files 61#################################################################################### 62function(generateUnityFile _UNITY_FILE _SRC_FILES) 63 set(files ${${_SRC_FILES}}) 64 # Generate a unique filename for the unity build translation unit 65 set(unit_build_file ${CMAKE_CURRENT_BINARY_DIR}/ub_${_UNITY_FILE}.cpp) 66 set_source_files_properties(${files} PROPERTIES HEADER_FILE_ONLY true) 67 # Open the ub file 68 FILE(WRITE ${unit_build_file} "// Unity Build generated by CMake\n") 69 # Add include statement for each translation unit 70 foreach(sourceFile ${files} ) 71 #FILE( APPEND ${unit_build_file} "#include <${CMAKE_CURRENT_SOURCE_DIR}/${sourceFile}>\n") 72 FILE( APPEND ${unit_build_file} "#include \"${sourceFile}\"\n") 73 endforeach() 74 # Complement list of translation units with the name of ub 75 set(${_UNITY_FILE} ${unit_build_file} PARENT_SCOPE) 76 source_group("Generated Files" FILES ${unit_build_file}) 77endfunction() 78 79#################################################################################### 80# Returns the name of the Directory, where the file in the FILE_PATH is located. 81#################################################################################### 82function(getNameOfDir FILE_PATH DIR_NAME) 83 get_filename_component(HAS_FILE_IN_PATH ${${FILE_PATH}} EXT) 84 if (HAS_FILE_IN_PATH) 85 get_filename_component(PATH_WITHOUT_FILENAME ${${FILE_PATH}} PATH) 86 get_filename_component(NAME_OF_DIR ${PATH_WITHOUT_FILENAME} NAME) 87 set(${DIR_NAME} ${NAME_OF_DIR} PARENT_SCOPE) 88 else() 89 get_filename_component(NAME_OF_DIR ${${FILE_PATH}} NAME) 90 set(${DIR_NAME} ${NAME_OF_DIR} PARENT_SCOPE) 91 endif() 92endfunction() 93 94#################################################################################### 95# Returns relative path from the given file path; starting from CMAKE_CURRENT_SOURCE_DIR 96#################################################################################### 97 98function(getRelativePath FILE_PATH RELATIVE_PATH) 99 string(LENGTH ${CMAKE_CURRENT_SOURCE_DIR} CUR_DIR_LEN) 100 get_filename_component(PATH_WITHOUT_FILE ${${FILE_PATH}} PATH) 101 string(LENGTH ${PATH_WITHOUT_FILE} FULL_PATH_LEN) 102 math(EXPR REL_PATH_LEN ${FULL_PATH_LEN}-${CUR_DIR_LEN}) 103 math(EXPR REL_PATH_START "${CUR_DIR_LEN}") 104 string(SUBSTRING ${PATH_WITHOUT_FILE} ${REL_PATH_START} ${REL_PATH_LEN} REL_PATH) 105 string(REGEX REPLACE "^/" "" out_path "${REL_PATH}") 106 set(${RELATIVE_PATH} ${out_path} PARENT_SCOPE) 107endfunction() 108 109#################################################################################### 110# Loads a FOLDER, which should contain a FOLDER.cmake. 111# In this file all source and header files should be declared. 112# In this cmake files all files have to be declared relative. 113# They will be read with absolut path. 114# FOLDER <= The name of the folder 115# _HEADER_FILES => The list of header files 116# _SOURCE_FILES => The list of source files 117# [OPTIONAL] 3rdArg => performs the installation of the header and source files 118#################################################################################### 119function(loadFolder FOLDER _HEADER_FILES _SOURCE_FILES) 120 set(FULL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${FOLDER}.cmake) 121 include(${FULL_PATH}) 122 get_filename_component(ABS_PATH_TO_FILES ${FULL_PATH} PATH) 123 set(shouldInstall ${ARGV3}) 124 set(QT_MOC_HEADERS) 125 set(QT_UI_FILES) 126 set(QT_QRC_FILES) 127 128 foreach(headerFile ${HEADER_FILES} ) 129 if (${headerFile} MATCHES ".*.h.in$") 130 string ( REGEX REPLACE ".h.in$" ".h" out_path ${headerFile} ) 131 configure_file(${headerFile} ${CMAKE_CURRENT_BINARY_DIR}/${out_path} @ONLY) 132 set(FULL_HEADER_PATH ${ABS_PATH_TO_FILES}/${headerFile}) 133 getRelativePath(FULL_HEADER_PATH REL_PATH) 134 set(FULL_HEADER_PATH ${CMAKE_CURRENT_BINARY_DIR}/${out_path}) 135 if (REL_PATH) 136 string ( REGEX REPLACE "[\\/]" "\\\\" normalized_path ${REL_PATH} ) 137 source_group ( ${normalized_path} FILES ${FULL_HEADER_PATH} ) 138 endif() 139 list(APPEND ALL_HPP_FILES ${FULL_HEADER_PATH}) 140 elseif (${headerFile} MATCHES ".*.rc.in$") 141 string ( REGEX REPLACE ".rc.in$" ".rc" out_path ${headerFile} ) 142 configure_file(${headerFile} ${CMAKE_CURRENT_BINARY_DIR}/${out_path} @ONLY) 143 source_group("Generated Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/${out_path}) 144 list(APPEND ALL_HPP_FILES ${CMAKE_CURRENT_BINARY_DIR}/${out_path}) 145 elseif (${headerFile} MATCHES ".*.ui$") 146 set(FULL_HEADER_PATH ${ABS_PATH_TO_FILES}/${headerFile}) 147 list(APPEND QT_UI_FILES ${FULL_HEADER_PATH}) 148 list(APPEND ALL_HPP_FILES ${FULL_HEADER_PATH}) 149 elseif (${headerFile} MATCHES ".*.qrc$") 150 set(FULL_HEADER_PATH ${ABS_PATH_TO_FILES}/${headerFile}) 151 list(APPEND QT_QRC_FILES ${FULL_HEADER_PATH}) 152 list(APPEND ALL_HPP_FILES ${FULL_HEADER_PATH}) 153 else() 154 set(FULL_HEADER_PATH ${ABS_PATH_TO_FILES}/${headerFile}) 155 file(STRINGS ${FULL_HEADER_PATH} var REGEX "Q_OBJECT") 156 if(var) 157 list(APPEND QT_MOC_HEADERS ${FULL_HEADER_PATH}) 158 endif() 159 160 # returns the relative path, from the current source dir 161 getRelativePath(FULL_HEADER_PATH REL_PATH) 162 list(APPEND HEADER_LIST_OF_CUR_DIR ${FULL_HEADER_PATH}) 163 endif() 164 # get the name of the current directory 165 getNameOfDir(CMAKE_CURRENT_SOURCE_DIR DIRNAME) 166 if (${shouldInstall}) 167 if (NOT ${FULL_HEADER_PATH} MATCHES ".*_p.h$") # we don't want to install header files which are marked as private 168 install(FILES ${FULL_HEADER_PATH} DESTINATION "include/${DIRNAME}/${REL_PATH}") 169 endif() 170 endif() 171 endforeach() 172 173 # and now the source files 174 list(APPEND QML_SOURCES) 175 foreach(srcFile ${SOURCE_FILES} ) 176 # the source_group placement doesn't work at the moment 177 if (${srcFile} MATCHES ".*.qml$") 178 string(REGEX REPLACE "[\\/]" "_" qrc_resource_file ${srcFile} ) 179 string(REGEX REPLACE ".qml$" ".qrc" qrc_resource_file ${qrc_resource_file} ) 180 set(qrc_resource_file ${CMAKE_CURRENT_BINARY_DIR}/${qrc_resource_file}) 181 file(WRITE ${qrc_resource_file} "<!DOCTYPE RCC><RCC version=\"1.0\"><qresource prefix=\"/\"><file alias=\"${srcFile}\">${ABS_PATH_TO_FILES}/${srcFile}</file></qresource></RCC>") 182 qt5_add_resources(compiled_resource_file ${qrc_resource_file}) 183 source_group("Generated Files" FILES ${compiled_resource_file}) 184 source_group("Generated Files" FILES ${qrc_resource_file}) 185 list(APPEND QML_SOURCES ${compiled_resource_file}) 186 elseif (${srcFile} MATCHES ".*.ui$") 187 set(FULL_SRC_PATH ${ABS_PATH_TO_FILES}/${srcFile}) 188 list(APPEND QT_UI_FILES ${FULL_SRC_PATH}) 189 list(APPEND SOURCE_LIST_OF_CUR_DIR ${FULL_SRC_PATH}) 190 elseif (${srcFile} MATCHES ".*.qrc$") 191 set(FULL_SRC_PATH ${ABS_PATH_TO_FILES}/${srcFile}) 192 list(APPEND QT_QRC_FILES ${FULL_SRC_PATH}) 193 list(APPEND SOURCE_LIST_OF_CUR_DIR ${FULL_SRC_PATH}) 194 else() 195 list(APPEND SOURCE_LIST_OF_CUR_DIR ${ABS_PATH_TO_FILES}/${srcFile}) 196 endif() 197 198 list(APPEND SOURCE_LIST_OF_CUR_DIR ${ABS_PATH_TO_FILES}/${srcFile}) 199 endforeach() 200 201 list(APPEND QT_MOC_SOURCES) 202 203 if (QT_MOC_HEADERS) 204 qt5_wrap_cpp(QT_MOC_SOURCES ${QT_MOC_HEADERS}) 205 source_group("Generated Files" FILES ${QT_MOC_SOURCES}) 206 endif() 207 208 list(APPEND QT_UI_SOURCES) 209 if (QT_UI_FILES) 210 qt5_wrap_ui(QT_UI_SOURCES ${QT_UI_FILES}) 211 source_group("Generated Files" FILES ${QT_UI_SOURCES}) 212 endif() 213 214 list(APPEND QT_QRC_SOURCES) 215 if (QT_QRC_FILES) 216 qt5_add_resources(QT_QRC_SOURCES ${QT_QRC_FILES}) 217 source_group("Generated Files" FILES ${QT_QRC_SOURCES}) 218 endif() 219 220 list(APPEND ALL_HPP_FILES ${${_HEADER_FILES}} ${HEADER_LIST_OF_CUR_DIR}) 221 list(APPEND ALL_CPP_FILES ${${_SOURCE_FILES}} ${SOURCE_LIST_OF_CUR_DIR} ${QT_MOC_SOURCES} ${QT_UI_SOURCES} ${QT_QRC_SOURCES} ${QML_SOURCES}) 222 set(${_HEADER_FILES} ${ALL_HPP_FILES} PARENT_SCOPE) 223 set(${_SOURCE_FILES} ${ALL_CPP_FILES} PARENT_SCOPE) 224 225 createSrcGroups(HEADER_LIST_OF_CUR_DIR) 226 createSrcGroups(SOURCE_LIST_OF_CUR_DIR) 227 message( STATUS "${FOLDER} directory included" ) 228endfunction() 229 230#################################################################################### 231# This function checks if the current generator is used for a Viusal Studio build 232# _INPUT This variable will be set to TRUE if its a Visual Studio build, otherwise to FALSE. 233#################################################################################### 234function (is_vs_based_build _INPUT) 235 if(${CMAKE_GENERATOR} MATCHES "Visual Studio") 236 set(${_INPUT} TRUE PARENT_SCOPE) 237 else() 238 set(${_INPUT} FALSE PARENT_SCOPE) 239 endif() 240endfunction() 241 242#################################################################################### 243# Copy a release dependency in the correct CMAKE_RUNTIME_OUTPUT_DIRECTORY 244# _INPUT The full path of the dependency incl. FileName 245# _OUTPUT The directory where the libraries should be installed. 246# OPTIONAL: RELATIVE Path - as third argument an optional relative path can be specified 247#################################################################################### 248 249function(copy_dependency_release _INPUT _OUTPUT) 250 is_vs_based_build(VS_BUILD) 251 252 # when this is a DEBUG build we dont copy the files 253 if(NOT VS_BUILD) 254 if(${CMAKE_BUILD_TYPE} STREQUAL Debug) 255 return() 256 endif() 257 endif() 258 # as third argument an optional relative path can be specified 259 set(REL_PATH ${ARGV2}) 260 set(_PATH ${_INPUT}) 261 # make the path to normal path with / as dir separator 262 string ( REGEX REPLACE "[\\/]" "/" FILE_PATH ${_PATH} ) 263 get_filename_component(FILE_NAME ${FILE_PATH} NAME) 264 265 if (VS_BUILD) 266 if (IS_DIRECTORY ${_INPUT}) 267 file(COPY ${_INPUT} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/${REL_PATH}) 268 else() 269 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release/${REL_PATH}/${FILE_NAME} COPYONLY) 270 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/RelWithDebInfo/${REL_PATH}/${FILE_NAME} COPYONLY) 271 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MinSizeRel/${REL_PATH}/${FILE_NAME} COPYONLY) 272 endif() 273 else() 274 if (IS_DIRECTORY ${_INPUT}) 275 file(COPY ${_INPUT} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${REL_PATH}) 276 else() 277 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${REL_PATH}/${FILE_NAME} COPYONLY) 278 endif() 279 endif() 280 281 if (IS_DIRECTORY ${_INPUT}) 282 install(DIRECTORY 283 ${FILE_PATH} 284 DESTINATION ${_OUTPUT}/${REL_PATH} 285 CONFIGURATIONS Release) 286 else() 287 install(FILES 288 ${FILE_PATH} 289 DESTINATION ${_OUTPUT}/${REL_PATH} 290 CONFIGURATIONS Release) 291 endif() 292endfunction() 293 294#################################################################################### 295# Copy a debug dependency in the correct CMAKE_RUNTIME_OUTPUT_DIRECTORY 296# _INPUT The full path of the dependency incl. FileName 297# _OUTPUT The directory where the libraries should be installed. 298# OPTIONAL: RELATIVE Path - as third argument an optional relative path can be specified 299#################################################################################### 300 301function(copy_dependency_debug _INPUT _OUTPUT) 302 is_vs_based_build(VS_BUILD) 303 304 # when this is NOT a DEBUG build we dont copy the files 305 if(NOT VS_BUILD) 306 if(NOT ${CMAKE_BUILD_TYPE} STREQUAL Debug) 307 return() 308 endif() 309 endif() 310 # as third argument an optional relative path can be specified 311 set(REL_PATH ${ARGV2}) 312 set(_PATH ${_INPUT}) 313 # make the path to normal path with / as dir separator 314 string ( REGEX REPLACE "[\\/]" "////" FILE_PATH ${_PATH} ) 315 get_filename_component(FILE_NAME ${FILE_PATH} NAME) 316 317 if (VS_BUILD) 318 if (IS_DIRECTORY ${_INPUT}) 319 file(COPY ${_INPUT} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/${REL_PATH}) 320 else() 321 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug/${REL_PATH}/${FILE_NAME} COPYONLY) 322 endif() 323 else() 324 if (IS_DIRECTORY ${_INPUT}) 325 file(COPY ${_INPUT} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${REL_PATH}) 326 else() 327 configure_file(${FILE_PATH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${REL_PATH}/${FILE_NAME} COPYONLY) 328 endif() 329 endif() 330 331 if (IS_DIRECTORY ${_INPUT}) 332 install(DIRECTORY 333 ${FILE_PATH} 334 DESTINATION ${_OUTPUT}/${REL_PATH} 335 CONFIGURATIONS Debug) 336 else() 337 install(FILES 338 ${FILE_PATH} 339 DESTINATION ${_OUTPUT}/${REL_PATH} 340 CONFIGURATIONS Debug) 341 endif() 342endfunction() 343 344#################################################################################### 345# Creates a PreCompiled Header 346# _PRECOMPILED_HEADER The full path of the dependency incl. FileName 347# _SRC_FILES (Only works with CPP files) 348#################################################################################### 349function(activate_precompiled_headers _PRECOMPILED_HEADER _SOURCE_FILES) 350 set(SRC_FILES ${${_SOURCE_FILES}}) 351 get_filename_component(pch_basename ${_PRECOMPILED_HEADER} NAME_WE) 352 set(pch_abs ${CMAKE_CURRENT_SOURCE_DIR}/${_PRECOMPILED_HEADER}) 353 set(pch_unity ${CMAKE_CURRENT_BINARY_DIR}/${pch_basename}.cpp) 354 355 if(MSVC) 356 # First specify the name of the PCH file 357 # it seems to be that nmake build cant handle the $(IntDir) variable 358 if(NOT MSVC_IDE) 359 set(pch_bin ${CMAKE_CURRENT_BINARY_DIR}/${pch_basename}.pch) 360 else() 361 set(pch_bin "$(IntDir)/${pch_basename}.pch") 362 endif() 363 # Generate precompiled header translation unit 364 if (NOT EXISTS ${pch_unity}) 365 file(WRITE ${pch_unity} "// Precompiled header unity generated by CMake\n") 366 file(APPEND ${pch_unity} "#include <${pch_abs}>\n") 367 endif() 368 # this creates the precompild header 369 set_source_files_properties(${pch_unity} 370 PROPERTIES COMPILE_FLAGS "/Yc\"${pch_abs}\" /Fp\"${pch_bin}\"" 371 OBJECT_OUTPUTS "${pch_bin}") 372 # Update properties of source files to use the precompiled header. 373 # Additionally, force the inclusion of the precompiled header at beginning of each source file. 374 set_source_files_properties(${SRC_FILES} 375 PROPERTIES COMPILE_FLAGS "/Yu\"${pch_abs}\" /FI\"${pch_abs}\" /Fp\"${pch_bin}\"" 376 OBJECT_DEPENDS "${pch_bin}") 377 # Finally, update the source file collection to contain the precompiled header translation unit 378 set(${_SOURCE_FILES} ${pch_unity} ${pch_abs} ${${_SOURCE_FILES}} PARENT_SCOPE) 379 380 source_group("Generated Files" FILES ${pch_unity}) 381 get_filename_component(PATH_TO_PCH ${_PRECOMPILED_HEADER} DIRECTORY) 382 if (PATH_TO_PCH) 383 string ( REGEX REPLACE "[\\/]" "\\\\" normalized_path ${PATH_TO_PCH} ) 384 source_group(${normalized_path} FILES ${pch_abs}) 385 endif() 386 endif() 387endfunction() 388 389#################################################################################### 390# Adds warnings compiler options to the target depending on the category 391# target Target name 392#################################################################################### 393function( set_compiler_warnings target) 394 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 395 set(WARNINGS "-Werror" 396 "-Wall") 397 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 398 set(WARNINGS "-Werror" 399 "-Wall") 400 elseif(MSVC) 401 set(WARNINGS "/WX" 402 "/W4") 403 endif() 404 405 target_compile_options(${target} PRIVATE ${WARNINGS}) 406endfunction() 407 408#################################################################################### 409# Adds or replace a compiler option 410# _OLD_OPTION The option which should be replaced 411# _NEW_OPTION The new option which should be added 412#################################################################################### 413function( replace_compiler_option _OLD_OPTION _NEW_OPTION) 414 foreach(flag_var 415 CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 416 CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 417 if(${flag_var} MATCHES ${_OLD_OPTION}) 418 # the whitespace after_OLD_OPTION is necessary to really match only the flag and not some sub flag (/MD should match by /MDd) 419 string(REGEX REPLACE "${_OLD_OPTION} " "${_NEW_OPTION} " ${flag_var} "${${flag_var}}") 420 else() 421 set(${flag_var} "${${flag_var}} ${_NEW_OPTION} ") 422 endif() 423 set(${flag_var} ${${flag_var}} PARENT_SCOPE) 424 endforeach() 425endfunction() 426 427#################################################################################### 428# enables or disables the user of RTTI for all following source files. 429# _ENABLE If true, will enable RTTI, otherwise will disable RTTI. 430#################################################################################### 431macro(enable_rtti _ENABLE) 432 set(enable_rtti_opt "") 433 set(disable_rtti_opt "") 434 if (MSVC) 435 set(enable_rtti_opt "/GR") 436 set(disable_rtti_opt "/GR-") 437 elseif(CMAKE_COMPILER_IS_GNUCXX ) 438 set(enable_rtti_opt "-frtti") 439 set(disable_rtti_opt "-fno-rtti") 440 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 441 set(enable_rtti_opt "-frtti") 442 set(disable_rtti_opt "-fno-rtti") 443 else() 444 message(FATAL_ERROR "Don't know how to enable/disable RTTI for this compiler.") 445 endif() 446 447 if (${_ENABLE}) 448 message(STATUS "Enabled: use of RTTI") 449 replace_compiler_option("${disable_rtti_opt}" "${enable_rtti_opt}") 450 else() 451 message(STATUS "Disabled: use of RTTI") 452 replace_compiler_option("${enable_rtti_opt}" "${disable_rtti_opt}") 453 endif() 454endmacro() 455 456 457#################################################################################### 458# Returns the name of the used compiler. 459# _COMPILER_NAME 460#################################################################################### 461function(getCompilerName _COMPILER_NAME) 462 if(MSVC_VERSION EQUAL 1400) 463 set(COMPILER_NAME "vs2005") 464 elseif(MSVC_VERSION EQUAL 1500) 465 set(COMPILER_NAME "vs2008") 466 elseif(MSVC_VERSION EQUAL 1600) 467 set(COMPILER_NAME "vs2010") 468 elseif(MSVC_VERSION EQUAL 1700) 469 set(COMPILER_NAME "vs2012") 470 elseif(MSVC_VERSION EQUAL 1800) 471 set(COMPILER_NAME "vs2013") 472 elseif(MSVC_VERSION EQUAL 1900) 473 set(COMPILER_NAME "vs2015") 474 elseif((MSVC_VERSION EQUAL 1910 OR MSVC_VERSION GREATER 1910) AND (MSVC_VERSION EQUAL 1919 OR MSVC_VERSION LESS 1919)) 475 set(COMPILER_NAME "vs2017") 476 elseif(CMAKE_COMPILER_IS_GNUCXX) 477 set(COMPILER_NAME "gcc") 478 if(WIN32) 479 execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_OUTPUT) 480 string(REGEX REPLACE "([0-9]+\\.[0-9]+).*" "\\1" GCC_VERSION "${GCC_VERSION_OUTPUT}") 481 set(COMPILER_NAME ${COMPILER_NAME}${GCC_VERSION}) 482 endif() 483 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 484 set(COMPILER_NAME "clang") 485 else() 486 message(WARNING "Can not retrieve compiler name!") 487 return() 488 endif() 489 490 set(${_COMPILER_NAME} ${COMPILER_NAME} PARENT_SCOPE) 491endfunction() 492 493#################################################################################### 494# This will install the PDB files also into the "bin" folder of the installation directory 495# _TARGET_NAME The name of the target 496#################################################################################### 497 498function(install_pdb_files _TARGET_NAME) 499 if (MSVC) 500 install(FILES $<TARGET_PDB_FILE:${_TARGET_NAME}> DESTINATION "bin" CONFIGURATIONS Debug RelWithDebInfo) 501 endif() 502endfunction() 503 504 505#################################################################################### 506# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes 507# _COMPILER_NAME 508#################################################################################### 509macro(getenv_path VAR) 510 set(ENV_${VAR} $ENV{${VAR}}) 511 # replace won't work if var is blank 512 if (ENV_${VAR}) 513 string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) 514 endif () 515endmacro() 516 517macro(generateLibraryVersionVariables MAJOR MINOR PATCH PRODUCT_NAME PRODUCT_CPY_RIGHT PRODUCT_LICENSE) 518 set(LIBRARY_VERSION_MAJOR ${MAJOR}) 519 set(LIBRARY_VERSION_MINOR ${MINOR}) 520 set(LIBRARY_VERSION_PATCH ${PATCH}) 521 set(LIBRARY_VERSION ${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}) 522 set(LIBRARY_VERSION_STR "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") 523 math(EXPR LIBRARY_VERSION_CALC "${LIBRARY_VERSION_MAJOR}*1000 + ${LIBRARY_VERSION_MINOR}*100 + ${LIBRARY_VERSION_PATCH}") 524 set(LIBRARY_PRODUCT_NAME ${PRODUCT_NAME}) 525 set(LIBRARY_COPYRIGHT ${PRODUCT_CPY_RIGHT}) 526 set(LIBRARY_LICENSE ${PRODUCT_LICENSE}) 527endmacro() 528 529function(get_latest_supported_cxx CXX_STANDARD) 530 if (POLICY CMP0067) 531 cmake_policy(SET CMP0067 NEW) 532 endif() 533 534 # we need to set CMAKE_CXX_STANDARD in order to use the flags for 'check_cxx_source_compiles' 535 if(${CMAKE_VERSION} VERSION_LESS "3.8.0") 536 set(CMAKE_CXX_STANDARD 14) 537 else() 538 set(CMAKE_CXX_STANDARD 17) 539 endif() 540 541 include(CheckCXXSourceCompiles) 542 543 check_cxx_source_compiles(" 544 #include <type_traits> 545 typedef void F(); 546 typedef void G() noexcept; 547 548 std::enable_if< 549 !std::is_same<F, G>::value, 550 int 551 >::type i = 42; 552 553 int main() { return 0; } 554 " 555 HAS_NO_EXCEPT_TYPE_SIGNATURE_SUPPORT) 556 557 check_cxx_source_compiles(" 558 #include <type_traits> 559 struct foo { void func() const noexcept {} }; 560 template<typename T> 561 void test_func(T) 562 { 563 static_assert(std::is_member_function_pointer<T>::value, \"Failed\"); 564 } 565 int main() { test_func(&foo::func); return 0; } 566 " 567 HAS_STL_NO_EXCEPT_TYPE_SIGNATURE_SUPPORT) 568 569 check_cxx_source_compiles(" 570 constexpr int abs(int x) 571 { 572 if(x < 0) x = -x; 573 return x; 574 } 575 576 int main() { } 577 " 578 HAS_CXX_CONSTEXPR) 579 580 check_cxx_source_compiles( " 581 #include <type_traits> 582 template<typename T> 583 struct template_type_trait : std::false_type {}; 584 585 template<template < bool > class T, bool N> 586 struct template_type_trait<T<N>> : std::true_type {}; 587 588 template<template <std::size_t> class T, std::size_t N> 589 struct template_type_trait<T<N>> : std::true_type {}; 590 591 template<std::size_t T> 592 struct bar{}; 593 594 int main() { static bool foo = template_type_trait<bar<100>>::value;} 595 " 596 HAS_PARTIAL_SPECIALIZATION_FOR_ARRAYS) 597 598 if (HAS_NO_EXCEPT_TYPE_SIGNATURE_SUPPORT AND HAS_STL_NO_EXCEPT_TYPE_SIGNATURE_SUPPORT AND 599 HAS_PARTIAL_SPECIALIZATION_FOR_ARRAYS) 600 set(MAX_CXX_STD 17) 601 else() 602 if (HAS_CXX_CONSTEXPR) 603 set(MAX_CXX_STD 14) 604 else() 605 set(MAX_CXX_STD 11) 606 endif() 607 endif() 608 609 set(${CXX_STANDARD} ${MAX_CXX_STD} PARENT_SCOPE) 610endfunction() 611 612