commit 17daab86231a9b1d5fced8d57d7cc5b4e68ed992 Author: Andrey Astafyev Date: Wed Dec 8 14:32:04 2021 +0300 Начало проекта diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..951eb8d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.0) +project(myx-cmake VERSION 0.1.2) + +include(GNUInstallDirs) +install(DIRECTORY MyxCMake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake") + diff --git a/MyxCMake/MyxCMakeConfig.cmake b/MyxCMake/MyxCMakeConfig.cmake new file mode 100644 index 0000000..f74cff9 --- /dev/null +++ b/MyxCMake/MyxCMakeConfig.cmake @@ -0,0 +1,54 @@ +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # IN_LIST operator + +get_filename_component(MYX_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + +set(MYX_CMAKE_FUNCTIONS_DIR "${MYX_CMAKE_DIR}/functions") +if(NOT IS_DIRECTORY "${MYX_CMAKE_FUNCTIONS_DIR}") + message(STATUS "MyxCMake: Functions directory is not found.") +else() + if(NOT ${MYX_CMAKE_FUNCTIONS_DIR} IN_LIST CMAKE_MODULE_PATH) + list(INSERT CMAKE_MODULE_PATH 0 "${MYX_CMAKE_FUNCTIONS_DIR}") + endif() +endif() + +set(MYX_CMAKE_THIRDPARTY_DIR "${MYX_CMAKE_DIR}/thirdparty") +if(NOT IS_DIRECTORY "${MYX_CMAKE_THIRDPARTY_DIR}") + message(STATUS "MyxCMake: Thirdparty submodule is not found.") +else() + if(NOT ${MYX_CMAKE_THIRDPARTY_DIR} IN_LIST CMAKE_MODULE_PATH) + list(INSERT CMAKE_MODULE_PATH 0 "${MYX_CMAKE_THIRDPARTY_DIR}") + endif() +endif() + +set(MYX_CMAKE_SANITIZERS_DIR "${MYX_CMAKE_DIR}/sanitizers") +if(NOT IS_DIRECTORY "${MYX_CMAKE_SANITIZERS_DIR}") + message(STATUS "MyxCMake: Sanitizers submodule is not found.") +else() + if(NOT ${MYX_CMAKE_SANITIZERS_DIR} IN_LIST CMAKE_MODULE_PATH) + list(INSERT CMAKE_MODULE_PATH 0 "${MYX_CMAKE_SANITIZERS_DIR}") + find_package(Sanitizers) + endif() +endif() + +set(MYX_CMAKE_FIND_DIR "${MYX_CMAKE_DIR}/find") +if(NOT IS_DIRECTORY "${MYX_CMAKE_FIND_DIR}") + message(STATUS "MyxCMake: Custom find submodules are not found.") +else() + if(NOT ${MYX_CMAKE_FIND_DIR} IN_LIST CMAKE_MODULE_PATH) + list(INSERT CMAKE_MODULE_PATH 0 "${MYX_CMAKE_FIND_DIR}") + endif() +endif() + +set(MYX_CMAKE_MODULES_DIR "${MYX_CMAKE_DIR}/modules") +if(NOT IS_DIRECTORY "${MYX_CMAKE_MODULES_DIR}") + message(FATAL_ERROR "MyxCMake: Requried modules directory is not found.") +else() + if(NOT ${MYX_CMAKE_MODULES_DIR} IN_LIST CMAKE_MODULE_PATH) + list(INSERT CMAKE_MODULE_PATH 0 "${MYX_CMAKE_MODULES_DIR}") + endif() +endif() + +include(MyxCMakeCommon) + +cmake_policy(POP) diff --git a/MyxCMake/find/FindCgalWidget.cmake b/MyxCMake/find/FindCgalWidget.cmake new file mode 100644 index 0000000..06b1bdd --- /dev/null +++ b/MyxCMake/find/FindCgalWidget.cmake @@ -0,0 +1,45 @@ +if(NOT CGAL_WIDGET_IS_EXTERNAL_PROJECT) + set(CGAL_WIDGET_PREFIX "" CACHE PATH "The path to the prefix of an cgal-widget installation") + set(CGAL_WIDGET_INCLUDE_DIR "" CACHE PATH "The path to the headers of an cgal-widget installation") + set(CGAL_WIDGET_LIBRARY_DIR "" CACHE PATH "The path to the library of an cgal-widget installation") + + set(_search_paths "") + if(CGAL_WIDGET_INCLUDE_DIR AND EXISTS ${CGAL_WIDGET_INCLUDE_DIR}) + list(APPEND _search_paths ${CGAL_WIDGET_INCLUDE_DIR}) + endif() + if(CGAL_WIDGET_PREFIX AND EXISTS ${CGAL_WIDGET_PREFIX}) + list(APPEND _search_paths "${CGAL_WIDGET_PREFIX}/include") + endif() + find_path( + CGAL_WIDGET_INCLUDE_DIRS + NAMES cgal-widget/cgal-widget.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(CGAL_WIDGET_LIBRARY_DIR AND EXISTS ${CGAL_WIDGET_LIBRARY_DIR}) + list(APPEND _search_paths ${CGAL_WIDGET_LIBRARY_DIR}) + endif() + if(CGAL_WIDGET_PREFIX AND EXISTS ${CGAL_WIDGET_PREFIX}) + list(APPEND _search_paths "${CGAL_WIDGET_PREFIX}/lib") + endif() + find_library( + CGAL_WIDGET_LIBRARIES + NAMES preprocmath + PATHS ${_search_paths}) + unset(_search_paths) + + if(CGAL_WIDGET_INCLUDE_DIRS AND CGAL_WIDGET_LIBRARIES) + set(CGAL_WIDGET_FOUND TRUE) + endif() + + if(CGAL_WIDGET_FOUND) + if(NOT CGAL_WIDGET_FIND_QUIETLY) + message(STATUS "Found cgal-widget") + endif() + set(HAVE_CGAL_WIDGET 1) + elseif(CGAL_WIDGET_FOUND) + if(CGAL_WIDGET_FIND_REQUIRED) + message(FATAL_ERROR "Could not find cgal-widget") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindCgalWidgetThirdparty.cmake b/MyxCMake/find/FindCgalWidgetThirdparty.cmake new file mode 100644 index 0000000..b4a669e --- /dev/null +++ b/MyxCMake/find/FindCgalWidgetThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(CGAL_WIDGET_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(CGAL_WIDGET_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(CGAL_WIDGET_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(CGAL_WIDGET_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(CGAL_WIDGET_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libcgal-widget.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + cgal-widget + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/cgal-widget + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(CgalWidgetThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} cgal-widget-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${CGAL_WIDGET_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(CGAL_WIDGET_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindFcProtocol.cmake b/MyxCMake/find/FindFcProtocol.cmake new file mode 100644 index 0000000..1f2b635 --- /dev/null +++ b/MyxCMake/find/FindFcProtocol.cmake @@ -0,0 +1,32 @@ +if(NOT FC_PROTOCOL_IS_EXTERNAL_PROJECT) + set(FC_PROTOCOL_PREFIX "" CACHE PATH "The path to the prefix of an FC protocols installation") + set(FC_PROTOCOL_INCLUDE_DIR "" CACHE PATH "The path to the headers of an FC protocols installation") + + set(_search_paths "") + if(EXISTS FC_PROTOCOL_INCLUDE_DIR) + list(APPEND _search_paths ${FC_PROTOCOL_INCLUDE_DIR}) + endif() + if(EXISTS FC_PROTOCOL_PREFIX) + list(APPEND _search_paths "${FC_PROTOCOL_PREFIX}/include") + endif() + find_path( + FC_PROTOCOL_INCLUDE_DIRS + NAMES fc-protocol/hw/result.hpp + PATHS ${_search_paths}) + unset(_search_paths) + + if(FC_PROTOCOL_INCLUDE_DIRS) + set(FC_PROTOCOL_FOUND TRUE) + endif() + + if(FC_PROTOCOL_FOUND) + if(NOT FC_PROTOCOL_FIND_QUIETLY) + message(STATUS "Found FC protocol") + endif() + set(HAVE_FC_PROTOCOL 1) + elseif(FC_PROTOCOL_FOUND) + if(FC_PROTOCOL_FIND_REQUIRED) + message(FATAL_ERROR "Could not find FC protocol") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindFcProtocolThirdparty.cmake b/MyxCMake/find/FindFcProtocolThirdparty.cmake new file mode 100644 index 0000000..58af740 --- /dev/null +++ b/MyxCMake/find/FindFcProtocolThirdparty.cmake @@ -0,0 +1,30 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(FC_PROTOCOL_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(FC_PROTOCOL_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(FC_PROTOCOL_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + fc-protocol + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/fc-protocol + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(FcProtocolThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} fc-protocol-install-headers) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(FC_PROTOCOL_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindFsp.cmake b/MyxCMake/find/FindFsp.cmake new file mode 100644 index 0000000..bf0f2bc --- /dev/null +++ b/MyxCMake/find/FindFsp.cmake @@ -0,0 +1,45 @@ +if(NOT FSP_IS_EXTERNAL_PROJECT) + set(FSP_PREFIX "" CACHE PATH "The path to the prefix of an libfsp installation") + set(FSP_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libfsp installation") + set(FSP_LIBRARY_DIR "" CACHE PATH "The path to the library of an libfsp installation") + + set(_search_paths "") + if(FSP_INCLUDE_DIR AND EXISTS ${FSP_INCLUDE_DIR}) + list(APPEND _search_paths ${FSP_INCLUDE_DIR}) + endif() + if(FSP_PREFIX AND EXISTS ${FSP_PREFIX}) + list(APPEND _search_paths "${FSP_PREFIX}/include") + endif() + find_path( + FSP_INCLUDE_DIRS + NAMES fsp/mods.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(FSP_LIBRARY_DIR AND EXISTS ${FSP_LIBRARY_DIR}) + list(APPEND _search_paths ${FSP_LIBRARY_DIR}) + endif() + if(FSP_PREFIX AND EXISTS ${FSP_PREFIX}) + list(APPEND _search_paths "${FSP_PREFIX}/lib") + endif() + find_library( + FSP_LIBRARIES + NAMES fsp + PATHS ${_search_paths}) + unset(_search_paths) + + if(FSP_INCLUDE_DIRS AND FSP_LIBRARIES) + set(FSP_FOUND TRUE) + endif() + + if(FSP_FOUND) + if(NOT FSP_FIND_QUIETLY) + message(STATUS "Found libfsp") + endif() + set(HAVE_FSP 1) + elseif(FSP_FOUND) + if(FSP_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libfsp") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindFspThirdparty.cmake b/MyxCMake/find/FindFspThirdparty.cmake new file mode 100644 index 0000000..8e5b5b1 --- /dev/null +++ b/MyxCMake/find/FindFspThirdparty.cmake @@ -0,0 +1,43 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(FSP_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(FSP_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(FSP_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(FSP_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(FSP_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libfsp.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libfsp + DEPENDS libpreprocmath libionobase myxlib + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libfsp + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + -DPREPROCMATH_PREFIX=${CMAKE_BINARY_DIR} + -DIONOBASE_PREFIX=${CMAKE_BINARY_DIR} + -DMYXLIB_PREFIX=${CMAKE_BINARY_DIR} + ) +if(FspThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} fsp-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${FSP_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(FSP_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindGEOS.cmake b/MyxCMake/find/FindGEOS.cmake new file mode 100644 index 0000000..f46ce21 --- /dev/null +++ b/MyxCMake/find/FindGEOS.cmake @@ -0,0 +1,183 @@ +# Find GEOS +# ~~~~~~~~~ +# Copyright (c) 2008, Mateusz Loskot +# (based on FindGDAL.cmake by Magnus Homann) +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# CMake module to search for GEOS library +# +# If it's found it sets GEOS_FOUND to TRUE +# and following variables are set: +# GEOS_INCLUDE_DIR +# GEOS_LIBRARY +# + +IF(EXISTS ${CMAKE_SOURCE_DIR}/cmake/MacPlistMacros.cmake) + INCLUDE (${CMAKE_SOURCE_DIR}/cmake/MacPlistMacros.cmake) +ENDIF() + +IF(WIN32) + + IF (MINGW) + FIND_PATH(GEOS_INCLUDE_DIR geos_c.h /usr/local/include /usr/include c:/msys/local/include) + FIND_LIBRARY(GEOS_LIBRARY NAMES geos_c PATHS /usr/local/lib /usr/lib c:/msys/local/lib) + ENDIF (MINGW) + + IF (MSVC) + FIND_PATH(GEOS_INCLUDE_DIR geos_c.h $ENV{LIB_DIR}/include $ENV{INCLUDE}) + FIND_LIBRARY(GEOS_LIBRARY NAMES geos geos_c_i geos_c PATHS + "$ENV{LIB_DIR}/lib" + $ENV{LIB} + ) + ENDIF (MSVC) + +ELSE(WIN32) + + IF(UNIX) + # try to use framework on mac + # want clean framework path, not unix compatibility path + IF (APPLE) + IF (CMAKE_FIND_FRAMEWORK MATCHES "FIRST" + OR CMAKE_FRAMEWORK_PATH MATCHES "ONLY" + OR NOT CMAKE_FIND_FRAMEWORK) + SET (CMAKE_FIND_FRAMEWORK_save ${CMAKE_FIND_FRAMEWORK} CACHE STRING "" FORCE) + SET (CMAKE_FIND_FRAMEWORK "ONLY" CACHE STRING "" FORCE) + FIND_LIBRARY(GEOS_LIBRARY GEOS) + IF (GEOS_LIBRARY) + # they're all the same in a framework + SET (GEOS_INCLUDE_DIR ${GEOS_LIBRARY}/Headers CACHE PATH "Path to a file.") + # set GEOS_CONFIG to make later test happy, not used here, may not exist + SET (GEOS_CONFIG ${GEOS_LIBRARY}/unix/bin/geos-config CACHE FILEPATH "Path to a program.") + # version in info.plist + GET_VERSION_PLIST (${GEOS_LIBRARY}/Resources/Info.plist GEOS_VERSION) + IF (NOT GEOS_VERSION) + MESSAGE (FATAL_ERROR "Could not determine GEOS version from framework.") + ENDIF (NOT GEOS_VERSION) + STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1" GEOS_VERSION_MAJOR "${GEOS_VERSION}") + STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\2" GEOS_VERSION_MINOR "${GEOS_VERSION}") + IF (GEOS_VERSION_MAJOR LESS 3) + MESSAGE (FATAL_ERROR "GEOS version is too old (${GEOS_VERSION}). Use 3.0.0 or higher.") + ENDIF (GEOS_VERSION_MAJOR LESS 3) + ENDIF (GEOS_LIBRARY) + SET (CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_save} CACHE STRING "" FORCE) + ENDIF () + ENDIF (APPLE) + + IF(CYGWIN) + FIND_LIBRARY(GEOS_LIBRARY NAMES geos_c PATHS /usr/lib /usr/local/lib) + ENDIF(CYGWIN) + + IF (NOT GEOS_INCLUDE_DIR OR NOT GEOS_LIBRARY OR NOT GEOS_CONFIG) + # didn't find OS X framework, and was not set by user + SET(GEOS_CONFIG_PREFER_PATH "$ENV{GEOS_HOME}/bin" CACHE STRING "preferred path to GEOS (geos-config)") + FIND_PROGRAM(GEOS_CONFIG geos-config + ${GEOS_CONFIG_PREFER_PATH} + /usr/local/bin/ + /usr/bin/ + ) + #MESSAGE("DBG GEOS_CONFIG ${GEOS_CONFIG}") + + IF (GEOS_CONFIG) + + EXEC_PROGRAM(${GEOS_CONFIG} + ARGS --version + OUTPUT_VARIABLE GEOS_VERSION) + STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\1" GEOS_VERSION_MAJOR "${GEOS_VERSION}") + STRING(REGEX REPLACE "([0-9]+)\\.([0-9]+)\\.([0-9]+)" "\\2" GEOS_VERSION_MINOR "${GEOS_VERSION}") + + IF (GEOS_VERSION_MAJOR LESS 3 OR (GEOS_VERSION_MAJOR EQUAL 3 AND GEOS_VERSION_MINOR LESS 3) ) + MESSAGE (FATAL_ERROR "GEOS version is too old (${GEOS_VERSION}). Use 3.3.0 or higher.") + ENDIF (GEOS_VERSION_MAJOR LESS 3 OR (GEOS_VERSION_MAJOR EQUAL 3 AND GEOS_VERSION_MINOR LESS 3) ) + + # set INCLUDE_DIR to prefix+include + EXEC_PROGRAM(${GEOS_CONFIG} + ARGS --prefix + OUTPUT_VARIABLE GEOS_PREFIX) + + FIND_PATH(GEOS_INCLUDE_DIR + geos_c.h + ${GEOS_PREFIX}/include + /usr/local/include + /usr/include + ) + + ## extract link dirs for rpath + EXEC_PROGRAM(${GEOS_CONFIG} + ARGS --libs + OUTPUT_VARIABLE GEOS_CONFIG_LIBS ) + + ## split off the link dirs (for rpath) + ## use regular expression to match wildcard equivalent "-L*" + ## with is a space or a semicolon + STRING(REGEX MATCHALL "[-][L]([^ ;])+" + GEOS_LINK_DIRECTORIES_WITH_PREFIX + "${GEOS_CONFIG_LIBS}" ) + #MESSAGE("DBG GEOS_LINK_DIRECTORIES_WITH_PREFIX=${GEOS_LINK_DIRECTORIES_WITH_PREFIX}") + + ## remove prefix -L because we need the pure directory for LINK_DIRECTORIES + + IF (GEOS_LINK_DIRECTORIES_WITH_PREFIX) + STRING(REGEX REPLACE "[-][L]" "" GEOS_LINK_DIRECTORIES ${GEOS_LINK_DIRECTORIES_WITH_PREFIX} ) + ENDIF (GEOS_LINK_DIRECTORIES_WITH_PREFIX) + + ### XXX - mloskot: geos-config --libs does not return -lgeos_c, so set it manually + ## split off the name + ## use regular expression to match wildcard equivalent "-l*" + ## with is a space or a semicolon + #STRING(REGEX MATCHALL "[-][l]([^ ;])+" + # GEOS_LIB_NAME_WITH_PREFIX + # "${GEOS_CONFIG_LIBS}" ) + #MESSAGE("DBG GEOS_CONFIG_LIBS=${GEOS_CONFIG_LIBS}") + #MESSAGE("DBG GEOS_LIB_NAME_WITH_PREFIX=${GEOS_LIB_NAME_WITH_PREFIX}") + SET(GEOS_LIB_NAME_WITH_PREFIX -lgeos_c CACHE STRING INTERNAL) + + ## remove prefix -l because we need the pure name + + IF (GEOS_LIB_NAME_WITH_PREFIX) + STRING(REGEX REPLACE "[-][l]" "" GEOS_LIB_NAME ${GEOS_LIB_NAME_WITH_PREFIX} ) + ENDIF (GEOS_LIB_NAME_WITH_PREFIX) + #MESSAGE("DBG GEOS_LIB_NAME=${GEOS_LIB_NAME}") + + IF (APPLE) + IF (NOT GEOS_LIBRARY) + # work around empty GEOS_LIBRARY left by framework check + # while still preserving user setting if given + # ***FIXME*** need to improve framework check so below not needed + SET(GEOS_LIBRARY ${GEOS_LINK_DIRECTORIES}/lib${GEOS_LIB_NAME}.dylib CACHE STRING INTERNAL FORCE) + ENDIF (NOT GEOS_LIBRARY) + ELSE (APPLE) + FIND_LIBRARY(GEOS_LIBRARY NAMES ${GEOS_LIB_NAME} PATHS ${GEOS_LIB_DIRECTORIES}/lib) + ENDIF (APPLE) + #MESSAGE("DBG GEOS_LIBRARY=${GEOS_LIBRARY}") + + ELSE(GEOS_CONFIG) + MESSAGE("FindGEOS.cmake: geos-config not found. Please set it manually. GEOS_CONFIG=${GEOS_CONFIG}") + ENDIF(GEOS_CONFIG) + ENDIF(NOT GEOS_INCLUDE_DIR OR NOT GEOS_LIBRARY OR NOT GEOS_CONFIG) + ENDIF(UNIX) +ENDIF(WIN32) + +IF(GEOS_INCLUDE_DIR AND NOT GEOS_VERSION) + FILE(READ ${GEOS_INCLUDE_DIR}/geos_c.h VERSIONFILE) + STRING(REGEX MATCH "#define GEOS_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+(dev)?\"" GEOS_VERSION ${VERSIONFILE}) + STRING(REGEX MATCH "[0-9]+\\.[0-9]\\.[0-9]+" GEOS_VERSION ${GEOS_VERSION}) +ENDIF(GEOS_INCLUDE_DIR AND NOT GEOS_VERSION) + +IF (GEOS_INCLUDE_DIR AND GEOS_LIBRARY) + SET(GEOS_FOUND TRUE) +ENDIF (GEOS_INCLUDE_DIR AND GEOS_LIBRARY) + +IF (GEOS_FOUND) + + IF (NOT GEOS_FIND_QUIETLY) + MESSAGE(STATUS "Found GEOS: ${GEOS_LIBRARY} (${GEOS_VERSION})") + ENDIF (NOT GEOS_FIND_QUIETLY) + +ELSE (GEOS_FOUND) + + MESSAGE(GEOS_INCLUDE_DIR=${GEOS_INCLUDE_DIR}) + MESSAGE(GEOS_LIBRARY=${GEOS_LIBRARY}) + MESSAGE(FATAL_ERROR "Could not find GEOS") + +ENDIF (GEOS_FOUND) diff --git a/MyxCMake/find/FindImitator.cmake b/MyxCMake/find/FindImitator.cmake new file mode 100644 index 0000000..bc233aa --- /dev/null +++ b/MyxCMake/find/FindImitator.cmake @@ -0,0 +1,45 @@ +if(NOT IMITATOR_IS_EXTERNAL_PROJECT) + set(IMITATOR_PREFIX "" CACHE PATH "The path to the prefix of an libimitator installation") + set(IMITATOR_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libimitator installation") + set(IMITATOR_LIBRARY_DIR "" CACHE PATH "The path to the library of an libimitator installation") + + set(_search_paths "") + if(IMITATOR_INCLUDE_DIR AND EXISTS ${IMITATOR_INCLUDE_DIR}) + list(APPEND _search_paths ${IMITATOR_INCLUDE_DIR}) + endif() + if(IMITATOR_PREFIX AND EXISTS ${IMITATOR_PREFIX}) + list(APPEND _search_paths "${IMITATOR_PREFIX}/include") + endif() + find_path( + IMITATOR_INCLUDE_DIRS + NAMES imitator/imitator.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(IMITATOR_LIBRARY_DIR AND EXISTS ${IMITATOR_LIBRARY_DIR}) + list(APPEND _search_paths ${IMITATOR_LIBRARY_DIR}) + endif() + if(IMITATOR_PREFIX AND EXISTS ${IMITATOR_PREFIX}) + list(APPEND _search_paths "${IMITATOR_PREFIX}/lib") + endif() + find_library( + IMITATOR_LIBRARIES + NAMES imitator + PATHS ${_search_paths}) + unset(_search_paths) + + if(IMITATOR_INCLUDE_DIRS AND IMITATOR_LIBRARIES) + set(IMITATOR_FOUND TRUE) + endif() + + if(IMITATOR_FOUND) + if(NOT IMITATOR_FIND_QUIETLY) + message(STATUS "Found libimitator") + endif() + set(HAVE_IMITATOR 1) + elseif(IMITATOR_FOUND) + if(IMITATOR_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libimitator") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindImitatorThirdparty.cmake b/MyxCMake/find/FindImitatorThirdparty.cmake new file mode 100644 index 0000000..7a715b0 --- /dev/null +++ b/MyxCMake/find/FindImitatorThirdparty.cmake @@ -0,0 +1,41 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(IMITATOR_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(IMITATOR_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(IMITATOR_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(IMITATOR_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(IMITATOR_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libimitator.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libimitator + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libimitator + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + -DPREPROCMATH_PREFIX=${CMAKE_BINARY_DIR} + -DMYXLIB_PREFIX=${CMAKE_BINARY_DIR} + ) +if(ImitatorThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} imitator-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${IMITATOR_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(IMITATOR_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindIonobase.cmake b/MyxCMake/find/FindIonobase.cmake new file mode 100644 index 0000000..47e6125 --- /dev/null +++ b/MyxCMake/find/FindIonobase.cmake @@ -0,0 +1,46 @@ +if(NOT IONOBASE_IS_EXTERNAL_PROJECT) + set(IONOBASE_PREFIX "" CACHE PATH "The path to the prefix of an libionobase installation") + set(IONOBASE_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libionobase installation") + set(IONOBASE_LIBRARY_DIR "" CACHE PATH "The path to the library of an libionobase installation") + + set(_search_paths "") + if(IONOBASE_INCLUDE_DIR AND EXISTS ${IONOBASE_INCLUDE_DIR}) + list(APPEND _search_paths ${IONOBASE_INCLUDE_DIR}) + endif() + if(IONOBASE_PREFIX AND EXISTS ${IONOBASE_PREFIX}) + list(APPEND _search_paths "${IONOBASE_PREFIX}/include") + endif() + find_path( + IONOBASE_INCLUDE_DIRS + NAMES interchfor.h + PATH_SUFFIXES ionobase + PATHS ${_search_paths}) + + set(_search_paths "") + if(IONOBASE_LIBRARY_DIR AND EXISTS ${IONOBASE_LIBRARY_DIR}) + list(APPEND _search_paths ${IONOBASE_LIBRARY_DIR}) + endif() + if(IONOBASE_PREFIX AND EXISTS ${IONOBASE_PREFIX}) + list(APPEND _search_paths "${IONOBASE_PREFIX}/lib") + endif() + find_library( + IONOBASE_LIBRARIES + NAMES ionobase + PATHS ${_search_paths}) + unset(_search_paths) + + if(IONOBASE_INCLUDE_DIRS AND IONOBASE_LIBRARIES) + set(IONOBASE_FOUND TRUE) + endif() + + if(IONOBASE_FOUND) + if(NOT IONOBASE_FIND_QUIETLY) + message(STATUS "Found libionobase") + endif() + set(HAVE_IONOBASE 1) + elseif(IONOBASE_FOUND) + if(IONOBASE_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libionobase") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindIonobaseThirdparty.cmake b/MyxCMake/find/FindIonobaseThirdparty.cmake new file mode 100644 index 0000000..b2f9ae9 --- /dev/null +++ b/MyxCMake/find/FindIonobaseThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(IONOBASE_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(IONOBASE_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/ionobase + CACHE PATH "" FORCE) +set(IONOBASE_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/ionobase + CACHE PATH "" FORCE) +set(IONOBASE_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(IONOBASE_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libionobase.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libionobase + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libionobase + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(IonobaseThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} ionobase-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${IONOBASE_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(IONOBASE_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindMPFR.cmake b/MyxCMake/find/FindMPFR.cmake new file mode 100644 index 0000000..cf4b701 --- /dev/null +++ b/MyxCMake/find/FindMPFR.cmake @@ -0,0 +1,32 @@ +# Copyright (c) 2008-2010 Kent State University +# Copyright (c) 2011-2012 Texas A&M University +# +# This file is distributed under the MIT License. See the accompanying file +# LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms +# and conditions. + +# NOTE: MPFR prefix is understood to be the path to the root of the MPFR +# installation library. + +set(MPFR_PREFIX "" CACHE PATH "The path to the prefix of an MPFR installation") + +find_path(MPFR_INCLUDE_DIRS mpfr.h + PATHS ${MPFR_PREFIX}/include) + +find_library(MPFR_LIBRARIES NAMES mpfr + PATHS ${MPFR_PREFIX}/lib) + +if(MPFR_INCLUDE_DIRS AND MPFR_LIBRARIES) + set(MPFR_FOUND TRUE) +endif() + +if(MPFR_FOUND) + if(NOT MPFR_FIND_QUIETLY) + MESSAGE(STATUS "Found MPFR: ${MPFR_LIBRARIES}") + endif() + set(HAVE_MPFR 1) +elseif(MPFR_FOUND) + if(MPFR_FIND_REQUIRED) + message(FATAL_ERROR "Could not find MPFR") + endif() +endif() diff --git a/MyxCMake/find/FindMPFRCppThirdparty.cmake b/MyxCMake/find/FindMPFRCppThirdparty.cmake new file mode 100644 index 0000000..1797d17 --- /dev/null +++ b/MyxCMake/find/FindMPFRCppThirdparty.cmake @@ -0,0 +1,15 @@ +# Подключение внешних проектов +include(ExternalProject) + +if(MPFR_FOUND) + ExternalProject_Add( + mpfrcpp + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/mpreal + INSTALL_DIR ${CMAKE_BINARY_DIR}/include + CONFIGURE_COMMAND true + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_COMMAND} -E copy /mpreal.h ) +endif() + +set(MPFRCPP_PREFIX ${CMAKE_BINARY_DIR} CACHE FILEPATH "" FORCE) +set(MPFRCPP_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} CACHE PATH "" FORCE) diff --git a/MyxCMake/find/FindMathGL.cmake b/MyxCMake/find/FindMathGL.cmake new file mode 100644 index 0000000..355025f --- /dev/null +++ b/MyxCMake/find/FindMathGL.cmake @@ -0,0 +1,41 @@ +set(MATHGP_PREFIX "" CACHE PATH "The path to the prefix of an MathGL installation") + +find_path(MATHGL_INCLUDE_DIR NAMES mgl2/mgl.h + PATHS + ${MPFR_PREFIX}/include + /opt/local/include + /usr/include + /usr/local/include + ) + +find_library(MATHGL_LIBRARIES NAMES mgl mgl + PATHS + ${MPFR_PREFIX}/lib + /opt/local/include + /usr/include + /usr/local/include + ) + +find_library(MATHGL_QT5_LIBRARIES NAMES mgl-qt5 + PATHS + ${MPFR_PREFIX}/lib + /opt/local/include + /usr/include + /usr/local/include + ) + +if(MATHGL_INCLUDE_DIR AND MATHGL_LIBRARIES) + get_filename_component(MATHGL_LIBRARY_DIR ${MATHGL_LIBRARIES} PATH) + set(MATHGL_FOUND TRUE) +endif() + +if(MATHGL_FOUND) + if(NOT MATHGL_FIND_QUIETLY) + MESSAGE(STATUS "Found MathGL: ${MATHGL_LIBRARIES}") + endif() + set(HAVE_MATHGL 1) +elseif(MATHGL_FOUND) + if(MATHGL_FIND_REQUIRED) + message(FATAL_ERROR "Could not find MATHGL") + endif() +endif() diff --git a/MyxCMake/find/FindMyxNotifications.cmake b/MyxCMake/find/FindMyxNotifications.cmake new file mode 100644 index 0000000..f5412e1 --- /dev/null +++ b/MyxCMake/find/FindMyxNotifications.cmake @@ -0,0 +1,45 @@ +if(NOT MYX_NOTIFICATIONS_IS_EXTERNAL_PROJECT) + set(MYX_NOTIFICATIONS_PREFIX "" CACHE PATH "The path to the prefix of an myx-notifications installation") + set(MYX_NOTIFICATIONS_INCLUDE_DIR "" CACHE PATH "The path to the headers of an myx-notifications installation") + set(MYX_NOTIFICATIONS_LIBRARY_DIR "" CACHE PATH "The path to the library of an myx-notifications installation") + + set(_search_paths "") + if(MYX_NOTIFICATIONS_INCLUDE_DIR AND EXISTS ${MYX_NOTIFICATIONS_INCLUDE_DIR}) + list(APPEND _search_paths ${MYX_NOTIFICATIONS_INCLUDE_DIR}) + endif() + if(MYX_NOTIFICATIONS_PREFIX AND EXISTS ${MYX_NOTIFICATIONS_PREFIX}) + list(APPEND _search_paths "${MYX_NOTIFICATIONS_PREFIX}/include") + endif() + find_path( + MYX_NOTIFICATIONS_INCLUDE_DIRS + NAMES myx/notifications/widget.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(MYX_NOTIFICATIONS_LIBRARY_DIR AND EXISTS ${MYX_NOTIFICATIONS_LIBRARY_DIR}) + list(APPEND _search_paths ${MYX_NOTIFICATIONS_LIBRARY_DIR}) + endif() + if(MYX_NOTIFICATIONS_PREFIX AND EXISTS ${MYX_NOTIFICATIONS_PREFIX}) + list(APPEND _search_paths "${MYX_NOTIFICATIONS_PREFIX}/lib") + endif() + find_library( + MYX_NOTIFICATIONS_LIBRARIES + NAMES myx-notifications + PATHS ${_search_paths}) + unset(_search_paths) + + if(MYX_NOTIFICATIONS_INCLUDE_DIRS AND MYX_NOTIFICATIONS_LIBRARIES) + set(MYX_NOTIFICATIONS_FOUND TRUE) + endif() + + if(MYX_NOTIFICATIONS_FOUND) + if(NOT MYX_NOTIFICATIONS_FIND_QUIETLY) + message(STATUS "Found myx-notifications") + endif() + set(HAVE_MYX_NOTIFICATIONS 1) + elseif(MYX_NOTIFICATIONS_FOUND) + if(MYX_NOTIFICATIONS_FIND_REQUIRED) + message(FATAL_ERROR "Could not find myx-notifications") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindMyxNotificationsThirdparty.cmake b/MyxCMake/find/FindMyxNotificationsThirdparty.cmake new file mode 100644 index 0000000..77634f5 --- /dev/null +++ b/MyxCMake/find/FindMyxNotificationsThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(MYX_NOTIFICATIONS_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(MYX_NOTIFICATIONS_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_NOTIFICATIONS_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_NOTIFICATIONS_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(MYX_NOTIFICATIONS_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-notifications.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + myx-notifications + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myx-notifications + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(MyxNotificationsThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} myx-notifications-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${MYX_NOTIFICATIONS_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(MYX_NOTIFICATIONS_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindMyxQPing.cmake b/MyxCMake/find/FindMyxQPing.cmake new file mode 100644 index 0000000..fbbc70f --- /dev/null +++ b/MyxCMake/find/FindMyxQPing.cmake @@ -0,0 +1,45 @@ +if(NOT MYX_QPING_IS_EXTERNAL_PROJECT) + set(MYX_QPING_PREFIX "" CACHE PATH "The path to the prefix of an myx-qping installation") + set(MYX_QPING_INCLUDE_DIR "" CACHE PATH "The path to the headers of an myx-qping installation") + set(MYX_QPING_LIBRARY_DIR "" CACHE PATH "The path to the library of an myx-qping installation") + + set(_search_paths "") + if(MYX_QPING_INCLUDE_DIR AND EXISTS ${MYX_QPING_INCLUDE_DIR}) + list(APPEND _search_paths ${MYX_QPING_INCLUDE_DIR}) + endif() + if(MYX_QPING_PREFIX AND EXISTS ${MYX_QPING_PREFIX}) + list(APPEND _search_paths "${MYX_QPING_PREFIX}/include") + endif() + find_path( + MYX_QPING_INCLUDE_DIRS + NAMES myx/qping/ping.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(MYX_QPING_LIBRARY_DIR AND EXISTS ${MYX_QPING_LIBRARY_DIR}) + list(APPEND _search_paths ${MYX_QPING_LIBRARY_DIR}) + endif() + if(MYX_QPING_PREFIX AND EXISTS ${MYX_QPING_PREFIX}) + list(APPEND _search_paths "${MYX_QPING_PREFIX}/lib") + endif() + find_library( + MYX_QPING_LIBRARIES + NAMES myx-qping + PATHS ${_search_paths}) + unset(_search_paths) + + if(MYX_QPING_INCLUDE_DIRS AND MYX_QPING_LIBRARIES) + set(MYX_QPING_FOUND TRUE) + endif() + + if(MYX_QPING_FOUND) + if(NOT MYX_QPING_FIND_QUIETLY) + message(STATUS "Found myx-qping") + endif() + set(HAVE_MYX_QPING 1) + elseif(MYX_QPING_FOUND) + if(MYX_QPING_FIND_REQUIRED) + message(FATAL_ERROR "Could not find myx-qping") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindMyxQPingThirdparty.cmake b/MyxCMake/find/FindMyxQPingThirdparty.cmake new file mode 100644 index 0000000..c124761 --- /dev/null +++ b/MyxCMake/find/FindMyxQPingThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(MYX_QPING_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(MYX_QPING_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_QPING_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_QPING_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(MYX_QPING_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-qping.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + myx-qping + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myx-qping + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(MyxQPingThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} myx-qping-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${MYX_QPING_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(MYX_QPING_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindMyxRedis.cmake b/MyxCMake/find/FindMyxRedis.cmake new file mode 100644 index 0000000..754274d --- /dev/null +++ b/MyxCMake/find/FindMyxRedis.cmake @@ -0,0 +1,45 @@ +if(NOT MYX_REDIS_IS_EXTERNAL_PROJECT) + set(MYX_REDIS_PREFIX "" CACHE PATH "The path to the prefix of an myx-redis installation") + set(MYX_REDIS_INCLUDE_DIR "" CACHE PATH "The path to the headers of an myx-redis installation") + set(MYX_REDIS_LIBRARY_DIR "" CACHE PATH "The path to the library of an myx-redis installation") + + set(_search_paths "") + if(MYX_REDIS_INCLUDE_DIR AND EXISTS ${MYX_REDIS_INCLUDE_DIR}) + list(APPEND _search_paths ${MYX_REDIS_INCLUDE_DIR}) + endif() + if(MYX_REDIS_PREFIX AND EXISTS ${MYX_REDIS_PREFIX}) + list(APPEND _search_paths "${MYX_REDIS_PREFIX}/include") + endif() + find_path( + MYX_REDIS_INCLUDE_DIRS + NAMES myx/redis/sync_client.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(MYX_REDIS_LIBRARY_DIR AND EXISTS ${MYX_REDIS_LIBRARY_DIR}) + list(APPEND _search_paths ${MYX_REDIS_LIBRARY_DIR}) + endif() + if(MYX_REDIS_PREFIX AND EXISTS ${MYX_REDIS_PREFIX}) + list(APPEND _search_paths "${MYX_REDIS_PREFIX}/lib") + endif() + find_library( + MYX_REDIS_LIBRARIES + NAMES myx-redis + PATHS ${_search_paths}) + unset(_search_paths) + + if(MYX_REDIS_INCLUDE_DIRS AND MYX_REDIS_LIBRARIES) + set(MYX_REDIS_FOUND TRUE) + endif() + + if(MYX_REDIS_FOUND) + if(NOT MYX_REDIS_FIND_QUIETLY) + message(STATUS "Found myx-redis") + endif() + set(HAVE_MYX_REDIS 1) + elseif(MYX_REDIS_FOUND) + if(MYX_REDIS_FIND_REQUIRED) + message(FATAL_ERROR "Could not find myx-redis") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindMyxRedisThirdparty.cmake b/MyxCMake/find/FindMyxRedisThirdparty.cmake new file mode 100644 index 0000000..5e73dfb --- /dev/null +++ b/MyxCMake/find/FindMyxRedisThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(MYX_REDIS_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(MYX_REDIS_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_REDIS_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYX_REDIS_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(MYX_REDIS_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-redis.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + myx-redis + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myx-redis + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(MyxRedisThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} myx-redis-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${MYX_REDIS_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(MYX_REDIS_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindMyxlib.cmake b/MyxCMake/find/FindMyxlib.cmake new file mode 100644 index 0000000..4cca54a --- /dev/null +++ b/MyxCMake/find/FindMyxlib.cmake @@ -0,0 +1,78 @@ +#[=======================================================================[.rst: +FindMyxlib +-------- + +Поиск библиотеки Myxlib + +Входные переменные +^^^^^^^^^^^^^^^^^^ + +``MYXLIB_PREFIX`` + корневой каталог установленной библиотеки. +``MYXLIB_INCLUDE_DIR`` + каталог, в котором производится поиск заголовочных файлов. +``MYXLIB_LIBRARY_DIR`` + каталог, в котором производится поиск библиотек. + +Выходные переменные +^^^^^^^^^^^^^^^^^^^ + +``MYXLIB_FOUND`` + true, если MYXLIB найдена +``MYXLIB_INCLUDE_DIRS`` + каталог с найденными заголовочными файлами +``MYXLIB_LIBRARIES`` + каталог с найденными библиотеками + +#]=======================================================================] + +if(NOT MYXLIB_IS_EXTERNAL_PROJECT) + set(MYXLIB_PREFIX "" CACHE PATH "The path to the prefix of an myxlib installation") + set(MYXLIB_INCLUDE_DIR "" CACHE PATH "The path to the headers of an myxlib installation") + set(MYXLIB_LIBRARY_DIR "" CACHE PATH "The path to the library of an myxlib installation") + + set(_search_paths "") + if(MYXLIB_INCLUDE_DIR AND EXISTS ${MYXLIB_INCLUDE_DIR}) + list(APPEND _search_paths ${MYXLIB_INCLUDE_DIR}) + endif() + if(MYXLIB_PREFIX AND EXISTS ${MYXLIB_PREFIX}) + list(APPEND _search_paths "${MYXLIB_PREFIX}/include") + endif() + find_path( + MYXLIB_INCLUDE_DIRS + NAMES myx/core/config.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(MYXLIB_LIBRARY_DIR AND EXISTS ${MYXLIB_LIBRARY_DIR}) + list(APPEND _search_paths ${MYXLIB_LIBRARY_DIR}) + endif() + if(MYXLIB_PREFIX AND EXISTS ${MYXLIB_PREFIX}) + list(APPEND _search_paths "${MYXLIB_PREFIX}/lib") + endif() + find_library( + MYXLIB_QT_LIBRARIES + NAMES myx-qt + PATHS ${_search_paths}) + find_library( + MYXLIB_FILESYSTEM_LIBRARIES + NAMES myx-filesystem + PATHS ${_search_paths}) + unset(_search_paths) + set(MYXLIB_LIBRARIES ${MYXLIB_QT_LIBRARIES} ${MYXLIB_FILESYSTEM_LIBRARIES}) + + if(MYXLIB_INCLUDE_DIRS AND MYXLIB_LIBRARIES) + set(MYXLIB_FOUND TRUE) + endif() + + if(MYXLIB_FOUND) + if(NOT MYXLIB_FIND_QUIETLY) + message(STATUS "Found myxlib") + endif() + set(HAVE_MYXLIB 1) + elseif(MYXLIB_FOUND) + if(MYXLIB_FIND_REQUIRED) + message(FATAL_ERROR "Could not find myxlib") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindMyxlibThirdparty.cmake b/MyxCMake/find/FindMyxlibThirdparty.cmake new file mode 100644 index 0000000..b0861a3 --- /dev/null +++ b/MyxCMake/find/FindMyxlibThirdparty.cmake @@ -0,0 +1,46 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(MYXLIB_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(MYXLIB_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYXLIB_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(MYXLIB_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(MYXLIB_QT_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-qt.a + CACHE FILEPATH "" FORCE) +set(MYXLIB_FILESYSTEM_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-filesystem.a + CACHE FILEPATH "" FORCE) +set(MYXLIB_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-qt.a + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libmyx-filesystem.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + myxlib + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/myxlib + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(MyxlibThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} myxlib-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${MYXLIB_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(MYXLIB_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindPreproc.cmake b/MyxCMake/find/FindPreproc.cmake new file mode 100644 index 0000000..e4c97d5 --- /dev/null +++ b/MyxCMake/find/FindPreproc.cmake @@ -0,0 +1,45 @@ +if(NOT PREPROC_IS_EXTERNAL_PROJECT) + set(PREPROC_PREFIX "" CACHE PATH "The path to the prefix of an libpreproc installation") + set(PREPROC_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libpreproc installation") + set(PREPROC_LIBRARY_DIR "" CACHE PATH "The path to the library of an libpreproc installation") + + set(_search_paths "") + if(PREPROC_INCLUDE_DIR AND EXISTS ${PREPROC_INCLUDE_DIR}) + list(APPEND _search_paths ${PREPROC_INCLUDE_DIR}) + endif() + if(PREPROC_PREFIX AND EXISTS ${PREPROC_PREFIX}) + list(APPEND _search_paths "${PREPROC_PREFIX}/include") + endif() + find_path( + PREPROC_INCLUDE_DIRS + NAMES preproc/mark.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(PREPROC_LIBRARY_DIR AND EXISTS ${PREPROC_LIBRARY_DIR}) + list(APPEND _search_paths ${PREPROC_LIBRARY_DIR}) + endif() + if(PREPROC_PREFIX AND EXISTS ${PREPROC_PREFIX}) + list(APPEND _search_paths "${PREPROC_PREFIX}/lib") + endif() + find_library( + PREPROC_LIBRARIES + NAMES preproc + PATHS ${_search_paths}) + unset(_search_paths) + + if(PREPROC_INCLUDE_DIRS AND PREPROC_LIBRARIES) + set(PREPROC_FOUND TRUE) + endif() + + if(PREPROC_FOUND) + if(NOT PREPROC_FIND_QUIETLY) + message(STATUS "Found libpreproc") + endif() + set(HAVE_PREPROC 1) + elseif(PREPROC_FOUND) + if(PREPROC_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libpreproc") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindPreprocThirdparty.cmake b/MyxCMake/find/FindPreprocThirdparty.cmake new file mode 100644 index 0000000..4b000a4 --- /dev/null +++ b/MyxCMake/find/FindPreprocThirdparty.cmake @@ -0,0 +1,41 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(PREPROC_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(PREPROC_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(PREPROC_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(PREPROC_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(PREPROC_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libpreproc.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libpreproc + DEPENDS libpreprocmath + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libpreproc + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + -DPREPROCMATH_PREFIX=${CMAKE_BINARY_DIR} + ) +if(PreprocThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} preproc-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${PREPROC_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(PREPROC_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindPreprocmath.cmake b/MyxCMake/find/FindPreprocmath.cmake new file mode 100644 index 0000000..81c7600 --- /dev/null +++ b/MyxCMake/find/FindPreprocmath.cmake @@ -0,0 +1,45 @@ +if(NOT PREPROCMATH_IS_EXTERNAL_PROJECT) + set(PREPROCMATH_PREFIX "" CACHE PATH "The path to the prefix of an libpreprocmath installation") + set(PREPROCMATH_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libpreprocmath installation") + set(PREPROCMATH_LIBRARY_DIR "" CACHE PATH "The path to the library of an libpreprocmath installation") + + set(_search_paths "") + if(PREPROCMATH_INCLUDE_DIR AND EXISTS ${PREPROCMATH_INCLUDE_DIR}) + list(APPEND _search_paths ${PREPROCMATH_INCLUDE_DIR}) + endif() + if(PREPROCMATH_PREFIX AND EXISTS ${PREPROCMATH_PREFIX}) + list(APPEND _search_paths "${PREPROCMATH_PREFIX}/include") + endif() + find_path( + PREPROCMATH_INCLUDE_DIRS + NAMES preprocmath/params.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(PREPROCMATH_LIBRARY_DIR AND EXISTS ${PREPROCMATH_LIBRARY_DIR}) + list(APPEND _search_paths ${PREPROCMATH_LIBRARY_DIR}) + endif() + if(PREPROCMATH_PREFIX AND EXISTS ${PREPROCMATH_PREFIX}) + list(APPEND _search_paths "${PREPROCMATH_PREFIX}/lib") + endif() + find_library( + PREPROCMATH_LIBRARIES + NAMES preprocmath + PATHS ${_search_paths}) + unset(_search_paths) + + if(PREPROCMATH_INCLUDE_DIRS AND PREPROCMATH_LIBRARIES) + set(PREPROCMATH_FOUND TRUE) + endif() + + if(PREPROCMATH_FOUND) + if(NOT PREPROCMATH_FIND_QUIETLY) + message(STATUS "Found libpreprocmath") + endif() + set(HAVE_PREPROCMATH 1) + elseif(PREPROCMATH_FOUND) + if(PREPROCMATH_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libpreprocmath") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindPreprocmathThirdparty.cmake b/MyxCMake/find/FindPreprocmathThirdparty.cmake new file mode 100644 index 0000000..215a7d6 --- /dev/null +++ b/MyxCMake/find/FindPreprocmathThirdparty.cmake @@ -0,0 +1,39 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(PREPROCMATH_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(PREPROCMATH_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(PREPROCMATH_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(PREPROCMATH_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(PREPROCMATH_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libpreprocmath.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libpreprocmath + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libpreprocmath + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(PreprocmathThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} preprocmath-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${PREPROCMATH_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(PREPROCMATH_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindProj.cmake b/MyxCMake/find/FindProj.cmake new file mode 100644 index 0000000..6887158 --- /dev/null +++ b/MyxCMake/find/FindProj.cmake @@ -0,0 +1,76 @@ +# Find Proj +# ~~~~~~~~~ +# Copyright (c) 2007, Martin Dobias +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# CMake module to search for Proj library +# +# If it's found it sets PROJ_FOUND to TRUE +# and following variables are set: +# PROJ_INCLUDE_DIR +# PROJ_LIBRARY + +# FIND_PATH and FIND_LIBRARY normally search standard locations +# before the specified paths. To search non-standard paths first, +# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH +# and then again with no specified paths to search the default +# locations. When an earlier FIND_* succeeds, subsequent FIND_*s +# searching for the same item do nothing. + +# try to use framework on mac +# want clean framework path, not unix compatibility path +IF (APPLE) + IF (CMAKE_FIND_FRAMEWORK MATCHES "FIRST" + OR CMAKE_FRAMEWORK_PATH MATCHES "ONLY" + OR NOT CMAKE_FIND_FRAMEWORK) + SET (CMAKE_FIND_FRAMEWORK_save ${CMAKE_FIND_FRAMEWORK} CACHE STRING "" FORCE) + SET (CMAKE_FIND_FRAMEWORK "ONLY" CACHE STRING "" FORCE) + #FIND_PATH(PROJ_INCLUDE_DIR PROJ/proj_api.h) + FIND_LIBRARY(PROJ_LIBRARY PROJ) + IF (PROJ_LIBRARY) + # FIND_PATH doesn't add "Headers" for a framework + SET (PROJ_INCLUDE_DIR ${PROJ_LIBRARY}/Headers CACHE PATH "Path to a file.") + ENDIF (PROJ_LIBRARY) + SET (CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_save} CACHE STRING "" FORCE) + ENDIF () +ENDIF (APPLE) + +FIND_PATH(PROJ_INCLUDE_DIR proj_api.h + "$ENV{INCLUDE}" + "$ENV{LIB_DIR}/include" + ) + +FIND_LIBRARY(PROJ_LIBRARY NAMES proj_i proj PATHS + "$ENV{LIB}" + "$ENV{LIB_DIR}/lib" + ) + +IF (PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + SET(PROJ_FOUND TRUE) +ENDIF (PROJ_INCLUDE_DIR AND PROJ_LIBRARY) + + +IF (PROJ_FOUND) + # This macro checks if the symbol exists + include(CheckLibraryExists) + check_library_exists("${PROJ_LIBRARY}" proj_info "" PROJ_HAS_INFO) + + IF (NOT PROJ_FIND_QUIETLY) + IF (PROJ_HAS_INFO) + FILE(READ ${PROJ_INCLUDE_DIR}/proj.h proj_version) + STRING(REGEX REPLACE "^.*PROJ_VERSION_MAJOR +([0-9]+).*$" "\\1" PROJ_VERSION_MAJOR "${proj_version}") + STRING(REGEX REPLACE "^.*PROJ_VERSION_MINOR +([0-9]+).*$" "\\1" PROJ_VERSION_MINOR "${proj_version}") + STRING(REGEX REPLACE "^.*PROJ_VERSION_PATCH +([0-9]+).*$" "\\1" PROJ_VERSION_PATCH "${proj_version}") + STRING(CONCAT PROJ_VERSION_STR "(" ${PROJ_VERSION_MAJOR} "." ${PROJ_VERSION_MINOR} "." ${PROJ_VERSION_PATCH} ")") + ENDIF (PROJ_HAS_INFO) + MESSAGE(STATUS "Found Proj: ${PROJ_LIBRARY} ${PROJ_VERSION_STR}") + ENDIF (NOT PROJ_FIND_QUIETLY) + +ELSE (PROJ_FOUND) + + IF (PROJ_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Proj") + ENDIF (PROJ_FIND_REQUIRED) + +ENDIF (PROJ_FOUND) diff --git a/MyxCMake/find/FindPythonModule.cmake b/MyxCMake/find/FindPythonModule.cmake new file mode 100644 index 0000000..16e0bc4 --- /dev/null +++ b/MyxCMake/find/FindPythonModule.cmake @@ -0,0 +1,45 @@ +# Find a Python module +# Found at http://www.cmake.org/pipermail/cmake/2011-January/041666.html +# To use do: find_python_module(NumPy REQUIRED) +# Reports also version of package, but you can't currently enforce a specific version to be +# searched for... + +include(FindPackageHandleStandardArgs) +function(find_python_module module) + # Fail if Python interpreter not known + if(NOT PYTHON_EXECUTABLE) + message(FATAL_ERROR "Use find_package(PythonInterp) first!") + endif() + string(TOLOWER ${module} _module_lower) + if(NOT ${_module_lower}) + if(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED") + set(${module}_FIND_REQUIRED TRUE) + endif() + # Find module location + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} "-c" "import re, ${_module_lower}; print(re.compile('/__init__.py.*').sub('',${_module_lower}.__file__))" + RESULT_VARIABLE _${module}_status + OUTPUT_VARIABLE _${module}_location + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(NOT _${module}_status) + set(${module} ${_${module}_location} CACHE STRING "Location of Python module ${module}") + endif() + # Find module version + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} "-c" "import re, ${_module_lower}; print(re.compile('/__init__.py.*').sub('',${_module_lower}.__version__))" + OUTPUT_VARIABLE _${module}_ver + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + + find_package_handle_standard_args(${module} + FOUND_VAR ${module}_FOUND + REQUIRED_VARS ${module} + VERSION_VAR _${module}_ver + ) +endfunction() diff --git a/MyxCMake/find/FindQGIS.cmake b/MyxCMake/find/FindQGIS.cmake new file mode 100644 index 0000000..4f9fa6c --- /dev/null +++ b/MyxCMake/find/FindQGIS.cmake @@ -0,0 +1,248 @@ +## Once run this will define: +## +## QGIS_FOUND = system has QGIS lib +## +## QGIS_CORE_LIBRARY = full path to the CORE library +## QGIS_GUI_LIBRARY = full path to the GUI library +## QGIS_ANALYSIS_LIBRARY = full path to the ANALYSIS library +## QGIS_PLUGIN_DIR = full path to where QGIS plugins are installed +## QGIS_INCLUDE_DIR = where to find headers +## QGIS_UI_INCLUDE_DIR = where to find ui_* generated headers +## +## QGIS_VERSION = version as defined in qgsconfig.h, as major.minor.patch +## +## Definitions or ENV variables affecting search locations +## +## OSGEO4W_ROOT = [A-Z]:/path/to/OSGeo4W/install/root +## (^ use forward slashes!) +## OSGEO4W_QGIS_SUBDIR = qgis[-rel|-ltr][-dev], in OSGEO4W_ROOT/apps/ +## QGIS_MAC_PATH = /path/to/any/QGIS.app/Contents +## QGIS_BUILD_PATH = [A-Z:]/path/to/QGIS/build/directory +## +## Tim Sutton +## Larry Shaffer (2017-01-31) + +#MESSAGE("Searching for QGIS") +IF(WIN32) + # OSGEO4W_QGIS_SUBDIR relative install: qgis[-rel|-ltr][-dev], etc. + IF (NOT OSGEO4W_QGIS_SUBDIR OR "${OSGEO4W_QGIS_SUBDIR}" STREQUAL "") + IF (NOT "$ENV{OSGEO4W_QGIS_SUBDIR}" STREQUAL "") + SET (OSGEO4W_QGIS_SUBDIR $ENV{OSGEO4W_QGIS_SUBDIR}) + ELSE () + SET (OSGEO4W_QGIS_SUBDIR qgis) + ENDIF () + ENDIF () + + #MESSAGE("Searching for QGIS in $ENV{PROGRAMFILES}/QGIS") + IF (MINGW) + FIND_PATH(QGIS_PLUGIN_DIR + NAMES libofflineeditingplugin.dll + PATHS + "$ENV{PROGRAMFILES}/QGIS/plugins" + ) + FIND_PATH(QGIS_INCLUDE_DIR + NAMES qgsapplication.h + PATHS + "$ENV{PROGRAMFILES}/QGIS/include" + ) + FIND_LIBRARY(QGIS_CORE_LIBRARY + NAMES qgis_core + PATHS + "$ENV{PROGRAMFILES}/QGIS/" + ) + FIND_LIBRARY(QGIS_GUI_LIBRARY + NAMES qgis_gui + PATHS + "$ENV{PROGRAMFILES}/QGIS/" + ) + ENDIF (MINGW) + + IF (MSVC) + FIND_PATH(QGIS_PLUGIN_DIR + NAMES offlineeditingplugin.dll + PATHS + "$ENV{OSGEO4W_ROOT}/apps/${OSGEO4W_QGIS_SUBDIR}/plugins" + "$ENV{PROGRAMFILES}/QGIS/plugins" + ) + FIND_PATH(QGIS_INCLUDE_DIR + NAMES qgsapplication.h + PATHS + "$ENV{INCLUDE}" + "$ENV{LIB_DIR}/include/qgis" + "$ENV{OSGEO4W_ROOT}/include" + "$ENV{OSGEO4W_ROOT}/apps/${OSGEO4W_QGIS_SUBDIR}/include" + "$ENV{PROGRAMFILES}/QGIS/include" + ) + FIND_LIBRARY(QGIS_CORE_LIBRARY + NAMES qgis_core + PATHS + "$ENV{LIB_DIR}/lib/" + "$ENV{LIB}" + "$ENV{OSGEO4W_ROOT}/lib" + "$ENV{OSGEO4W_ROOT}/apps/${OSGEO4W_QGIS_SUBDIR}/lib" + "$ENV{PROGRAMFILES}/QGIS/lib" + ) + FIND_LIBRARY(QGIS_GUI_LIBRARY + NAMES qgis_gui + PATHS + "$ENV{LIB_DIR}" + "$ENV{LIB}" + "$ENV{OSGEO4W_ROOT}/lib" + "$ENV{OSGEO4W_ROOT}/apps/${OSGEO4W_QGIS_SUBDIR}/lib" + "$ENV{PROGRAMFILES}/QGIS/lib" + ) + FIND_LIBRARY(QGIS_ANALYSIS_LIBRARY + NAMES qgis_analysis + PATHS + "$ENV{LIB_DIR}" + "$ENV{LIB}" + "$ENV{OSGEO4W_ROOT}/lib" + "$ENV{OSGEO4W_ROOT}/apps/${OSGEO4W_QGIS_SUBDIR}/lib" + "$ENV{PROGRAMFILES}/QGIS/lib" + ) + ENDIF (MSVC) +ELSE(WIN32) + IF(UNIX) + #MESSAGE("Searching for QGIS in /usr/bin; /usr/local/bin") + FIND_PATH(QGIS_PLUGIN_DIR + NAMES libofflineeditingplugin.so + PATHS + ${QGIS_BUILD_PATH}/PlugIns/qgis + ${QGIS_MAC_PATH}/PlugIns/qgis + ${QGIS_PREFIX_PATH}/lib/qgis/plugins/ + /usr/lib64/qgis/plugins + /usr/lib/qgis + /usr/lib/qgis/plugins + /usr/local/lib/qgis/plugins + "$ENV{LIB_DIR}/lib/qgis/plugins" + "$ENV{LIB_DIR}/lib/qgis" + ) + FIND_PATH(QGIS_INCLUDE_DIR + NAMES qgis.h + PATHS + ${QGIS_BUILD_PATH}/output/lib/qgis_core.framework/Headers + ${QGIS_MAC_PATH}/Frameworks/qgis_core.framework/Headers + {QGIS_PREFIX_PATH}/include/qgis + /usr/include/qgis + /usr/local/include/qgis + /Library/Frameworks/qgis_core.framework/Headers + "$ENV{LIB_DIR}/include/qgis" + ) + FIND_PATH(QGIS_UI_INCLUDE_DIR + NAMES ui_qgscredentialdialog.h + PATHS + ${QGIS_BUILD_PATH}/src/ui + ${QGIS_MAC_PATH}/Frameworks/qgis_gui.framework/Headers + {QGIS_PREFIX_PATH}/include/qgis + /usr/include/qgis + /usr/local/include/qgis + /Library/Frameworks/qgis_gui.framework/Headers + "$ENV{LIB_DIR}/include/qgis" + ) + # also get other frameworks' headers folders on OS X + IF (APPLE) + FIND_PATH(QGIS_GUI_INCLUDE_DIR + NAMES qgsguiutils.h + PATHS + ${QGIS_BUILD_PATH}/output/lib + ${QGIS_MAC_PATH}/Frameworks + /Library/Frameworks + PATH_SUFFIXES qgis_gui.framework/Headers + ) + FIND_PATH(QGIS_ANALYSIS_INCLUDE_DIR + NAMES qgsinterpolator.h + PATHS + ${QGIS_BUILD_PATH}/output/lib + ${QGIS_MAC_PATH}/Frameworks + /Library/Frameworks + PATH_SUFFIXES qgis_analysis.framework/Headers + ) + SET(QGIS_INCLUDE_DIR + ${QGIS_INCLUDE_DIR} + ${QGIS_GUI_INCLUDE_DIR} + ${QGIS_ANALYSIS_INCLUDE_DIR} + ${QGIS_UI_INCLUDE_DIR} + ) + ENDIF (APPLE) + + FIND_LIBRARY(QGIS_CORE_LIBRARY + NAMES qgis_core + PATHS + ${QGIS_BUILD_PATH}/output/lib + ${QGIS_MAC_PATH}/Frameworks + ${QGIS_MAC_PATH}/lib + ${QGIS_PREFIX_PATH}/lib/ + /usr/lib64 + /usr/lib + /usr/local/lib + /Library/Frameworks + "$ENV{LIB_DIR}/lib/" + ) + FIND_LIBRARY(QGIS_GUI_LIBRARY + NAMES qgis_gui + PATHS + ${QGIS_BUILD_PATH}/output/lib + ${QGIS_MAC_PATH}/Frameworks + ${QGIS_MAC_PATH}/lib + ${QGIS_PREFIX_PATH}/lib/ + /usr/lib64 + /usr/lib + /usr/local/lib + /Library/Frameworks + "$ENV{LIB_DIR}/lib/" + ) + FIND_LIBRARY(QGIS_ANALYSIS_LIBRARY + NAMES qgis_analysis + PATHS + ${QGIS_BUILD_PATH}/output/lib + ${QGIS_MAC_PATH}/Frameworks + ${QGIS_MAC_PATH}/lib + ${QGIS_PREFIX_PATH}/lib/ + /usr/lib64 + /usr/lib + /usr/local/lib + /Library/Frameworks + "$ENV{LIB_DIR}/lib/" + ) + ENDIF(UNIX) +ENDIF(WIN32) + +IF (QGIS_INCLUDE_DIR) + SET(QGIS_VERSION QGIS_VERSION-NOTFOUND) + FIND_FILE(_qgsconfig_h qgsconfig.h PATHS ${QGIS_INCLUDE_DIR}) + IF (_qgsconfig_h) + FILE(READ ${_qgsconfig_h} _qgsconfig) + IF (_qgsconfig) + # version defined like #define VERSION "2.14.8-Essen" + FILE(STRINGS "${_qgsconfig_h}" _qgsversion_str REGEX "^#define VERSION .*$") + STRING(REGEX REPLACE "^#define VERSION +\"([0-9]+\\.[0-9]+\\.[0-9]+).*$" "\\1" _qgsversion "${_qgsversion_str}") + IF (_qgsversion) + SET(QGIS_VERSION ${_qgsversion}) + ELSE () + MESSAGE(WARNING "No QGIS version determined: failed to parse qgsconfig.h") + ENDIF () + ELSE() + MESSAGE(WARNING "No QGIS version determined: failed to read qgsconfig.h") + ENDIF () + ELSE () + MESSAGE(WARNING "No QGIS version determined: failed to find qgsconfig.h") + ENDIF () +ENDIF () + +IF (QGIS_INCLUDE_DIR AND QGIS_CORE_LIBRARY AND QGIS_GUI_LIBRARY AND QGIS_ANALYSIS_LIBRARY) + SET(QGIS_FOUND TRUE) +ENDIF () + +IF (QGIS_FOUND) + IF (NOT QGIS_FIND_QUIETLY) + MESSAGE(STATUS "Found QGIS: ${QGIS_VERSION}") + MESSAGE(STATUS "Found QGIS core: ${QGIS_CORE_LIBRARY}") + MESSAGE(STATUS "Found QGIS gui: ${QGIS_GUI_LIBRARY}") + MESSAGE(STATUS "Found QGIS analysis: ${QGIS_ANALYSIS_LIBRARY}") + MESSAGE(STATUS "Found QGIS plugins directory: ${QGIS_PLUGIN_DIR}") + ENDIF (NOT QGIS_FIND_QUIETLY) +ELSE (QGIS_FOUND) + IF (QGIS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find QGIS") + ENDIF (QGIS_FIND_REQUIRED) +ENDIF (QGIS_FOUND) diff --git a/MyxCMake/find/FindQGLViewer.cmake b/MyxCMake/find/FindQGLViewer.cmake new file mode 100644 index 0000000..e769d9e --- /dev/null +++ b/MyxCMake/find/FindQGLViewer.cmake @@ -0,0 +1,75 @@ +# - Try to find QGLViewer +# Once done this will define +# +# QGLVIEWER_FOUND - system has QGLViewer +# QGLVIEWER_INCLUDE_DIR - the QGLViewer include directory +# QGLVIEWER_LIBRARIES - Link these to use QGLViewer +# QGLVIEWER_DEFINITIONS - Compiler switches required for using QGLViewer +# + +# first look in user defined locations +find_path(QGLVIEWER_INCLUDE_DIR + NAMES QGLViewer/qglviewer.h + NO_DEFAULT_PATH + PATHS ENV QGLVIEWERROOT + /usr/local/include + ) + +find_library(QGLVIEWER_LIBRARY_RELEASE + NAMES qglviewer-qt5 qglviewer QGLViewer-qt5 QGLViewer QGLViewer2-qt5 QGLViewer2 + NO_DEFAULT_PATH + PATHS ENV QGLVIEWERROOT + ENV LD_LIBRARY_PATH + ENV LIBRARY_PATH + /usr/local/lib + PATH_SUFFIXES QGLViewer QGLViewer/release + ) + +find_library(QGLVIEWER_LIBRARY_DEBUG + NAMES dqglviewer dQGLViewer-qt5 dQGLViewer dQGLViewer2-qt5 dQGLViewer2 QGLViewerd2-qt5 QGLViewerd2 + NO_DEFAULT_PATH + PATHS /usr/local/lib + ENV QGLVIEWERROOT + ENV LD_LIBRARY_PATH + ENV LIBRARY_PATH + PATH_SUFFIXES QGLViewer QGLViewer/debug + ) + +#now try the standard paths +if (NOT QGLVIEWER_INCLUDE_DIR OR NOT QGLVIEWER_LIBRARY_RELEASE OR NOT QGLVIEWER_LIBRARY_DEBUG) +find_path(QGLVIEWER_INCLUDE_DIR + NAMES QGLViewer/qglviewer.h) + +find_library(QGLVIEWER_LIBRARY_RELEASE + NAMES qglviewer-qt5 qglviewer QGLViewer-qt5 QGLViewer QGLViewer2-qt5 QGLViewer2) + +find_library(QGLVIEWER_LIBRARY_DEBUG + NAMES dqglviewer dQGLViewer-qt5 dQGLViewer dQGLViewer2-qt5 dQGLViewer2 QGLViewerd2-qt5 QGLViewerd2) + +endif() + +if(QGLVIEWER_LIBRARY_RELEASE) + if(QGLVIEWER_LIBRARY_DEBUG) + set(QGLVIEWER_LIBRARIES_ optimized ${QGLVIEWER_LIBRARY_RELEASE} debug ${QGLVIEWER_LIBRARY_DEBUG}) + else() + set(QGLVIEWER_LIBRARIES_ ${QGLVIEWER_LIBRARY_RELEASE}) + endif() + + set(QGLVIEWER_LIBRARIES ${QGLVIEWER_LIBRARIES_} CACHE FILEPATH "The QGLViewer library") + +endif() + +IF(QGLVIEWER_INCLUDE_DIR AND QGLVIEWER_LIBRARIES) + SET(QGLVIEWER_FOUND TRUE) +ENDIF(QGLVIEWER_INCLUDE_DIR AND QGLVIEWER_LIBRARIES) + +IF(QGLVIEWER_FOUND) + IF(NOT QGLViewer_FIND_QUIETLY) + MESSAGE(STATUS "Found QGLViewer: ${QGLVIEWER_LIBRARIES}") + ENDIF(NOT QGLViewer_FIND_QUIETLY) +ELSE(QGLVIEWER_FOUND) + IF(QGLViewer_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find QGLViewer") + ENDIF(QGLViewer_FIND_REQUIRED) +ENDIF(QGLVIEWER_FOUND) + diff --git a/MyxCMake/find/FindQuadmath.cmake b/MyxCMake/find/FindQuadmath.cmake new file mode 100644 index 0000000..eb5ac86 --- /dev/null +++ b/MyxCMake/find/FindQuadmath.cmake @@ -0,0 +1,50 @@ +# Module that checks whether the compiler supports the +# quadruple precision floating point math +# +# Sets the following variables: +# QUADMATH_FOUND +# QUADMATH_LIBRARIES +# +# perform tests +include(CheckCSourceCompiles) +include(CheckCXXSourceCompiles) +include(CMakePushCheckState) +include(CheckCXXCompilerFlag) + +if(NOT DEFINED USE_QUADMATH OR USE_QUADMATH) + if(NOT DEFINED HAVE_EXTENDED_NUMERIC_LITERALS) + check_cxx_compiler_flag("-Werror -fext-numeric-literals" HAVE_EXTENDED_NUMERIC_LITERALS) + endif() + + if (HAVE_EXTENDED_NUMERIC_LITERALS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") + endif() + + cmake_push_check_state(RESET) + list(APPEND CMAKE_REQUIRED_LIBRARIES "quadmath") + CHECK_CXX_SOURCE_COMPILES(" +#include + +int main(void){ + __float128 foo = sqrtq(123.456); + foo = FLT128_MIN; +}" QUADMATH_FOUND) + cmake_pop_check_state() + + if (QUADMATH_FOUND) + set(QUADMATH_LIBRARIES "quadmath") + set(QUADMATH_FOUND "${QUADMATH_FOUND}") + set(HAVE_QUADMATH 1) + endif() +endif() + +if (USE_QUADMATH AND NOT QUADMATH_FOUND) + message(FATAL_ERROR "Quadruple precision math support was explicitly requested but is unavailable!") +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Quadmath + DEFAULT_MSG + QUADMATH_LIBRARIES + QUADMATH_FOUND + ) diff --git a/MyxCMake/find/FindQwt.cmake b/MyxCMake/find/FindQwt.cmake new file mode 100644 index 0000000..d9e4386 --- /dev/null +++ b/MyxCMake/find/FindQwt.cmake @@ -0,0 +1,57 @@ +# Find Qwt +# ~~~~~~~~ +# Copyright (c) 2010, Tim Sutton +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# +# Once run this will define: +# +# QWT_FOUND = system has QWT lib +# QWT_LIBRARY = full path to the QWT library +# QWT_INCLUDE_DIR = where to find headers +# + + +set(QWT_LIBRARY_NAMES qwt-qt5 qwt6-qt5 qwt qwt6) + +find_library(QWT_LIBRARY + NAMES ${QWT_LIBRARY_NAMES} + PATHS + /usr/lib + /usr/local/lib + /usr/local/lib/qt5 + "$ENV{LIB_DIR}/lib" + "$ENV{LIB}" +) + +set(_qwt_fw) +if(QWT_LIBRARY MATCHES "/qwt.*\\.framework") + string(REGEX REPLACE "^(.*/qwt.*\\.framework).*$" "\\1" _qwt_fw "${QWT_LIBRARY}") +endif() + +FIND_PATH(QWT_INCLUDE_DIR NAMES qwt.h PATHS + "${_qwt_fw}/Headers" + /usr/include + /usr/include/qt5 + /usr/local/include + /usr/local/include/qt5 + "$ENV{LIB_DIR}/include" + "$ENV{INCLUDE}" + PATH_SUFFIXES qwt-qt5 qwt qwt6 +) + +IF (QWT_INCLUDE_DIR AND QWT_LIBRARY) + SET(QWT_FOUND TRUE) +ENDIF (QWT_INCLUDE_DIR AND QWT_LIBRARY) + +IF (QWT_FOUND) + FILE(READ ${QWT_INCLUDE_DIR}/qwt_global.h qwt_header) + STRING(REGEX REPLACE "^.*QWT_VERSION_STR +\"([^\"]+)\".*$" "\\1" QWT_VERSION_STR "${qwt_header}") + IF (NOT QWT_FIND_QUIETLY) + MESSAGE(STATUS "Found Qwt: ${QWT_LIBRARY} (${QWT_VERSION_STR})") + ENDIF (NOT QWT_FIND_QUIETLY) +ELSE (QWT_FOUND) + IF (QWT_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Qwt") + ENDIF (QWT_FIND_REQUIRED) +ENDIF (QWT_FOUND) diff --git a/MyxCMake/find/FindQwtPlot3D.cmake b/MyxCMake/find/FindQwtPlot3D.cmake new file mode 100644 index 0000000..d79c439 --- /dev/null +++ b/MyxCMake/find/FindQwtPlot3D.cmake @@ -0,0 +1,55 @@ +# Find QwtPlot3D +# ~~~~~~~~~~~~~ +# Once run this will define: +# +# QWTPLOT3D_FOUND = system has QwtPlot3D lib +# QWTPLOT3D_LIBRARY = full path to the QwtPlot3D library +# QWTPLOT3D_INCLUDE_DIR = where to find headers +# + + +set(QWTPLOT3D_LIBRARY_NAMES qwtplot3d-qt5) + +find_library(QWTPLOT3D_LIBRARY + NAMES ${QWTPLOT3D_LIBRARY_NAMES} + PATHS + /usr/lib + /usr/local/lib + /usr/local/lib/qt5 + "$ENV{LIB_DIR}/lib" + "$ENV{LIB}" +) + +set(_qwt_fw) +if(QWTPLOT3D_LIBRARY MATCHES "/qwt.*\\.framework") + string(REGEX REPLACE "^(.*/qwt.*\\.framework).*$" "\\1" _qwt_fw "${QWTPLOT3D_LIBRARY}") +endif() + +FIND_PATH(QWTPLOT3D_INCLUDE_DIR NAMES qwt3d_plot.h PATHS + "${_qwt_fw}/Headers" + /usr/include + /usr/include/qt5 + /usr/local/include + /usr/local/include/qt5 + "$ENV{LIB_DIR}/include" + "$ENV{INCLUDE}" + PATH_SUFFIXES qwtplot3d +) + +IF (QWTPLOT3D_INCLUDE_DIR AND QWTPLOT3D_LIBRARY) + SET(QWTPLOT3D_FOUND TRUE) +ENDIF (QWTPLOT3D_INCLUDE_DIR AND QWTPLOT3D_LIBRARY) + +IF (QWTPLOT3D_FOUND) + FILE(READ ${QWTPLOT3D_INCLUDE_DIR}/qwt3d_global.h qwt_header) + STRING(REGEX REPLACE "^.*QWT3D_MAJOR_VERSION +([0-9]+).*$" "\\1" QWT3D_MAJOR_VERSION "${qwt_header}") + STRING(REGEX REPLACE "^.*QWT3D_MINOR_VERSION +([0-9]+).*$" "\\1" QWT3D_MINOR_VERSION "${qwt_header}") + STRING(REGEX REPLACE "^.*QWT3D_PATCH_VERSION +([0-9]+).*$" "\\1" QWT3D_PATCH_VERSION "${qwt_header}") + IF (NOT QWTPLOT3D_FIND_QUIETLY) + MESSAGE(STATUS "Found QwtPlot3D: ${QWTPLOT3D_LIBRARY} (${QWT3D_MAJOR_VERSION}.${QWT3D_MINOR_VERSION}.${QWT3D_PATCH_VERSION})") + ENDIF (NOT QWTPLOT3D_FIND_QUIETLY) +ELSE (QWTPLOT3D_FOUND) + IF (QWTPLOT3D_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find QwtPlot3D") + ENDIF (QWTPLOT3D_FIND_REQUIRED) +ENDIF (QWTPLOT3D_FOUND) diff --git a/MyxCMake/find/FindQwtPolar.cmake b/MyxCMake/find/FindQwtPolar.cmake new file mode 100644 index 0000000..0fad8cd --- /dev/null +++ b/MyxCMake/find/FindQwtPolar.cmake @@ -0,0 +1,53 @@ +# Find QwtPolar +# ~~~~~~~~~~~~~ +# Once run this will define: +# +# QWTPOLAR_FOUND = system has QWTPOLAR lib +# QWTPOLAR_LIBRARY = full path to the QWTPOLAR library +# QWTPOLAR_INCLUDE_DIR = where to find headers +# + + +set(QWTPOLAR_LIBRARY_NAMES qwtpolar) + +find_library(QWTPOLAR_LIBRARY + NAMES ${QWTPOLAR_LIBRARY_NAMES} + PATHS + /usr/lib + /usr/local/lib + /usr/local/lib/qt5 + "$ENV{LIB_DIR}/lib" + "$ENV{LIB}" +) + +set(_qwt_fw) +if(QWTPOLAR_LIBRARY MATCHES "/qwt.*\\.framework") + string(REGEX REPLACE "^(.*/qwt.*\\.framework).*$" "\\1" _qwt_fw "${QWTPOLAR_LIBRARY}") +endif() + +FIND_PATH(QWTPOLAR_INCLUDE_DIR NAMES qwt_polar.h PATHS + "${_qwt_fw}/Headers" + /usr/include + /usr/include/qt5 + /usr/local/include + /usr/local/include/qt5 + "$ENV{LIB_DIR}/include" + "$ENV{INCLUDE}" + PATH_SUFFIXES qwt-qt5 qwt qwt6 +) + +IF (QWTPOLAR_INCLUDE_DIR AND QWTPOLAR_LIBRARY) + SET(QWTPOLAR_FOUND TRUE) +ENDIF (QWTPOLAR_INCLUDE_DIR AND QWTPOLAR_LIBRARY) + +IF (QWTPOLAR_FOUND) + FILE(READ ${QWTPOLAR_INCLUDE_DIR}/qwt_polar_global.h qwt_header) + STRING(REGEX REPLACE "^.*QWT_POLAR_VERSION_STR +\"([^\"]+)\".*$" "\\1" QWT_POLAR_VERSION_STR "${qwt_header}") + IF (NOT QWTPOLAR_FIND_QUIETLY) + MESSAGE(STATUS "Found QwtPolar: ${QWTPOLAR_LIBRARY} (${QWT_POLAR_VERSION_STR})") + ENDIF (NOT QWTPOLAR_FIND_QUIETLY) +ELSE (QWTPOLAR_FOUND) + IF (QWTPOLAR_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find QwtPolar") + ENDIF (QWTPOLAR_FIND_REQUIRED) +ENDIF (QWTPOLAR_FOUND) diff --git a/MyxCMake/find/FindSignalView.cmake b/MyxCMake/find/FindSignalView.cmake new file mode 100644 index 0000000..32a8a88 --- /dev/null +++ b/MyxCMake/find/FindSignalView.cmake @@ -0,0 +1,45 @@ +if(NOT SIGNALVIEW_IS_EXTERNAL_PROJECT) + set(SIGNALVIEW_PREFIX "" CACHE PATH "The path to the prefix of an libsignalview installation") + set(SIGNALVIEW_INCLUDE_DIR "" CACHE PATH "The path to the headers of an libsignalview installation") + set(SIGNALVIEW_LIBRARY_DIR "" CACHE PATH "The path to the library of an libsignalview installation") + + set(_search_paths "") + if(SIGNALVIEW_INCLUDE_DIR AND EXISTS ${SIGNALVIEW_INCLUDE_DIR}) + list(APPEND _search_paths ${SIGNALVIEW_INCLUDE_DIR}) + endif() + if(SIGNALVIEW_PREFIX AND EXISTS ${SIGNALVIEW_PREFIX}) + list(APPEND _search_paths "${SIGNALVIEW_PREFIX}/include") + endif() + find_path( + SIGNALVIEW_INCLUDE_DIRS + NAMES signalview/wndSignalView.hpp + PATHS ${_search_paths}) + + set(_search_paths "") + if(SIGNALVIEW_LIBRARY_DIR AND EXISTS ${SIGNALVIEW_LIBRARY_DIR}) + list(APPEND _search_paths ${SIGNALVIEW_LIBRARY_DIR}) + endif() + if(SIGNALVIEW_PREFIX AND EXISTS ${SIGNALVIEW_PREFIX}) + list(APPEND _search_paths "${SIGNALVIEW_PREFIX}/lib") + endif() + find_library( + SIGNALVIEW_LIBRARIES + NAMES signalview + PATHS ${_search_paths}) + unset(_search_paths) + + if(SIGNALVIEW_INCLUDE_DIRS AND SIGNALVIEW_LIBRARIES) + set(SIGNALVIEW_FOUND TRUE) + endif() + + if(SIGNALVIEW_FOUND) + if(NOT SIGNALVIEW_FIND_QUIETLY) + message(STATUS "Found libsignalview") + endif() + set(HAVE_SIGNALVIEW 1) + elseif(SIGNALVIEW_FOUND) + if(SIGNALVIEW_FIND_REQUIRED) + message(FATAL_ERROR "Could not find libsignalview") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindSignalViewThirdparty.cmake b/MyxCMake/find/FindSignalViewThirdparty.cmake new file mode 100644 index 0000000..59fd332 --- /dev/null +++ b/MyxCMake/find/FindSignalViewThirdparty.cmake @@ -0,0 +1,41 @@ +# Подключение внешних проектов +include(ExternalProject) + +set(SIGNALVIEW_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(SIGNALVIEW_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(SIGNALVIEW_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(SIGNALVIEW_LIBRARY_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} + CACHE PATH "" FORCE) +set(SIGNALVIEW_LIBRARIES + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/libsignalview.a + CACHE FILEPATH "" FORCE) + +# cmake-format: off +list(APPEND _ext_project_args + libsignalview + DEPENDS libpreprocmath + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/libsignalview + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + -DPREPROCMATH_PREFIX=${CMAKE_BINARY_DIR} + ) +if(SignalViewThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} signalview-install-headers) +else() + list(APPEND _ext_project_args + BUILD_BYPRODUCTS ${SIGNALVIEW_LIBRARIES}) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(SIGNALVIEW_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on diff --git a/MyxCMake/find/FindSphinx.cmake b/MyxCMake/find/FindSphinx.cmake new file mode 100644 index 0000000..3ea7f62 --- /dev/null +++ b/MyxCMake/find/FindSphinx.cmake @@ -0,0 +1,38 @@ +# - This module looks for Sphinx +# Find the Sphinx documentation generator +# +# This modules defines +# SPHINX_EXECUTABLE +# SPHINX_FOUND + +#============================================================================= +# Copyright 2002-2009 Kitware, Inc. +# Copyright 2009-2011 Peter Colberg +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +find_program(SPHINX_EXECUTABLE NAMES sphinx-build + HINTS + $ENV{SPHINX_DIR} + HINTS ${SPHINX_ROOT}/bin + PATH_SUFFIXES bin + DOC "Sphinx documentation generator" +) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Sphinx DEFAULT_MSG + SPHINX_EXECUTABLE +) + +mark_as_advanced( + SPHINX_EXECUTABLE +) diff --git a/MyxCMake/find/FindVeerProtocols.cmake b/MyxCMake/find/FindVeerProtocols.cmake new file mode 100644 index 0000000..fcc810f --- /dev/null +++ b/MyxCMake/find/FindVeerProtocols.cmake @@ -0,0 +1,32 @@ +if(NOT VEER_PROTOCOLS_IS_EXTERNAL_PROJECT) + set(VEER_PROTOCOLS_PREFIX "" CACHE PATH "The path to the prefix of veer protocols installation") + set(VEER_PROTOCOLS_INCLUDE_DIR "" CACHE PATH "The path to the headers of veer protocols installation") + + set(_search_paths "") + if(EXISTS VEER_PROTOCOLS_INCLUDE_DIR) + list(APPEND _search_paths ${VEER_PROTOCOLS_INCLUDE_DIR}) + endif() + if(EXISTS VEER_PROTOCOLS_PREFIX) + list(APPEND _search_paths ${VEER_PROTOCOLS_PREFIX}/include) + endif() + find_path( + VEER_PROTOCOLS_INCLUDE_DIRS + NAMES veer/common/ports.hpp + PATHS ${_search_paths}) + unset(_search_paths) + + if(VEER_PROTOCOLS_INCLUDE_DIRS) + set(VEER_PROTOCOLS_FOUND TRUE) + endif() + + if(VEER_PROTOCOLS_FOUND) + if(NOT VEER_PROTOCOLS_FIND_QUIETLY) + message(STATUS "Found veer protocols") + endif() + set(HAVE_VEER_PROTOCOLS 1) + elseif(VEER_PROTOCOLS_FOUND) + if(VEER_PROTOCOLS_FIND_REQUIRED) + message(FATAL_ERROR "Could not find veer protocols") + endif() + endif() +endif() diff --git a/MyxCMake/find/FindVeerProtocolsThirdparty.cmake b/MyxCMake/find/FindVeerProtocolsThirdparty.cmake new file mode 100644 index 0000000..07a8a30 --- /dev/null +++ b/MyxCMake/find/FindVeerProtocolsThirdparty.cmake @@ -0,0 +1,30 @@ +# Подключение внешних проектов +include(ExternalProject) + +# cmake-format: off +list(APPEND _ext_project_args + veer-protocols + SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/veer-protocols + INSTALL_DIR ${CMAKE_BINARY_DIR} + CMAKE_ARGS ${CMLIB_EXT_PROJ_DEFAULT_ARGS} + ) +if(VeerProtocolsThirdparty_FIND_COMPONENTS STREQUAL "headers") + list(APPEND _ext_project_args + BUILD_COMMAND true + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} veer-protocols-install-headers) +endif() +ExternalProject_Add(${_ext_project_args}) +unset(_ext_project_args) + +set(VEER_PROTOCOLS_IS_EXTERNAL_PROJECT ON CACHE BOOL "" FORCE) +# cmake-format: on + +set(VEER_PROTOCOLS_PREFIX + ${CMAKE_BINARY_DIR} + CACHE FILEPATH "" FORCE) +set(VEER_PROTOCOLS_INCLUDE_DIR + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) +set(VEER_PROTOCOLS_INCLUDE_DIRS + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR} + CACHE PATH "" FORCE) diff --git a/MyxCMake/functions/MyxCMakeGenerateGitInfoHeader.cmake b/MyxCMake/functions/MyxCMakeGenerateGitInfoHeader.cmake new file mode 100644 index 0000000..c3a6a4f --- /dev/null +++ b/MyxCMake/functions/MyxCMakeGenerateGitInfoHeader.cmake @@ -0,0 +1,19 @@ +function(myx_cmake_generate_git_info_header) + set(output_file ${CMAKE_BINARY_DIR}/include/myx_cmake_git_info.hpp) + if(MYX_CMAKE_GENERATED_HEADERS_PATH) + set(output_file ${MYX_CMAKE_GENERATED_HEADERS_PATH}/myx_cmake_git_info.hpp) + elseif(ARGV0) + set(output_file ${ARGV0}) + endif() + +# cmake-format: off + if(NOT TARGET myx-cmake-git-info-header) + add_custom_target(myx-cmake-git-info-header ALL + ${CMAKE_COMMAND} -DMYX_CMAKE_PROJECT_NAME_UPPER=${MYX_CMAKE_PROJECT_NAME_UPPER} + -DMYX_CMAKE_MODULE_DIR=${MYX_CMAKE_MODULE_DIR} + -DMYX_CMAKE_GIT_INFO_FILE=${output_file} -P ${CMAKE_CURRENT_LIST_DIR}/MyxCMakeGitInfo.cmake + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + endif() +# cmake-format: on +endfunction() + diff --git a/MyxCMake/functions/MyxCMakeGeneratePrivateConfigHeader.cmake b/MyxCMake/functions/MyxCMakeGeneratePrivateConfigHeader.cmake new file mode 100644 index 0000000..4eabcd0 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeGeneratePrivateConfigHeader.cmake @@ -0,0 +1,14 @@ +function(myx_cmake_generate_private_config_header) + include(${CMAKE_CURRENT_LIST_DIR}/MyxCMakeLargeFiles.cmake) + myx_cmake_test_large_files(HAVE_LARGEFILES) + + set(output_file ${CMAKE_BINARY_DIR}/include/myx_cmake_private_config.hpp) + if(MYX_CMAKE_GENERATED_HEADERS_PATH) + set(output_file ${CMLIB_GENERATED_HEADERS_PATH}/myx_cmake_private_config.hpp) + elseif(ARGV0) + set(output_file ${ARGV0}) + endif() + + get_property(PROJECT_VERSION_INT GLOBAL PROPERTY PROJECT_VERSION_INT) + configure_file(${CMAKE_CURRENT_LIST_DIR}/hpp/myx_cmake_private_config.hpp.in ${output_file}) +endfunction() diff --git a/MyxCMake/functions/MyxCMakeGitInfo.cmake b/MyxCMake/functions/MyxCMakeGitInfo.cmake new file mode 100644 index 0000000..98af8d7 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeGitInfo.cmake @@ -0,0 +1,25 @@ +set(MYX_CMAKE_GIT_REV "N/A") +set(MYX_CMAKE_GIT_DIFF "") +set(MYX_CMAKE_GIT_TAG "N/A") +set(MYX_CMAKE_GIT_BRANCH "N/A") + +find_program(GIT_EXECUTABLE git) +if(GIT_EXECUTABLE) + execute_process(COMMAND git log --pretty=format:'%h' -n 1 OUTPUT_VARIABLE MYX_CMAKE_GIT_REV ERROR_QUIET) + + # Check whether we got any revision (which isn't always the case, + # e.g. when someone downloaded a zip file from Github instead of a checkout) + if(NOT "${MYX_CMAKE_GIT_REV}" STREQUAL "") + execute_process(COMMAND bash -c "git diff --quiet --exit-code || echo +" OUTPUT_VARIABLE MYX_CMAKE_GIT_DIFF) + execute_process(COMMAND git describe --exact-match --tags OUTPUT_VARIABLE MYX_CMAKE_GIT_TAG ERROR_QUIET) + execute_process(COMMAND git rev-parse --abbrev-ref HEAD OUTPUT_VARIABLE MYX_CMAKE_GIT_BRANCH) + + string(STRIP "${MYX_CMAKE_GIT_REV}" MYX_CMAKE_GIT_REV) + string(SUBSTRING "${MYX_CMAKE_GIT_REV}" 1 7 MYX_CMAKE_GIT_REV) + string(STRIP "${MYX_CMAKE_GIT_DIFF}" MYX_CMAKE_GIT_DIFF) + string(STRIP "${MYX_CMAKE_GIT_TAG}" MYX_CMAKE_GIT_TAG) + string(STRIP "${MYX_CMAKE_GIT_BRANCH}" MYX_CMAKE_GIT_BRANCH) + endif() +endif() + +configure_file(${CMAKE_CURRENT_LIST_DIR}/hpp/mux_cmake_git_info.hpp.in ${MYX_CMAKE_GIT_VERSION_FILE}) diff --git a/MyxCMake/functions/MyxCMakeHighPrecisionMath.cmake b/MyxCMake/functions/MyxCMakeHighPrecisionMath.cmake new file mode 100644 index 0000000..0480251 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeHighPrecisionMath.cmake @@ -0,0 +1,11 @@ +find_package(Quadmath) +if(QUADMATH_FOUND) + add_definitions(-DHAVE_QUADMATH=1) +else() + find_package(MPFR) + if(MPFR_FOUND) + find_package(MPFRCppThirdparty) + else() + message(FATAL_ERROR "Nor Quadmath, nor MPFR found.") + endif() +endif() diff --git a/MyxCMake/functions/MyxCMakeLargeFiles.cmake b/MyxCMake/functions/MyxCMakeLargeFiles.cmake new file mode 100644 index 0000000..7960348 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeLargeFiles.cmake @@ -0,0 +1,158 @@ +# +# This file is part of the GROMACS molecular simulation package. +# +# Copyright (c) 2009,2010,2012,2014,2019, by the GROMACS development team, led by +# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, +# and including many others, as listed in the AUTHORS file in the +# top-level source directory and at http://www.gromacs.org. +# +# GROMACS is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# GROMACS is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with GROMACS; if not, see +# http://www.gnu.org/licenses, or write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# If you want to redistribute modifications to GROMACS, please +# consider that scientific software is very special. Version +# control is crucial - bugs must be traceable. We will be happy to +# consider code for inclusion in the official distribution, but +# derived work must not be called official GROMACS. Details are found +# in the README & COPYING files - if they are missing, get the +# official version at http://www.gromacs.org. +# +# To help us fund GROMACS development, we humbly ask that you cite +# the research papers on the package. Check out http://www.gromacs.org. + +# Forked from Gromacs + +# - Define macro to check large file support +# +# myx_cmake_test_large_files(VARIABLE) +# +# VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present. +# This macro will also set defines necessary enable large file support, for instance +# _LARGE_FILES +# _LARGEFILE_SOURCE +# _FILE_OFFSET_BITS 64 +# HAVE_FSEEKO +# HAVE__FSEEKI64 +# +# However, it is YOUR job to make sure these defines are set in a cmakedefine so they +# end up in a config.h file that is included in your source if necessary! + +include(CheckTypeSize) + +macro(myx_cmake_test_large_files VARIABLE) + if(NOT DEFINED ${VARIABLE}) + + # On most platforms it is probably overkill to first test the flags for 64-bit off_t, + # and then separately fseeko. However, in the future we might have 128-bit filesystems + # (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64. + + message(STATUS "Checking for 64-bit off_t") + + # First check without any special flags + try_compile(FILE64_OK "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/largefiles/TestFileOffsetBits.c") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present") + endif() + + if(NOT FILE64_OK) + # Test with _FILE_OFFSET_BITS=64 + try_compile(FILE64_OK "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/largefiles/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64") + set(_FILE_OFFSET_BITS 64 CACHE INTERNAL "64-bit off_t requires _FILE_OFFSET_BITS=64") + endif() + endif() + + if(NOT FILE64_OK) + # Test with _LARGE_FILES + try_compile(FILE64_OK "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/largefiles/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGE_FILES") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES") + set(_LARGE_FILES 1 CACHE INTERNAL "64-bit off_t requires _LARGE_FILES") + endif() + endif() + + if(NOT FILE64_OK) + # Test with _LARGEFILE_SOURCE + try_compile(FILE64_OK "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/largefiles/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE 1 CACHE INTERNAL "64-bit off_t requires _LARGEFILE_SOURCE") + endif() + endif() + + if(NOT FILE64_OK) + message(STATUS "Checking for 64-bit off_t - not present") + else() + # 64-bit off_t found. Now check that ftello/fseeko is available. + + # Set the flags we might have determined to be required above + configure_file("${CMAKE_CURRENT_LIST_DIR}/largefiles/TestLargeFiles.c.in" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + + message(STATUS "Checking for fseeko/ftello") + # Test if ftello/fseeko are available + try_compile(FSEEKO_COMPILE_OK "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + if(FSEEKO_COMPILE_OK) + message(STATUS "Checking for fseeko/ftello - present") + endif() + + if(NOT FSEEKO_COMPILE_OK) + # glibc 2.2 neds _LARGEFILE_SOURCE for fseeko (but not 64-bit off_t...) + try_compile( + FSEEKO_COMPILE_OK "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE") + if(FSEEKO_COMPILE_OK) + message(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE 1 CACHE INTERNAL "64-bit fseeko requires _LARGEFILE_SOURCE") + else() + set(FILE64_OK 0) + message(STATUS "64-bit off_t present but fseeko/ftello not found!") + endif() + endif() + endif() + + # cmake-lint: disable=C0103 + if(NOT FILE64_OK) + # now check for Windows stuff + try_compile(FILE64_OK "${CMAKE_BINARY_DIR}" "${CMAKE_CURRENT_LIST_DIR}/largefiles/TestWindowsFSeek.c") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _fseeki64") + set(HAVE__FSEEKI64 1 CACHE INTERNAL "64-bit off_t requires _fseeki64") + endif() + endif() + + if(FSEEKO_COMPILE_OK) + set(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) + set(HAVE_FSEEKO 1 CACHE INTERNAL "64bit fseeko is available" FORCE) + elseif(HAVE__FSEEKI64) + set(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) + set(HAVE__FSEEKI64 1 CACHE INTERNAL "Windows 64-bit fseek" FORCE) + else() + check_type_size("long int" SIZEOF_LONG_INT) + if(SIZEOF_LONG_INT EQUAL 8) #standard fseek is OK for 64bit + set(${VARIABLE} 1 CACHE INTERNAL "Result of test for large file support" FORCE) + else() + message(FATAL_ERROR "Checking for 64bit file support failed.") + endif() + endif() + + endif() +endmacro(myx_cmake_test_large_files VARIABLE) diff --git a/MyxCMake/functions/MyxCMakeQtTranslation.cmake b/MyxCMake/functions/MyxCMakeQtTranslation.cmake new file mode 100644 index 0000000..aabfe7c --- /dev/null +++ b/MyxCMake/functions/MyxCMakeQtTranslation.cmake @@ -0,0 +1,58 @@ +function(myx_cmake_qt5_translation outfiles) + find_package(Qt5 COMPONENTS LinguistTools REQUIRED) + + set(options) + set(oneValueArgs BASE_NAME OUTPUT_DIR) + set(multiValueArgs SOURCES LANGUAGES) + + cmake_parse_arguments(_QTTR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(_base_name ${_QTTR_BASE_NAME}) + set(_sources ${_QTTR_SOURCES}) + set(_output_dir ${_QTTR_OUTPUT_DIR}) + set(_languages ${_QTTR_LANGUAGES}) + + set(L10N_QRC_BODY "") + make_directory(${_output_dir}) + + foreach(lang ${_languages}) + set(_ts "${_base_name}_${lang}.ts") + set(_qm "${_base_name}_${lang}.qm") + list(APPEND _ts_list ${_output_dir}/${_ts}) + list(APPEND _l10n_names_list "${_base_name}_l10n_${lang}") + string(APPEND L10N_QRC_BODY "${CMAKE_BINARY_DIR}/${_qm}\n") + + add_custom_target( + ${_base_name}_l10n_${lang} COMMAND ${Qt5_LUPDATE_EXECUTABLE} ${_sources} -ts ${_output_dir}/${_ts} + -target-language ${lang} DEPENDS ${_sources}) + + if(NOT EXISTS "${_output_dir}/${_ts}") + add_custom_target(${_ts} DEPENDS ${_base_name}_l10n_${lang}) + else() + add_custom_target(${_ts} COMMAND echo "Skipping lupdate for ${_ts}") + endif() + + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/${_qm} COMMAND ${Qt5_LRELEASE_EXECUTABLE} ARGS ${_output_dir}/${_ts} -qm + ${CMAKE_BINARY_DIR}/${_qm} DEPENDS ${_ts} ${_sources}) + endforeach() + + # configure_file(${CMLIB_MODULE_DIR}/qrc/l10n.qrc.in ${CMAKE_BINARY_DIR}/${_base_name}_l10n.qrc) + file(WRITE ${CMAKE_BINARY_DIR}/${_base_name}_l10n.qrc + "\n" + " \n" + " ${L10N_QRC_BODY}\n" + " \n" + "\n" + ) + qt5_add_resources(${outfiles} ${CMAKE_BINARY_DIR}/${_base_name}_l10n.qrc) + add_custom_target(${_base_name}_qrc DEPENDS ${_qrc}) + add_custom_target(${_base_name}_l10n DEPENDS ${_l10n_names_list}) + if(NOT TARGET l10n) + add_custom_target(l10n) + endif() + add_dependencies(l10n ${_base_name}_l10n) + + # add_dependencies(${_target} ${_target}_qrc) + # target_sources(${_target} PUBLIC ${_qrc}) + set(${outfiles} ${${outfiles}} PARENT_SCOPE) +endfunction() diff --git a/MyxCMake/functions/MyxCMakeRemoveFlag.cmake b/MyxCMake/functions/MyxCMakeRemoveFlag.cmake new file mode 100644 index 0000000..a614017 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeRemoveFlag.cmake @@ -0,0 +1,73 @@ +# https://stackoverflow.com/a/49216539 +# +# Removes the specified compile flag from the specified target. +# _target - The target to remove the compile flag from +# _flag - The compile flag to remove +# +# Pre: apply_global_cxx_flags_to_all_targets() must be invoked. +# +# cmake-lint: disable=C0103 +macro(myx_cmake_remove_flag_from_target _target _flag) + get_target_property(_target_cxx_flags ${_target} COMPILE_OPTIONS) + if(_target_cxx_flags) + list(REMOVE_ITEM _target_cxx_flags ${_flag}) + set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${_target_cxx_flags}") + endif() +endmacro() + +# +# Removes the specified compiler flag from the specified file. +# _target - The target that _file belongs to +# _file - The file to remove the compiler flag from +# _flag - The compiler flag to remove. +# +# Pre: apply_global_cxx_flags_to_all_targets() must be invoked. +# +# cmake-lint: disable=C0103 +macro(myx_cmake_remove_flag_from_file _target _file _flag) + get_target_property(_target_sources ${_target} SOURCES) + # Check if a sync is required, in which case we'll force a rewrite of the cache variables. + if(_flag_sync_required) + unset(_cached_${_target}_cxx_flags CACHE) + unset(_cached_${_target}_${_file}_cxx_flags CACHE) + endif() + get_target_property(_${_target}_cxx_flags ${_target} COMPILE_OPTIONS) + # On first entry, cache the target compile flags and apply them to each source file + # in the target. + if(NOT _cached_${_target}_cxx_flags) + # Obtain and cache the target compiler options, then clear them. + get_target_property(_target_cxx_flags ${_target} COMPILE_OPTIONS) + set(_cached_${_target}_cxx_flags "${_target_cxx_flags}" CACHE INTERNAL "") + set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "") + # Apply the target compile flags to each source file. + foreach(_source_file ${_target_sources}) + # Check for pre-existing flags set by set_source_files_properties(). + get_source_file_property(_source_file_cxx_flags ${_source_file} COMPILE_FLAGS) + if(_source_file_cxx_flags) + separate_arguments(_source_file_cxx_flags UNIX_COMMAND ${_source_file_cxx_flags}) + list(APPEND _source_file_cxx_flags "${_target_cxx_flags}") + else() + set(_source_file_cxx_flags "${_target_cxx_flags}") + endif() + # Apply the compile flags to the current source file. + string(REPLACE ";" " " _source_file_cxx_flags_string "${_source_file_cxx_flags}") + set_source_files_properties(${_source_file} PROPERTIES COMPILE_FLAGS "${_source_file_cxx_flags_string}") + endforeach() + endif() + list(FIND _target_sources ${_file} _file_found_at) + if(_file_found_at GREATER -1) + if(NOT _cached_${_target}_${_file}_cxx_flags) + # Cache the compile flags for the specified file. + # This is the list that we'll be removing flags from. + get_source_file_property(_source_file_cxx_flags ${_file} COMPILE_FLAGS) + separate_arguments(_source_file_cxx_flags UNIX_COMMAND ${_source_file_cxx_flags}) + set(_cached_${_target}_${_file}_cxx_flags ${_source_file_cxx_flags} CACHE INTERNAL "") + endif() + # Remove the specified flag, then re-apply the rest. + list(REMOVE_ITEM _cached_${_target}_${_file}_cxx_flags ${_flag}) + string(REPLACE ";" " " _cached_${_target}_${_file}_cxx_flags_string + "${_cached_${_target}_${_file}_cxx_flags}") + set_source_files_properties(${_file} PROPERTIES COMPILE_FLAGS + "${_cached_${_target}_${_file}_cxx_flags_string}") + endif() +endmacro() diff --git a/MyxCMake/functions/MyxCMakeWriteCompilerDetectionHeader.cmake b/MyxCMake/functions/MyxCMakeWriteCompilerDetectionHeader.cmake new file mode 100644 index 0000000..12ecff7 --- /dev/null +++ b/MyxCMake/functions/MyxCMakeWriteCompilerDetectionHeader.cmake @@ -0,0 +1,30 @@ +function(myx_cmake_write_compiler_detection_header) + + if(${CMAKE_VERSION} VERSION_LESS "3.6.0") + return() + endif() + + include(WriteCompilerDetectionHeader) + + set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/include/compiler_features.hpp) + if(MYX_CMAKE_GENERATED_HEADER_FILENAME) + set(OUTPUT_FILE ${MYX_CMAKE_GENERATED_HEADER_FILENAME}) + endif() + + write_compiler_detection_header( + FILE ${OUTPUT_FILE} + PREFIX ${MYX_CMAKE_PROJECT_NAME_CANONICAL} + COMPILERS GNU Clang MSVC Intel + FEATURES + cxx_nullptr + cxx_override + cxx_alignas + cxx_alignof + cxx_attributes + cxx_auto_type + cxx_constexpr + cxx_digit_separators + cxx_range_for) + unset(OUTPUT_FILE) +endfunction() + diff --git a/MyxCMake/functions/hpp/myx_cmake_git_info.hpp.in b/MyxCMake/functions/hpp/myx_cmake_git_info.hpp.in new file mode 100644 index 0000000..873791c --- /dev/null +++ b/MyxCMake/functions/hpp/myx_cmake_git_info.hpp.in @@ -0,0 +1,31 @@ +#ifndef @MYX_CMAKE_PROJECT_NAME_UPPER@_MYX_CMAKE_GIT_INFO_HPP_ +#define @MYX_CMAKE_PROJECT_NAME_UPPER@_MYX_CMAKE_GIT_INFO_HPP_ + +#pragma once + +#if defined (@MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_REV) +#error "Duplicate definition of macros @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_REV" +#else +#define @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_REV "@MYX_CMAKE_GIT_REV@" +#endif + +#if defined (@MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_DIFF) +#error "Duplicate definition of macros @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_DIFF" +#else +#define @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_DIFF "@MYX_CMAKE_GIT_DIFF@" +#endif + +#if defined (@MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_BRANCH) +#error "Duplicate definition of macros @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_BRANCH" +#else +#define @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_BRANCH "@MYX_CMAKE_GIT_BRANCH@" +#endif + +#if defined (@MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_TAG) +#error "Duplicate definition of macros @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_TAG" +#else +#define @MYX_CMAKE_PROJECT_NAME_UPPER@_GIT_TAG "@MYX_CMAKE_GIT_TAG@" +#endif + +#endif /* @MYX_CMAKE_PROJECT_NAME_UPPER@_MYX_CMAKE_GIT_INFO_HPP_ */ + diff --git a/MyxCMake/functions/hpp/myx_cmake_private_config.hpp.in b/MyxCMake/functions/hpp/myx_cmake_private_config.hpp.in new file mode 100644 index 0000000..ce055d0 --- /dev/null +++ b/MyxCMake/functions/hpp/myx_cmake_private_config.hpp.in @@ -0,0 +1,94 @@ +#ifndef @CMLIB_PROJECT_NAME_UPPER@_CMLIB_CONFIG_HPP_ +#define @CMLIB_PROJECT_NAME_UPPER@_CMLIB_CONFIG_HPP_ + +#pragma once + +#define @CMLIB_PROJECT_NAME_UPPER@_VERSION_STR "@PROJECT_VERSION@" +#define @CMLIB_PROJECT_NAME_UPPER@_VERSION_INT @PROJECT_VERSION_INT@ + +#if defined (CMLIB_ORGANIZATION_NAME) +#error "Duplicate definition of macros CMLIB_ORGANIZATION_NAME" +#else +#define CMLIB_ORGANIZATION_NAME "@CMLIB_ORGANIZATION_NAME@" +#endif + +#if defined (CMLIB_ORGANIZATION_NAME_LOWER) +#error "Duplicate definition of macros CMLIB_ORGANIZATION_NAME_LOWER" +#else +#define CMLIB_ORGANIZATION_NAME_LOWER "@CMLIB_ORGANIZATION_NAME_LOWER@" +#endif + +#if defined (CMLIB_ORGANIZATION_NAME_UPPER) +#error "Duplicate definition of macros CMLIB_ORGANIZATION_NAME_UPPER" +#else +#define CMLIB_ORGANIZATION_NAME_UPPER "@CMLIB_ORGANIZATION_NAME_UPPER@" +#endif + +#if defined (CMLIB_PROJECT_NAME) +#error "Duplicate definition of macros CMLIB_PROJECT_NAME" +#else +#define CMLIB_PROJECT_NAME "@CMAKE_PROJECT_NAME@" +#endif + +#if defined (CMLIB_PROJECT_NAME_LOWER) +#error "Duplicate definition of macros CMLIB_PROJECT_NAME_LOWER" +#else +#define CMLIB_PROJECT_NAME_LOWER "@CMLIB_PROJECT_NAME_LOWER@" +#endif + +#if defined (CMLIB_PROJECT_NAME_UPPER) +#error "Duplicate definition of macros CMLIB_PROJECT_NAME_UPPER" +#else +#define CMLIB_PROJECT_NAME_UPPER "@CMLIB_PROJECT_NAME_UPPER@" +#endif + +#if defined (CMLIB_THEME_NAME) +#error "Duplicate definition of macros CMLIB_THEME_NAME" +#else +#define CMLIB_THEME_NAME "@CMLIB_THEME_NAME@" +#endif + +#if defined (CMLIB_THEME_NAME_LOWER) +#error "Duplicate definition of macros CMLIB_THEME_NAME_LOWER" +#else +#define CMLIB_THEME_NAME_LOWER "@CMLIB_THEME_NAME_LOWER@" +#endif + +#if defined (CMLIB_THEME_NAME_UPPER) +#error "Duplicate definition of macros CMLIB_THEME_NAME_UPPER" +#else +#define CMLIB_THEME_NAME_UPPER "@CMLIB_THEME_NAME_UPPER@" +#endif + +#if defined (CMLIB_AUTHOR_NAME) +#error "Duplicate definition of macros CMLIB_AUTHOR_NAME" +#else +#define CMLIB_AUTHOR_NAME "@CMLIB_AUTHOR_NAME@" +#endif + +#if defined (CMLIB_AUTHOR_EMAIL) +#error "Duplicate definition of macros CMLIB_AUTHOR_EMAIL" +#else +#define CMLIB_AUTHOR_EMAIL "@CMLIB_AUTHOR_EMAIL@" +#endif + +#if defined (CMLIB_DESCRIPTION) +#error "Duplicate definition of macros CMLIB_DESCRIPTION" +#else +#define CMLIB_DESCRIPTION "@CMLIB_DESCRIPTION@" +#endif + +#if defined (CMLIB_BUILD_TYPE) +#error "Duplicate definition of macros CMLIB_BUILD_TYPE" +#else +#define CMLIB_BUILD_TYPE "@CMAKE_BUILD_TYPE@" +#endif + +#if defined (CMLIB_BUILD_DATE) +#error "Duplicate definition of macros CMLIB_BUILD_DATE" +#else +#define CMLIB_BUILD_DATE "@TODAY@" +#endif + +#endif /* @CMLIB_PROJECT_NAME_UPPER@_CMLIB_CONFIG_HPP_ */ + diff --git a/MyxCMake/functions/largefiles/TestFileOffsetBits.c b/MyxCMake/functions/largefiles/TestFileOffsetBits.c new file mode 100644 index 0000000..cd679c1 --- /dev/null +++ b/MyxCMake/functions/largefiles/TestFileOffsetBits.c @@ -0,0 +1,11 @@ +#include + +/* Cause a compile-time error if off_t is smaller than 64 bits */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; + +int main(int argc, char **argv) +{ + return 0; +} + diff --git a/MyxCMake/functions/largefiles/TestLargeFiles.c.in b/MyxCMake/functions/largefiles/TestLargeFiles.c.in new file mode 100644 index 0000000..3c8baa0 --- /dev/null +++ b/MyxCMake/functions/largefiles/TestLargeFiles.c.in @@ -0,0 +1,24 @@ +#cmakedefine _LARGEFILE_SOURCE +#cmakedefine _LARGEFILE64_SOURCE +#cmakedefine _LARGE_FILES +#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ + +#include +#include +#include + +int main(int argc, char **argv) +{ + /* Cause a compile-time error if off_t is smaller than 64 bits, + * and make sure we have ftello / fseeko. + */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[ (LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1 ]; + FILE *fp = fopen(argv[0],"r"); + off_t offset = ftello( fp ); + + fseeko( fp, offset, SEEK_CUR ); + fclose(fp); + return off_t_is_large[0] || argc; +} + diff --git a/MyxCMake/functions/largefiles/TestWindowsFSeek.c b/MyxCMake/functions/largefiles/TestWindowsFSeek.c new file mode 100644 index 0000000..ad9f0be --- /dev/null +++ b/MyxCMake/functions/largefiles/TestWindowsFSeek.c @@ -0,0 +1,11 @@ + +#include + +int main() +{ + __int64 off=0; + + _fseeki64(NULL, off, SEEK_SET); + + return 0; +} diff --git a/MyxCMake/modules/MyxCMakeAddSharedLibrary.cmake b/MyxCMake/modules/MyxCMakeAddSharedLibrary.cmake new file mode 100644 index 0000000..fa123a2 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeAddSharedLibrary.cmake @@ -0,0 +1,21 @@ +# Создание динамической библиотеки из объектной библиотеки +function(myx_cmake_add_shared_library target) + get_target_property(_target_type ${target} TYPE) + if(NOT _target_type STREQUAL OBJECT_LIBRARY) + message( + FATAL_ERROR + "MyxCMake: add_shared_library needs target of type OBJECT_LIBRARY") + return() + endif() + + add_library(${target}-shared SHARED $) + set_target_properties( + ${target}-shared + PROPERTIES OUTPUT_NAME ${target} + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + LIBRARY_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + install(TARGETS ${target}-static LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +endfunction() diff --git a/MyxCMake/modules/MyxCMakeAddStaticLibrary.cmake b/MyxCMake/modules/MyxCMakeAddStaticLibrary.cmake new file mode 100644 index 0000000..6b5c2b7 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeAddStaticLibrary.cmake @@ -0,0 +1,19 @@ +# Создание статической библиотеки из объектной библиотеки +function(myx_cmake_add_static_library target) + get_target_property(_target_type ${target} TYPE) + if(NOT _target_type STREQUAL OBJECT_LIBRARY) + message( + FATAL_ERROR + "MyxCMake: add_static_library needs target of type OBJECT_LIBRARY") + return() + endif() + + add_library(${target}-static STATIC $) + set_target_properties( + ${target}-static + PROPERTIES OUTPUT_NAME ${target} + ARCHIVE_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + install(TARGETS ${target}-static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +endfunction() diff --git a/MyxCMake/modules/MyxCMakeBuildTypes.cmake b/MyxCMake/modules/MyxCMakeBuildTypes.cmake new file mode 100644 index 0000000..d477c76 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeBuildTypes.cmake @@ -0,0 +1,96 @@ +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # IN_LIST operator + +option(MYX_CMAKE_ENABLE_WARNING_FLAGS "Enable autodetected warning flags" ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS + ON + CACHE BOOL "Enable generation of compile_commands.json." FORCE) + +# Добавление конфигурации для профилирования +if(CMAKE_CONFIGURATION_TYPES) + if(NOT "Profile" IN_LIST CMAKE_CONFIGURATION_TYPES) + list(APPEND CMAKE_CONFIGURATION_TYPES Profile) + endif() +else() + set(_allowed_build_types None Debug Release Profile RelWithDebInfo MinSizeRel) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${_allowed_build_types}) + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE + Debug + CACHE STRING "" FORCE) + elseif(NOT "${CMAKE_BUILD_TYPE}" IN_LIST _allowed_build_types) + message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}") + endif() +endif() + +set(_gcc_debug_flags "-ggdb -fno-omit-frame-pointer") +set(_gcc_profile_flags "-pg") + +if(CMAKE_BUILD_TYPE STREQUAL Profile) + # Ключи компиляции для режима профилирования в зависимости от типа компилятора + if(CMAKE_CXX_COMPILER_IS_CLANG OR CMAKE_CXX_COMPILER_IS_GCC) + set(CMAKE_C_FLAGS_PROFILE + "${CMAKE_C_FLAGS_RELEASE} ${_gcc_debug_flags} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + set(CMAKE_CXX_FLAGS_PROFILE + "${CMAKE_CXX_FLAGS_RELEASE} ${MYX_CMAKE_DETECTED_CXX_FLAGS} ${_gcc_debug_flags} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + set(CMAKE_EXE_LINKER_FLAGS_PROFILE + "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + set(CMAKE_SHARED_LINKER_FLAGS_PROFILE + "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + set(CMAKE_STATIC_LINKER_FLAGS_PROFILE + "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + set(CMAKE_MODULE_LINKER_FLAGS_PROFILE + "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${_gcc_profile_flags}" + CACHE STRING "" FORCE) + elseif(CMAKE_CXX_COMPILER_IS_Intel) + message("Set options for profiling with Intel C++") + elseif(CMAKE_CXX_COMPILER_IS_MSVC) + message("Set options for profiling with Visual Studio C++") + endif() + set(CMAKE_VERBOSE_MAKEFILE + ON + CACHE BOOL "Enable generation of verbose build scripts." FORCE) +elseif(CMAKE_BUILD_TYPE STREQUAL Debug) + # В режиме отладки подробный вывод сообщений компилятора + if(CMAKE_CXX_COMPILER_IS_CLANG OR CMAKE_CXX_COMPILER_IS_GCC) + string(REPLACE " ${_gcc_debug_flags}" "" CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG} ${_gcc_debug_flags}" + CACHE STRING "" FORCE) + + string(REPLACE " ${_gcc_debug_flags}" "" CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG}") + if(MYX_CMAKE_ENABLE_WARNING_FLAGS) + set(CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG} ${MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG} ${_gcc_debug_flags}" + CACHE STRING "" FORCE) + else() + set(CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG} ${_gcc_debug_flags}" + CACHE STRING "" FORCE) + endif() + endif() + set(CMAKE_VERBOSE_MAKEFILE + ON + CACHE BOOL "Enable generation of verbose build scripts." FORCE) +elseif(CMAKE_BUILD_TYPE STREQUAL Release) + set(CMAKE_CXX_FLAGS_RELEASE + "${CMAKE_CXX_FLAGS_RELEASE} ${MYX_CMAKE_DETECTED_CXX_FLAGS}" + CACHE STRING "" FORCE) +elseif(CMAKE_BUILD_TYPE STREQUAL None) + # Режим None используется для статического анализа кода + set(CMAKE_VERBOSE_MAKEFILE + ON + CACHE BOOL "Enable generation of verbose build scripts." FORCE) +endif() + +unset(_gcc_debug_flags) +unset(_gcc_profile_flags) + +cmake_policy(POP) diff --git a/MyxCMake/modules/MyxCMakeCPack.cmake b/MyxCMake/modules/MyxCMakeCPack.cmake new file mode 100644 index 0000000..209fcc8 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCPack.cmake @@ -0,0 +1,69 @@ +# Общие настройки для пакета: организация, автор, версия +set(CPACK_PACKAGE_VENDOR ${MYX_CMAKE_ORGANIZATION_NAME_LOWER} CACHE STRING "") +set(CPACK_PACKAGE_NAME ${MYX_CMAKE_PROJECT_NAME_LOWER} CACHE STRING "") +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION} CACHE STRING "") + +# Параметры для архива исходных текстов +if(NOT CPACK_SOURCE_GENERATOR) + set(CPACK_SOURCE_GENERATOR "TGZ") +endif() +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${MYX_CMAKE_PROJECT_NAME_LOWER}-${CPACK_PACKAGE_VERSION}") + +# Типы генераторов для бинарных архивов +if(NOT CPACK_GENERATOR) + set(CPACK_GENERATOR "TGZ" "DEB") +endif() + +# Параметры для архива собранного проекта +set(CPACK_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR}) +if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(CPACK_TARGET_ARCH "amd64") +endif() +set(CPACK_PACKAGE_FILE_NAME "${MYX_CMAKE_PROJECT_NAME_LOWER}_${CPACK_TARGET_ARCH}_${CPACK_PACKAGE_VERSION}") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "${MYX_CMAKE_PROJECT_NAME_LOWER}-${CPACK_PACKAGE_VERSION}") + +# Список масок для исключения из архива исходных текстов +set(CPACK_SOURCE_IGNORE_FILES + "${CPACK_SOURCE_IGNORE_FILES}" + "${CMAKE_BINARY_DIR}" + "^${CMAKE_SOURCE_DIR}/.?build.?/" + "^${CMAKE_SOURCE_DIR}/.?output.?/" + "^${CMAKE_SOURCE_DIR}/files/var" + "^${CMAKE_SOURCE_DIR}/files/log" + "CMakeLists.txt.user.*" + ".*.autosave" + ".*.status" + "~$" + "\\\\.swp$") + +option(MYX_CMAKE_COMPACT_SOURCE_PACKAGE "Make compact source package" ON) +if(MYX_CMAKE_COMPACT_SOURCE_PACKAGE) + # Список масок для исключения из архива исходных текстов для более компактного архива + set(CPACK_SOURCE_IGNORE_FILES + "${CPACK_SOURCE_IGNORE_FILES}" + "\\\\.git" + "/\\\\.git/" + "/\\\\.gitlab-ci/" + "\\\\.clang-tidy$" + "\\\\.cmake-format$" + "\\\\.gitignore$" + "\\\\.gitattributes$" + "\\\\.gitmodules$" + "\\\\.gitlab-ci.yml$") +endif() + +set(CPACK_PROJECT_CONFIG_FILE ${CMAKE_CURRENT_LIST_DIR}/MyxCMakeCPackProject.cmake) + +option(MYX_CMAKE_CPACK_DEFAULT_SCHEME "Use packaging default scheme" ON) + +# Правила для сборки обычных архивов +if(MYX_CMAKE_CPACK_DEFAULT_SCHEME) + set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + set(CPACK_COMPONENTS_GROUPING IGNORE) +endif() + +# Правила для сборки пакетов для Debian +include(CMLibCPackDeb) + +# Подключение модуля, выполняющего сборку архивов и пакетов +include(CPack) diff --git a/MyxCMake/modules/MyxCMakeCPackDeb.cmake b/MyxCMake/modules/MyxCMakeCPackDeb.cmake new file mode 100644 index 0000000..5d71750 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCPackDeb.cmake @@ -0,0 +1,81 @@ +# По умолчанию пакет собирается для дистрибутива unstable +if(NOT DEBIAN_PACKAGE_TYPE) + set(DEBIAN_PACKAGE_TYPE "unstable") +endif() + +if(NOT CPACK_DEBIAN_PACKAGE_SECTION) + set(CPACK_DEBIAN_PACKAGE_SECTION "misc") +endif() + +if(NOT CPACK_DEBIAN_PACKAGE_PRIORITY) + set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") +endif() + +# По умолчанию пакет для Debian делится на компоненты +if(NOT CPACK_DEB_COMPONENT_INSTALL) + set(CPACK_DEB_COMPONENT_INSTALL ON) +endif() + +if(MYX_CMAKE_CPACK_DEFAULT_SCHEME) + # Если имя компонента по умолчанию не определено, то устанавливается MAIN + if(NOT CMAKE_INSTALL_DEFAULT_COMPONENT_NAME) + set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME main) + endif() + + # В списке компонентов обязательно должны быть main, base-dev, libs-dev и doc + list( + APPEND + CPACK_COMPONENTS_ALL + main + base-dev + libs-dev + doc) + list(REMOVE_DUPLICATES CPACK_COMPONENTS_ALL) + + # Правило формирования имени пакета и файла для компонента main + set(CPACK_DEBIAN_MAIN_PACKAGE_NAME "${MYX_CMAKE_PROJECT_NAME_LOWER}") + set(CPACK_DEBIAN_MAIN_FILE_NAME + ${MYX_CMAKE_PROJECT_NAME_LOWER}_${CPACK_PACKAGE_VERSION}_${CPACK_TARGET_ARCH}.deb) + + # Правило формирования имени пакета и файла для компонента base-dev + set(CPACK_DEBIAN_BASE-DEV_PACKAGE_NAME "lib${MYX_CMAKE_PROJECT_NAME_LOWER}-base-dev") + set(CPACK_DEBIAN_BASE-DEV_FILE_NAME + lib${MYX_CMAKE_PROJECT_NAME_LOWER}-base-dev_${CPACK_PACKAGE_VERSION}_${CPACK_TARGET_ARCH}.deb) + + # Правило формирования имени пакета и файла для компонента libs-dev + set(CPACK_DEBIAN_LIBS-DEV_PACKAGE_NAME lib${MYX_CMAKE_PROJECT_NAME_LOWER}-dev) + set(CPACK_DEBIAN_LIBS-DEV_FILE_NAME + lib${MYX_CMAKE_PROJECT_NAME_LOWER}-dev_${CPACK_PACKAGE_VERSION}_${CPACK_TARGET_ARCH}.deb) + + set(CPACK_DEBIAN_LIBS-DEV_PACKAGE_DEPENDS "lib${MYX_CMAKE_PROJECT_NAME_LOWER}-base-dev") + + foreach(component ${CPACK_COMPONENTS_ALL}) + string(TOLOWER ${component} _cl) + string(TOUPPER ${component} _cu) + # Правила формирования имени пакета и файла для остальных компонентов + if(NOT ${_cl} STREQUAL main AND NOT ${_cl} STREQUAL base-dev AND NOT ${_cl} STREQUAL libs-dev) + set(CPACK_DEBIAN_${_cu}_PACKAGE_NAME "${MYX_CMAKE_PROJECT_NAME_LOWER}-${_cl}") + set(CPACK_DEBIAN_${_cu}_FILE_NAME + "${MYX_CMAKE_PROJECT_NAME_LOWER}-${_cl}_${CPACK_PACKAGE_VERSION}_${CPACK_TARGET_ARCH}.deb") + endif() + + # Если в каталоге ${CMAKE_SOURCE_DIR}/cmake/deb/${_cl} находятся сценарии сопровождающего + # postinst, preinst, postrm и prerm, то они будут добавлены к пакету. + if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/preinst") + list(APPEND CPACK_DEBIAN_${_cu}_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/preinst") + endif() + if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/postinst") + list(APPEND CPACK_DEBIAN_${_cu}_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/postinst") + endif() + if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/prerm") + list(APPEND CPACK_DEBIAN_${_cu}_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/prerm") + endif() + if(EXISTS "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/postrm") + list(APPEND CPACK_DEBIAN_${_cu}_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/deb/${_cl}/postrm") + endif() + endforeach() +endif() + +if(UNIX AND NOT TARGET deb) + add_custom_target(deb WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND cpack -G DEB) +endif() diff --git a/MyxCMake/modules/MyxCMakeCPackProject.cmake b/MyxCMake/modules/MyxCMakeCPackProject.cmake new file mode 100644 index 0000000..097afe2 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCPackProject.cmake @@ -0,0 +1,5 @@ +if(CPACK_GENERATOR MATCHES "DEB") + set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_NAME}") +else() + set(CPACK_PACKAGING_INSTALL_PREFIX "${PROJECT_NAME}") +endif() diff --git a/MyxCMake/modules/MyxCMakeCheckPaths.cmake b/MyxCMake/modules/MyxCMakeCheckPaths.cmake new file mode 100644 index 0000000..6c06f9e --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCheckPaths.cmake @@ -0,0 +1,22 @@ +# Запись результатов сборки проекта внутрь иерархии каталогов с исходными +# текстами приводит к засорению файлами формируемыми на этапе сборки, которые +# затрудняют разработку, поиск в оригинальных файлах и мешают ориентироваться в +# проекте. При работе с несколькими типами сборки, например, отладка и выпуск, +# появляется необходимость корректного полного удаления результатов предыдущего +# варианта. + +get_filename_component(_source_realpath "${CMAKE_SOURCE_DIR}" REALPATH) +get_filename_component(_binary_realpath "${CMAKE_BINARY_DIR}" REALPATH) +get_filename_component(_install_realpath "${CMAKE_INSTALL_PREFIX}" REALPATH) + +if(_install_realpath STREQUAL _binary_realpath) + message(FATAL_ERROR "MyxCMake: Cannot install into build directory.") +endif() + +if(_install_realpath STREQUAL _source_realpath) + message(FATAL_ERROR "MyxCMake: Cannot install into source directory.") +endif() + +if(_source_realpath STREQUAL _binary_realpath) + message(FATAL_ERROR "MyxCMake: In-source builds are not allowed.") +endif() diff --git a/MyxCMake/modules/MyxCMakeCodeAnalyzeClangCheck.cmake b/MyxCMake/modules/MyxCMakeCodeAnalyzeClangCheck.cmake new file mode 100644 index 0000000..aee4360 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCodeAnalyzeClangCheck.cmake @@ -0,0 +1,34 @@ +set(CLANG_CHECK_NAMES clang-check) +foreach(V RANGE 9 15) + list(INSERT CLANG_CHECK_NAMES 0 "clang-check-${V}") +endforeach() + +find_program(CLANG_CHECK_EXE NAMES ${CLANG_CHECK_NAMES}) +if(CLANG_CHECK_EXE) + option(MYX_CMAKE_CLANG_CHECK_FIX "MyxCMake: perform fixes for Clang Check" OFF) +endif() +unset(V) +unset(CLANG_CHECK_NAMES) + +function(myx_cmake_clang_check_analyze target) + set(_args --analyze --extra-arg="-Wno-unknown-warning-option") + get_target_property(__sources ${target} SOURCES) + list(FILTER __sources EXCLUDE REGEX "qrc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "moc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "ui_.*\\.h$") + + if(CLANG_CHECK_EXE) + if(MYX_CMAKE_CLANG_ANALYZE_FIX) + list(APPEND _args "--fixit") + endif() + if(NOT TARGET myx-cmake-clang-check-analyze) + add_custom_target(myx-cmake-clang-check-analyze) + endif() + add_custom_target(${target}-clang-check-analyze WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CLANG_CHECK_EXE} ${_args} -p ${CMAKE_BINARY_DIR} ${__sources}) + add_dependencies(${target}-clang-check-analyze ${target}) + add_dependencies(myx-cmake-clang-check-analyze ${target}-clang-check-analyze) + else() + message(STATUS "MyxCMake: Clang Check analyzer is not found") + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCodeAnalyzeClangTidy.cmake b/MyxCMake/modules/MyxCMakeCodeAnalyzeClangTidy.cmake new file mode 100644 index 0000000..b3504a6 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCodeAnalyzeClangTidy.cmake @@ -0,0 +1,34 @@ +set(CLANG_TIDY_NAMES clang-tidy) +foreach(V RANGE 9 15) + list(INSERT CLANG_TIDY_NAMES 0 "clang-tidy-${V}") +endforeach() + +find_program(CLANG_TIDY_EXE NAMES ${CLANG_TIDY_NAMES}) +if(CLANG_TIDY_EXE) + option(MYX_CMAKE_CLANG_TIDY_FIX "MyxCMake: perform fixes for Clang Tidy" OFF) +endif() +unset(V) +unset(CLANG_TIDY_NAMES) + +function(myx_cmake_clang_tidy_analyze target) + set(_args -extra-arg="-Wno-unknown-warning-option") + get_target_property(__sources ${target} SOURCES) + list(FILTER __sources EXCLUDE REGEX "qrc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "moc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "ui_.*\\.h$") + + if(CLANG_TIDY_EXE) + if(MYX_CMAKE_CLANG_TIDY_FIX) + list(APPEND _args "--fix") + endif() + if(NOT TARGET myx-cmake-clang-tidy-analyze) + add_custom_target(myx-cmake-clang-tidy-analyze) + endif() + add_custom_target(${target}-clang-tidy-analyze WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CLANG_TIDY_EXE} ${_args} -p ${CMAKE_BINARY_DIR} ${__sources}) + add_dependencies(${target}-clang-tidy-analyze ${target}) + add_dependencies(myx-cmake-clang-tidy-analyze ${target}-clang-tidy-analyze) + else() + message(STATUS "MyxCMake: Clang Tidy analyzer is not found") + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCodeAnalyzeClazy.cmake b/MyxCMake/modules/MyxCMakeCodeAnalyzeClazy.cmake new file mode 100644 index 0000000..0e7b4d9 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCodeAnalyzeClazy.cmake @@ -0,0 +1,57 @@ +find_program(CLAZY_EXE NAMES clazy-standalone) + +set(CLANG_APPLY_REPLACEMENTS_NAMES clang-apply-replacements) +foreach(V RANGE 9 15) + list(INSERT CLANG_APPLY_REPLACEMENTS 0 "clang-apply-replacements-${V}") +endforeach() + +find_program(CLANG_APPLY_REPLACEMENTS_EXE NAMES ${CLANG_APPLY_REPLACEMENTS_NAMES}) +if(CLANG_TIDY_EXE) + option(MYX_CMAKE_CLANG_TIDY_FIX "MyxCMake: perform fixes for Clang Tidy" OFF) +endif() +unset(V) +unset(CLANG_TIDY_NAMES) + +if(CLAZY_EXE AND CLANG_APPLY_REPLACEMENTS_EXE) + option(MYX_CMAKE_CLAZY_FIX "MyxCMake: perform fixes for Clazy" OFF) +endif() + +function(myx_cmake_clazy_analyze target) + set(options) + set(oneValueArgs CHECKS) + set(multiValueArgs) + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_CHECKS) + set(ARG_CHECKS "level2,container-inside-loop,heap-allocated-small-trivial-type,inefficient-qlist,isempty-vs-count,qt-keywords,unneeded-cast" + ) + endif() + + get_target_property(__sources ${target} SOURCES) + list(FILTER __sources EXCLUDE REGEX "qrc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "moc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "ui_.*\\.h$") + set(_args -checks=${ARG_CHECKS} -extra-arg="-Wno-unknown-warning-option" + -export-fixes=clazy-fixes-file.yaml) + + if(CLAZY_EXE) + if(NOT TARGET myx-cmake-clazy-analyze) + add_custom_target(myx-cmake-clazy-analyze) + endif() + if(MYX_CMAKE_CLAZY_FIX) + add_custom_target( + ${target}-clazy-analyze + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CLAZY_EXE} ${_args} -p ${CMAKE_BINARY_DIR} ${__sources} + COMMAND ${CLANG_APPLY_REPLACEMENTS_EXE} ${CMAKE_BINARY_DIR}) + else() + add_custom_target(${target}-clazy-analyze WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CLAZY_EXE} ${_args} -p ${CMAKE_BINARY_DIR} ${__sources}) + endif() + add_dependencies(${target}-clazy-analyze ${target}) + add_dependencies(myx-cmake-clazy-analyze ${target}-clazy-analyze) + else() + message(STATUS "MyxCMake: Clazy standalone analyzer is not found") + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCodeAnalyzePvsStudio.cmake b/MyxCMake/modules/MyxCMakeCodeAnalyzePvsStudio.cmake new file mode 100644 index 0000000..0ec4225 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCodeAnalyzePvsStudio.cmake @@ -0,0 +1,63 @@ +if(CMAKE_EXPORT_COMPILE_COMMANDS) + find_program(PVS_STUDIO_ANALYZER_EXE NAMES pvs-studio-analyzer) + include(PVS-Studio) +else() + message(STATUS "MyxCMake: CMAKE_EXPORT_COMPILE_COMMANDS is not set. PVS checks will be disabled.") +endif() + +function(myx_cmake_pvs_studio_analyze target) + if(PVS_STUDIO_ANALYZER_EXE) + if(NOT TARGET myx-cmake-pvs-studio-analyze) + add_custom_target(myx-cmake-pvs-studio-analyze) + endif() + + set(PVS_STUDIO_CONFIG "${CMAKE_BINARY_DIR}/PVS-Studio-${target}.cfg") + set(PVS_STUDIO_CONFIG_COMMAND "${CMAKE_COMMAND}" -E echo "sourcetree-root=${CMAKE_SOURCE_DIR}" > "${PVS_STUDIO_CONFIG}") + + add_custom_command(OUTPUT "${PVS_STUDIO_CONFIG}" + COMMAND ${PVS_STUDIO_CONFIG_COMMAND} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Generating PVS-Studio.cfg") + + set(PVS_STUDIO_HEADER "${CMAKE_BINARY_DIR}/include/pvs_studio_suppression_${target}.hpp") + file(WRITE ${PVS_STUDIO_HEADER} + "#ifndef PVS_STUDIO_HPP_\n" + "#define PVS_STUDIO_HPP_\n" + "#pragma once\n" + "//-V813_MINSIZE=33\n" + "#endif // PVS_STUDIO_HPP_\n" + ) + + get_target_property(__sources ${target} SOURCES) + list(FILTER __sources EXCLUDE REGEX "qrc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "moc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "ui_.*\\.h$") + + pvs_studio_add_target( + TARGET ${target}-pvs-studio-analyze + CONFIG ${PVS_STUDIO_CONFIG} + DEPENDS ${PVS_STUDIO_CONFIG} + LOG "${CMAKE_BINARY_DIR}/PVS-Studio-${target}.log" + SOURCES ${__sources} + COMPILE_COMMANDS HIDE_HELP + OUTPUT FORMAT errorfile + ARGS --exclude-path ${CMAKE_CURRENT_BINARY_DIR}/${target}_autogen + MODE GA:1,2,3;64:1;OP:1,2;CS:1,2) + + add_dependencies(myx-cmake-pvs-studio-analyze ${target}-pvs-studio-analyze) + + get_target_property(__target_type ${target} TYPE) + if(${__target_type} STREQUAL INTERFACE_LIBRARY) + set(__target_type INTERFACE) + else() + set(__target_type PRIVATE) + endif() + if(MSVC) + target_compile_options(${target} BEFORE ${__target_type} /FI ${PVS_STUDIO_HEADER}) + else() # GCC/Clang + target_compile_options(${target} BEFORE ${__target_type} -include ${PVS_STUDIO_HEADER}) + endif() + else() + message(STATUS "MyxCMake: PVS-Studio analyzer is not found") + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCodeCoverage.cmake b/MyxCMake/modules/MyxCMakeCodeCoverage.cmake new file mode 100644 index 0000000..bfa730e --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCodeCoverage.cmake @@ -0,0 +1,34 @@ +option(MYX_CMAKE_CODE_COVERAGE "MyxCMake: enable code coverage" OFF) + +if(MYX_CMAKE_CODE_COVERAGE) + find_program(LCOV_EXE NAMES lcov) + find_program(GENHTML_EXE NAMES genhtml) +endif() + +function(myx_cmake_code_coverage target) + if(CMAKE_CXX_COMPILER_IS_GCC AND MYX_CMAKE_CODE_COVERAGE) + target_compile_options(${target} PUBLIC "--coverage") + set_property( + TARGET ${target} + APPEND_STRING + PROPERTY LINK_FLAGS " --coverage") + + if(LCOV_EXE) + add_custom_target( + ${target}-coverage + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${LCOV_EXE} --test-name ${target} --output "${target}.lcov" + --capture --directory ${CMAKE_BINARY_DIR}) + add_dependencies(${target}-coverage ${target}) + + if(GENHTML_EXE) + add_custom_target( + ${target}-coverage-report + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${GENHTML_EXE} --output-directory "${target}-coverage-html" + "${target}.lcov") + add_dependencies(${target}-coverage-report ${target}-coverage) + endif() + endif() + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCommon.cmake b/MyxCMake/modules/MyxCMakeCommon.cmake new file mode 100644 index 0000000..6fbb8a6 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCommon.cmake @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.3 FATAL_ERROR) + +include(GNUInstallDirs) +include(MyxCMakeCheckPaths) + +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS + ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS};tpp;tcc) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +include(MyxCMakeProjectVersion) +include(MyxCMakeRequiredVariables) +include(MyxCMakeGlobalFunctions) +include(MyxCMakeGlobalVariables) +include(MyxCMakeToday) +include(MyxCMakeLSBInfo) +include(MyxCMakeCompiler) +include(MyxCMakeCompilerFlags) +include(MyxCMakeDistCC) +include(MyxCMakeUnityBuild) +include(MyxCMakePrecompiledHeaders) +include(MyxCMakeBuildTypes) +include(MyxCMakeDebugOutputOptions) + +include(MyxCMakeCodeAnalyzeClangCheck) +include(MyxCMakeCodeAnalyzeClangTidy) +include(MyxCMakeCodeAnalyzeClazy) +include(MyxCMakeCodeAnalyzePvsStudio) +include(MyxCMakeCodeCoverage) +include(MyxCMakeFormatSources) +include(MyxCMakeCommonTargetProperties) +include(MyxCMakeAddSharedLibrary) +include(MyxCMakeAddStaticLibrary) +include(MyxCMakePkgConfig) +include(MyxCMakeNinjaGeneratorHelper) +include(CMLibGit) + + + +# include(CMLibDocDoxygen) include(CMLibDocBreathe) +# include(CMLibExternalProject) + +include(MyxCMakeCPack) +include(MyxCMakeUninstall) diff --git a/MyxCMake/modules/MyxCMakeCommonTargetProperties.cmake b/MyxCMake/modules/MyxCMakeCommonTargetProperties.cmake new file mode 100644 index 0000000..6b02b5a --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCommonTargetProperties.cmake @@ -0,0 +1,157 @@ +function(myx_cmake_common_target_properties target) + get_target_property(_target_type ${target} TYPE) + + set(__visibility PUBLIC) + if(_target_type STREQUAL INTERFACE_LIBRARY) + set(__visibility INTERFACE) + else() + # + if(TARGET Qt5::Core) + if(_target_type STREQUAL EXECUTABLE) + target_compile_options(${target} + PUBLIC ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}) + endif() + if(NOT MYX_CMAKE_DEBUG_OUTPUT) + target_compile_definitions(${target} PUBLIC QT_NO_DEBUG_OUTPUT) + endif() + if(NOT MYX_CMAKE_INFO_OUTPUT) + target_compile_definitions(${target} PUBLIC QT_NO_INFO_OUTPUT) + endif() + if(NOT MYX_CMAKE_WARNING_OUTPUT) + target_compile_definitions(${target} PUBLIC QT_NO_WARNING_OUTPUT) + endif() + endif() + if(CMAKE_CXX_COMPILER_IS_GCC AND NOT APPLE) + set_property( + TARGET ${target} + APPEND_STRING + PROPERTY LINK_FLAGS " -Wl,--no-as-needed") + endif() + + # Исключение файлов qrc из списка объединяемых файлов + get_target_property(__sources ${target} SOURCES) + foreach(src IN LISTS __sources) + string(REGEX MATCH ".*/qrc_.*\\.cpp$" __qrc ${src}) + if(__qrc) + set_property(SOURCE ${__qrc} PROPERTY COTIRE_EXCLUDED ON) + set_property(SOURCE ${__qrc} PROPERTY SKIP_UNITY_BUILD_INCLUSION ON) + endif() + endforeach() + + target_include_directories( + ${target} + PUBLIC $ + $ + $ + $) + + endif() + + target_compile_features(${target} ${__visibility} cxx_alias_templates + cxx_nullptr cxx_override) + if(_target_type STREQUAL EXECUTABLE) + set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON) + set_target_properties( + ${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) + if(CMAKE_CXX_COMPILE_OPTIONS_PIE) + target_compile_options(${target} PUBLIC ${CMAKE_CXX_COMPILE_OPTIONS_PIE}) + endif() + if(CMAKE_CXX_COMPILER_IS_GCC AND MYX_CMAKE_CODE_COVERAGE) + myx_cmake_code_coverage(${target}) + endif() + endif() + + if(APPLE) + target_compile_definitions(${target} ${__visibility} Darwin) + endif() + + if(_target_type STREQUAL OBJECT_LIBRARY) + # target_include_directories(${target} PUBLIC + # $) + set_target_properties(${target} PROPERTIES POSITION_INDEPENDENT_CODE ON) + endif() + + # LTO only for executables (not libraries) in Release build type + if(_target_type STREQUAL EXECUTABLE AND CMAKE_BUILD_TYPE STREQUAL Release) + check_cxx_compiler_flag(-flto CXX_HAS_LTO_FLAG) + check_cxx_compiler_flag(-fno-fat-lto-objects CXX_HAS_NO_FAT_LTO_FLAG) + if(CXX_HAS_LTO_FLAG) + target_compile_options(${target} PUBLIC "-flto") + set_property( + TARGET ${target} + APPEND_STRING + PROPERTY LINK_FLAGS " -flto") + if(CXX_HAS_NO_FAT_LTO_FLAG) + target_compile_options(${target} PUBLIC "-fno-fat-lto-objects") + set_property( + TARGET ${target} + APPEND_STRING + PROPERTY LINK_FLAGS " -fno-fat-lto-objects") + endif() + endif() + endif() + + # cmake-format: off + if(COMMAND cotire) + set_property(TARGET ${target} + PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${MYX_CMAKE_PRECOMPILED_HEADERS}) + set_property(TARGET ${target} + PROPERTY COTIRE_ADD_UNITY_BUILD ${MYX_CMAKE_UNITY_BUILD}) + endif() + # cmake-format: on + + if(CMAKE_BUILD_TYPE STREQUAL Profile) + target_compile_definitions(${target} ${__visibility} PROFILE) + elseif(CMAKE_BUILD_TYPE STREQUAL Debug) + target_compile_definitions(${target} ${__visibility} DEBUG) + elseif(CMAKE_BUILD_TYPE STREQUAL Release) + target_compile_definitions(${target} ${__visibility} RELEASE) + elseif(CMAKE_BUILD_TYPE STREQUAL None) + target_compile_definitions(${target} ${__visibility} ANALYSIS) + endif() + target_compile_definitions( + ${target} ${__visibility} + "MYX_CMAKE_LSB_ID_${MYX_CMAKE_LSB_DISTRIBUTOR_ID}") + target_compile_definitions( + ${target} ${__visibility} + "MYX_CMAKE_LSB_CODENAME_${MYX_CMAKE_LSB_CODENAME}") + + myx_cmake_clang_tidy_analyze(${target}) + myx_cmake_clang_check_analyze(${target}) + myx_cmake_clazy_analyze(${target}) + myx_cmake_pvs_studio_analyze(${target}) + myx_cmake_format_sources(${target}) + + # Создание в каталоге ${CMAKE_BINARY_DIR} стандартных каталогов bin,include,lib + if(NOT TARGET ${target}-default-directories) + add_custom_target( + ${target}-default-directories + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/include + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/lib + ) + add_dependencies(${target} ${target}-default-directories) + endif() + + # Создание в каталоге ${CMAKE_BINARY_DIR} символических ссылок на каталоги в ${CMAKE_SOURCE_DIR}/files + if(NOT TARGET ${target}-symlinks AND UNIX) + add_custom_target( + ${target}-symlinks + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + # Ссылка на каталог с журналами + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/files/log + ${CMAKE_BINARY_DIR}/log + # Ссылка на каталог с обрабатываемыми данными + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/files/var + ${CMAKE_BINARY_DIR}/var + # Ссылка на каталог с постоянными данными + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/files/share + ${CMAKE_BINARY_DIR}/share + # Ссылка на каталог настроек + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/files/etc + ${CMAKE_BINARY_DIR}/etc) + add_dependencies(${target} ${target}-symlinks) + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeCompiler.cmake b/MyxCMake/modules/MyxCMakeCompiler.cmake new file mode 100644 index 0000000..514efac --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCompiler.cmake @@ -0,0 +1,64 @@ +# C compiler name +if(CMAKE_C_COMPILER_ID STREQUAL "Intel") + set(CMAKE_C_COMPILER_IS_INTEL ON) +elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL + "AppleClang") + set(CMAKE_C_COMPILER_IS_CLANG ON) +elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(CMAKE_C_COMPILER_IS_GCC ON) +elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_C_COMPILER_IS_MSVC ON) +endif() + +# C++ compiler name +if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + set(CMAKE_CXX_COMPILER_IS_INTEL ON) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL + "AppleClang") + set(CMAKE_CXX_COMPILER_IS_CLANG ON) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_COMPILER_IS_GCC ON) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_CXX_COMPILER_IS_MSVC ON) +endif() + +# Предпочтительные пути к утилитам для компоновки +if(CMAKE_CXX_COMPILER_IS_GCC) + # Astra Linux Smolensk 1.5 + if(MYX_CMAKE_LSB_DISTRIBUTOR_ID STREQUAL "AstraLinuxSE" + AND MYX_CMAKE_LSB_CODENAME STREQUAL "smolensk" + AND MYX_CMAKE_LSB_RELEASE STREQUAL "1.5") + find_program(CMAKE_GCC_AR NAMES "/usr/bin/x86_64-linux-gnu-gcc-ar-4.7") + find_program(CMAKE_GCC_NM NAMES "/usr/bin/x86_64-linux-gnu-gcc-nm-4.7") + find_program(CMAKE_GCC_RANLIB + NAMES "/usr/bin/x86_64-linux-gnu-gcc-ranlib-4.7") + # Elbrus E2K + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "e2k") + find_program(CMAKE_GCC_AR + NAMES "/usr/${CMAKE_SYSTEM_PROCESSOR}-linux/bin/ar") + find_program(CMAKE_GCC_NM + NAMES "/usr/${CMAKE_SYSTEM_PROCESSOR}-linux/bin/nm") + find_program(CMAKE_GCC_RANLIB + NAMES "/usr/${CMAKE_SYSTEM_PROCESSOR}-linux/bin/ranlib") + else() + find_program(CMAKE_GCC_AR NAMES "gcc-ar" "ar") + find_program(CMAKE_GCC_NM NAMES "gcc-nm" "nm") + find_program(CMAKE_GCC_RANLIB NAMES "gcc-ranlib" "ranlib") + endif() + + if(CMAKE_GCC_AR) + set(CMAKE_AR + ${CMAKE_GCC_AR} + CACHE STRING "" FORCE) + endif() + if(CMAKE_GCC_NM) + set(CMAKE_NM + ${CMAKE_GCC_NM} + CACHE STRING "" FORCE) + endif() + if(CMAKE_GCC_RANLIB) + set(CMAKE_RANLIB + ${CMAKE_GCC_RANLIB} + CACHE STRING "" FORCE) + endif() +endif() diff --git a/MyxCMake/modules/MyxCMakeCompilerFlags.cmake b/MyxCMake/modules/MyxCMakeCompilerFlags.cmake new file mode 100644 index 0000000..a498944 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeCompilerFlags.cmake @@ -0,0 +1,240 @@ +# based on https://github.com/bluescarni/yacma + +include(CheckCXXCompilerFlag) + +macro(CHECK_ENABLE_CXX_FLAG flag) + set(CMAKE_REQUIRED_QUIET TRUE) + check_cxx_compiler_flag("${flag}" CHECK_CXX_FLAG) + unset(CMAKE_REQUIRED_QUIET) + + if(CHECK_CXX_FLAG) + message(STATUS "'${flag}': flag is supported.") + string(CONCAT _MYX_CMAKE_DETECTED_CXX_FLAGS + "${_MYX_CMAKE_DETECTED_CXX_FLAGS} ${flag}") + else() + message(STATUS "'${flag}': flag is NOT supported.") + endif() + # NOTE: check_cxx_compiler stores variables in the cache. + unset(CHECK_CXX_FLAG CACHE) +endmacro() + +macro(CHECK_ENABLE_DEBUG_CXX_FLAG flag) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_REQUIRED_QUIET TRUE) + check_cxx_compiler_flag("${flag}" CHECK_CXX_FLAG_DEBUG) + unset(CMAKE_REQUIRED_QUIET) + + if(CHECK_CXX_FLAG_DEBUG) + message(STATUS "'${flag}': debug flag is supported.") + string(CONCAT _MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG + "${_MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG} ${flag}") + else() + message(STATUS "'${flag}': debug flag is NOT supported.") + endif() + # NOTE: check_cxx_compiler stores variables in the cache. + unset(CHECK_CXX_FLAG_DEBUG CACHE) + endif() +endmacro() + +function(myx_cmake_set_cxx_standard version) + # Выбор стандарта по умолчанию (можно переопределить в проекте) + set(CMAKE_CXX_STANDARD_REQUIRED + YES + PARENT_SCOPE) + + if(version EQUAL 11) + set(CMAKE_CXX_STANDARD + 11 + PARENT_SCOPE) + set(CMAKE_CXX_EXTENSIONS + YES + PARENT_SCOPE) + endif() + + if(version EQUAL 14) + set(CMAKE_CXX_STANDARD + 14 + PARENT_SCOPE) + set(CMAKE_CXX_EXTENSIONS + YES + PARENT_SCOPE) + endif() + + if(version EQUAL 17) + if(${CMAKE_VERSION} VERSION_LESS "3.10.0") + check_cxx_compiler_flag(-std=gnu++17 HAVE_FLAG_STD_GNUXX17) + if(HAVE_FLAG_STD_GNUXX17) + add_compile_options("-std=gnu++17") + else() + check_cxx_compiler_flag(-std=gnu++1z HAVE_FLAG_STD_GNUXX1Z) + if(HAVE_FLAG_STD_GNUXX1Z) + add_compile_options("-std=gnu++1z") + else() + check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17) + if(HAVE_FLAG_STD_CXX17) + add_compile_options("-std=c++17") + else() + check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z) + if(HAVE_FLAG_STD_CXX1Z) + add_compile_options("-std=c++1z") + endif() + endif() + endif() + endif() + else() + set(CMAKE_CXX_STANDARD + 17 + PARENT_SCOPE) + set(CMAKE_CXX_EXTENSIONS + YES + PARENT_SCOPE) + endif() + endif() +endfunction() + +if(NOT MYX_CMAKE_CXX_FLAGS_AUTODETECTION_DONE) + set(_MYX_CMAKE_DETECTED_CXX_FLAGS "") + set(_MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG "") + + # Configuration bits specific for clang. + if(CMAKE_CXX_COMPILER_IS_CLANG) + if(CMAKE_COLOR_MAKEFILE) + check_enable_cxx_flag(-fcolor-diagnostics) + endif() + # For now it seems like -Wshadow from clang behaves better than GCC's, just + # enable it here for the time being. + check_enable_debug_cxx_flag(-Wshadow) + # New warnings in clang 8. NOTE: a few issues with macros here, let's + # disable for now. CHECK_ENABLE_DEBUG_CXX_FLAG(-Wextra-semi-stmt) New + # warnings in clang 10. + check_enable_debug_cxx_flag(-Wtautological-overlap-compare) + check_enable_debug_cxx_flag(-Wtautological-compare) + check_enable_debug_cxx_flag(-Wtautological-bitwise-compare) + check_enable_debug_cxx_flag(-Wbitwise-conditional-parentheses) + check_enable_debug_cxx_flag(-Wrange-loop-analysis) + check_enable_debug_cxx_flag(-Wmisleading-indentation) + check_enable_debug_cxx_flag(-Wc99-designator) + check_enable_debug_cxx_flag(-Wreorder-init-list) + check_enable_debug_cxx_flag(-Wsizeof-pointer-div) + check_enable_debug_cxx_flag(-Wsizeof-array-div) + check_enable_debug_cxx_flag(-Wxor-used-as-pow) + check_enable_debug_cxx_flag(-Wfinal-dtor-non-final-class) + # NOTE: this is a new flag in Clang 13 which seems to give + # incorrect warnings for UDLs. + check_enable_debug_cxx_flag(-Wno-reserved-identifier) + endif() + + # Common configuration for GCC, clang and Intel. + if(CMAKE_CXX_COMPILER_IS_CLANG + OR CMAKE_CXX_COMPILER_IS_INTEL + OR CMAKE_CXX_COMPILER_IS_GCC) + check_enable_debug_cxx_flag(-Wall) + check_enable_debug_cxx_flag(-Wextra) + check_enable_debug_cxx_flag(-Wnon-virtual-dtor) + check_enable_debug_cxx_flag(-Wnoexcept) + check_enable_debug_cxx_flag(-Wlogical-op) + check_enable_debug_cxx_flag(-Wconversion) + check_enable_debug_cxx_flag(-Wdeprecated) + # This limit is supposed to be at least 1024 in C++11, but for some reason + # clang sets this to 256, and gcc to 900. + check_enable_cxx_flag(-ftemplate-depth=1024) + check_enable_debug_cxx_flag(-Wold-style-cast) + check_enable_debug_cxx_flag(-Wdisabled-optimization) + # This is useful when the compiler decides the template backtrace is too + # verbose. + check_enable_debug_cxx_flag(-ftemplate-backtrace-limit=0) + check_enable_debug_cxx_flag(-fstack-protector-all) + # A few suggestion flags. + check_enable_debug_cxx_flag(-Wsuggest-attribute=pure) + check_enable_debug_cxx_flag(-Wsuggest-attribute=const) + check_enable_debug_cxx_flag(-Wsuggest-attribute=noreturn) + check_enable_debug_cxx_flag(-Wsuggest-attribute=format) + # From GCC 5. + check_enable_debug_cxx_flag(-Wodr) + check_enable_debug_cxx_flag(-Wsuggest-final-types) + check_enable_debug_cxx_flag(-Wsuggest-final-methods) + check_enable_debug_cxx_flag(-Wsuggest-override) + # From GCC 6. + check_enable_debug_cxx_flag(-Wshift-negative-value) + check_enable_debug_cxx_flag(-Wshift-overflow=2) + check_enable_debug_cxx_flag(-Wduplicated-cond) + check_enable_debug_cxx_flag(-Wnull-dereference) + # From GCC 7. + check_enable_debug_cxx_flag(-Wrestrict) + check_enable_debug_cxx_flag(-Waligned-new) + check_enable_debug_cxx_flag(-fdiagnostics-parseable-fixits) + check_enable_debug_cxx_flag(-fdiagnostics-generate-patch) + # From GCC 8. + check_enable_debug_cxx_flag(-Wcast-align=strict) + # This is supposed to produce a nice graphical visualization of mismatching + # template errors. + check_enable_cxx_flag(-fdiagnostics-show-template-tree) + check_enable_debug_cxx_flag(-fdiagnostics-show-option) + + check_enable_debug_cxx_flag(-pedantic) + check_enable_debug_cxx_flag(-Wcast-align) + check_enable_debug_cxx_flag(-Wcast-qual) + check_enable_debug_cxx_flag(-Wctor-dtor-privacy) + check_enable_debug_cxx_flag(-Wdisabled-optimization) + check_enable_debug_cxx_flag(-Wformat=2) + check_enable_debug_cxx_flag(-Winit-self) + check_enable_debug_cxx_flag(-Wmissing-include-dirs) + check_enable_debug_cxx_flag(-Woverloaded-virtual) + check_enable_debug_cxx_flag(-Wredundant-decls) + check_enable_debug_cxx_flag(-Wsign-promo) + check_enable_debug_cxx_flag(-Wstrict-overflow=5) + check_enable_debug_cxx_flag(-Wundef) + check_enable_debug_cxx_flag(-Wno-unused) + check_enable_debug_cxx_flag(-Wno-variadic-macros) + check_enable_debug_cxx_flag(-Wno-parentheses) + check_enable_debug_cxx_flag(-Wstrict-null-sentinel) + check_enable_debug_cxx_flag(-Wshadow-all) + endif() + + if(CMAKE_CXX_COMPILER_IS_GCC) + if(CMAKE_COLOR_MAKEFILE) + check_enable_cxx_flag(-fdiagnostics-color=auto) + endif() + # The -Wmaybe-uninitialized flag is enabled by -Wall, but it is known to + # emit a lot of possibly spurious warnings. Let's just disable it. + check_enable_debug_cxx_flag(-Wno-maybe-uninitialized) + # New in GCC 9. + check_enable_debug_cxx_flag(-Waddress-of-packed-member) + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.999") + # NOTE: GCC >= 6 seems to be wrongly warning about visibility attributes + # in some situations: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947 + # Let's just disable the warning for now. + check_enable_cxx_flag(-Wno-attributes) + endif() + endif() + + # cmake-format: off + if(MYX_CMAKE_LSB_DISTRIBUTOR_ID STREQUAL "AstraLinuxSE" AND + MYX_CMAKE_LSB_CODENAME STREQUAL "smolensk" AND + MYX_CMAKE_LSB_RELEASE STREQUAL "1.5") + # cmake-format: on + myx_cmake_set_cxx_standard(11) + elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "e2k") + myx_cmake_set_cxx_standard(14) + check_enable_debug_cxx_flag(-Wno-invalid-offsetof) + list(APPEND CMAKE_LIBRARY_PATH "/usr/lib/e2k-linux-gnu") + else() + myx_cmake_set_cxx_standard(17) + # -Wshadow gives a lot of false positives with GCC 4.7.2 in Astra Linux 1.5 + if(CMAKE_CXX_COMPILER_IS_GCC) + check_enable_debug_cxx_flag(-Wshadow) + endif() + endif() + + # Set the cache variables. + set(MYX_CMAKE_DETECTED_CXX_FLAGS + "${_MYX_CMAKE_DETECTED_CXX_FLAGS}" + CACHE INTERNAL "") + set(MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG + "${_MYX_CMAKE_DETECTED_CXX_FLAGS_DEBUG}" + CACHE INTERNAL "") + set(MYX_CMAKE_CXX_FLAGS_AUTODETECTION_DONE + YES + CACHE INTERNAL "") +endif() diff --git a/MyxCMake/modules/MyxCMakeDebugOutputOptions.cmake b/MyxCMake/modules/MyxCMakeDebugOutputOptions.cmake new file mode 100644 index 0000000..19aeb8e --- /dev/null +++ b/MyxCMake/modules/MyxCMakeDebugOutputOptions.cmake @@ -0,0 +1,18 @@ +# По умолчанию отключена отладочная печать (если не включена явно программистом) +option(MYX_CMAKE_DEBUG_OUTPUT "Enable debug output" OFF) +option(MYX_CMAKE_INFO_OUTPUT "Enable info output" OFF) +option(MYX_CMAKE_WARNING_OUTPUT "Enable warning output" OFF) + +# Если сборка производится в режиме для отладки, то включаются флаги для +# разрешения отладочной печати +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(MYX_CMAKE_DEBUG_OUTPUT + ON + CACHE BOOL "" FORCE) + set(MYX_CMAKE_INFO_OUTPUT + ON + CACHE BOOL "" FORCE) + set(MYX_CMAKE_WARNING_OUTPUT + ON + CACHE BOOL "" FORCE) +endif() diff --git a/MyxCMake/modules/MyxCMakeDistCC.cmake b/MyxCMake/modules/MyxCMakeDistCC.cmake new file mode 100644 index 0000000..4b0b193 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeDistCC.cmake @@ -0,0 +1,13 @@ +find_program(DISTCC_EXECUTABLE distcc) +mark_as_advanced(DISTCC_EXECUTABLE) +if(DISTCC_EXECUTABLE) + foreach(lang C CXX) + if(NOT DEFINED CMAKE_${lang}_COMPILER_LAUNCHER + AND NOT CMAKE_${lang}_COMPILER MATCHES ".*/distcc$") + message(STATUS "MyxCMake: distcc enabled for ${lang}") + set(CMAKE_${lang}_COMPILER_LAUNCHER + ${DISTCC_EXECUTABLE} + CACHE STRING "") + endif() + endforeach() +endif() diff --git a/MyxCMake/modules/MyxCMakeFormatSources.cmake b/MyxCMake/modules/MyxCMakeFormatSources.cmake new file mode 100644 index 0000000..17c800b --- /dev/null +++ b/MyxCMake/modules/MyxCMakeFormatSources.cmake @@ -0,0 +1,52 @@ +function(myx_cmake_format_sources target) + + get_target_property(__sources ${target} SOURCES) + list(FILTER __sources EXCLUDE REGEX "qrc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "moc_.*\\.cpp$") + list(FILTER __sources EXCLUDE REGEX "ui_.*\\.h$") + + if(NOT TARGET myx-cmake-format-sources) + add_custom_target(myx-cmake-format-sources) + endif() + if(NOT TARGET myx-cmake-check-format-sources) + add_custom_target(myx-cmake-check-format-sources) + endif() + if(NOT TARGET myx-cmake-add-doxygen-comments) + add_custom_target(myx-cmake-add-doxygen-comments) + endif() + + find_program(UNCRUSTIFY_EXE NAMES uncrustify) + if(UNCRUSTIFY_EXE) + if(EXISTS ${CMAKE_SOURCE_DIR}/files/etc/uncrustify.cfg) + list(APPEND UNCRUSTIFY_OPTS -c ${CMAKE_SOURCE_DIR}/files/etc/uncrustify.cfg) + endif() + # cmake-format: off + add_custom_target(${target}-check-format-sources-uncrustify + COMMAND ${UNCRUSTIFY_EXE} ${UNCRUSTIFY_OPTS} --check ${__sources}) + list(APPEND UNCRUSTIFY_OPTS --replace --no-backup) + add_custom_target(${target}-format-sources-uncrustify + COMMAND ${UNCRUSTIFY_EXE} ${UNCRUSTIFY_OPTS} --mtime ${__sources}) + add_custom_target(${target}-add-doxygen-comments-uncrustify + COMMAND ${UNCRUSTIFY_EXE} ${UNCRUSTIFY_OPTS} + --set cmt_insert_file_header=fileheader.txt + --set cmt_insert_file_footer=filefooter.txt + --set cmt_insert_func_header=funcheader.txt + --set cmt_insert_class_header=classheader.txt + --set cmt_insert_before_ctor_dtor=true ${__sources}) + # cmake-format: on + add_dependencies(myx-cmake-check-format-sources ${target}-check-format-sources-uncrustify) + add_dependencies(myx-cmake-format-sources ${target}-format-sources-uncrustify) + add_dependencies(myx-cmake-add-doxygen-comments ${target}-add-doxygen-comments-uncrustify) + else() + message(STATUS "MyxCMake: uncrustify executable is not found") + endif() + + find_program(DOS2UNIX_EXE NAMES dos2unix) + if(DOS2UNIX_EXE) + list(APPEND DOS2UNIX_OPTS -k -r) + add_custom_target(${target}-format-sources-dos2unix COMMAND ${DOS2UNIX_EXE} ${DOS2UNIX_OPTS} ${__sources}) + add_dependencies(myx-cmake-format-sources ${target}-format-sources-dos2unix) + else() + message(STATUS "MyxCMake: dos2unix executable is not found") + endif() +endfunction() diff --git a/MyxCMake/modules/MyxCMakeGlobalFunctions.cmake b/MyxCMake/modules/MyxCMakeGlobalFunctions.cmake new file mode 100644 index 0000000..5d31aec --- /dev/null +++ b/MyxCMake/modules/MyxCMakeGlobalFunctions.cmake @@ -0,0 +1,19 @@ +# Формирование строки, состоящей из заглавных символов, цифр и подчёркиваний +function(myx_cmake_canonical_string in_string out_string) + string(TOUPPER ${in_string} _arg_uppercase) + string(REGEX REPLACE "[ -]" "_" _arg_fixed ${_arg_uppercase}) + set(${out_string} + ${_arg_fixed} + PARENT_SCOPE) +endfunction() + +# Добавление общего префикса ко всем переменным в списке +function(myx_cmake_list_transform_prepend var prefix) + set(temp "") + foreach(filename ${${var}}) + list(APPEND temp "${prefix}${filename}") + endforeach() + set(${var} + "${temp}" + PARENT_SCOPE) +endfunction() diff --git a/MyxCMake/modules/MyxCMakeGlobalVariables.cmake b/MyxCMake/modules/MyxCMakeGlobalVariables.cmake new file mode 100644 index 0000000..35d96d0 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeGlobalVariables.cmake @@ -0,0 +1,29 @@ +if(NOT MYX_CMAKE_THEME_NAME) + set(MYX_CMAKE_THEME_NAME "default") +endif() + +# cmake-format: off +myx_cmake_canonical_string(${MYX_CMAKE_ORGANIZATION_NAME} MYX_CMAKE_ORGANIZATION_NAME_CANONICAL) +myx_cmake_canonical_string(${PROJECT_NAME} MYX_CMAKE_PROJECT_NAME_CANONICAL) +myx_cmake_canonical_string(${MYX_CMAKE_THEME_NAME} MYX_CMAKE_THEME_NAME_CANONICAL) + +string(TOLOWER ${MYX_CMAKE_ORGANIZATION_NAME_CANONICAL} MYX_CMAKE_ORGANIZATION_NAME_LOWER) +string(TOLOWER ${MYX_CMAKE_PROJECT_NAME_CANONICAL} MYX_CMAKE_PROJECT_NAME_LOWER) +string(TOLOWER ${MYX_CMAKE_THEME_NAME_CANONICAL} MYX_CMAKE_THEME_NAME_LOWER) + +string(TOUPPER ${MYX_CMAKE_ORGANIZATION_NAME_CANONICAL} MYX_CMAKE_ORGANIZATION_NAME_UPPER) +string(TOUPPER ${MYX_CMAKE_PROJECT_NAME_CANONICAL} MYX_CMAKE_PROJECT_NAME_UPPER) +string(TOUPPER ${MYX_CMAKE_THEME_NAME_CANONICAL} MYX_CMAKE_THEME_NAME_UPPER) +# cmake-format: on + +option(MYX_CMAKE_ADD_THEME_PREFIX "Append theme name to install prefix" OFF) +if(MYX_CMAKE_ADD_THEME_PREFIX AND NOT MYX_CMAKE_THEME_PREFIX_APPENDED) + if(NOT MYX_CMAKE_THEME_NAME_LOWER STREQUAL "default") + set(MYX_CMAKE_THEME_PREFIX_APPENDED + ON + CACHE BOOL "" FORCE) + set(CMAKE_INSTALL_PREFIX + "${CMAKE_INSTALL_PREFIX}/${MYX_CMAKE_THEME_NAME}" + CACHE PATH "" FORCE) + endif() +endif() diff --git a/MyxCMake/modules/MyxCMakeLSBInfo.cmake b/MyxCMake/modules/MyxCMakeLSBInfo.cmake new file mode 100644 index 0000000..36b2d0c --- /dev/null +++ b/MyxCMake/modules/MyxCMakeLSBInfo.cmake @@ -0,0 +1,29 @@ +if(CMAKE_CROSSCOMPILING) + return() +endif() + +if(MYX_CMAKE_LSB_RELEASE) + return() +endif() + +set(MYX_CMAKE_LSB_DISTRIBUTOR_ID "unknown") +set(MYX_CMAKE_LSB_CODENAME "unknown") +set(MYX_CMAKE_LSB_RELEASE "unknown") + +if(EXISTS /etc/mcst_version) + set(MYX_CMAKE_LSB_DISTRIBUTOR_ID "ElbrusD") + set(MYX_CMAKE_LSB_CODENAME "Jessie") + execute_process( + COMMAND cat /etc/mcst_version + OUTPUT_VARIABLE MYX_CMAKE_LSB_RELEASE + OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + find_program(_lsb_release_executable lsb_release) + # cmake-format: off + if(_lsb_release_executable) + execute_process(COMMAND ${_lsb_release_executable} -si OUTPUT_VARIABLE MYX_CMAKE_LSB_DISTRIBUTOR_ID OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${_lsb_release_executable} -sc OUTPUT_VARIABLE MYX_CMAKE_LSB_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND ${_lsb_release_executable} -sr OUTPUT_VARIABLE MYX_CMAKE_LSB_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE) + # cmake-format: on + endif() +endif() diff --git a/MyxCMake/modules/MyxCMakeNinjaGeneratorHelper.cmake b/MyxCMake/modules/MyxCMakeNinjaGeneratorHelper.cmake new file mode 100644 index 0000000..64935d4 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeNinjaGeneratorHelper.cmake @@ -0,0 +1,9 @@ +# Если выбран генератор Ninja, то в основном сборочном каталоге создаётся файл +# Makefile, который обрабатывается командой make и передаёт исполнение системе +# сборки ninja. Таким образом можно выполнять команду make, даже если правила +# сборки проекта сгенерированы для ninja. + +if(CMAKE_GENERATOR MATCHES Ninja) + file(WRITE ${CMAKE_BINARY_DIR}/Makefile + ".PHONY: build\n" "%:\n" "\t@ninja \$@\n" "build:\n" "\t@ninja\n") +endif() diff --git a/MyxCMake/modules/MyxCMakePkgConfig.cmake b/MyxCMake/modules/MyxCMakePkgConfig.cmake new file mode 100644 index 0000000..c775262 --- /dev/null +++ b/MyxCMake/modules/MyxCMakePkgConfig.cmake @@ -0,0 +1,47 @@ +function(myx_cmake_generate_pkgconfig target) + set(options) + set(oneVA COMPONENT) + set(multiVA) + + cmake_parse_arguments(ARG "${options}" "${oneVA}" "${multiVA}" ${ARGN}) + + if(NOT ARG_COMPONENT) + set(ARG_COMPONENT "base-dev") + endif() + + get_target_property(_target_type ${target} TYPE) + + if(_target_type STREQUAL INTERFACE_LIBRARY) + file( + WRITE "${CMAKE_BINARY_DIR}/${target}.pc" + "prefix=${CMAKE_INSTALL_PREFIX}\n" + "exec_prefix=${CMAKE_INSTALL_PREFIX}\n" + "includedir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n" + "\n" + "Name: ${target}\n" + "Description: ${target} header-only library\n" + "Version: ${PROJECT_VERSION}\n" + "\n" + "Requires:\n" + "Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n") + else() + file( + WRITE "${CMAKE_BINARY_DIR}/${target}.pc" + "prefix=${CMAKE_INSTALL_PREFIX}\n" + "exec_prefix=${CMAKE_INSTALL_PREFIX}\n" + "libdir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\n" + "includedir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n" + "\n" + "Name: ${target}\n" + "Description: ${target} library\n" + "Version: ${PROJECT_VERSION}\n" + "\n" + "Requires:\n" + "Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -l${target}\n" + "Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n") + endif() + install( + FILES "${CMAKE_BINARY_DIR}/${target}.pc" + COMPONENT ${ARG_COMPONENT} + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endfunction() diff --git a/MyxCMake/modules/MyxCMakePrecompiledHeaders.cmake b/MyxCMake/modules/MyxCMakePrecompiledHeaders.cmake new file mode 100644 index 0000000..8605e75 --- /dev/null +++ b/MyxCMake/modules/MyxCMakePrecompiledHeaders.cmake @@ -0,0 +1,10 @@ +if(${CMAKE_VERSION} VERSION_LESS "3.16.0") + include(cotire OPTIONAL) + if(COMMAND cotire) + option(MYX_CMAKE_PRECOMPILED_HEADERS "MyxCMake: enable precompiled headers" + OFF) + endif() +else() + option(MYX_CMAKE_PRECOMPILED_HEADERS "MyxCMake: enable precompiled headers" + OFF) +endif() diff --git a/MyxCMake/modules/MyxCMakeProjectVersion.cmake b/MyxCMake/modules/MyxCMakeProjectVersion.cmake new file mode 100644 index 0000000..de5ffa6 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeProjectVersion.cmake @@ -0,0 +1,17 @@ +function(myx_cmake_check_project_version) + if(NOT ${PROJECT_VERSION_PATCH} MATCHES "([0-9]+)") + message(FATAL_ERROR "MyxCMake: Please set project version in X.Y.Z format") + endif() +endfunction() + +function(myx_cmake_set_project_version_int) + myx_cmake_check_project_version() + math( + EXPR + _version_int + "(${PROJECT_VERSION_MAJOR} << 16) + (${PROJECT_VERSION_MINOR} << 8) + ${PROJECT_VERSION_PATCH}" + ) + set_property(GLOBAL PROPERTY PROJECT_VERSION_INT ${_version_int}) +endfunction() + +myx_cmake_set_project_version_int() diff --git a/MyxCMake/modules/MyxCMakeRequiredVariables.cmake b/MyxCMake/modules/MyxCMakeRequiredVariables.cmake new file mode 100644 index 0000000..04a19d4 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeRequiredVariables.cmake @@ -0,0 +1,34 @@ +# +# Обязательные переменные, значения которым необходимо присвоить в файле +# CMakeLists.txt до подключения MyxCMake, либо передать из командной строки +# через ключ -D +# +if(NOT MYX_CMAKE_ORGANIZATION_NAME) + message( + FATAL_ERROR + "MyxCMake: Required variable MYX_CMAKE_ORGANIZATION_NAME is not defined") +endif() + +if(NOT MYX_CMAKE_AUTHOR_NAME) + message( + FATAL_ERROR + "MyxCMake: Required variable MYX_CMAKE_AUTHOR_NAME is not defined") +endif() + +if(NOT MYX_CMAKE_AUTHOR_EMAIL) + message( + FATAL_ERROR + "MyxCMake: Required variable MYX_CMAKE_AUTHOR_EMAIL is not defined") +endif() +set(CPACK_PACKAGE_CONTACT + "${MYX_CMAKE_AUTHOR_NAME} <${MYX_CMAKE_AUTHOR_EMAIL}>" + CACHE STRING "") + +if(NOT MYX_CMAKE_DESCRIPTION) + message( + FATAL_ERROR + "MyxCMake: Required variable MYX_CMAKE_DESCRIPTION is not defined") +endif() +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY + ${MYX_CMAKE_DESCRIPTION} + CACHE STRING "") diff --git a/MyxCMake/modules/MyxCMakeToday.cmake b/MyxCMake/modules/MyxCMakeToday.cmake new file mode 100644 index 0000000..10e7b7e --- /dev/null +++ b/MyxCMake/modules/MyxCMakeToday.cmake @@ -0,0 +1,8 @@ +if(NOT TODAY) + if(WIN32) + execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE TODAY) + else() + execute_process(COMMAND "date" "+%d/%m/%Y" OUTPUT_VARIABLE TODAY) + endif() + string(REGEX REPLACE "(..)/(..)/(....).*" "\\3-\\2-\\1" TODAY ${TODAY}) +endif() diff --git a/MyxCMake/modules/MyxCMakeUninstall.cmake b/MyxCMake/modules/MyxCMakeUninstall.cmake new file mode 100644 index 0000000..948ded5 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeUninstall.cmake @@ -0,0 +1,6 @@ +if(NOT TARGET uninstall) + configure_file("${CMAKE_CURRENT_LIST_DIR}/CMLibUninstall.cmake.in" + "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) + + add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake) +endif() diff --git a/MyxCMake/modules/MyxCMakeUninstall.cmake.in b/MyxCMake/modules/MyxCMakeUninstall.cmake.in new file mode 100644 index 0000000..0f747a1 --- /dev/null +++ b/MyxCMake/modules/MyxCMakeUninstall.cmake.in @@ -0,0 +1,31 @@ +if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) + +# Удаление пустых каталогов +foreach(_file ${files}) + set(_res 0) + while(_res EQUAL 0) + get_filename_component(_file ${_file} DIRECTORY) + execute_process(COMMAND rmdir ${_file} RESULT_VARIABLE _res OUTPUT_QUIET ERROR_QUIET) + endwhile() +endforeach() + diff --git a/MyxCMake/modules/MyxCMakeUnityBuild.cmake b/MyxCMake/modules/MyxCMakeUnityBuild.cmake new file mode 100644 index 0000000..64e83df --- /dev/null +++ b/MyxCMake/modules/MyxCMakeUnityBuild.cmake @@ -0,0 +1,8 @@ +if(${CMAKE_VERSION} VERSION_LESS "3.16.0") + include(cotire OPTIONAL) + if(COMMAND cotire) + option(MYX_CMAKE_UNITY_BUILD "Enable unity build" OFF) + endif() +else() + option(MYX_CMAKE_UNITY_BUILD "Enable unity build" OFF) +endif() diff --git a/MyxCMake/sanitizers/.cmake-format.py b/MyxCMake/sanitizers/.cmake-format.py new file mode 100644 index 0000000..4cdfbbf --- /dev/null +++ b/MyxCMake/sanitizers/.cmake-format.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python3 + +# ---------------------------------- +# Options affecting listfile parsing +# ---------------------------------- +with section("parse"): + + # Specify structure for custom cmake functions + additional_commands = { + 'add_doxygen': { 'flags' : [], + 'kwargs': { 'LATEX': 1, + 'HTML': 1, + 'COMMENT': 1}}, + 'add_breathe': { 'flags' : [], + 'kwargs': { 'COMMENT': 1}}, + 'add_common_library': { 'flags' : [], + 'kwargs': { 'OUTPUT_NAME': 1, + 'SOURCES': '*', + 'TARGET': 1}}, + 'qt5_translation': { 'flags' : [], + 'kwargs': { 'OUTPUT_DIR': 1, + 'LANGUAGES': '*', + 'SOURCES': '*', + 'BASE_NAME': 1}}, + 'pvs_studio_add_target': { 'flags' : [ 'COMPILE_COMMANDS', + 'OUTPUT', + 'HIDE_HELP'], + 'kwargs': { 'ARGS': '*', + 'CONFIG': '*', + 'DEPENDS': '*', + 'FORMAT': '*', + 'MODE': '*', + 'TARGET': 1}}, + 'write_compiler_detection_header': { 'flags' : [], + 'kwargs': { 'COMPILERS': '*', + 'FEATURES': '*', + 'FILE': '*', + 'PREFIX': '*'}}} + + # Specify variable tags. + vartags = [] + + # Specify property tags. + proptags = [] + +# ----------------------------- +# Options affecting formatting. +# ----------------------------- +with section("format"): + + # How wide to allow formatted cmake files + line_width = 100 + + # How many spaces to tab for indent + tab_size = 4 + + # If an argument group contains more than this many sub-groups (parg or kwarg + # groups) then force it to a vertical layout. + max_subgroups_hwrap = 3 + + # If a positional argument group contains more than this many arguments, then + # force it to a vertical layout. + max_pargs_hwrap = 5 + + # If a cmdline positional group consumes more than this many lines without + # nesting, then invalidate the layout (and nest) + max_rows_cmdline = 2 + + # If true, separate flow control names from their parentheses with a space + separate_ctrl_name_with_space = False + + # If true, separate function names from parentheses with a space + separate_fn_name_with_space = False + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on its own line. + dangle_parens = False + + # If the trailing parenthesis must be 'dangled' on its on line, then align it + # to this reference: `prefix`: the start of the statement, `prefix-indent`: + # the start of the statement, plus one indentation level, `child`: align to + # the column of the arguments + dangle_align = 'prefix' + + # If the statement spelling length (including space and parenthesis) is + # smaller than this amount, then force reject nested layouts. + min_prefix_chars = 4 + + # If the statement spelling length (including space and parenthesis) is larger + # than the tab width by more than this amount, then force reject un-nested + # layouts. + max_prefix_chars = 2 + + # If a candidate layout is wrapped horizontally but it exceeds this many + # lines, then reject the layout. + max_lines_hwrap = 2 + + # What style line endings to use in the output. + line_ending = 'unix' + + # Format command names consistently as 'lower' or 'upper' case + command_case = 'canonical' + + # Format keywords consistently as 'lower' or 'upper' case + keyword_case = 'upper' + + # A list of command names which should always be wrapped + always_wrap = [] + + # If true, the argument lists which are known to be sortable will be sorted + # lexicographicall + enable_sort = True + + # If true, the parsers may infer whether or not an argument list is sortable + # (without annotation). + autosort = False + + # By default, if cmake-format cannot successfully fit everything into the + # desired linewidth it will apply the last, most agressive attempt that it + # made. If this flag is True, however, cmake-format will print error, exit + # with non-zero status code, and write-out nothing + require_valid_layout = False + + # A dictionary mapping layout nodes to a list of wrap decisions. See the + # documentation for more information. + layout_passes = {} + +# ------------------------------------------------ +# Options affecting comment reflow and formatting. +# ------------------------------------------------ +with section("markup"): + + # What character to use for bulleted lists + bullet_char = '*' + + # What character to use as punctuation after numerals in an enumerated list + enum_char = '.' + + # If comment markup is enabled, don't reflow the first comment block in each + # listfile. Use this to preserve formatting of your copyright/license + # statements. + first_comment_is_literal = False + + # If comment markup is enabled, don't reflow any comment block which matches + # this (regex) pattern. Default is `None` (disabled). + literal_comment_pattern = None + + # Regular expression to match preformat fences in comments default= + # ``r'^\s*([`~]{3}[`~]*)(.*)$'`` + fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' + + # Regular expression to match rulers in comments default= + # ``r'^\s*[^\w\s]{3}.*[^\w\s]{3}$'`` + ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' + + # If a comment line matches starts with this pattern then it is explicitly a + # trailing comment for the preceeding argument. Default is '#<' + explicit_trailing_pattern = '#<' + + # If a comment line starts with at least this many consecutive hash + # characters, then don't lstrip() them off. This allows for lazy hash rulers + # where the first hash char is not separated by space + hashruler_min_length = 10 + + # If true, then insert a space between the first hash char and remaining hash + # chars in a hash ruler, and normalize its length to fill the column + canonicalize_hashrulers = True + + # enable comment markup parsing and reflow + enable_markup = False + +# ---------------------------- +# Options affecting the linter +# ---------------------------- +with section("lint"): + + # a list of lint codes to disable + disabled_codes = ['C0113'] + + # regular expression pattern describing valid function names + function_pattern = '[0-9a-z_]+' + + # regular expression pattern describing valid macro names + macro_pattern = '[0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # scope + global_var_pattern = '[0-9A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with global + # scope (but internal semantic) + internal_var_pattern = '_[0-9A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for variables with local + # scope + local_var_pattern = '[0-9a-z_]+' + + # regular expression pattern describing valid names for privatedirectory + # variables + private_var_pattern = '_[0-9a-z_]+' + + # regular expression pattern describing valid names for publicdirectory + # variables + public_var_pattern = '[0-9A-Z][0-9A-Z_]+' + + # regular expression pattern describing valid names for keywords used in + # functions or macros + keyword_pattern = '[0-9A-Z_]+' + + # In the heuristic for C0201, how many conditionals to match within a loop in + # before considering the loop a parser. + max_conditionals_custom_parser = 2 + + # Require at least this many newlines between statements + min_statement_spacing = 1 + + # Require no more than this many newlines between statements + max_statement_spacing = 2 + max_returns = 6 + max_branches = 12 + max_arguments = 5 + max_localvars = 15 + max_statements = 50 + +# ------------------------------- +# Options affecting file encoding +# ------------------------------- +with section("encode"): + + # If true, emit the unicode byte-order mark (BOM) at the start of the file + emit_byteorder_mark = False + + # Specify the encoding of the input file. Defaults to utf-8 + input_encoding = 'utf-8' + + # Specify the encoding of the output file. Defaults to utf-8. Note that cmake + # only claims to support utf-8 so be careful when using anything else + output_encoding = 'utf-8' + +# ------------------------------------- +# Miscellaneous configurations options. +# ------------------------------------- +with section("misc"): + + # A dictionary containing any per-command configuration overrides. Currently + # only `command_case` is supported. + per_command = {} + diff --git a/MyxCMake/sanitizers/FindASan.cmake b/MyxCMake/sanitizers/FindASan.cmake new file mode 100644 index 0000000..9bdd10a --- /dev/null +++ b/MyxCMake/sanitizers/FindASan.cmake @@ -0,0 +1,45 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional. + "-g -fsanitize=address -fno-omit-frame-pointer" "-g -fsanitize=address" + # Older deprecated flag for ASan + "-g -faddress-sanitizer") + +include(sanitize-helpers) + +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer" "ASan") + +find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH}) +mark_as_advanced(ASan_WRAPPER) + +function(add_sanitize_address TARGET) + # TODO: check conditions for target: + # if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY)) + # message(FATAL_ERROR "AddressSanitizer is not compatible with ThreadSanitizer or MemorySanitizer.") + # endif () + + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "AddressSanitizer" "ASan") +endfunction() diff --git a/MyxCMake/sanitizers/FindCFI.cmake b/MyxCMake/sanitizers/FindCFI.cmake new file mode 100644 index 0000000..d216cb6 --- /dev/null +++ b/MyxCMake/sanitizers/FindCFI.cmake @@ -0,0 +1,42 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +option(SANITIZE_CFI "Enable Control Flow Integrity (CFI) for sanitized targets." OFF) + +set(FLAG_CANDIDATES + # FIXME: Brief comment on why the additional flags + # In this case you need a + # linker that does optimization at + # linking time such as LLVM lld or GNU gold. + "-g -fsanitize=cfi -fvisibility=hidden -flto -fuse-ld=lld") + +# There might be some conflict with the other sanitizer +# hence it might need an if statement here. + +# add some handy functions +include(sanitize-helpers) + +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ControlFlowIntegrity" "CFI") + +function(add_sanitize_cfi TARGET) + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "ControlFlowIntegrity" "CFI") +endfunction() diff --git a/MyxCMake/sanitizers/FindLeakSan.cmake b/MyxCMake/sanitizers/FindLeakSan.cmake new file mode 100644 index 0000000..b52ca57 --- /dev/null +++ b/MyxCMake/sanitizers/FindLeakSan.cmake @@ -0,0 +1,37 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2019 Barcelona Supercomputing Center +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_LEAK "Enable LeakSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES "-g -fsanitize=leak") + +include(sanitize-helpers) + +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "LeakSanitizer" "LeakSan") + +function(add_sanitize_leak TARGET) + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "LeakSanitizer" "LeakSan") +endfunction() diff --git a/MyxCMake/sanitizers/FindMSan.cmake b/MyxCMake/sanitizers/FindMSan.cmake new file mode 100644 index 0000000..38c98a5 --- /dev/null +++ b/MyxCMake/sanitizers/FindMSan.cmake @@ -0,0 +1,49 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES "-g -fsanitize=memory") + +include(sanitize-helpers) + +if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + message(NOTICE "MemorySanitizer disabled for target ${TARGET} because " + "MemorySanitizer is supported for Linux systems only.") +elseif(NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) + message(NOTICE "MemorySanitizer disabled for target ${TARGET} because " + "MemorySanitizer is supported for 64bit systems only.") +else() + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer" "MSan") +endif() + +function(add_sanitize_memory TARGET) + # TODO: check conditions for target: + # if (SANITIZE_MEMORY AND (SANITIZE_THREAD OR SANITIZE_ADDRESS)) + # message(FATAL_ERROR "AddressSanitizer is not compatible with ThreadSanitizer or MemorySanitizer.") + # endif () + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "MemorySanitizer" "MSan") +endfunction() diff --git a/MyxCMake/sanitizers/FindSS.cmake b/MyxCMake/sanitizers/FindSS.cmake new file mode 100644 index 0000000..8b5ee84 --- /dev/null +++ b/MyxCMake/sanitizers/FindSS.cmake @@ -0,0 +1,37 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +# associated documentation files (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, publish, distribute, +# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all copies or +# substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +# OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +option(SANITIZE_SS "Enable SafeStack for sanitized targets." OFF) + +set(FLAG_CANDIDATES "-g -fsanitize=safe-stack") + +# There might be some conflict with the other sanitizer +# hence it might need an if statement here. + +# add some handy functions +include(sanitize-helpers) + +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "SafeStack" "SS") + +function(add_sanitize_ss TARGET) + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "SafeStack" "SS") +endfunction() diff --git a/MyxCMake/sanitizers/FindSanitizers.cmake b/MyxCMake/sanitizers/FindSanitizers.cmake new file mode 100644 index 0000000..53d1b27 --- /dev/null +++ b/MyxCMake/sanitizers/FindSanitizers.cmake @@ -0,0 +1,109 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# If any of the used compiler is a GNU compiler, add a second option to static +# link against the sanitizers. +option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off) + +set(FIND_QUIETLY_FLAG "") +if(DEFINED Sanitizers_FIND_QUIETLY) + set(FIND_QUIETLY_FLAG "QUIET") +endif() + +find_package(ASan ${FIND_QUIETLY_FLAG}) +find_package(TSan ${FIND_QUIETLY_FLAG}) +find_package(MSan ${FIND_QUIETLY_FLAG}) +find_package(UBSan ${FIND_QUIETLY_FLAG}) +find_package(LeakSan ${FIND_QUIETLY_FLAG}) +find_package(CFI ${FIND_QUIETLY_FLAG}) +find_package(SS ${FIND_QUIETLY_FLAG}) + +function(sanitizer_add_blacklist_file FILE) + if(NOT IS_ABSOLUTE ${FILE}) + set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}") + endif() + get_filename_component(FILE "${FILE}" REALPATH) + + sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}" "SanitizerBlacklist" "SanBlist") +endfunction() + +function(add_sanitizers ...) + # If no sanitizer is enabled, return immediately. + if(NOT + (SANITIZE_ADDRESS + OR SANITIZE_MEMORY + OR SANITIZE_THREAD + OR SANITIZE_UNDEFINED + OR SANITIZE_LEAK + OR SANITIZE_CFI + OR SANITIZE_SS)) + message(STATUS "No sanitizer selected.") + return() + endif() + + if(SANITIZE_ADDRESS AND SANITIZE_THREAD) + message( + FATAL_ERROR + "Incompatible Sanitizer combination enabled: AddressSanitizer, ThreadSanitizer") + endif() + if(SANITIZE_ADDRESS AND SANITIZE_MEMORY) + message( + FATAL_ERROR + "Incompatible Sanitizer combination enabled: AddressSanitizer, MemorySanitizer") + endif() + + if(SANITIZE_MEMORY AND SANITIZE_THREAD) + message( + FATAL_ERROR + "Incompatible Sanitizer combination enabled: MemorySanitizer, ThreadSanitizer") + endif() + + foreach(TARGET ${ARGV}) + sanitizer_check_target(${TARGET}) + + # Add sanitizers for target. + if(SANITIZE_ADDRESS) + add_sanitize_address(${TARGET}) + endif() + if(SANITIZE_THREAD) + add_sanitize_thread(${TARGET}) + endif() + if(SANITIZE_MEMORY) + add_sanitize_memory(${TARGET}) + endif() + if(SANITIZE_UNDEFINED) + add_sanitize_undefined(${TARGET}) + endif() + if(SANITIZE_LEAK) + add_sanitize_leak(${TARGET}) + endif() + if(SANITIZE_CFI) + add_sanitize_cfi(${TARGET}) + endif() + if(SANITIZE_SS) + add_sanitize_ss(${TARGET}) + endif() + endforeach() +endfunction(add_sanitizers) diff --git a/MyxCMake/sanitizers/FindTSan.cmake b/MyxCMake/sanitizers/FindTSan.cmake new file mode 100644 index 0000000..3c1c179 --- /dev/null +++ b/MyxCMake/sanitizers/FindTSan.cmake @@ -0,0 +1,53 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES "-g -fsanitize=thread") + +include(sanitize-helpers) + +if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + message(NOTICE "ThreadSanitizer disabled for target ${TARGET} because " + "ThreadSanitizer is supported for Linux systems and macOS only.") + set(SANITIZE_THREAD Off CACHE BOOL "Enable ThreadSanitizer for sanitized targets." FORCE) +elseif(NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) + message(NOTICE "ThreadSanitizer disabled for target ${TARGET} because " + "ThreadSanitizer is supported for 64bit systems only.") + set(SANITIZE_THREAD Off CACHE BOOL "Enable ThreadSanitizer for sanitized targets." FORCE) +else() + sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer" "TSan") +endif() + +function(add_sanitize_thread TARGET) + # ThreadSanitizer is not compatible with MemorySanitizer. + # + # if(SANITIZE_THREAD AND SANITIZE_MEMORY) + # message(FATAL_ERROR "ThreadSanitizer is not compatible with " "MemorySanitizer.") + # endif() + + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan") +endfunction() diff --git a/MyxCMake/sanitizers/FindUBSan.cmake b/MyxCMake/sanitizers/FindUBSan.cmake new file mode 100644 index 0000000..c248d9c --- /dev/null +++ b/MyxCMake/sanitizers/FindUBSan.cmake @@ -0,0 +1,37 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(SANITIZE_UNDEFINED "Enable UndefinedBehaviorSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES "-g -fsanitize=undefined") + +include(sanitize-helpers) + +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "UndefinedBehaviorSanitizer" "UBSan") + +function(add_sanitize_undefined TARGET) + sanitizer_check_target(${TARGET}) + sanitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan") +endfunction() diff --git a/MyxCMake/sanitizers/asan-wrapper b/MyxCMake/sanitizers/asan-wrapper new file mode 100755 index 0000000..5d54103 --- /dev/null +++ b/MyxCMake/sanitizers/asan-wrapper @@ -0,0 +1,55 @@ +#!/bin/sh + +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# This script is a wrapper for AddressSanitizer. In some special cases you need +# to preload AddressSanitizer to avoid error messages - e.g. if you're +# preloading another library to your application. At the moment this script will +# only do something, if we're running on a Linux platform. OSX might not be +# affected. + + +# Exit immediately, if platform is not Linux. +if [ "$(uname)" != "Linux" ] +then + exec $@ +fi + + +# Get the used libasan of the application ($1). If a libasan was found, it will +# be prepended to LD_PRELOAD. +libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1) +if [ -n "$libasan" ] +then + if [ -n "$LD_PRELOAD" ] + then + export LD_PRELOAD="$libasan:$LD_PRELOAD" + else + export LD_PRELOAD="$libasan" + fi +fi + +# Execute the application. +exec $@ diff --git a/MyxCMake/sanitizers/sanitize-helpers.cmake b/MyxCMake/sanitizers/sanitize-helpers.cmake new file mode 100644 index 0000000..8c91f9f --- /dev/null +++ b/MyxCMake/sanitizers/sanitize-helpers.cmake @@ -0,0 +1,199 @@ +# The MIT License (MIT) +# +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany +# 2021 Markus Eggenbauer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Helper function to get the language of a source file. +function(sanitizer_lang_of_source FILE RETURN_VAR) + get_filename_component(LONGEST_EXT "${FILE}" EXT) + # If extension is empty return. This can happen for extensionless headers + if("${LONGEST_EXT}" STREQUAL "") + set(${RETURN_VAR} "" PARENT_SCOPE) + return() + endif() + # Get shortest extension as some files can have dot in their names + string(REGEX REPLACE "^.*(\\.[^.]+)$" "\\1" FILE_EXT ${LONGEST_EXT}) + string(TOLOWER "${FILE_EXT}" FILE_EXT) + string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT) + + get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach(LANG ${ENABLED_LANGUAGES}) + list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP) + if(NOT ${TEMP} EQUAL -1) + set(${RETURN_VAR} "${LANG}" PARENT_SCOPE) + return() + endif() + endforeach() + + set(${RETURN_VAR} "" PARENT_SCOPE) +endfunction() + +# Helper function to get compilers used by a target. +function(sanitizer_target_compilers TARGET RETURN_VAR) + # Check if all sources for target use the same compiler. If a target uses + # e.g. C and Fortran mixed and uses different compilers (e.g. clang and + # gfortran) this can trigger huge problems, because different compilers may + # use different implementations for sanitizers. + set(BUFFER "") + get_target_property(TSOURCES ${TARGET} SOURCES) + foreach(FILE ${TSOURCES}) + # If expression was found, FILE is a generator-expression for an object + # library. Object libraries will be ignored. + string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE}) + if("${_file}" STREQUAL "") + sanitizer_lang_of_source(${FILE} LANG) + if(LANG) + list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID}) + endif() + endif() + endforeach() + + list(REMOVE_DUPLICATES BUFFER) + set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE) +endfunction() + +# Helper function to check compiler flags for language compiler. +function(sanitizer_check_compiler_flag FLAG LANG VARIABLE) + if(${LANG} STREQUAL "C") + include(CheckCCompilerFlag) + check_c_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif(${LANG} STREQUAL "CXX") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif(${LANG} STREQUAL "Fortran") + # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible + # with older Cmake versions, we will check if this module is present + # before we use it. Otherwise we will define Fortran coverage support as + # not available. + include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED) + if(INCLUDED) + CHECK_Fortran_COMPILER_FLAG("${FLAG}" ${VARIABLE}) + elseif(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VARIABLE}") + message(STATUS "Performing Test ${VARIABLE}" " - Failed (Check not supported)") + endif() + endif() +endfunction() + +# Helper function to test compiler flags. +function(sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX) + set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY}) + + get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach(LANG ${ENABLED_LANGUAGES}) + # Sanitizer flags are not dependend on language, but the used compiler. + # So instead of searching flags foreach language, search flags foreach + # compiler used. + set(COMPILER ${CMAKE_${LANG}_COMPILER_ID}) + if(NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS) + foreach(FLAG ${FLAG_CANDIDATES}) + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]") + endif() + + set(CMAKE_REQUIRED_FLAGS "${FLAG}") + unset(${PREFIX}_FLAG_DETECTED CACHE) + sanitizer_check_compiler_flag("${FLAG}" ${LANG} ${PREFIX}_FLAG_DETECTED) + + if(${PREFIX}_FLAG_DETECTED) + # If compiler is a GNU compiler, search for static flag, if + # SANITIZE_LINK_STATIC is enabled. + if(SANITIZE_LINK_STATIC AND (COMPILER STREQUAL "GNU")) + string(TOLOWER ${PREFIX} PREFIX_lower) + sanitizer_check_compiler_flag("-static-lib${PREFIX_lower}" ${LANG} + ${PREFIX}_STATIC_FLAG_DETECTED) + + if(${PREFIX}_STATIC_FLAG_DETECTED) + set(FLAG "-static-lib${PREFIX_lower} ${FLAG}") + endif() + endif() + + set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" + CACHE STRING "${NAME} flags for ${COMPILER} compiler.") + mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS) + break() + endif() + endforeach() + + if(NOT ${PREFIX}_FLAG_DETECTED) + set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING + "${NAME} flags for ${COMPILER} compiler.") + mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS) + + message( + NOTICE "${NAME} is not available for ${COMPILER} " + "compiler. Targets using this compiler will be " "compiled without ${NAME}.") + endif() + endif() + endforeach() +endfunction() + +# Helper to assign sanitizer flags for TARGET. +function(sanitizer_add_flags TARGET NAME PREFIX) + # Get list of compilers used by target and check, if sanitizer is available + # for this target. Other compiler checks like check for conflicting + # compilers will be done in add_sanitizers function. + sanitizer_target_compilers(${TARGET} TARGET_COMPILER) + list(LENGTH TARGET_COMPILER NUM_COMPILERS) + if("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL "") + return() + endif() + + # Set compile- and link-flags for target. + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS + " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS + " ${SanBlist_${TARGET_COMPILER}_FLAGS}") + set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS + " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}") +endfunction() + +macro(sanitizer_check_target TARGET) + # Check if this target will be compiled by exactly one compiler. Other- + # wise sanitizers can't be used and a warning should be printed once. + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if(TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + message(NOTICE "Can't use any sanitizers for target ${TARGET}, " + "because it is an interface library and cannot be " "compiled directly.") + return() + endif() + sanitizer_target_compilers(${TARGET} TARGET_COMPILER) + list(LENGTH TARGET_COMPILER NUM_COMPILERS) + if(NUM_COMPILERS GREATER 1) + message( + NOTICE "Can't use any sanitizers for target ${TARGET}, " + "because it will be compiled by incompatible compilers. " + "Target will be compiled without sanitizers.") + return() + + # If the target is compiled by no or no known compiler, give a warning. + elseif(NUM_COMPILERS EQUAL 0) + message( + NOTICE "Sanitizers for target ${TARGET} may not be" + " usable, because it uses no or an unknown compiler. " + "This is a false warning for targets using only " "object lib(s) as input.") + return() + endif() +endmacro(sanitizer_check_target) diff --git a/MyxCMake/thirdparty/PVS-Studio.cmake b/MyxCMake/thirdparty/PVS-Studio.cmake new file mode 100644 index 0000000..1a095a7 --- /dev/null +++ b/MyxCMake/thirdparty/PVS-Studio.cmake @@ -0,0 +1,564 @@ +# 2006-2008 (c) Viva64.com Team +# 2008-2018 (c) OOO "Program Verification Systems" +# +# Version 12 + +cmake_minimum_required(VERSION 2.8.12) +cmake_policy(SET CMP0054 NEW) + +if (PVS_STUDIO_AS_SCRIPT) + # This code runs at build time. + # It executes pvs-studio-analyzer and propagates its return value. + + set(in_cl_params FALSE) + set(additional_args) + + foreach (arg ${PVS_STUDIO_COMMAND}) + if (NOT in_cl_params) + if ("${arg}" STREQUAL "--cl-params") + set(in_cl_params TRUE) + endif () + else () + # A workaround for macOS frameworks (e.g. QtWidgets.framework) + # You can test this workaround on this project: https://github.com/easyaspi314/MidiEditor/tree/gba + if (APPLE AND "${arg}" MATCHES "^-I(.*)\\.framework$") + STRING(REGEX REPLACE "^-I(.*)\\.framework$" "\\1.framework" framework "${arg}") + if (IS_ABSOLUTE "${framework}") + get_filename_component(framework "${framework}" DIRECTORY) + list(APPEND additional_args "-iframework") + list(APPEND additional_args "${framework}") + endif () + endif () + endif () + endforeach () + + execute_process(COMMAND ${PVS_STUDIO_COMMAND} ${additional_args} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE error) + + if (result AND NOT output MATCHES "^No compilation units were found\\.") + message(FATAL_ERROR "PVS-Studio exited with non-zero code.\nStdout:\n${output}\nStderr:\n${error}\n") + endif() + + return() +endif () + +if(__PVS_STUDIO_INCLUDED) + return() +endif() +set(__PVS_STUDIO_INCLUDED TRUE) + +set(PVS_STUDIO_SCRIPT "${CMAKE_CURRENT_LIST_FILE}") + +function (pvs_studio_log TEXT) + if (PVS_STUDIO_DEBUG) + message("PVS-Studio: ${TEXT}") + endif () +endfunction () + +function (pvs_studio_relative_path VAR ROOT FILEPATH) + set("${VAR}" "${FILEPATH}" PARENT_SCOPE) + if ("${FILEPATH}" MATCHES "^/.*$" OR "${FILEPATH}" MATCHES "^.:/.*$") + file(RELATIVE_PATH RPATH "${ROOT}" "${FILEPATH}") + if (NOT "${RPATH}" MATCHES "^\\.\\..*$") + set("${VAR}" "${RPATH}" PARENT_SCOPE) + endif () + endif () +endfunction () + +function (pvs_studio_join_path VAR DIR1 DIR2) + if ("${DIR2}" MATCHES "^(/|~|.:/).*$" OR "${DIR1}" STREQUAL "") + set("${VAR}" "${DIR2}" PARENT_SCOPE) + else () + set("${VAR}" "${DIR1}/${DIR2}" PARENT_SCOPE) + endif () +endfunction () + +macro (pvs_studio_append_flags_from_property CXX C DIR PREFIX) + if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND") + foreach (PROP ${PROPERTY}) + pvs_studio_join_path(PROP "${DIR}" "${PROP}") + + if (APPLE AND "${PREFIX}" STREQUAL "-I" AND IS_ABSOLUTE "${PROP}" AND "${PROP}" MATCHES "\\.framework$") + get_filename_component(FRAMEWORK "${PROP}" DIRECTORY) + list(APPEND "${CXX}" "-iframework") + list(APPEND "${CXX}" "${FRAMEWORK}") + list(APPEND "${C}" "-iframework") + list(APPEND "${C}" "${FRAMEWORK}") + pvs_studio_log("framework: ${FRAMEWORK}") + elseif (NOT "${PROP}" STREQUAL "") + list(APPEND "${CXX}" "${PREFIX}${PROP}") + list(APPEND "${C}" "${PREFIX}${PROP}") + endif() + endforeach () + endif () +endmacro () + +macro (pvs_studio_append_standard_flag FLAGS STANDARD) + if ("${STANDARD}" MATCHES "^(99|11|14|17)$") + if ("${PVS_STUDIO_PREPROCESSOR}" MATCHES "gcc|clang") + list(APPEND "${FLAGS}" "-std=c++${STANDARD}") + endif () + endif () +endmacro () + +function (pvs_studio_set_directory_flags DIRECTORY CXX C) + set(CXX_FLAGS "${${CXX}}") + set(C_FLAGS "${${C}}") + + get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" INCLUDE_DIRECTORIES) + pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "${DIRECTORY}" "-I") + + get_directory_property(PROPERTY DIRECTORY "${DIRECTORY}" COMPILE_DEFINITIONS) + pvs_studio_append_flags_from_property(CXX_FLAGS C_FLAGS "" "-D") + + set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE) + set("${C}" "${C_FLAGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_set_target_flags TARGET CXX C) + set(CXX_FLAGS "${${CXX}}") + set(C_FLAGS "${${C}}") + + if (NOT MSVC) + list(APPEND CXX_FLAGS "$<$:--sysroot=${CMAKE_SYSROOT}>") + list(APPEND C_FLAGS "$<$:--sysroot=${CMAKE_SYSROOT}>") + endif () + + set(prop_incdirs "$") + list(APPEND CXX_FLAGS "$<$:-I$-I>>") + list(APPEND C_FLAGS "$<$:-I$-I>>") + + set(prop_compdefs "$") + list(APPEND CXX_FLAGS "$<$:-D$-D>>") + list(APPEND C_FLAGS "$<$:-D$-D>>") + + set(prop_compopt "$") + list(APPEND CXX_FLAGS "$<$:$>>") + list(APPEND C_FLAGS "$<$:$>>") + + set("${CXX}" "${CXX_FLAGS}" PARENT_SCOPE) + set("${C}" "${C_FLAGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_set_source_file_flags SOURCE) + set(LANGUAGE "") + + string(TOLOWER "${SOURCE}" SOURCE_LOWER) + if ("${LANGUAGE}" STREQUAL "" AND "${SOURCE_LOWER}" MATCHES "^.*\\.(c|cpp|cc|cx|cxx|cp|c\\+\\+)$") + if ("${SOURCE}" MATCHES "^.*\\.c$") + set(LANGUAGE C) + else () + set(LANGUAGE CXX) + endif () + endif () + + if ("${LANGUAGE}" STREQUAL "C") + set(CL_PARAMS ${PVS_STUDIO_C_FLAGS} ${PVS_STUDIO_TARGET_C_FLAGS} -DPVS_STUDIO) + elseif ("${LANGUAGE}" STREQUAL "CXX") + set(CL_PARAMS ${PVS_STUDIO_CXX_FLAGS} ${PVS_STUDIO_TARGET_CXX_FLAGS} -DPVS_STUDIO) + endif () + + set(PVS_STUDIO_LANGUAGE "${LANGUAGE}" PARENT_SCOPE) + set(PVS_STUDIO_CL_PARAMS "${CL_PARAMS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_analyze_file SOURCE SOURCE_DIR BINARY_DIR) + set(PLOGS ${PVS_STUDIO_PLOGS}) + pvs_studio_set_source_file_flags("${SOURCE}") + + get_filename_component(SOURCE "${SOURCE}" REALPATH) + + get_source_file_property(PROPERTY "${SOURCE}" HEADER_FILE_ONLY) + if (PROPERTY) + return() + endif () + + pvs_studio_relative_path(SOURCE_RELATIVE "${SOURCE_DIR}" "${SOURCE}") + pvs_studio_join_path(SOURCE "${SOURCE_DIR}" "${SOURCE}") + + set(LOG "${BINARY_DIR}/PVS-Studio/${SOURCE_RELATIVE}.plog") + get_filename_component(LOG "${LOG}" REALPATH) + get_filename_component(PARENT_DIR "${LOG}" DIRECTORY) + + if (EXISTS "${SOURCE}" AND NOT TARGET "${LOG}" AND NOT "${PVS_STUDIO_LANGUAGE}" STREQUAL "") + # A workaround to support implicit dependencies for ninja generators. + set(depPvsArg) + set(depCommandArg) + if (CMAKE_VERSION VERSION_GREATER 3.6 AND "${CMAKE_GENERATOR}" STREQUAL "Ninja") + pvs_studio_relative_path(relLog "${CMAKE_BINARY_DIR}" "${LOG}") + set(depPvsArg --dep-file "${LOG}.d" --dep-file-target "${relLog}") + set(depCommandArg DEPFILE "${LOG}.d") + endif () + + # https://public.kitware.com/Bug/print_bug_page.php?bug_id=14353 + # https://public.kitware.com/Bug/file/5436/expand_command.cmake + # + # It is a workaround to expand generator expressions. + set(cmdline "${PVS_STUDIO_BIN}" analyze + --output-file "${LOG}" + --source-file "${SOURCE}" + ${depPvsArg} + ${PVS_STUDIO_ARGS} + --cl-params "${PVS_STUDIO_CL_PARAMS}" "${SOURCE}") + + string(REPLACE ";" "$" cmdline "${cmdline}") + set(pvscmd "${CMAKE_COMMAND}" + -D PVS_STUDIO_AS_SCRIPT=TRUE + -D "PVS_STUDIO_COMMAND=${cmdline}" + -P "${PVS_STUDIO_SCRIPT}" + ) + + add_custom_command(OUTPUT "${LOG}" + COMMAND "${CMAKE_COMMAND}" -E make_directory "${PARENT_DIR}" + COMMAND "${CMAKE_COMMAND}" -E remove_directory "${LOG}" + COMMAND ${pvscmd} + WORKING_DIRECTORY "${BINARY_DIR}" + DEPENDS "${SOURCE}" "${PVS_STUDIO_SUPPRESS_BASE}" "${PVS_STUDIO_DEPENDS}" + IMPLICIT_DEPENDS "${PVS_STUDIO_LANGUAGE}" "${SOURCE}" + ${depCommandArg} + VERBATIM + COMMENT "Analyzing ${PVS_STUDIO_LANGUAGE} file ${SOURCE_RELATIVE}") + list(APPEND PLOGS "${LOG}") + endif () + set(PVS_STUDIO_PLOGS "${PLOGS}" PARENT_SCOPE) +endfunction () + +function (pvs_studio_analyze_target TARGET DIR) + set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}") + set(PVS_STUDIO_TARGET_CXX_FLAGS "") + set(PVS_STUDIO_TARGET_C_FLAGS "") + + get_target_property(PROPERTY "${TARGET}" SOURCES) + pvs_studio_relative_path(BINARY_DIR "${CMAKE_SOURCE_DIR}" "${DIR}") + if ("${BINARY_DIR}" MATCHES "^/.*$") + pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "PVS-Studio/__${BINARY_DIR}") + else () + pvs_studio_join_path(BINARY_DIR "${CMAKE_BINARY_DIR}" "${BINARY_DIR}") + endif () + + file(MAKE_DIRECTORY "${BINARY_DIR}") + + pvs_studio_set_directory_flags("${DIR}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS) + pvs_studio_set_target_flags("${TARGET}" PVS_STUDIO_TARGET_CXX_FLAGS PVS_STUDIO_TARGET_C_FLAGS) + + if (NOT "${PROPERTY}" STREQUAL "NOTFOUND" AND NOT "${PROPERTY}" STREQUAL "PROPERTY-NOTFOUND") + foreach (SOURCE ${PROPERTY}) + pvs_studio_join_path(SOURCE "${DIR}" "${SOURCE}") + pvs_studio_analyze_file("${SOURCE}" "${DIR}" "${BINARY_DIR}") + endforeach () + endif () + + set(PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}" PARENT_SCOPE) +endfunction () + +set(PVS_STUDIO_RECURSIVE_TARGETS) +set(PVS_STUDIO_RECURSIVE_TARGETS_NEW) + +macro(pvs_studio_get_recursive_targets TARGET) + get_target_property(libs "${TARGET}" LINK_LIBRARIES) + foreach (lib IN LISTS libs) + list(FIND PVS_STUDIO_RECURSIVE_TARGETS "${lib}" index) + if (TARGET "${lib}" AND "${index}" STREQUAL -1) + get_target_property(target_type "${lib}" TYPE) + if (NOT "${target_type}" STREQUAL "INTERFACE_LIBRARY") + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS "${lib}") + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${lib}") + pvs_studio_get_recursive_targets("${lib}") + endif () + endif () + endforeach () +endmacro() + +option(PVS_STUDIO_DISABLE OFF "Disable PVS-Studio targets") +option(PVS_STUDIO_DEBUG OFF "Add debug info") + +# pvs_studio_add_target +# Target options: +# ALL add PVS-Studio target to default build (default: off) +# TARGET target name of analysis target (default: pvs) +# ANALYZE targets... targets to analyze +# RECURSIVE analyze target's dependencies (requires CMake 3.5+) +# COMPILE_COMMANDS use compile_commands.json instead of targets (specified by the 'ANALYZE' option) to determine files for analysis +# (set CMAKE_EXPORT_COMPILE_COMMANDS, available only for Makefile and Ninja generators) +# +# Output options: +# OUTPUT prints report to stdout +# LOG path path to report (default: ${CMAKE_CURRENT_BINARY_DIR}/PVS-Studio.log) +# FORMAT format format of report +# MODE mode analyzers/levels filter (default: GA:1,2) +# HIDE_HELP do not print help message +# +# Analyzer options: +# PLATFORM name linux32/linux64 (default: linux64) +# PREPROCESSOR name preprocessor type: gcc/clang (default: auto detected) +# LICENSE path path to PVS-Studio.lic (default: ~/.config/PVS-Studio/PVS-Studio.lic) +# CONFIG path path to PVS-Studio.cfg +# CFG_TEXT text embedded PVS-Studio.cfg +# SUPPRESS_BASE path to suppress base file +# KEEP_COMBINED_PLOG do not delete combined plog file *.pvs.raw for further processing with plog-converter +# +# Misc options: +# DEPENDS targets.. additional target dependencies +# SOURCES path... list of source files to analyze +# BIN path path to pvs-studio-analyzer (Unix) or CompilerCommandsAnalyzer.exe (Windows) +# CONVERTER path path to plog-converter (Unix) or HtmlGenerator.exe (Windows) +# C_FLAGS flags... additional C_FLAGS +# CXX_FLAGS flags... additional CXX_FLAGS +# ARGS args... additional pvs-studio-analyzer/CompilerCommandsAnalyzer.exe flags +# CONVERTER_ARGS args... additional plog-converter/HtmlGenerator.exe flags +function (pvs_studio_add_target) + macro (default VAR VALUE) + if ("${${VAR}}" STREQUAL "") + set("${VAR}" "${VALUE}") + endif () + endmacro () + + set(PVS_STUDIO_SUPPORTED_PREPROCESSORS "gcc|clang|visualcpp") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(DEFAULT_PREPROCESSOR "clang") + elseif (MSVC) + set(DEFAULT_PREPROCESSOR "visualcpp") + else () + set(DEFAULT_PREPROCESSOR "gcc") + endif () + + set(OPTIONAL OUTPUT ALL RECURSIVE HIDE_HELP KEEP_COMBINED_PLOG COMPILE_COMMANDS KEEP_INTERMEDIATE_FILES) + set(SINGLE LICENSE CONFIG TARGET LOG FORMAT BIN CONVERTER PLATFORM PREPROCESSOR CFG_TEXT SUPPRESS_BASE) + set(MULTI SOURCES C_FLAGS CXX_FLAGS ARGS DEPENDS ANALYZE MODE CONVERTER_ARGS) + cmake_parse_arguments(PVS_STUDIO "${OPTIONAL}" "${SINGLE}" "${MULTI}" ${ARGN}) + + + default(PVS_STUDIO_C_FLAGS "") + default(PVS_STUDIO_CXX_FLAGS "") + default(PVS_STUDIO_TARGET "pvs") + default(PVS_STUDIO_LOG "PVS-Studio.log") + + set(PATHS) + if (WIN32) + set(ROOT "PROGRAMFILES(X86)") + set(ROOT "$ENV{${ROOT}}/PVS-Studio") + string(REPLACE \\ / ROOT "${ROOT}") + + if (EXISTS "${ROOT}") + set(PATHS "${ROOT}") + endif () + + default(PVS_STUDIO_BIN "CompilerCommandsAnalyzer.exe") + default(PVS_STUDIO_CONVERTER "HtmlGenerator.exe") + else () + default(PVS_STUDIO_BIN "pvs-studio-analyzer") + default(PVS_STUDIO_CONVERTER "plog-converter") + endif () + + find_program(PVS_STUDIO_BIN_PATH "${PVS_STUDIO_BIN}" ${PATHS}) + set(PVS_STUDIO_BIN "${PVS_STUDIO_BIN_PATH}") + + if (NOT EXISTS "${PVS_STUDIO_BIN}") + message(FATAL_ERROR "pvs-studio-analyzer is not found") + endif () + + find_program(PVS_STUDIO_CONVERTER_PATH "${PVS_STUDIO_CONVERTER}" ${PATHS}) + set(PVS_STUDIO_CONVERTER "${PVS_STUDIO_CONVERTER_PATH}") + + if (NOT EXISTS "${PVS_STUDIO_CONVERTER}") + message(FATAL_ERROR "plog-converter is not found") + endif () + + default(PVS_STUDIO_MODE "GA:1,2") + default(PVS_STUDIO_PREPROCESSOR "${DEFAULT_PREPROCESSOR}") + if (WIN32) + default(PVS_STUDIO_PLATFORM "x64") + else () + default(PVS_STUDIO_PLATFORM "linux64") + endif () + + string(REPLACE ";" "+" PVS_STUDIO_MODE "${PVS_STUDIO_MODE}") + + if ("${PVS_STUDIO_CONFIG}" STREQUAL "" AND NOT "${PVS_STUDIO_CFG_TEXT}" STREQUAL "") + set(PVS_STUDIO_CONFIG "${CMAKE_BINARY_DIR}/PVS-Studio.cfg") + + set(PVS_STUDIO_CONFIG_COMMAND "${CMAKE_COMMAND}" -E echo "${PVS_STUDIO_CFG_TEXT}" > "${PVS_STUDIO_CONFIG}") + + add_custom_command(OUTPUT "${PVS_STUDIO_CONFIG}" + COMMAND ${PVS_STUDIO_CONFIG_COMMAND} + WORKING_DIRECTORY "${BINARY_DIR}" + COMMENT "Generating PVS-Studio.cfg") + + list(APPEND PVS_STUDIO_DEPENDS "${PVS_STUDIO_CONFIG}") + endif () + if (NOT "${PVS_STUDIO_PREPROCESSOR}" MATCHES "^${PVS_STUDIO_SUPPORTED_PREPROCESSORS}$") + message(FATAL_ERROR "Preprocessor ${PVS_STUDIO_PREPROCESSOR} isn't supported. Available options: ${PVS_STUDIO_SUPPORTED_PREPROCESSORS}.") + endif () + + pvs_studio_append_standard_flag(PVS_STUDIO_CXX_FLAGS "${CMAKE_CXX_STANDARD}") + pvs_studio_set_directory_flags("${CMAKE_CURRENT_SOURCE_DIR}" PVS_STUDIO_CXX_FLAGS PVS_STUDIO_C_FLAGS) + + if (NOT "${PVS_STUDIO_LICENSE}" STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --lic-file "${PVS_STUDIO_LICENSE}") + endif () + + if (NOT ${PVS_STUDIO_CONFIG} STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --cfg "${PVS_STUDIO_CONFIG}") + endif () + + list(APPEND PVS_STUDIO_ARGS --platform "${PVS_STUDIO_PLATFORM}" + --preprocessor "${PVS_STUDIO_PREPROCESSOR}") + + if (NOT "${PVS_STUDIO_SUPPRESS_BASE}" STREQUAL "") + pvs_studio_join_path(PVS_STUDIO_SUPPRESS_BASE "${CMAKE_CURRENT_SOURCE_DIR}" "${PVS_STUDIO_SUPPRESS_BASE}") + list(APPEND PVS_STUDIO_ARGS --suppress-file "${PVS_STUDIO_SUPPRESS_BASE}") + endif () + + if (NOT "${CMAKE_CXX_COMPILER}" STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --cxx "${CMAKE_CXX_COMPILER}") + endif () + + if (NOT "${CMAKE_C_COMPILER}" STREQUAL "") + list(APPEND PVS_STUDIO_ARGS --cc "${CMAKE_C_COMPILER}") + endif () + + if (PVS_STUDIO_KEEP_INTERMEDIATE_FILES) + list(APPEND PVS_STUDIO_ARGS --dump-files) + endif() + + string(REGEX REPLACE [123,:] "" ANALYZER_MODE ${PVS_STUDIO_MODE}) + if (NOT "$ANALYZER_MODE" STREQUAL "GA") + list (APPEND PVS_STUDIO_ARGS -a "${ANALYZER_MODE}") + endif () + + set(PVS_STUDIO_PLOGS "") + + set(PVS_STUDIO_RECURSIVE_TARGETS_NEW) + if (${PVS_STUDIO_RECURSIVE}) + foreach (TARGET IN LISTS PVS_STUDIO_ANALYZE) + list(APPEND PVS_STUDIO_RECURSIVE_TARGETS_NEW "${TARGET}") + pvs_studio_get_recursive_targets("${TARGET}") + endforeach () + endif () + + set(inc_path) + + foreach (TARGET ${PVS_STUDIO_ANALYZE}) + set(DIR "${CMAKE_CURRENT_SOURCE_DIR}") + string(FIND "${TARGET}" ":" DELIM) + if ("${DELIM}" GREATER "-1") + math(EXPR DELIMI "${DELIM}+1") + string(SUBSTRING "${TARGET}" "${DELIMI}" "-1" DIR) + string(SUBSTRING "${TARGET}" "0" "${DELIM}" TARGET) + pvs_studio_join_path(DIR "${CMAKE_CURRENT_SOURCE_DIR}" "${DIR}") + else () + get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR) + if (EXISTS "${TARGET_SOURCE_DIR}") + set(DIR "${TARGET_SOURCE_DIR}") + endif () + endif () + pvs_studio_analyze_target("${TARGET}" "${DIR}") + list(APPEND PVS_STUDIO_DEPENDS "${TARGET}") + + if ("${inc_path}" STREQUAL "") + set(inc_path "$") + else () + set(inc_path "${inc_path}$$") + endif () + endforeach () + + foreach (TARGET ${PVS_STUDIO_RECURSIVE_TARGETS_NEW}) + set(DIR "${CMAKE_CURRENT_SOURCE_DIR}") + get_target_property(TARGET_SOURCE_DIR "${TARGET}" SOURCE_DIR) + if (EXISTS "${TARGET_SOURCE_DIR}") + set(DIR "${TARGET_SOURCE_DIR}") + endif () + pvs_studio_analyze_target("${TARGET}" "${DIR}") + list(APPEND PVS_STUDIO_DEPENDS "${TARGET}") + endforeach () + + set(PVS_STUDIO_TARGET_CXX_FLAGS "") + set(PVS_STUDIO_TARGET_C_FLAGS "") + foreach (SOURCE ${PVS_STUDIO_SOURCES}) + pvs_studio_analyze_file("${SOURCE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") + endforeach () + + if (PVS_STUDIO_COMPILE_COMMANDS) + set(COMPILE_COMMANDS_LOG "${PVS_STUDIO_LOG}.pvs.analyzer.raw") + if (NOT CMAKE_EXPORT_COMPILE_COMMANDS) + message(FATAL_ERROR "You should set CMAKE_EXPORT_COMPILE_COMMANDS to TRUE") + endif () + add_custom_command( + OUTPUT "${COMPILE_COMMANDS_LOG}" + COMMAND "${PVS_STUDIO_BIN}" analyze -i + --output-file "${COMPILE_COMMANDS_LOG}.always" + ${PVS_STUDIO_ARGS} + COMMENT "Analyzing with PVS-Studio" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + DEPENDS "${PVS_STUDIO_SUPPRESS_BASE}" "${PVS_STUDIO_DEPENDS}" + ) + list(APPEND PVS_STUDIO_PLOGS_LOGS "${COMPILE_COMMANDS_LOG}.always") + list(APPEND PVS_STUDIO_PLOGS_DEPENDENCIES "${COMPILE_COMMANDS_LOG}") + endif () + + pvs_studio_relative_path(LOG_RELATIVE "${CMAKE_BINARY_DIR}" "${PVS_STUDIO_LOG}") + if (PVS_STUDIO_PLOGS OR PVS_STUDIO_COMPILE_COMMANDS) + if (WIN32) + string(REPLACE / \\ PVS_STUDIO_PLOGS "${PVS_STUDIO_PLOGS}") + endif () + if (WIN32) + set(COMMANDS COMMAND type ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}" 2>nul || cd .) + else () + set(COMMANDS COMMAND cat ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_LOGS} > "${PVS_STUDIO_LOG}" 2>/dev/null || true) + endif () + set(COMMENT "Generating ${LOG_RELATIVE}") + if (NOT "${PVS_STUDIO_FORMAT}" STREQUAL "" OR PVS_STUDIO_OUTPUT) + if ("${PVS_STUDIO_FORMAT}" STREQUAL "") + set(PVS_STUDIO_FORMAT "errorfile") + endif () + list(APPEND COMMANDS + COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw" + COMMAND "${CMAKE_COMMAND}" -E rename "${PVS_STUDIO_LOG}" "${PVS_STUDIO_LOG}.pvs.raw" + COMMAND "${PVS_STUDIO_CONVERTER}" "${PVS_STUDIO_CONVERTER_ARGS}" -t "${PVS_STUDIO_FORMAT}" "${PVS_STUDIO_LOG}.pvs.raw" -o "${PVS_STUDIO_LOG}" -a "${PVS_STUDIO_MODE}" + ) + if(NOT PVS_STUDIO_KEEP_COMBINED_PLOG) + list(APPEND COMMANDS COMMAND "${CMAKE_COMMAND}" -E remove -f "${PVS_STUDIO_LOG}.pvs.raw") + endif() + endif () + else () + set(COMMANDS COMMAND "${CMAKE_COMMAND}" -E touch "${PVS_STUDIO_LOG}") + set(COMMENT "Generating ${LOG_RELATIVE}: no sources found") + endif () + + if (WIN32) + string(REPLACE / \\ PVS_STUDIO_LOG "${PVS_STUDIO_LOG}") + endif () + + add_custom_command(OUTPUT "${PVS_STUDIO_LOG}" + ${COMMANDS} + COMMENT "${COMMENT}" + DEPENDS ${PVS_STUDIO_PLOGS} ${PVS_STUDIO_PLOGS_DEPENDENCIES} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") + + if (PVS_STUDIO_ALL) + set(ALL "ALL") + else () + set(ALL "") + endif () + + if (PVS_STUDIO_OUTPUT) + if (PVS_STUDIO_HIDE_HELP AND NOT WIN32) + set(COMMANDS COMMAND grep -v " error: Help:" ${PVS_STUDIO_LOG} 1>&2 || exit 0) + elseif (WIN32) + set(COMMANDS COMMAND type "${PVS_STUDIO_LOG}" 1>&2) + else () + set(COMMANDS COMMAND cat "${PVS_STUDIO_LOG}" 1>&2) + endif() + else () + set(COMMANDS "") + endif () + + add_custom_target("${PVS_STUDIO_TARGET}" ${ALL} ${COMMANDS} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + DEPENDS ${PVS_STUDIO_DEPENDS} "${PVS_STUDIO_LOG}") + + # A workaround to add implicit dependencies of source files from include directories + set_target_properties("${PVS_STUDIO_TARGET}" PROPERTIES INCLUDE_DIRECTORIES "${inc_path}") +endfunction () diff --git a/MyxCMake/thirdparty/cotire.cmake b/MyxCMake/thirdparty/cotire.cmake new file mode 100644 index 0000000..23d5131 --- /dev/null +++ b/MyxCMake/thirdparty/cotire.cmake @@ -0,0 +1,4236 @@ +# - cotire (compile time reducer) +# +# See the cotire manual for usage hints. +# +#============================================================================= +# Copyright 2012-2018 Sascha Kratky +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +#============================================================================= + +if(__COTIRE_INCLUDED) + return() +endif() +set(__COTIRE_INCLUDED TRUE) + +# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode +# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid +if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(PUSH) +endif() +cmake_minimum_required(VERSION 2.8.12) +if (NOT CMAKE_SCRIPT_MODE_FILE) + cmake_policy(POP) +endif() + +set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") +set (COTIRE_CMAKE_MODULE_VERSION "1.8.1") + +# activate select policies +if (POLICY CMP0025) + # Compiler id for Apple Clang is now AppleClang + cmake_policy(SET CMP0025 NEW) +endif() + +if (POLICY CMP0026) + # disallow use of the LOCATION target property + cmake_policy(SET CMP0026 NEW) +endif() + +if (POLICY CMP0038) + # targets may not link directly to themselves + cmake_policy(SET CMP0038 NEW) +endif() + +if (POLICY CMP0039) + # utility targets may not have link dependencies + cmake_policy(SET CMP0039 NEW) +endif() + +if (POLICY CMP0040) + # target in the TARGET signature of add_custom_command() must exist + cmake_policy(SET CMP0040 NEW) +endif() + +if (POLICY CMP0045) + # error on non-existent target in get_target_property + cmake_policy(SET CMP0045 NEW) +endif() + +if (POLICY CMP0046) + # error on non-existent dependency in add_dependencies + cmake_policy(SET CMP0046 NEW) +endif() + +if (POLICY CMP0049) + # do not expand variables in target source entries + cmake_policy(SET CMP0049 NEW) +endif() + +if (POLICY CMP0050) + # disallow add_custom_command SOURCE signatures + cmake_policy(SET CMP0050 NEW) +endif() + +if (POLICY CMP0051) + # include TARGET_OBJECTS expressions in a target's SOURCES property + cmake_policy(SET CMP0051 NEW) +endif() + +if (POLICY CMP0053) + # simplify variable reference and escape sequence evaluation + cmake_policy(SET CMP0053 NEW) +endif() + +if (POLICY CMP0054) + # only interpret if() arguments as variables or keywords when unquoted + cmake_policy(SET CMP0054 NEW) +endif() + +if (POLICY CMP0055) + # strict checking for break() command + cmake_policy(SET CMP0055 NEW) +endif() + +include(CMakeParseArguments) +include(ProcessorCount) + +function (cotire_get_configuration_types _configsVar) + set (_configs "") + if (CMAKE_CONFIGURATION_TYPES) + list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) + endif() + if (CMAKE_BUILD_TYPE) + list (APPEND _configs "${CMAKE_BUILD_TYPE}") + endif() + if (_configs) + list (REMOVE_DUPLICATES _configs) + set (${_configsVar} ${_configs} PARENT_SCOPE) + else() + set (${_configsVar} "None" PARENT_SCOPE) + endif() +endfunction() + +function (cotire_get_source_file_extension _sourceFile _extVar) + # get_filename_component returns extension from first occurrence of . in file name + # this function computes the extension from last occurrence of . in file name + string (FIND "${_sourceFile}" "." _index REVERSE) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) + else() + set (_sourceExt "") + endif() + set (${_extVar} "${_sourceExt}" PARENT_SCOPE) +endfunction() + +macro (cotire_check_is_path_relative_to _path _isRelativeVar) + set (${_isRelativeVar} FALSE) + if (IS_ABSOLUTE "${_path}") + foreach (_dir ${ARGN}) + file (RELATIVE_PATH _relPath "${_dir}" "${_path}") + if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) + set (${_isRelativeVar} TRUE) + break() + endif() + endforeach() + endif() +endmacro() + +function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) + if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") + else() + set (_languageExtensions "") + endif() + if (CMAKE_${_language}_IGNORE_EXTENSIONS) + set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") + else() + set (_ignoreExtensions "") + endif() + if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) + set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") + else() + set (_excludeExtensions "") + endif() + if (COTIRE_DEBUG AND _languageExtensions) + message (STATUS "${_language} source file extensions: ${_languageExtensions}") + endif() + if (COTIRE_DEBUG AND _ignoreExtensions) + message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") + endif() + if (COTIRE_DEBUG AND _excludeExtensions) + message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") + endif() + if (CMAKE_VERSION VERSION_LESS "3.1.0") + set (_allSourceFiles ${ARGN}) + else() + # as of CMake 3.1 target sources may contain generator expressions + # since we cannot obtain required property information about source files added + # through generator expressions at configure time, we filter them out + string (GENEX_STRIP "${ARGN}" _allSourceFiles) + endif() + set (_filteredSourceFiles "") + set (_excludedSourceFiles "") + foreach (_sourceFile ${_allSourceFiles}) + get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) + get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) + get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) + if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) + cotire_get_source_file_extension("${_sourceFile}" _sourceExt) + if (_sourceExt) + list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) + if (_ignoreIndex LESS 0) + list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) + if (_excludeIndex GREATER -1) + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) + if (_sourceIndex GREATER -1) + # consider source file unless it is excluded explicitly + get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) + if (_sourceIsExcluded) + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (APPEND _filteredSourceFiles "${_sourceFile}") + endif() + else() + get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) + if ("${_sourceLanguage}" STREQUAL "${_language}") + # add to excluded sources, if file is not ignored and has correct language without having the correct extension + list (APPEND _excludedSourceFiles "${_sourceFile}") + endif() + endif() + endif() + endif() + endif() + endif() + endforeach() + # separate filtered source files from already cotired ones + # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire + set (_sourceFiles "") + set (_cotiredSourceFiles "") + foreach (_sourceFile ${_filteredSourceFiles}) + get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) + if (_sourceIsCotired) + list (APPEND _cotiredSourceFiles "${_sourceFile}") + else() + get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) + if (_sourceCompileFlags) + # add to excluded sources, if file has custom compile flags + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + get_source_file_property(_sourceCompileOptions "${_sourceFile}" COMPILE_OPTIONS) + if (_sourceCompileOptions) + # add to excluded sources, if file has list of custom compile options + list (APPEND _excludedSourceFiles "${_sourceFile}") + else() + list (APPEND _sourceFiles "${_sourceFile}") + endif() + endif() + endif() + endforeach() + if (COTIRE_DEBUG) + if (_sourceFiles) + message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") + endif() + if (_excludedSourceFiles) + message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") + endif() + if (_cotiredSourceFiles) + message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") + endif() + endif() + set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) + set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) + set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) + set (_filteredObjects "") + foreach (_object ${ARGN}) + get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (NOT _propertyValue) + list (APPEND _filteredObjects "${_object}") + endif() + endif() + endforeach() + set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_file_property_values _valuesVar _property) + set (_values "") + foreach (_sourceFile ${ARGN}) + get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) + if (_propertyValue) + list (APPEND _values "${_propertyValue}") + endif() + endforeach() + set (${_valuesVar} ${_values} PARENT_SCOPE) +endfunction() + +function (cotire_resolve_config_properties _configurations _propertiesVar) + set (_properties "") + foreach (_property ${ARGN}) + if ("${_property}" MATCHES "") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") + list (APPEND _properties ${_configProperty}) + endforeach() + else() + list (APPEND _properties ${_property}) + endif() + endforeach() + set (${_propertiesVar} ${_properties} PARENT_SCOPE) +endfunction() + +function (cotire_copy_set_properties _configurations _type _source _target) + cotire_resolve_config_properties("${_configurations}" _properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) + if (_isSet) + get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) + set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") + endif() + endforeach() +endfunction() + +function (cotire_get_target_usage_requirements _target _config _targetRequirementsVar) + set (_targetRequirements "") + get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) + while (_librariesToProcess) + # remove from head + list (GET _librariesToProcess 0 _library) + list (REMOVE_AT _librariesToProcess 0) + if (_library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") + set (_library "${CMAKE_MATCH_1}") + elseif (_config STREQUAL "None" AND _library MATCHES "^\\$<\\$:([A-Za-z0-9_:-]+)>$") + set (_library "${CMAKE_MATCH_1}") + endif() + if (TARGET ${_library}) + list (FIND _targetRequirements ${_library} _index) + if (_index LESS 0) + list (APPEND _targetRequirements ${_library}) + # BFS traversal of transitive libraries + get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) + if (_libraries) + list (APPEND _librariesToProcess ${_libraries}) + list (REMOVE_DUPLICATES _librariesToProcess) + endif() + endif() + endif() + endwhile() + set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) +endfunction() + +function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + set (_flagPrefix "[/-]") + else() + set (_flagPrefix "--?") + endif() + set (_optionFlag "") + set (_matchedOptions "") + set (_unmatchedOptions "") + foreach (_compileFlag ${ARGN}) + if (_compileFlag) + if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") + # option with separate argument + list (APPEND _matchedOptions "${_compileFlag}") + set (_optionFlag "") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") + # remember option + set (_optionFlag "${CMAKE_MATCH_2}") + elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") + # option with joined argument + list (APPEND _matchedOptions "${CMAKE_MATCH_3}") + set (_optionFlag "") + else() + # flush remembered option + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + set (_optionFlag "") + endif() + # add to unfiltered options + list (APPEND _unmatchedOptions "${_compileFlag}") + endif() + endif() + endforeach() + if (_optionFlag) + list (APPEND _matchedOptions "${_optionFlag}") + endif() + if (COTIRE_DEBUG AND _matchedOptions) + message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") + endif() + if (COTIRE_DEBUG AND _unmatchedOptions) + message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") + endif() + set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) + set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) +endfunction() + +function (cotire_is_target_supported _target _isSupportedVar) + if (NOT TARGET "${_target}") + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + get_target_property(_imported ${_target} IMPORTED) + if (_imported) + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + get_target_property(_targetType ${_target} TYPE) + if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + set (${_isSupportedVar} FALSE PARENT_SCOPE) + return() + endif() + set (${_isSupportedVar} TRUE PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_flags _config _language _target _flagsVar) + string (TOUPPER "${_config}" _upperConfig) + # collect options from CMake language variables + set (_compileFlags "") + if (CMAKE_${_language}_FLAGS) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") + endif() + if (CMAKE_${_language}_FLAGS_${_upperConfig}) + set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") + endif() + if (_target) + # add target compile flags + get_target_property(_targetflags ${_target} COMPILE_FLAGS) + if (_targetflags) + set (_compileFlags "${_compileFlags} ${_targetflags}") + endif() + endif() + if (UNIX) + separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") + elseif(WIN32) + separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") + else() + separate_arguments(_compileFlags) + endif() + # target compile options + if (_target) + get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) + if (_targetOptions) + list (APPEND _compileFlags ${_targetOptions}) + endif() + endif() + # interface compile options from linked library targets + if (_target) + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) + if (_targetOptions) + list (APPEND _compileFlags ${_targetOptions}) + endif() + endforeach() + endif() + # handle language standard properties + if (CMAKE_${_language}_STANDARD_DEFAULT) + # used compiler supports language standard levels + if (_target) + get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) + if (_targetLanguageStandard) + set (_type "EXTENSION") + get_property(_isSet TARGET ${_target} PROPERTY ${_language}_EXTENSIONS SET) + if (_isSet) + get_target_property(_targetUseLanguageExtensions ${_target} ${_language}_EXTENSIONS) + if (NOT _targetUseLanguageExtensions) + set (_type "STANDARD") + endif() + endif() + if (CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION) + list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_${_type}_COMPILE_OPTION}") + endif() + endif() + endif() + endif() + # handle the POSITION_INDEPENDENT_CODE target property + if (_target) + get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) + if (_targetPIC) + get_target_property(_targetType ${_target} TYPE) + if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") + elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") + endif() + endif() + endif() + # handle visibility target properties + if (_target) + get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) + if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") + endif() + get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) + if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) + list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") + endif() + endif() + # platform specific flags + if (APPLE) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) + if (NOT _architectures) + get_target_property(_architectures ${_target} OSX_ARCHITECTURES) + endif() + if (_architectures) + foreach (_arch ${_architectures}) + list (APPEND _compileFlags "-arch" "${_arch}") + endforeach() + endif() + if (CMAKE_OSX_SYSROOT) + if (CMAKE_${_language}_SYSROOT_FLAG) + list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") + else() + list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") + endif() + endif() + if (CMAKE_OSX_DEPLOYMENT_TARGET) + if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) + list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") + else() + list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + endif() + endif() + if (COTIRE_DEBUG AND _compileFlags) + message (STATUS "Target ${_target} compile flags: ${_compileFlags}") + endif() + set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) + set (_includeDirs "") + set (_systemIncludeDirs "") + # default include dirs + if (CMAKE_INCLUDE_CURRENT_DIR) + list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") + list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") + endif() + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + # parse additional include directories from target compile flags + if (CMAKE_INCLUDE_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_dirs "") + cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) + if (_dirs) + list (APPEND _includeDirs ${_dirs}) + endif() + endif() + endif() + # parse additional system include directories from target compile flags + if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_dirs "") + cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) + if (_dirs) + list (APPEND _systemIncludeDirs ${_dirs}) + endif() + endif() + endif() + # target include directories + get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) + if (_target) + get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _systemIncludeDirs ${_targetDirs}) + endif() + endif() + # interface include directories from linked library targets + if (_target) + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_linkedTargetType ${_linkedTarget} TYPE) + if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND + _linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + # CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR + # at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR + # which are only available with CMake 3.4 or later. + get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + endif() + get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _dirs ${_targetDirs}) + endif() + get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if (_targetDirs) + list (APPEND _systemIncludeDirs ${_targetDirs}) + endif() + endforeach() + endif() + if (dirs) + list (REMOVE_DUPLICATES _dirs) + endif() + list (LENGTH _includeDirs _projectInsertIndex) + foreach (_dir ${_dirs}) + if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) + cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") + if (_isRelative) + list (LENGTH _includeDirs _len) + if (_len EQUAL _projectInsertIndex) + list (APPEND _includeDirs "${_dir}") + else() + list (INSERT _includeDirs _projectInsertIndex "${_dir}") + endif() + math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") + else() + list (APPEND _includeDirs "${_dir}") + endif() + else() + list (APPEND _includeDirs "${_dir}") + endif() + endforeach() + list (REMOVE_DUPLICATES _includeDirs) + list (REMOVE_DUPLICATES _systemIncludeDirs) + list (REMOVE_ITEM _systemIncludeDirs "/usr/include") + if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) + list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) + endif() + if (WIN32 AND NOT MINGW) + # convert Windows paths in include directories to CMake paths + if (_includeDirs) + set (_paths "") + foreach (_dir ${_includeDirs}) + file (TO_CMAKE_PATH "${_dir}" _path) + list (APPEND _paths "${_path}") + endforeach() + set (_includeDirs ${_paths}) + endif() + if (_systemIncludeDirs) + set (_paths "") + foreach (_dir ${_systemIncludeDirs}) + file (TO_CMAKE_PATH "${_dir}" _path) + list (APPEND _paths "${_path}") + endforeach() + set (_systemIncludeDirs ${_paths}) + endif() + endif() + if (COTIRE_DEBUG AND _includeDirs) + message (STATUS "Target ${_target} include dirs: ${_includeDirs}") + endif() + set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) + if (COTIRE_DEBUG AND _systemIncludeDirs) + message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") + endif() + set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_export_symbol _target _exportSymbolVar) + set (_exportSymbol "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_enableExports ${_target} ENABLE_EXPORTS) + if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR + (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) + get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) + if (NOT _exportSymbol) + set (_exportSymbol "${_target}_EXPORTS") + endif() + string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) + endif() + set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) + string (TOUPPER "${_config}" _upperConfig) + set (_configDefinitions "") + # CMAKE_INTDIR for multi-configuration build systems + if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") + list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") + endif() + # target export define symbol + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + list (APPEND _configDefinitions "${_defineSymbol}") + endif() + # directory compile definitions + get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # target compile definitions + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + # interface compile definitions from linked library targets + set (_linkedTargets "") + cotire_get_target_usage_requirements(${_target} ${_config} _linkedTargets) + foreach (_linkedTarget ${_linkedTargets}) + get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + endforeach() + # parse additional compile definitions from target compile flags + # and do not look at directory compile definitions, which we already handled + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) + if (_definitions) + list (APPEND _configDefinitions ${_definitions}) + endif() + list (REMOVE_DUPLICATES _configDefinitions) + if (COTIRE_DEBUG AND _configDefinitions) + message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") + endif() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) + # parse target compile flags omitting compile definitions and include directives + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + set (_flagFilter "D") + if (CMAKE_INCLUDE_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_flagFilter "${_flagFilter}|${_includeFlag}") + endif() + endif() + if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) + string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) + string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") + if (_includeFlag) + set (_flagFilter "${_flagFilter}|${_includeFlag}") + endif() + endif() + set (_compilerFlags "") + cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) + if (COTIRE_DEBUG AND _compilerFlags) + message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") + endif() + set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) +endfunction() + +function (cotire_add_sys_root_paths _pathsVar) + if (APPLE) + if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) + foreach (_path IN LISTS ${_pathsVar}) + if (IS_ABSOLUTE "${_path}") + get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) + if (EXISTS "${_path}") + list (APPEND ${_pathsVar} "${_path}") + endif() + endif() + endforeach() + endif() + endif() + set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) + set (_extraProperties ${ARGN}) + set (_result "") + if (_extraProperties) + list (FIND _extraProperties "${_sourceFile}" _index) + if (_index GREATER -1) + math (EXPR _index "${_index} + 1") + list (LENGTH _extraProperties _len) + math (EXPR _len "${_len} - 1") + foreach (_index RANGE ${_index} ${_len}) + list (GET _extraProperties ${_index} _value) + if (_value MATCHES "${_pattern}") + list (APPEND _result "${_value}") + else() + break() + endif() + endforeach() + endif() + endif() + set (${_resultVar} ${_result} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) + set (_compileDefinitions "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + string (TOUPPER "${_config}" _upperConfig) + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) + if (_definitions) + list (APPEND _compileDefinitions ${_definitions}) + endif() + if (COTIRE_DEBUG AND _compileDefinitions) + message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") + endif() + set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) + set (_configDefinitions "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) + if (_sourceDefinitions) + list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") + endif() + endforeach() + set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) + set (_sourceUndefs "") + if (NOT CMAKE_SCRIPT_MODE_FILE) + get_source_file_property(_undefs "${_sourceFile}" ${_property}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + endif() + cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) + if (_undefs) + list (APPEND _sourceUndefs ${_undefs}) + endif() + if (COTIRE_DEBUG AND _sourceUndefs) + message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") + endif() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +function (cotire_get_source_files_undefs _property _sourceUndefsVar) + set (_sourceUndefs "") + foreach (_sourceFile ${ARGN}) + cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) + if (_undefs) + list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") + endif() + endforeach() + set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) +endfunction() + +macro (cotire_set_cmd_to_prologue _cmdVar) + set (${_cmdVar} "${CMAKE_COMMAND}") + if (COTIRE_DEBUG) + list (APPEND ${_cmdVar} "--warn-uninitialized") + endif() + list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") + if (XCODE) + list (APPEND ${_cmdVar} "-DXCODE:BOOL=TRUE") + endif() + if (COTIRE_VERBOSE) + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") + elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") + list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") + endif() +endmacro() + +function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1) + if (NOT _compilerLauncher) + set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER}) + endif() + if (NOT _compilerExe) + set (_compilerExe "${CMAKE_${_language}_COMPILER}") + endif() + if (NOT _compilerArg1) + set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) + endif() + if (WIN32) + file (TO_NATIVE_PATH "${_compilerExe}" _compilerExe) + endif() + string (STRIP "${_compilerArg1}" _compilerArg1) + if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # compiler launcher is only supported for Makefile and Ninja + set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) + else() + set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_add_definitions_to_cmd _cmdVar _language) + foreach (_definition ${ARGN}) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + list (APPEND ${_cmdVar} "/D${_definition}") + else() + list (APPEND ${_cmdVar} "-D${_definition}") + endif() + endforeach() +endmacro() + +function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) + set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) + if (_includeDirs) + list (REMOVE_DUPLICATES _includeDirs) + foreach (_include ${_includeDirs}) + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + file (TO_NATIVE_PATH "${_include}" _include) + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") + else() + set (_index -1) + if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") + list (FIND ${_systemIncludesVar} "${_include}" _index) + endif() + if (_index GREATER -1) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + string(REPLACE " " "" _flag ${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}) + list (APPEND ${_cmdVar} "${_flag}") + list (APPEND ${_cmdVar} "${_include}") + else() + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") + endif() + else() + list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_SEP_${_language}}${_include}") + endif() + endif() + endforeach() + endif() + set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) +endfunction() + +function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) + if (APPLE) + set (_frameworkDirs "") + foreach (_include ${${_includesVar}}) + if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") + get_filename_component(_frameworkDir "${_include}" DIRECTORY) + list (APPEND _frameworkDirs "${_frameworkDir}") + endif() + endforeach() + set (_systemFrameworkDirs "") + foreach (_include ${${_systemIncludesVar}}) + if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") + get_filename_component(_frameworkDir "${_include}" DIRECTORY) + list (APPEND _systemFrameworkDirs "${_frameworkDir}") + endif() + endforeach() + if (_systemFrameworkDirs) + list (APPEND _frameworkDirs ${_systemFrameworkDirs}) + endif() + if (_frameworkDirs) + list (REMOVE_DUPLICATES _frameworkDirs) + foreach (_frameworkDir ${_frameworkDirs}) + set (_index -1) + if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") + list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) + endif() + if (_index GREATER -1) + list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") + else() + list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") + endif() + endforeach() + endif() + endif() + set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) +endfunction() + +macro (cotire_add_compile_flags_to_cmd _cmdVar) + foreach (_flag ${ARGN}) + list (APPEND ${_cmdVar} "${_flag}") + endforeach() +endmacro() + +function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) + if (EXISTS "${_file}") + set (_triggerFile "") + foreach (_dependencyFile ${ARGN}) + if (EXISTS "${_dependencyFile}") + # IS_NEWER_THAN returns TRUE if both files have the same timestamp + # thus we do the comparison in both directions to exclude ties + if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND + NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") + set (_triggerFile "${_dependencyFile}") + break() + endif() + endif() + endforeach() + if (_triggerFile) + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") + endif() + set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) + else() + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} is up-to-date.") + endif() + set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) + endif() + else() + if (COTIRE_VERBOSE) + get_filename_component(_fileName "${_file}" NAME) + message (STATUS "${_fileName} does not exist yet.") + endif() + set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) + set (${_relPathVar} "") + foreach (_includeDir ${_includeDirs}) + if (IS_DIRECTORY "${_includeDir}") + file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") + if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") + string (LENGTH "${${_relPathVar}}" _closestLen) + string (LENGTH "${_relPath}" _relLen) + if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) + set (${_relPathVar} "${_relPath}") + endif() + endif() + elseif ("${_includeDir}" STREQUAL "${_headerFile}") + # if path matches exactly, return short non-empty string + set (${_relPathVar} "1") + break() + endif() + endforeach() +endmacro() + +macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) + # check header path against ignored and honored include directories + cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) + if (_insideRelPath) + # header is inside, but could be become outside if there is a shorter outside match + cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) + if (_outsideRelPath) + string (LENGTH "${_insideRelPath}" _insideRelPathLen) + string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) + if (_outsideRelPathLen LESS _insideRelPathLen) + set (${_headerIsInside} FALSE) + else() + set (${_headerIsInside} TRUE) + endif() + else() + set (${_headerIsInside} TRUE) + endif() + else() + # header is outside + set (${_headerIsInside} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) + if (NOT EXISTS "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif (IS_DIRECTORY "${_headerFile}") + set (${_headerIsIgnoredVar} TRUE) + elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed") + # heuristic: ignore headers with embedded parent directory references or "-fixed" or "_fixed" in path + # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation + # with the error message "error: no include path in which to search for header" + set (${_headerIsIgnoredVar} TRUE) + else() + set (${_headerIsIgnoredVar} FALSE) + endif() +endmacro() + +macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) + # check header file extension + cotire_get_source_file_extension("${_headerFile}" _headerFileExt) + set (${_headerIsIgnoredVar} FALSE) + if (_headerFileExt) + list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) + if (_index GREATER -1) + set (${_headerIsIgnoredVar} TRUE) + endif() + endif() +endmacro() + +macro (cotire_parse_line _line _headerFileVar _headerDepthVar) + if (MSVC) + # cl.exe /showIncludes produces different output, depending on the language pack used, e.g.: + # English: "Note: including file: C:\directory\file" + # German: "Hinweis: Einlesen der Datei: C:\directory\file" + # We use a very general regular expression, relying on the presence of the : characters + if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + else() + if (_line MATCHES "^(\\.+) (.*)$") + # GCC like output + string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) + if (IS_ABSOLUTE "${CMAKE_MATCH_2}") + set (${_headerFileVar} "${CMAKE_MATCH_2}") + else() + get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) + endif() + else() + set (${_headerFileVar} "") + set (${_headerDepthVar} 0) + endif() + endif() +endmacro() + +function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) + if (WIN32) + # prevent CMake macro invocation errors due to backslash characters in Windows paths + string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") + endif() + # canonize slashes + string (REPLACE "//" "/" _scanOutput "${_scanOutput}") + # prevent semicolon from being interpreted as a line separator + string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") + # then separate lines + string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") + if ("${_language}" STREQUAL "CXX") + # Fix clang9's libc++ errno + message (STATUS "replacing with ") + string (REGEX REPLACE "include_next" "include" _scanOutput "${_scanOutput}") + endif() + list (LENGTH _scanOutput _len) + # remove duplicate lines to speed up parsing + list (REMOVE_DUPLICATES _scanOutput) + list (LENGTH _scanOutput _uniqueLen) + if (COTIRE_VERBOSE OR COTIRE_DEBUG) + message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") + if (_ignoredExtensions) + message (STATUS "Ignored extensions: ${_ignoredExtensions}") + endif() + if (_ignoredIncludeDirs) + message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") + endif() + if (_honoredIncludeDirs) + message (STATUS "Included paths: ${_honoredIncludeDirs}") + endif() + endif() + set (_sourceFiles ${ARGN}) + set (_selectedIncludes "") + set (_unparsedLines "") + # stack keeps track of inside/outside project status of processed header files + set (_headerIsInsideStack "") + foreach (_line IN LISTS _scanOutput) + if (_line) + cotire_parse_line("${_line}" _headerFile _headerDepth) + if (_headerFile) + cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) + if (COTIRE_DEBUG) + message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") + endif() + # update stack + list (LENGTH _headerIsInsideStack _stackLen) + if (_headerDepth GREATER _stackLen) + math (EXPR _stackLen "${_stackLen} + 1") + foreach (_index RANGE ${_stackLen} ${_headerDepth}) + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endforeach() + else() + foreach (_index RANGE ${_headerDepth} ${_stackLen}) + list (REMOVE_AT _headerIsInsideStack -1) + endforeach() + list (APPEND _headerIsInsideStack ${_headerIsInside}) + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerIsInsideStack}") + endif() + # header is a candidate if it is outside project + if (NOT _headerIsInside) + # get parent header file's inside/outside status + if (_headerDepth GREATER 1) + math (EXPR _index "${_headerDepth} - 2") + list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) + else() + set (_parentHeaderIsInside TRUE) + endif() + # select header file if parent header file is inside project + # (e.g., a project header file that includes a standard header file) + if (_parentHeaderIsInside) + cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) + if (NOT _headerIsIgnored) + cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) + if (NOT _headerIsIgnored) + list (APPEND _selectedIncludes "${_headerFile}") + else() + # fix header's inside status on stack, it is ignored by extension now + list (REMOVE_AT _headerIsInsideStack -1) + list (APPEND _headerIsInsideStack TRUE) + endif() + endif() + if (COTIRE_DEBUG) + message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") + endif() + endif() + endif() + else() + if (MSVC) + # for cl.exe do not keep unparsed lines which solely consist of a source file name + string (FIND "${_sourceFiles}" "${_line}" _index) + if (_index LESS 0) + list (APPEND _unparsedLines "${_line}") + endif() + else() + list (APPEND _unparsedLines "${_line}") + endif() + endif() + endif() + endforeach() + list (REMOVE_DUPLICATES _selectedIncludes) + set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) + set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) +endfunction() + +function (cotire_scan_includes _includesVar) + set(_options "") + set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES SCAN_RESULT) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES + IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) + # only consider existing source files for scanning + set (_existingSourceFiles "") + foreach (_sourceFile ${_sourceFiles}) + if (EXISTS "${_sourceFile}") + list (APPEND _existingSourceFiles "${_sourceFile}") + endif() + endforeach() + if (NOT _existingSourceFiles) + set (${_includesVar} "" PARENT_SCOPE) + return() + endif() + # add source files to be scanned + if (WIN32) + foreach (_sourceFile ${_existingSourceFiles}) + file (TO_NATIVE_PATH "${_sourceFile}" _sourceFileNative) + list (APPEND _cmd "${_sourceFileNative}") + endforeach() + else() + list (APPEND _cmd ${_existingSourceFiles}) + endif() + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + endif() + execute_process( + COMMAND ${_cmd} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE _result + OUTPUT_QUIET + ERROR_VARIABLE _output) + if (_result) + message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") + endif() + cotire_parse_includes( + "${_option_LANGUAGE}" "${_output}" + "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" + "${_option_IGNORE_EXTENSIONS}" + _includes _unparsedLines + ${_sourceFiles}) + if (_option_INCLUDE_PRIORITY_PATH) + set (_sortedIncludes "") + foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) + foreach (_include ${_includes}) + string (FIND ${_include} ${_priorityPath} _position) + if (_position GREATER -1) + list (APPEND _sortedIncludes ${_include}) + endif() + endforeach() + endforeach() + if (_sortedIncludes) + list (INSERT _includes 0 ${_sortedIncludes}) + list (REMOVE_DUPLICATES _includes) + endif() + endif() + set (${_includesVar} ${_includes} PARENT_SCOPE) + if (_option_UNPARSED_LINES) + set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) + endif() + if (_option_SCAN_RESULT) + set (${_option_SCAN_RESULT} ${_result} PARENT_SCOPE) + endif() +endfunction() + +macro (cotire_append_undefs _contentsVar) + set (_undefs ${ARGN}) + if (_undefs) + list (REMOVE_DUPLICATES _undefs) + foreach (_definition ${_undefs}) + list (APPEND ${_contentsVar} "#undef ${_definition}") + endforeach() + endif() +endmacro() + +macro (cotire_comment_str _language _commentText _commentVar) + if ("${_language}" STREQUAL "CMAKE") + set (${_commentVar} "# ${_commentText}") + else() + set (${_commentVar} "/* ${_commentText} */") + endif() +endmacro() + +function (cotire_write_file _language _file _contents _force) + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) + cotire_comment_str("${_language}" "${_file}" _header2) + set (_contents "${_header1}\n${_header2}\n${_contents}") + if (COTIRE_DEBUG) + message (STATUS "${_contents}") + endif() + if (_force OR NOT EXISTS "${_file}") + file (WRITE "${_file}" "${_contents}") + else() + file (READ "${_file}" _oldContents) + if (NOT "${_oldContents}" STREQUAL "${_contents}") + file (WRITE "${_file}" "${_contents}") + else() + if (COTIRE_DEBUG) + message (STATUS "${_file} unchanged") + endif() + endif() + endif() +endfunction() + +function (cotire_generate_unity_source _unityFile) + set(_options "") + set(_oneValueArgs LANGUAGE) + set(_multiValueArgs + DEPENDS SOURCES_COMPILE_DEFINITIONS + PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (_option_DEPENDS) + cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) + if (_unityFileIsUpToDate) + return() + endif() + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + if (NOT _option_PRE_UNDEFS) + set (_option_PRE_UNDEFS "") + endif() + if (NOT _option_SOURCES_PRE_UNDEFS) + set (_option_SOURCES_PRE_UNDEFS "") + endif() + if (NOT _option_POST_UNDEFS) + set (_option_POST_UNDEFS "") + endif() + if (NOT _option_SOURCES_POST_UNDEFS) + set (_option_SOURCES_POST_UNDEFS "") + endif() + set (_contents "") + if (_option_PROLOGUE) + list (APPEND _contents ${_option_PROLOGUE}) + endif() + if (_option_LANGUAGE AND _sourceFiles) + if ("${_option_LANGUAGE}" STREQUAL "CXX") + list (APPEND _contents "#ifdef __cplusplus") + elseif ("${_option_LANGUAGE}" STREQUAL "C") + list (APPEND _contents "#ifndef __cplusplus") + endif() + endif() + set (_compileUndefinitions "") + foreach (_sourceFile ${_sourceFiles}) + cotire_get_source_compile_definitions( + "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions + ${_option_SOURCES_COMPILE_DEFINITIONS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) + cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) + if (_option_PRE_UNDEFS) + list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) + endif() + if (_sourcePreUndefs) + list (APPEND _compileUndefinitions ${_sourcePreUndefs}) + endif() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_sourcePostUndefs) + list (APPEND _compileUndefinitions ${_sourcePostUndefs}) + endif() + if (_option_POST_UNDEFS) + list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) + endif() + foreach (_definition ${_compileDefinitions}) + if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") + list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") + list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") + else() + list (APPEND _contents "#define ${_definition}") + list (INSERT _compileUndefinitions 0 "${_definition}") + endif() + endforeach() + # use absolute path as source file location + get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) + if (WIN32) + file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) + endif() + list (APPEND _contents "#include \"${_sourceFileLocation}\"") + endforeach() + if (_compileUndefinitions) + cotire_append_undefs(_contents ${_compileUndefinitions}) + set (_compileUndefinitions "") + endif() + if (_option_LANGUAGE AND _sourceFiles) + list (APPEND _contents "#endif") + endif() + if (_option_EPILOGUE) + list (APPEND _contents ${_option_EPILOGUE}) + endif() + list (APPEND _contents "") + string (REPLACE ";" "\n" _contents "${_contents}") + if (COTIRE_VERBOSE) + message ("${_contents}") + endif() + cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) +endfunction() + +function (cotire_generate_prefix_header _prefixFile) + set(_options "") + set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION) + set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS + INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH + IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + if (_option_DEPENDS) + cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) + if (_prefixFileIsUpToDate) + # create empty log file + set (_unparsedLinesFile "${_prefixFile}.log") + file (WRITE "${_unparsedLinesFile}" "") + return() + endif() + endif() + set (_prologue "") + set (_epilogue "") + if (_option_COMPILER_ID MATCHES "Clang") + set (_prologue "#pragma clang system_header") + elseif (_option_COMPILER_ID MATCHES "GNU") + set (_prologue "#pragma GCC system_header") + elseif (_option_COMPILER_ID MATCHES "MSVC") + set (_prologue "#pragma warning(push, 0)") + set (_epilogue "#pragma warning(pop)") + elseif (_option_COMPILER_ID MATCHES "Intel") + # Intel compiler requires hdrstop pragma to stop generating PCH file + set (_epilogue "#pragma hdrstop") + endif() + set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) + cotire_scan_includes(_selectedHeaders ${_sourceFiles} + LANGUAGE "${_option_LANGUAGE}" + COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" + COMPILER_ARG1 "${_option_COMPILER_ARG1}" + COMPILER_ID "${_option_COMPILER_ID}" + COMPILER_VERSION "${_option_COMPILER_VERSION}" + COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} + COMPILE_FLAGS ${_option_COMPILE_FLAGS} + INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} + SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} + IGNORE_PATH ${_option_IGNORE_PATH} + INCLUDE_PATH ${_option_INCLUDE_PATH} + IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} + INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} + UNPARSED_LINES _unparsedLines + SCAN_RESULT _scanResult) + cotire_generate_unity_source("${_prefixFile}" + PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) + set (_unparsedLinesFile "${_prefixFile}.log") + if (_unparsedLines) + if (COTIRE_VERBOSE OR _scanResult OR NOT _selectedHeaders) + list (LENGTH _unparsedLines _skippedLineCount) + if (WIN32) + file (TO_NATIVE_PATH "${_unparsedLinesFile}" _unparsedLinesLogPath) + else() + set (_unparsedLinesLogPath "${_unparsedLinesFile}") + endif() + message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesLogPath}") + endif() + string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") + endif() + file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}\n") +endfunction() + +function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + # cl.exe options used + # /nologo suppresses display of sign-on banner + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /EP preprocess to stdout without #line directives + # /showIncludes list include files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP /showIncludes") + endif() + elseif (_compilerID MATCHES "GNU") + # GCC options used + # -H print the name of each header file used + # -E invoke preprocessor + # -fdirectives-only do not expand macros, requires GCC >= 4.3 + if (_flags) + # append to list + list (APPEND _flags -H -E) + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + list (APPEND _flags -fdirectives-only) + endif() + else() + # return as a flag string + set (_flags "-H -E") + if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") + set (_flags "${_flags} -fdirectives-only") + endif() + endif() + elseif (_compilerID MATCHES "Clang") + if (UNIX) + # Clang options used + # -H print the name of each header file used + # -E invoke preprocessor + # -fno-color-diagnostics do not print diagnostics in color + # -Eonly just run preprocessor, no output + if (_flags) + # append to list + list (APPEND _flags -H -E -fno-color-diagnostics -Xclang -Eonly) + else() + # return as a flag string + set (_flags "-H -E -fno-color-diagnostics -Xclang -Eonly") + endif() + elseif (WIN32) + # Clang-cl.exe options used + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /EP preprocess to stdout without #line directives + # -H print the name of each header file used + # -fno-color-diagnostics do not print diagnostics in color + # -Eonly just run preprocessor, no output + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags "${_sourceFileType${_language}}" /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP -fno-color-diagnostics -Xclang -H -Xclang -Eonly") + endif() + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + # Windows Intel options used + # /nologo do not display compiler version information + # /QH display the include file order + # /EP preprocess to stdout, omitting #line directives + # /TC process all source or unrecognized file types as C source files + # /TP process all source or unrecognized file types as C++ source files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) + else() + # return as a flag string + set (_flags "${_sourceFileType${_language}} /EP /QH") + endif() + else() + # Linux / Mac OS X Intel options used + # -H print the name of each header file used + # -EP preprocess to stdout, omitting #line directives + # -Kc++ process all source or unrecognized file types as C++ source files + if (_flags) + # append to list + if ("${_language}" STREQUAL "CXX") + list (APPEND _flags -Kc++) + endif() + list (APPEND _flags -H -EP) + else() + # return as a flag string + if ("${_language}" STREQUAL "CXX") + set (_flags "-Kc++ ") + endif() + set (_flags "${_flags}-H -EP") + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # cl.exe options used + # /Yc creates a precompiled header file + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + # /Zs syntax check only + # /Zm precompiled header memory allocation scaling factor + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" + "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + else() + # return as a flag string + set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + endif() + elseif (_compilerID MATCHES "GNU") + # GCC options used + # -x specify the source language + # -c compile but do not link + # -o place output in file + # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may + # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + if (_flags) + # append to list + list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") + else() + # return as a flag string + set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") + endif() + elseif (_compilerID MATCHES "Clang") + if (UNIX) + # Clang options used + # -x specify the source language + # -c compile but do not link + # -o place output in file + # -fno-pch-timestamp disable inclusion of timestamp in precompiled headers (clang 4.0.0+) + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + if (_flags) + # append to list + list (APPEND _flags -x "${_xLanguage_${_language}}" -c "${_prefixFile}" -o "${_pchFile}") + if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") + list (APPEND _flags -Xclang -fno-pch-timestamp) + endif() + else() + # return as a flag string + set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "4.0.0") + set (_flags "${_flags} -Xclang -fno-pch-timestamp") + endif() + endif() + elseif (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # Clang-cl.exe options used + # /Yc creates a precompiled header file + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /Zs syntax check only + # /TC treat all files named on the command line as C source files + # /TP treat all files named on the command line as C++ source files + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags "${_sourceFileType${_language}}" + "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + else() + # return as a flag string + set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + endif() + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) + # Windows Intel options used + # /nologo do not display compiler version information + # /Yc create a precompiled header (PCH) file + # /Fp specify a path or file name for precompiled header files + # /FI tells the preprocessor to include a specified file name as the header file + # /TC process all source or unrecognized file types as C source files + # /TP process all source or unrecognized file types as C++ source files + # /Zs syntax check only + # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + set (_sourceFileTypeC "/TC") + set (_sourceFileTypeCXX "/TP") + if (_flags) + # append to list + list (APPEND _flags /nologo "${_sourceFileType${_language}}" + "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "/Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} /Wpch-messages") + endif() + endif() + else() + # Linux / Mac OS X Intel options used + # -pch-dir location for precompiled header files + # -pch-create name of the precompiled header (PCH) to create + # -Kc++ process all source or unrecognized file types as C++ source files + # -fsyntax-only check only for correct syntax + # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + get_filename_component(_pchDir "${_pchFile}" DIRECTORY) + get_filename_component(_pchName "${_pchFile}" NAME) + set (_xLanguage_C "c-header") + set (_xLanguage_CXX "c++-header") + set (_pchSuppressMessages FALSE) + if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") + set(_pchSuppressMessages TRUE) + endif() + if (_flags) + # append to list + if ("${_language}" STREQUAL "CXX") + list (APPEND _flags -Kc++) + endif() + list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-create "${_pchName}" -fsyntax-only "${_hostFile}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + if (NOT _pchSuppressMessages) + list (APPEND _flags -Wpch-messages) + endif() + endif() + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + if (NOT _pchSuppressMessages) + set (_flags "${_flags} -Wpch-messages") + endif() + endif() + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) + set (_flags ${${_flagsVar}}) + if (_compilerID MATCHES "MSVC") + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + # cl.exe options used + # /Yu uses a precompiled header file during build + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + # /Zm precompiled header memory allocation scaling factor + if (_pchFile) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + if (_flags) + # append to list + list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + else() + # return as a flag string + set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/FI\"${_prefixFileNative}\"") + endif() + endif() + elseif (_compilerID MATCHES "GNU") + # GCC options used + # -include process include file as the first line of the primary source file + # -Winvalid-pch warns if precompiled header is found but cannot be used + # note: ccache requires the -include flag to be used in order to process precompiled header correctly + if (_flags) + # append to list + list (APPEND _flags -Winvalid-pch -include "${_prefixFile}") + else() + # return as a flag string + set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") + endif() + elseif (_compilerID MATCHES "Clang") + if (UNIX) + # Clang options used + # -include process include file as the first line of the primary source file + # note: ccache requires the -include flag to be used in order to process precompiled header correctly + if (_flags) + # append to list + list (APPEND _flags -include "${_prefixFile}") + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\"") + endif() + elseif (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + # Clang-cl.exe options used + # /Yu uses a precompiled header file during build + # /Fp specifies precompiled header binary file name + # /FI forces inclusion of file + if (_pchFile) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + if (_flags) + # append to list + list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/FI\"${_prefixFileNative}\"") + endif() + endif() + endif() + elseif (_compilerID MATCHES "Intel") + if (WIN32) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) + # Windows Intel options used + # /Yu use a precompiled header (PCH) file + # /Fp specify a path or file name for precompiled header files + # /FI tells the preprocessor to include a specified file name as the header file + # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + if (_pchFile) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) + if (_flags) + # append to list + list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + list (APPEND _flags "/Wpch-messages") + endif() + else() + # return as a flag string + set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + set (_flags "${_flags} /Wpch-messages") + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags "/FI${_prefixFileNative}") + else() + # return as a flag string + set (_flags "/FI\"${_prefixFileNative}\"") + endif() + endif() + else() + # Linux / Mac OS X Intel options used + # -pch-dir location for precompiled header files + # -pch-use name of the precompiled header (PCH) to use + # -include process include file as the first line of the primary source file + # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) + if (_pchFile) + get_filename_component(_pchDir "${_pchFile}" DIRECTORY) + get_filename_component(_pchName "${_pchFile}" NAME) + set (_pchSuppressMessages FALSE) + if ("${CMAKE_${_language}_FLAGS}" MATCHES ".*-Wno-pch-messages.*") + set(_pchSuppressMessages TRUE) + endif() + if (_flags) + # append to list + list (APPEND _flags -include "${_prefixFile}" -pch-dir "${_pchDir}" -pch-use "${_pchName}") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + if (NOT _pchSuppressMessages) + list (APPEND _flags -Wpch-messages) + endif() + endif() + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") + if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") + if (NOT _pchSuppressMessages) + set (_flags "${_flags} -Wpch-messages") + endif() + endif() + endif() + else() + # no precompiled header, force inclusion of prefix header + if (_flags) + # append to list + list (APPEND _flags -include "${_prefixFile}") + else() + # return as a flag string + set (_flags "-include \"${_prefixFile}\"") + endif() + endif() + endif() + else() + message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") + endif() + set (${_flagsVar} ${_flags} PARENT_SCOPE) +endfunction() + +function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) + set(_options "") + set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE) + set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGE) + set (_option_LANGUAGE "CXX") + endif() + if (NOT _option_COMPILER_ID) + set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") + endif() + if (NOT _option_COMPILER_VERSION) + set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") + endif() + cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") + cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) + cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) + cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) + cotire_add_pch_compilation_flags( + "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) + if (COTIRE_VERBOSE) + message (STATUS "execute_process: ${_cmd}") + endif() + if (MSVC_IDE OR _option_COMPILER_ID MATCHES "MSVC") + # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared + unset (ENV{VS_UNICODE_OUTPUT}) + elseif (_option_COMPILER_ID MATCHES "Clang" AND _option_COMPILER_VERSION VERSION_LESS "4.0.0") + if (_option_COMPILER_LAUNCHER MATCHES "ccache" OR + _option_COMPILER_EXECUTABLE MATCHES "ccache") + # Newer versions of Clang embed a compilation timestamp into the precompiled header binary, + # which results in "file has been modified since the precompiled header was built" errors if ccache is used. + # We work around the problem by disabling ccache upon pre-compiling the prefix header. + set (ENV{CCACHE_DISABLE} "true") + endif() + endif() + execute_process( + COMMAND ${_cmd} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE _result) + if (_result) + message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") + endif() +endfunction() + +function (cotire_check_precompiled_header_support _language _target _msgVar) + set (_unsupportedCompiler + "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") + # PCH supported since Visual Studio C++ 6.0 + # and CMake does not support an earlier version + set (${_msgVar} "" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") + # GCC PCH support requires version >= 3.4 + if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") + set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) + else() + set (${_msgVar} "" PARENT_SCOPE) + endif() + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") + if (UNIX) + # all Unix Clang versions have PCH support + set (${_msgVar} "" PARENT_SCOPE) + elseif (WIN32) + # only clang-cl is supported under Windows + get_filename_component(_compilerName "${CMAKE_${_language}_COMPILER}" NAME_WE) + if (NOT _compilerName MATCHES "cl$") + set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}. Use clang-cl instead." PARENT_SCOPE) + endif() + endif() + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") + # Intel PCH support requires version >= 8.0.0 + if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") + set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) + else() + set (${_msgVar} "" PARENT_SCOPE) + endif() + else() + set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) + endif() + # check if ccache is used as a compiler launcher + get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER) + get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" REALPATH) + if (_realCompilerExe MATCHES "ccache" OR _launcher MATCHES "ccache") + # verify that ccache configuration is compatible with precompiled headers + # always check environment variable CCACHE_SLOPPINESS, because earlier versions of ccache + # do not report the "sloppiness" setting correctly upon printing ccache configuration + if (DEFINED ENV{CCACHE_SLOPPINESS}) + if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "pch_defines" OR + NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") + set (${_msgVar} + "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." + PARENT_SCOPE) + endif() + else() + if (_realCompilerExe MATCHES "ccache") + set (_ccacheExe "${_realCompilerExe}") + else() + set (_ccacheExe "${_launcher}") + endif() + # ccache 3.7.0 replaced --print-config with --show-config + # use -p instead, which seems to work for all version for now, sigh + execute_process( + COMMAND "${_ccacheExe}" "-p" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _ccacheConfig OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + if (_result) + set (${_msgVar} "ccache configuration cannot be determined." PARENT_SCOPE) + elseif (NOT _ccacheConfig MATCHES "sloppiness.*=.*time_macros" OR + NOT _ccacheConfig MATCHES "sloppiness.*=.*pch_defines") + set (${_msgVar} + "ccache requires configuration setting \"sloppiness\" to be set to \"pch_defines,time_macros\"." + PARENT_SCOPE) + endif() + endif() + endif() + if (APPLE) + # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) + cotire_get_configuration_types(_configs) + foreach (_config ${_configs}) + set (_targetFlags "") + cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) + cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) + list (LENGTH _architectures _numberOfArchitectures) + if (_numberOfArchitectures GREATER 1) + string (REPLACE ";" ", " _architectureStr "${_architectures}") + set (${_msgVar} + "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." + PARENT_SCOPE) + break() + endif() + endforeach() + endif() +endfunction() + +macro (cotire_get_intermediate_dir _cotireDir) + # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types + get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) +endmacro() + +macro (cotire_setup_file_extension_variables) + set (_unityFileExt_C ".c") + set (_unityFileExt_CXX ".cxx") + set (_prefixFileExt_C ".h") + set (_prefixFileExt_CXX ".hxx") + set (_prefixSourceFileExt_C ".c") + set (_prefixSourceFileExt_CXX ".cxx") +endmacro() + +function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_unityFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") + cotire_get_intermediate_dir(_baseDir) + set (_unityFile "${_baseDir}/${_unityFileName}") + set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) +endfunction() + +function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_unityFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + cotire_get_intermediate_dir(_baseDir) + set (_startIndex 0) + set (_index 0) + set (_unityFiles "") + set (_sourceFiles ${ARGN}) + foreach (_sourceFile ${_sourceFiles}) + get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) + math (EXPR _unityFileCount "${_index} - ${_startIndex}") + if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) + if (_index GREATER 0) + # start new unity file segment + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (_startIndex ${_index}) + endif() + math (EXPR _index "${_index} + 1") + endforeach() + list (LENGTH _sourceFiles _numberOfSources) + if (_startIndex EQUAL 0) + # there is only a single unity file + cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) + elseif (_startIndex LESS _numberOfSources) + # end with final unity file segment + math (EXPR _endIndex "${_index} - 1") + set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") + list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") + endif() + set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) + if (COTIRE_DEBUG AND _unityFiles) + message (STATUS "unity files: ${_unityFiles}") + endif() +endfunction() + +function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _unityFileExt_${_language}) + set (${_prefixFileVar} "" PARENT_SCOPE) + return() + endif() + set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") + set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") + string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") + set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) +endfunction() + +function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) + cotire_setup_file_extension_variables() + if (NOT DEFINED _prefixSourceFileExt_${_language}) + set (${_prefixSourceFileVar} "" PARENT_SCOPE) + return() + endif() + string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") + set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) +endfunction() + +function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) + cotire_setup_file_extension_variables() + if (NOT _language) + set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") + elseif (DEFINED _prefixFileExt_${_language}) + set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") + set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") + else() + set (_prefixFileBaseName "") + set (_prefixFileName "") + endif() + set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) + set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) +endfunction() + +function (cotire_make_prefix_file_path _language _target _prefixFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_prefixFileVar} "" PARENT_SCOPE) + if (_prefixFileName) + if (NOT _language) + set (_language "C") + endif() + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") + cotire_get_intermediate_dir(_baseDir) + set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) + endif() + endif() +endfunction() + +function (cotire_make_pch_file_path _language _target _pchFileVar) + cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) + set (${_pchFileVar} "" PARENT_SCOPE) + if (_prefixFileBaseName AND _prefixFileName) + cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) + if (NOT _msg) + if (XCODE) + # For Xcode, we completely hand off the compilation of the prefix header to the IDE + return() + endif() + cotire_get_intermediate_dir(_baseDir) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") + # MSVC uses the extension .pch added to the prefix header base name + set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") + # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended + set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") + # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended + set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) + elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") + # Intel uses the extension .pchi added to the prefix header base name + set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +function (cotire_select_unity_source_files _unityFile _sourcesVar) + set (_sourceFiles ${ARGN}) + if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") + set (_startIndex ${CMAKE_MATCH_1}) + set (_endIndex ${CMAKE_MATCH_2}) + list (LENGTH _sourceFiles _numberOfSources) + if (NOT _startIndex LESS _numberOfSources) + math (EXPR _startIndex "${_numberOfSources} - 1") + endif() + if (NOT _endIndex LESS _numberOfSources) + math (EXPR _endIndex "${_numberOfSources} - 1") + endif() + set (_files "") + foreach (_index RANGE ${_startIndex} ${_endIndex}) + list (GET _sourceFiles ${_index} _file) + list (APPEND _files "${_file}") + endforeach() + else() + set (_files ${_sourceFiles}) + endif() + set (${_sourcesVar} ${_files} PARENT_SCOPE) +endfunction() + +function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) + set (_dependencySources "") + # depend on target's generated source files + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) + if (_generatedSources) + # but omit all generated source files that have the COTIRE_EXCLUDED property set to true + cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) + if (_excludedGeneratedSources) + list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) + endif() + # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly + cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) + if (_excludedNonDependencySources) + list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) + endif() + if (_generatedSources) + list (APPEND _dependencySources ${_generatedSources}) + endif() + endif() + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) + set (_dependencySources "") + # depend on target source files marked with custom COTIRE_DEPENDENCY property + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") + endif() + set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) +endfunction() + +function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) + set (_targetSources ${ARGN}) + cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) + cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) + # set up variables to be configured + set (COTIRE_TARGET_LANGUAGE "${_language}") + get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) + get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) + cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) + get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) + get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) + get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) + cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) + set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") + foreach (_config ${_configurations}) + string (TOUPPER "${_config}" _upperConfig) + cotire_get_target_include_directories( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) + cotire_get_target_compile_definitions( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) + cotire_get_target_compiler_flags( + "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) + cotire_get_source_files_compile_definitions( + "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) + endforeach() + get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER) + # set up COTIRE_TARGET_SOURCES + set (COTIRE_TARGET_SOURCES "") + foreach (_sourceFile ${_targetSources}) + get_source_file_property(_generated "${_sourceFile}" GENERATED) + if (_generated) + # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation + get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) + list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") + else() + list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") + endif() + endforeach() + # copy variable definitions to cotire target script + get_cmake_property(_vars VARIABLES) + string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") + # omit COTIRE_*_INIT variables + string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") + if (_initVars) + list (REMOVE_ITEM _matchVars ${_initVars}) + endif() + # omit COTIRE_VERBOSE which is passed as a CMake define on command line + list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) + set (_contents "") + set (_contentsHasGeneratorExpressions FALSE) + foreach (_var IN LISTS _matchVars ITEMS + XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES + CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION + CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 + CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_SEP_${_language} + CMAKE_INCLUDE_SYSTEM_FLAG_${_language} + CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG + CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG + CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) + if (DEFINED ${_var}) + string (REPLACE "\"" "\\\"" _value "${${_var}}") + set (_contents "${_contents}set (${_var} \"${_value}\")\n") + if (NOT _contentsHasGeneratorExpressions) + if ("${_value}" MATCHES "\\$<.*>") + set (_contentsHasGeneratorExpressions TRUE) + endif() + endif() + endif() + endforeach() + # generate target script file + get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) + set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") + cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) + if (_contentsHasGeneratorExpressions) + # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time + set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") + set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") + file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") + else() + set (_targetCotireConfigScript "${_targetCotireScript}") + endif() + set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) + set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) +endfunction() + +function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) + set (_sourceFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR + (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) + # for MSVC, Intel and Clang-cl, we attach the precompiled header compilation to the host file + # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion + if (_sourceFiles) + set (_flags "") + cotire_add_pch_compilation_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) + set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + if (COTIRE_DEBUG) + message (STATUS "set_property: SOURCE ${_hostFile} APPEND_STRING COMPILE_FLAGS ${_flags}") + endif() + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") + # make object file generated from host file depend on prefix header + set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") + # mark host file as cotired to prevent it from being used in another cotired target + set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generator, we add a custom command to precompile the prefix header + if (_targetScript) + cotire_set_cmd_to_prologue(_cmds) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath) + else() + file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}") + endif() + # make precompiled header compilation depend on the actual compiler executable used to force + # re-compilation when the compiler executable is updated. This prevents "created by a different GCC executable" + # warnings when the precompiled header is included. + get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} ${_realCompilerExe} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") + endif() + set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) + add_custom_command( + OUTPUT "${_pchFile}" + COMMAND ${_cmds} + DEPENDS "${_prefixFile}" "${_realCompilerExe}" + IMPLICIT_DEPENDS ${_language} "${_prefixFile}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}" + VERBATIM) + endif() + endif() +endfunction() + +function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) + if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" OR + (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) + # for MSVC, Intel and clang-cl, we include the precompiled header in all but the host file + # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation + set (_sourceFiles ${ARGN}) + list (LENGTH _sourceFiles _numberOfSourceFiles) + if (_numberOfSourceFiles GREATER 0) + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + set (_flags "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + if (COTIRE_DEBUG) + message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") + endif() + # make object files generated from source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + set (_sourceFiles ${_hostFile} ${ARGN}) + if (NOT _wholeTarget) + # for makefile based generator, we force the inclusion of the prefix header for a subset + # of the source files, if this is a multi-language target or has excluded files + set (_flags "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + if (COTIRE_DEBUG) + message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") + endif() + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + endif() + # make object files generated from source files depend on precompiled header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") + endif() +endfunction() + +function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) + set (_sourceFiles ${ARGN}) + # force the inclusion of the prefix header for the given source files + set (_flags "") + set (_pchFile "") + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _flags) + set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") + if (COTIRE_DEBUG) + message (STATUS "set_property: SOURCE ${_sourceFiles} APPEND_STRING COMPILE_FLAGS ${_flags}") + endif() + # mark sources as cotired to prevent them from being used in another cotired target + set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") + # make object files generated from source files depend on prefix header + set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") +endfunction() + +function (cotire_get_first_set_property_value _propertyValueVar _type _object) + set (_properties ${ARGN}) + foreach (_property ${_properties}) + get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) + if (_propertyValue) + set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) + return() + endif() + endforeach() + set (${_propertyValueVar} "" PARENT_SCOPE) +endfunction() + +function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) + set (_files ${ARGN}) + set (_filesPaths "") + foreach (_file ${_files}) + get_filename_component(_filePath "${_file}" ABSOLUTE) + list (APPEND _filesPaths "${_filePath}") + endforeach() + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") + if (_targetScript) + list (APPEND _prefixCmd "${_targetScript}") + endif() + list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") + endif() + set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath) + else() + file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") + endif() + get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) + get_filename_component(_joinedFileExt "${_joinedFile}" EXT) + if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") + set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}") + elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") + if (_joinedFileExt MATCHES "^\\.c") + set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}") + else() + set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}") + endif() + else() + set (_comment "Generating ${_joinedFileLogPath}") + endif() + add_custom_command( + OUTPUT "${_joinedFile}" + COMMAND ${_prefixCmd} + DEPENDS ${_files} + COMMENT "${_comment}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_target_pch_usage _languages _target _wholeTarget) + if (XCODE) + # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers + set (_prefixFiles "") + foreach (_language ${_languages}) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_prefixFile) + list (APPEND _prefixFiles "${_prefixFile}") + endif() + endforeach() + set (_cmds ${ARGN}) + list (LENGTH _prefixFiles _numberOfPrefixFiles) + if (_numberOfPrefixFiles GREATER 1) + # we also generate a generic, single prefix header which includes all language specific prefix headers + set (_language "") + set (_targetScript "") + cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) + cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) + else() + set (_prefixHeader "${_prefixFiles}") + endif() + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") + endif() + # because CMake PRE_BUILD command does not support dependencies, + # we check dependencies explicity in cotire script mode when the pre-build action is run + add_custom_command( + TARGET "${_target}" + PRE_BUILD ${_cmds} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Updating target ${_target} prefix headers" + VERBATIM) + # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") + set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") + elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generator, we force inclusion of the prefix header for all target source files + # if this is a single-language target without any excluded files + if (_wholeTarget) + set (_language "${_languages}") + # for MSVC, Intel and clang-cl, precompiled header inclusion is always done on the source file level + # see cotire_setup_pch_file_inclusion + if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT + (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_prefixFile) + get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) + set (_options COMPILE_OPTIONS) + cotire_add_prefix_pch_inclusion_flags( + "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" + "${_prefixFile}" "${_pchFile}" _options) + set_property(TARGET ${_target} APPEND PROPERTY ${_options}) + if (COTIRE_DEBUG) + message (STATUS "set_property: TARGET ${_target} APPEND PROPERTY ${_options}") + endif() + endif() + endif() + endif() + endif() +endfunction() + +function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) + set (_dependencySources "") + cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) + foreach (_unityFile ${_unityFiles}) + set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) + # set up compiled unity source dependencies via OBJECT_DEPENDS + # this ensures that missing source files are generated before the unity file is compiled + if (COTIRE_DEBUG AND _dependencySources) + message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") + endif() + if (_dependencySources) + # the OBJECT_DEPENDS property requires a list of full paths + set (_objectDependsPaths "") + foreach (_sourceFile ${_dependencySources}) + get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) + list (APPEND _objectDependsPaths "${_sourceLocation}") + endforeach() + set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) + endif() + if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") + # unity file compilation results in potentially huge object file, + # thus use /bigobj by default unter cl.exe and Windows Intel + set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") + endif() + cotire_set_cmd_to_prologue(_unityCmd) + list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") + if (CMAKE_VERSION VERSION_LESS "3.1.0") + set (_unityCmdDepends "${_targetScript}") + else() + # CMake 3.1.0 supports generator expressions in arguments to DEPENDS + set (_unityCmdDepends "${_targetConfigScript}") + endif() + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath) + else() + file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}") + endif() + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") + endif() + add_custom_command( + OUTPUT "${_unityFile}" + COMMAND ${_unityCmd} + DEPENDS ${_unityCmdDepends} + COMMENT "Generating ${_language} unity source ${_unityFileLogPath}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) + endforeach() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) + set (_sourceFiles ${ARGN}) + set (_dependencySources "") + cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) + cotire_set_cmd_to_prologue(_prefixCmd) + list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) + set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) + # make prefix header generation depend on the actual compiler executable used to force + # re-generation when the compiler executable is updated. This prevents "file not found" + # errors for compiler version specific system header files. + get_filename_component(_realCompilerExe "${CMAKE_${_language}_COMPILER}" ABSOLUTE) + if (COTIRE_DEBUG) + message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources} ${_realCompilerExe}") + endif() + if (MSVC_IDE) + file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath) + else() + file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") + endif() + get_filename_component(_prefixFileExt "${_prefixFile}" EXT) + if (_prefixFileExt MATCHES "^\\.c") + set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}") + else() + set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}") + endif() + # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist + # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence + # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files + set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") + if (TARGET ${_preTargetName}) + # custom helper target has already been generated while processing a different language + list (APPEND _dependencySources ${_preTargetName}) + else() + get_target_property(_targetSourceFiles ${_target} SOURCES) + cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) + if (_generatedSources) + add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) + cotire_init_target("${_preTargetName}") + list (APPEND _dependencySources ${_preTargetName}) + endif() + endif() + add_custom_command( + OUTPUT "${_prefixFile}" "${_prefixFile}.log" + COMMAND ${_prefixCmd} + DEPENDS ${_unityFiles} ${_dependencySources} "${_realCompilerExe}" + COMMENT "${_comment}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + VERBATIM) + list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) + set (_sourceFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma + cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) + else() + set (_prefixSourceFile "${_prefixFile}") + endif() + cotire_setup_prefix_generation_command( + ${_language} ${_target} "${_targetScript}" + "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # set up generation of a prefix source file which includes the prefix header + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) + endif() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) + set (_prefixHeaderFiles ${ARGN}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma + cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) + else() + set (_prefixSourceFile "${_prefixFile}") + endif() + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) + if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") + # set up generation of a prefix source file which includes the prefix header + cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) + endif() + set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) +endfunction() + +function (cotire_init_cotire_target_properties _target) + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") + cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") + if (NOT _isRelative) + set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") + endif() + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) + if (NOT _isSet) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") + endif() + get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) + if (NOT _isSet) + if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") + else() + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") + endif() + endif() +endfunction() + +function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + string (REPLACE ";" " " _languagesStr "${_languages}") + math (EXPR _numberOfExcludedFiles "${ARGC} - 4") + if (_numberOfExcludedFiles EQUAL 0) + set (_excludedStr "") + elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) + string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") + else() + set (_excludedStr "excluding ${_numberOfExcludedFiles} files") + endif() + set (_targetMsg "") + if (NOT _languages) + set (_targetMsg "Target ${_target} cannot be cotired.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH AND NOT _targetAddSCU) + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetUsePCH) + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") + endif() + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + elseif (NOT _targetAddSCU) + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") + endif() + if (_disableMsg) + set (_targetMsg "${_targetMsg} ${_disableMsg}") + endif() + else() + if (_excludedStr) + set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") + else() + set (_targetMsg "${_languagesStr} target ${_target} cotired.") + endif() + endif() + set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) +endfunction() + +function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) + set (_languages ${ARGN}) + set (_allSourceFiles "") + set (_allExcludedSourceFiles "") + set (_allCotiredSourceFiles "") + set (_targetLanguages "") + set (_pchEligibleTargetLanguages "") + get_target_property(_targetType ${_target} TYPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + set (_disableMsg "") + foreach (_language ${_languages}) + get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) + get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) + if (_prefixHeader OR _unityBuildFile) + message (STATUS "cotire: target ${_target} has already been cotired.") + set (${_targetLanguagesVar} "" PARENT_SCOPE) + return() + endif() + if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND DEFINED CMAKE_${_language}_COMPILER_ID) + if (CMAKE_${_language}_COMPILER_ID) + cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) + if (_disableMsg) + set (_targetUsePCH FALSE) + endif() + endif() + endif() + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _excludedSources OR _cotiredSources) + list (APPEND _targetLanguages ${_language}) + endif() + if (_sourceFiles) + list (APPEND _allSourceFiles ${_sourceFiles}) + endif() + list (LENGTH _sourceFiles _numberOfSources) + if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + list (APPEND _pchEligibleTargetLanguages ${_language}) + endif() + if (_excludedSources) + list (APPEND _allExcludedSourceFiles ${_excludedSources}) + endif() + if (_cotiredSources) + list (APPEND _allCotiredSourceFiles ${_cotiredSources}) + endif() + endforeach() + set (_targetMsgLevel STATUS) + if (NOT _targetLanguages) + string (REPLACE ";" " or " _languagesStr "${_languages}") + set (_disableMsg "No ${_languagesStr} source files.") + set (_targetUsePCH FALSE) + set (_targetAddSCU FALSE) + endif() + if (_targetUsePCH) + if (_allCotiredSourceFiles) + cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) + list (REMOVE_DUPLICATES _cotireTargets) + string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") + set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") + set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") + set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") + set (_targetMsgLevel SEND_ERROR) + set (_targetUsePCH FALSE) + elseif (NOT _pchEligibleTargetLanguages) + set (_disableMsg "Too few applicable sources.") + set (_targetUsePCH FALSE) + elseif (XCODE AND _allExcludedSourceFiles) + # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target + set (_disableMsg "Exclusion of source files not supported for generator Xcode.") + set (_targetUsePCH FALSE) + elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") + # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target + set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") + set (_targetUsePCH FALSE) + endif() + endif() + if (_targetAddSCU) + # disable unity builds if automatic Qt processing is used + get_target_property(_targetAutoMoc ${_target} AUTOMOC) + get_target_property(_targetAutoUic ${_target} AUTOUIC) + get_target_property(_targetAutoRcc ${_target} AUTORCC) + if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) + if (_disableMsg) + set (_disableMsg "${_disableMsg} Target uses automatic CMake Qt processing.") + else() + set (_disableMsg "Target uses automatic CMake Qt processing.") + endif() + set (_targetAddSCU FALSE) + endif() + endif() + set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) + set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) + cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) + if (_targetMsg) + if (NOT DEFINED COTIREMSG_${_target}) + set (COTIREMSG_${_target} "") + endif() + if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR + NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") + # cache message to avoid redundant messages on re-configure + set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") + message (${_targetMsgLevel} "${_targetMsg}") + endif() + endif() + list (LENGTH _targetLanguages _numberOfLanguages) + if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) + set (${_wholeTargetVar} FALSE PARENT_SCOPE) + else() + set (${_wholeTargetVar} TRUE PARENT_SCOPE) + endif() + set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) +endfunction() + +function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) + set (_sourceFiles ${ARGN}) + get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) + if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") + if (DEFINED CMAKE_MATCH_2) + set (_numberOfThreads "${CMAKE_MATCH_2}") + else() + set (_numberOfThreads "") + endif() + if (NOT _numberOfThreads) + # use all available cores + ProcessorCount(_numberOfThreads) + endif() + list (LENGTH _sourceFiles _numberOfSources) + math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") + elseif (NOT _maxIncludes MATCHES "[0-9]+") + set (_maxIncludes 0) + endif() + if (COTIRE_DEBUG) + message (STATUS "${_target} unity source max includes: ${_maxIncludes}") + endif() + set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) +endfunction() + +function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) + set (${_cmdsVar} "" PARENT_SCOPE) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (NOT _sourceFiles AND NOT _cotiredSources) + return() + endif() + set (_cmds "") + # check for user provided unity source file list + get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) + if (NOT _unitySourceFiles) + set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) + endif() + cotire_generate_target_script( + ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) + # set up unity files for parallel compilation + cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) + cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) + list (LENGTH _unityFiles _numberOfUnityFiles) + if (_numberOfUnityFiles EQUAL 0) + return() + elseif (_numberOfUnityFiles GREATER 1) + cotire_setup_unity_generation_commands( + ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) + endif() + # set up single unity file for prefix header generation + cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) + cotire_setup_unity_generation_commands( + ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) + cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) + # set up prefix header + if (_prefixFile) + # check for user provided prefix header files + get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) + if (_prefixHeaderFiles) + cotire_setup_prefix_generation_from_provided_command( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) + else() + cotire_setup_prefix_generation_from_unity_command( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) + endif() + # check if selected language has enough sources at all + list (LENGTH _sourceFiles _numberOfSources) + if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) + set (_targetUsePCH FALSE) + else() + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + endif() + if (_targetUsePCH) + cotire_make_pch_file_path(${_language} ${_target} _pchFile) + if (_pchFile) + # first file in _sourceFiles is passed as the host file + cotire_setup_pch_file_compilation( + ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + cotire_setup_pch_file_inclusion( + ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) + endif() + elseif (_prefixHeaderFiles) + # user provided prefix header must be included unconditionally + cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) + endif() + endif() + # mark target as cotired for language + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") + if (_prefixFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") + if (_targetUsePCH AND _pchFile) + set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") + endif() + endif() + set (${_cmdsVar} ${_cmds} PARENT_SCOPE) +endfunction() + +function (cotire_setup_clean_target _target) + set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") + if (NOT TARGET "${_cleanTargetName}") + cotire_set_cmd_to_prologue(_cmds) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") + add_custom_target(${_cleanTargetName} + COMMAND ${_cmds} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Cleaning up target ${_target} cotire generated files" + VERBATIM) + cotire_init_target("${_cleanTargetName}") + endif() +endfunction() + +function (cotire_setup_pch_target _languages _configurations _target) + if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") + # for makefile based generators, we add a custom target to trigger the generation of the cotire related files + set (_dependsFiles "") + foreach (_language ${_languages}) + set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) + if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel" AND NOT + (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "Clang")) + # MSVC, Intel and clang-cl only create precompiled header as a side effect + list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) + endif() + cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) + if (_dependsFile) + list (APPEND _dependsFiles "${_dependsFile}") + endif() + endforeach() + if (_dependsFiles) + set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") + add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) + cotire_init_target("${_pchTargetName}") + cotire_add_to_pch_all_target(${_pchTargetName}) + endif() + else() + # for other generators, we add the "clean all" target to clean up the precompiled header + cotire_setup_clean_all_target() + endif() +endfunction() + +function (cotire_filter_object_libraries _target _objectLibrariesVar) + set (_objectLibraries "") + foreach (_source ${ARGN}) + if (_source MATCHES "^\\$$") + list (APPEND _objectLibraries "${_source}") + endif() + endforeach() + set (${_objectLibrariesVar} ${_objectLibraries} PARENT_SCOPE) +endfunction() + +function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) + get_target_property(_targetSourceFiles ${_target} SOURCES) + set (_unityTargetSources ${_targetSourceFiles}) + foreach (_language ${_languages}) + get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) + if (_unityFiles) + # remove source files that are included in the unity source + set (_sourceFiles "") + set (_excludedSources "") + set (_cotiredSources "") + cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) + if (_sourceFiles OR _cotiredSources) + list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) + endif() + # add unity source files instead + list (APPEND _unityTargetSources ${_unityFiles}) + endif() + endforeach() + # handle object libraries which are part of the target's sources + get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) + if ("${_linkLibrariesStrategy}" MATCHES "^COPY_UNITY$") + cotire_filter_object_libraries(${_target} _objectLibraries ${_targetSourceFiles}) + if (_objectLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityObjectLibraries ${_objectLibraries}) + list (REMOVE_ITEM _unityTargetSources ${_objectLibraries}) + list (APPEND _unityTargetSources ${_unityObjectLibraries}) + endif() + endif() + set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) +endfunction() + +function (cotire_setup_unity_target_pch_usage _languages _target) + foreach (_language ${_languages}) + get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) + if (_unityFiles) + get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) + get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) + if (_userPrefixFile AND _prefixFile) + # user provided prefix header must be included unconditionally by unity sources + cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) + endif() + endif() + endforeach() +endfunction() + +function (cotire_setup_unity_build_target _languages _configurations _target) + get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) + if (NOT _unityTargetName) + set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") + endif() + # determine unity target sub type + get_target_property(_targetType ${_target} TYPE) + if ("${_targetType}" STREQUAL "EXECUTABLE") + set (_unityTargetSubType "") + elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") + set (_unityTargetSubType "${CMAKE_MATCH_1}") + else() + message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") + return() + endif() + # determine unity target sources + set (_unityTargetSources "") + cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) + # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created + set (CMAKE_AUTOMOC OFF) + set (CMAKE_AUTOUIC OFF) + set (CMAKE_AUTORCC OFF) + if (COTIRE_DEBUG) + message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") + endif() + # generate unity target + if ("${_targetType}" STREQUAL "EXECUTABLE") + add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + else() + add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) + endif() + # copy output location properties + set (_outputDirProperties + ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ + LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ + RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) + if (COTIRE_UNITY_OUTPUT_DIRECTORY) + set (_setDefaultOutputDir TRUE) + if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") + else() + # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) + cotire_resolve_config_properties("${_configurations}" _properties ${_outputDirProperties}) + foreach (_property ${_properties}) + get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) + if (_outputDir) + get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") + set (_setDefaultOutputDir FALSE) + endif() + endforeach() + if (_setDefaultOutputDir) + get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) + endif() + endif() + if (_setDefaultOutputDir) + set_target_properties(${_unityTargetName} PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" + LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" + RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") + endif() + else() + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + ${_outputDirProperties}) + endif() + # copy output name + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ + LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ + OUTPUT_NAME OUTPUT_NAME_ + RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ + PREFIX _POSTFIX SUFFIX + IMPORT_PREFIX IMPORT_SUFFIX) + # copy compile stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ + COMPILE_FLAGS COMPILE_OPTIONS + Fortran_FORMAT Fortran_MODULE_DIRECTORY + INCLUDE_DIRECTORIES + INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ + POSITION_INDEPENDENT_CODE + C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER + C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE + C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN + C_CLANG_TIDY CXX_CLANG_TIDY) + # copy compile features + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED + CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED + COMPILE_FEATURES) + # copy interface stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN + COMPATIBLE_INTERFACE_STRING + INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS + INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES + INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES + INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) + # copy link stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUILD_WITH_INSTALL_RPATH BUILD_WITH_INSTALL_NAME_DIR + INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH + LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED + LINK_FLAGS LINK_FLAGS_ + LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ + LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ + LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC + STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ + NO_SONAME SOVERSION VERSION + LINK_WHAT_YOU_USE BUILD_RPATH) + # copy cmake stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) + # copy Apple platform specific stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR + MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH + OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST + IOS_INSTALL_COMBINED XCODE_EXPLICIT_FILE_TYPE XCODE_PRODUCT_TYPE) + # copy Windows platform specific stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + GNUtoMS + COMPILE_PDB_NAME COMPILE_PDB_NAME_ + COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ + PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ + VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION + VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE + VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK + VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION + VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER + VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION + VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES + WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS + DEPLOYMENT_REMOTE_DIRECTORY VS_CONFIGURATION_TYPE + VS_SDK_REFERENCES VS_USER_PROPS VS_DEBUGGER_WORKING_DIRECTORY) + # copy Android platform specific stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + ANDROID_API ANDROID_API_MIN ANDROID_GUI + ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES + ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR + ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES + ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH + ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE) + # copy CUDA platform specific stuff + cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} + CUDA_PTX_COMPILATION CUDA_SEPARABLE_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS + CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED) + # use output name from original target + get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) + if (NOT _targetOutputName) + set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") + endif() + # use export symbol from original target + cotire_get_target_export_symbol("${_target}" _defineSymbol) + if (_defineSymbol) + set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") + if ("${_targetType}" STREQUAL "EXECUTABLE") + set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) + endif() + endif() + # enable parallel compilation for MSVC + if (MSVC AND "${CMAKE_GENERATOR}" MATCHES "Visual Studio") + list (LENGTH _unityTargetSources _numberOfUnityTargetSources) + if (_numberOfUnityTargetSources GREATER 1) + set_property(TARGET ${_unityTargetName} APPEND PROPERTY COMPILE_OPTIONS "/MP") + endif() + endif() + cotire_init_target(${_unityTargetName}) + cotire_add_to_unity_all_target(${_unityTargetName}) + set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") +endfunction(cotire_setup_unity_build_target) + +function (cotire_target _target) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + if (NOT _option_LANGUAGES) + get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + endif() + if (NOT _option_CONFIGURATIONS) + cotire_get_configuration_types(_option_CONFIGURATIONS) + endif() + # check if cotire can be applied to target at all + cotire_is_target_supported(${_target} _isSupported) + if (NOT _isSupported) + get_target_property(_imported ${_target} IMPORTED) + get_target_property(_targetType ${_target} TYPE) + if (_imported) + message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.") + else() + message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.") + endif() + return() + endif() + # resolve alias + get_target_property(_aliasName ${_target} ALIASED_TARGET) + if (_aliasName) + if (COTIRE_DEBUG) + message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") + endif() + set (_target ${_aliasName}) + endif() + # check if target needs to be cotired for build type + # when using configuration types, the test is performed at build time + cotire_init_cotire_target_properties(${_target}) + if (NOT CMAKE_CONFIGURATION_TYPES) + if (CMAKE_BUILD_TYPE) + list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) + else() + list (FIND _option_CONFIGURATIONS "None" _index) + endif() + if (_index EQUAL -1) + if (COTIRE_DEBUG) + message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") + endif() + return() + endif() + endif() + # when not using configuration types, immediately create cotire intermediate dir + if (NOT CMAKE_CONFIGURATION_TYPES) + cotire_get_intermediate_dir(_baseDir) + file (MAKE_DIRECTORY "${_baseDir}") + endif() + # choose languages that apply to the target + cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) + if (NOT _targetLanguages) + return() + endif() + set (_cmds "") + foreach (_language ${_targetLanguages}) + cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) + if (_cmd) + list (APPEND _cmds ${_cmd}) + endif() + endforeach() + get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) + if (_targetAddSCU) + cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + endif() + get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) + if (_targetUsePCH) + cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) + cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) + if (_targetAddSCU) + cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) + endif() + endif() + get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) + if (_targetAddCleanTarget) + cotire_setup_clean_target(${_target}) + endif() +endfunction(cotire_target) + +function (cotire_map_libraries _strategy _mappedLibrariesVar) + set (_mappedLibraries "") + foreach (_library ${ARGN}) + if (_library MATCHES "^\\$$") + set (_libraryName "${CMAKE_MATCH_1}") + set (_linkOnly TRUE) + set (_objectLibrary FALSE) + elseif (_library MATCHES "^\\$$") + set (_libraryName "${CMAKE_MATCH_1}") + set (_linkOnly FALSE) + set (_objectLibrary TRUE) + else() + set (_libraryName "${_library}") + set (_linkOnly FALSE) + set (_objectLibrary FALSE) + endif() + if ("${_strategy}" MATCHES "COPY_UNITY") + cotire_is_target_supported(${_libraryName} _isSupported) + if (_isSupported) + # use target's corresponding unity target, if available + get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME) + if (TARGET "${_libraryUnityTargetName}") + if (_linkOnly) + list (APPEND _mappedLibraries "$") + elseif (_objectLibrary) + list (APPEND _mappedLibraries "$") + else() + list (APPEND _mappedLibraries "${_libraryUnityTargetName}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + else() + list (APPEND _mappedLibraries "${_library}") + endif() + endforeach() + list (REMOVE_DUPLICATES _mappedLibraries) + set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) +endfunction() + +function (cotire_target_link_libraries _target) + cotire_is_target_supported(${_target} _isSupported) + if (NOT _isSupported) + return() + endif() + get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) + if (TARGET "${_unityTargetName}") + get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") + endif() + if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") + get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) + if (_linkLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries}) + set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}") + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}") + endif() + endif() + get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) + if (_interfaceLinkLibraries) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries}) + set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}") + if (COTIRE_DEBUG) + message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}") + endif() + endif() + get_target_property(_manualDependencies ${_target} MANUALLY_ADDED_DEPENDENCIES) + if (_manualDependencies) + cotire_map_libraries("${_linkLibrariesStrategy}" _unityManualDependencies ${_manualDependencies}) + if (_unityManualDependencies) + add_dependencies("${_unityTargetName}" ${_unityManualDependencies}) + endif() + endif() + endif() + endif() +endfunction(cotire_target_link_libraries) + +function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) + if (_targetName) + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") + else() + file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") + endif() + # filter files in intermediate directory + set (_filesToRemove "") + foreach (_file ${_cotireFiles}) + get_filename_component(_dir "${_file}" DIRECTORY) + get_filename_component(_dirName "${_dir}" NAME) + if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") + list (APPEND _filesToRemove "${_file}") + endif() + endforeach() + if (_filesToRemove) + if (COTIRE_VERBOSE) + message (STATUS "cleaning up ${_filesToRemove}") + endif() + file (REMOVE ${_filesToRemove}) + endif() +endfunction() + +function (cotire_init_target _targetName) + if (COTIRE_TARGETS_FOLDER) + set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") + endif() + set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) + if (MSVC_IDE) + set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) + endif() +endfunction() + +function (cotire_add_to_pch_all_target _pchTargetName) + set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_pchTargetName}) +endfunction() + +function (cotire_add_to_unity_all_target _unityTargetName) + set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + add_custom_target("${_targetName}" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + VERBATIM) + cotire_init_target("${_targetName}") + endif() + cotire_setup_clean_all_target() + add_dependencies(${_targetName} ${_unityTargetName}) +endfunction() + +function (cotire_setup_clean_all_target) + set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") + if (NOT TARGET "${_targetName}") + cotire_set_cmd_to_prologue(_cmds) + list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") + add_custom_target(${_targetName} + COMMAND ${_cmds} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + COMMENT "Cleaning up all cotire generated files" + VERBATIM) + cotire_init_target("${_targetName}") + endif() +endfunction() + +function (cotire) + set(_options "") + set(_oneValueArgs "") + set(_multiValueArgs LANGUAGES CONFIGURATIONS) + cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) + set (_targets ${_option_UNPARSED_ARGUMENTS}) + foreach (_target ${_targets}) + if (TARGET ${_target}) + cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) + else() + message (WARNING "cotire: ${_target} is not a target.") + endif() + endforeach() + foreach (_target ${_targets}) + if (TARGET ${_target}) + cotire_target_link_libraries(${_target}) + endif() + endforeach() +endfunction() + +if (CMAKE_SCRIPT_MODE_FILE) + + # cotire is being run in script mode + # locate -P on command args + set (COTIRE_ARGC -1) + foreach (_index RANGE ${CMAKE_ARGC}) + if (COTIRE_ARGC GREATER -1) + set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") + math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") + elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") + set (COTIRE_ARGC 0) + endif() + endforeach() + + # include target script if available + if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") + # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) + include("${COTIRE_ARGV2}") + endif() + + if (COTIRE_DEBUG) + message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") + endif() + + if (NOT COTIRE_BUILD_TYPE) + set (COTIRE_BUILD_TYPE "None") + endif() + string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) + set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) + set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) + set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) + # check if target has been cotired for actual build type COTIRE_BUILD_TYPE + list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) + if (_index GREATER -1) + set (_sources ${COTIRE_TARGET_SOURCES}) + set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) + else() + if (COTIRE_DEBUG) + message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") + endif() + set (_sources "") + set (_sourcesDefinitions "") + endif() + set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) + set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) + set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) + set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) + + if ("${COTIRE_ARGV1}" STREQUAL "unity") + + if (XCODE) + # executing pre-build action under Xcode, check dependency on target script + set (_dependsOption DEPENDS "${COTIRE_ARGV2}") + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) + + cotire_generate_unity_source( + "${COTIRE_ARGV3}" ${_sources} + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} + PRE_UNDEFS ${_targetPreUndefs} + POST_UNDEFS ${_targetPostUndefs} + SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} + SOURCES_POST_UNDEFS ${_sourcesPostUndefs} + ${_dependsOption}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") + + if (XCODE) + # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies + set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + set (_files "") + foreach (_index RANGE 4 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_generate_prefix_header( + "${COTIRE_ARGV3}" ${_files} + COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" + INCLUDE_PATH "${COTIRE_TARGET_INCLUDE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_INCLUDE_PATH}" + IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" + INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} + INCLUDE_DIRECTORIES ${_includeDirs} + SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags} + ${_dependsOption}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") + + set (_files "") + foreach (_index RANGE 5 ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + cotire_precompile_prefix_header( + "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" + COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}" + COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" + COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} + COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" + COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + INCLUDE_DIRECTORIES ${_includeDirs} + SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} + COMPILE_DEFINITIONS ${_compileDefinitions} + COMPILE_FLAGS ${_compileFlags}) + + elseif ("${COTIRE_ARGV1}" STREQUAL "combine") + + if (COTIRE_TARGET_LANGUAGE) + set (_combinedFile "${COTIRE_ARGV3}") + set (_startIndex 4) + else() + set (_combinedFile "${COTIRE_ARGV2}") + set (_startIndex 3) + endif() + set (_files "") + foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) + if (COTIRE_ARGV${_index}) + list (APPEND _files "${COTIRE_ARGV${_index}}") + endif() + endforeach() + + if (XCODE) + # executing pre-build action under Xcode, check dependency on files to be combined + set (_dependsOption DEPENDS ${_files}) + else() + # executing custom command, no need to re-check for dependencies + set (_dependsOption "") + endif() + + if (COTIRE_TARGET_LANGUAGE) + cotire_generate_unity_source( + "${_combinedFile}" ${_files} + LANGUAGE "${COTIRE_TARGET_LANGUAGE}" + ${_dependsOption}) + else() + cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) + endif() + + elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") + + cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") + + else() + message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") + endif() + +else() + + # cotire is being run in include mode + # set up all variable and property definitions + + if (NOT DEFINED COTIRE_DEBUG_INIT) + if (DEFINED COTIRE_DEBUG) + set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) + else() + set (COTIRE_DEBUG_INIT FALSE) + endif() + endif() + option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) + + if (NOT DEFINED COTIRE_VERBOSE_INIT) + if (DEFINED COTIRE_VERBOSE) + set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) + else() + set (COTIRE_VERBOSE_INIT FALSE) + endif() + endif() + option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING + "Ignore headers with the listed file extensions from the generated prefix header.") + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING + "Ignore headers from these directories when generating the prefix header.") + + set (COTIRE_ADDITIONAL_PREFIX_HEADER_INCLUDE_PATH "" CACHE STRING + "Include headers from these directories when generating the prefix header.") + + set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING + "Ignore sources with the listed file extensions from the generated unity source.") + + set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "2" CACHE STRING + "Minimum number of sources in target required to enable use of precompiled header.") + + if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) + if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) + elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") + # enable parallelization for generators that run multiple jobs by default + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") + else() + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") + endif() + endif() + set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING + "Maximum number of source files to include in a single unity source file.") + + if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) + set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") + endif() + if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) + set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") + endif() + if (NOT COTIRE_INTDIR) + set (COTIRE_INTDIR "cotire") + endif() + if (NOT COTIRE_PCH_ALL_TARGET_NAME) + set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") + endif() + if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) + set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") + endif() + if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) + set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") + endif() + if (NOT COTIRE_CLEAN_TARGET_SUFFIX) + set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") + endif() + if (NOT COTIRE_PCH_TARGET_SUFFIX) + set (COTIRE_PCH_TARGET_SUFFIX "_pch") + endif() + if (MSVC) + # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code + # use a bigger default factor of 170 percent (128 MB) + if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) + set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") + endif() + endif() + if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) + set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") + endif() + if (NOT DEFINED COTIRE_TARGETS_FOLDER) + set (COTIRE_TARGETS_FOLDER "cotire") + endif() + if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) + if ("${CMAKE_GENERATOR}" MATCHES "Ninja") + # generated Ninja build files do not work if the unity target produces the same output file as the cotired target + set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") + else() + set (COTIRE_UNITY_OUTPUT_DIRECTORY "") + endif() + endif() + + # define cotire cache variables + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of include directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "If not defined, defaults to empty list." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_INCLUDE_PATH" + BRIEF_DOCS "Include headers from these directories when generating the prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of include directories." + "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." + "If not defined, defaults to empty list." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" + BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." + FULL_DOCS + "The variable can be set to a semicolon separated list of file extensions." + "If a header file extension matches one in the list, it will be excluded from the generated prefix header." + "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." + "If not defined, defaults to inc;inl;ipp." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" + BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." + FULL_DOCS + "The variable can be set to a semicolon separated list of file extensions." + "If a source file extension matches one in the list, it will be excluded from the generated unity source file." + "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." + "If not defined, defaults to m;mm." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" + BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." + FULL_DOCS + "The variable can be set to an integer > 0." + "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." + "If not defined, defaults to 2." + ) + + define_property( + CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer >= 0." + "If 0, cotire will only create a single unity source file." + "If a target contains more than that number of source files, cotire will create multiple unity source files for it." + "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." + "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." + "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." + ) + + # define cotire directory properties + + define_property( + DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" + BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." + FULL_DOCS + "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" + BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_UNITY_BUILD." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" + BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." + FULL_DOCS + "See target property COTIRE_ADD_CLEAN." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" + BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." + FULL_DOCS + "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." + ) + + define_property( + DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" + BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." + FULL_DOCS + "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." + ) + + # define cotire target properties + + define_property( + TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED + BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." + FULL_DOCS + "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." + "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." + "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." + "The target name will be set to this target's name with the suffix _pch appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED + BRIEF_DOCS "Add a new target that performs a unity build for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." + "Most of the relevant target properties will be copied from this target to the new unity build target." + "Target dependencies and linked libraries have to be manually set up for the new unity build target." + "The unity target name will be set to this target's name with the suffix _unity appended." + "Inherited from directory." + "Defaults to TRUE." + ) + + define_property( + TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED + BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." + FULL_DOCS + "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." + "The clean target name will be set to this target's name with the suffix _clean_cotire appended." + "Inherited from directory." + "Defaults to FALSE." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED + BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." + "Inherited from directory." + "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED + BRIEF_DOCS "Honor headers from these directories when generating the prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." + "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," + "the option which yields the closer relative path match wins." + "Inherited from directory." + "If not set, this property is initialized to the empty list." + ) + + define_property( + TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED + BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." + FULL_DOCS + "The property can be set to a list of directories." + "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." + "Header files are sorted according to the order of the directories in the property." + "If not set, this property is initialized to the empty list." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after each target source file." + "Inherited from directory." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED + BRIEF_DOCS "Maximum number of source files to include in a single unity source file." + FULL_DOCS + "This may be set to an integer > 0." + "If a target contains more than that number of source files, cotire will create multiple unity build files for it." + "If not set, cotire will only create a single unity source file." + "Inherited from directory." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" + BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." + FULL_DOCS + "If set, cotire will only add the given file(s) to the generated unity source file." + "If not set, cotire will add all the target source files to the generated unity source file." + "The property can be set to a user provided unity source file." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" + BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." + FULL_DOCS + "If set, cotire will add the given header file(s) to the generated prefix header file." + "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." + "The property can be set to a user provided prefix header file (e.g., stdafx.h)." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED + BRIEF_DOCS "Define strategy for setting up unity target's link libraries." + FULL_DOCS + "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." + "If this property is set to COPY, the unity target's link libraries will be copied from this target." + "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." + "Inherited from directory." + "Defaults to empty." + ) + + define_property( + TARGET PROPERTY "COTIRE__UNITY_SOURCE" + BRIEF_DOCS "Read-only property. The generated unity source file(s)." + FULL_DOCS + "cotire sets this property to the path of the generated single computation unit source file for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PREFIX_HEADER" + BRIEF_DOCS "Read-only property. The generated prefix header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language prefix header for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" + BRIEF_DOCS "Read-only property. The generated precompiled header file." + FULL_DOCS + "cotire sets this property to the full path of the generated language precompiled header binary for the target." + "Defaults to empty string." + ) + + define_property( + TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" + BRIEF_DOCS "The name of the generated unity build target corresponding to this target." + FULL_DOCS + "This property can be set to the desired name of the unity target that will be created by cotire." + "If not set, the unity target name will be set to this target's name with the suffix _unity appended." + "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." + "Defaults to empty string." + ) + + # define cotire source properties + + define_property( + SOURCE PROPERTY "COTIRE_EXCLUDED" + BRIEF_DOCS "Do not modify source file's build command." + FULL_DOCS + "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." + "The source file will also be excluded from the generated unity source file." + "Source files that have their COMPILE_FLAGS property set will be excluded by default." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_DEPENDENCY" + BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." + FULL_DOCS + "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." + "If the file is modified, cotire will re-generate the prefix header source upon build." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file before this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" + BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." + FULL_DOCS + "This may be set to a semicolon-separated list of preprocessor symbols." + "cotire will add corresponding #undef directives to the generated unit source file after this file is included." + "Defaults to empty string." + ) + + define_property( + SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" + BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." + FULL_DOCS + "If this property is set to TRUE, cotire will complete the current unity file and start a new one." + "The new unity source file will include this source file as the first one." + "This property essentially works as a separator for unity source files." + "Defaults to FALSE." + ) + + define_property( + SOURCE PROPERTY "COTIRE_TARGET" + BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." + FULL_DOCS + "cotire sets this property to the name of target, that the source file's build command has been altered for." + "Defaults to empty string." + ) + + message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") + +endif() diff --git a/build_deb.sh b/build_deb.sh new file mode 100755 index 0000000..cc8a871 --- /dev/null +++ b/build_deb.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +V=$(grep -i "project.*VERSION" CMakeLists.txt | sed 's/.* \([0-9.]*\).*)/\1/') +D=$(mktemp -d "/tmp/myx-cmake.XXXXXX") +mkdir -p "$D/myx-cmake-$V" +cp -ap CMakeLists.txt MyxCMake "$D/myx-cmake-$V" +pushd "$D" +tar Jcf "myx-cmake_${V}.orig.tar.xz" "myx-cmake-$V" +popd +cp -ap debian "$D/myx-cmake-$V" +pushd "$D/myx-cmake-$V" +dch -D unstable -v "${V}-1" -m "New version." +debuild +popd + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..2599f60 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +myx-cmake (0.1.0-1) unstable; urgency=medium + + * New version. + + -- Andrey Astafyev Wed, 08 Dec 2021 14:23:03 +0300 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..22b8af3 --- /dev/null +++ b/debian/control @@ -0,0 +1,15 @@ +Source: myx-cmake +Section: utils +Priority: optional +Maintainer: Andrey Astafyev +Build-Depends: debhelper (>= 9), cmake +Standards-Version: 4.2.0 + +Package: myx-cmake +Architecture: all +Section: utils +Depends: cmake +Recommends: cmake-format +Description: CMake functions library + CMake functions library + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..050e29a --- /dev/null +++ b/debian/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ --buildsystem=cmake diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/source/options b/debian/source/options new file mode 100644 index 0000000..37913d1 --- /dev/null +++ b/debian/source/options @@ -0,0 +1,4 @@ +compression = "xz" +compression-level = 9 +extend-diff-ignore = "(^l10n\/.*ts)$" +