diff --git a/cmake/modules/3rdParty.cmake b/cmake/modules/3rdParty.cmake index e3501dd..2871b23 100644 --- a/cmake/modules/3rdParty.cmake +++ b/cmake/modules/3rdParty.cmake @@ -1,272 +1,273 @@ cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) -if(NOT DEFINED THIRD_PARTY_MODULE_LOADED) - - macro(save_default_library_suffixes) - set(DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - endmacro() - - macro(restore_default_library_suffixes) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES}) - unset(DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES) - endmacro() - - macro(configure_static_library_suffixes) - # allows to look for static libraries in particular - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a) - endif() - endmacro() - - macro(configure_dynamic_library_suffixes) - # allows to look for dynamic libraries in particular - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES .dll .dll.a) - elseif(APPLE) - set(CMAKE_FIND_LIBRARY_SUFFIXES .dylib .so) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .so) - endif() - endmacro() - - macro(link_against_library_varnames NAME LINKAGE REQUIRED PRIVATE_LIBRARIES_VARNAME PUBLIC_LIBRARIES_VARNAME PRIVATE_STATIC_LIBRARIES_VARNAME PUBLIC_STATIC_LIBRARIES_VARNAME) - # determine whether the library is required or optional - # FIXME: improve passing required argument - if("${REQUIRED}" STREQUAL "OPTIONAL") - set(${NAME}_REQUIRED "NO") - elseif("${REQUIRED}" STREQUAL "REQUIRED") - set(${NAME}_REQUIRED "REQUIRED") - else() - message(FATAL_ERROR "Invalid use of link_against_library; must specify either REQUIRED or OPTIONAL.") - endif() - - # add library to list of libraries to link against when building dynamic libraries or applications - # - prefer dynamic lib if linkage not explicitely specified - if(${NAME}_STATIC_LIB AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE" AND ((NOT (${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB)) OR (STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${LINKAGE}" STREQUAL "STATIC"))) - set(USE_${NAME} ON) - set(USE_STATIC_${NAME} ON) - list(APPEND LIBRARIES ${${NAME}_STATIC_LIB}) - message(STATUS "Linking ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} statically against external library ${NAME} (${${NAME}_STATIC_LIB}).") - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND ADDITIONAL_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - message(STATUS "Adding include path for ${NAME} to ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_STATIC_INCLUDE_DIR}") - endif() - - if(${${NAME}_STATIC_LIB} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS) - list(APPEND ${PUBLIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND PUBLIC_SHARED_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - endif() - else() - list(APPEND ${PRIVATE_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND PRIVATE_SHARED_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - endif() - endif() - - # add Qt resources of static library to be enabled - if(${NAME}_QT_RESOURCES) - message(STATUS "Adding ${${NAME}_QT_RESOURCES} to LIBRARIES_QT_RESOURCES for ${META_PROJECT_NAME}.") - list(APPEND LIBRARIES_QT_RESOURCES ${${NAME}_QT_RESOURCES}) - endif() - - elseif((${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB) AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE") OR ("${LINKAGE}" STREQUAL "SHARED"))) - set(USE_${NAME} ON) - set(USE_SHARED_${NAME} ON) - if(NOT ${NAME}_DYNAMIC_LIB) - set(${NAME}_DYNAMIC_LIB ${${NAME}_SHARED_LIB}) - endif() - list(APPEND LIBRARIES ${${NAME}_DYNAMIC_LIB}) - message(STATUS "Linking ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} dynamically against external library ${NAME} (${${NAME}_DYNAMIC_LIB}).") - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND ADDITIONAL_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - message(STATUS "Adding include path for ${NAME} to ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_DYNAMIC_INCLUDE_DIR}") - endif() - - if(${${NAME}_DYNAMIC_LIB} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS) - list(APPEND ${PUBLIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND PUBLIC_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - endif() - else() - list(APPEND ${PRIVATE_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND PRIVATE_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - endif() - endif() - else() - if(${NAME}_REQUIRED) - message(FATAL_ERROR "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") - else() - message(WARNING "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") - endif() - endif() - - # add library to list of libraries to be provided as transitive dependencies when building static libraries - # - prefer static lib if linkage not explicitely specified - if(${NAME}_STATIC_LIB AND ("${LINKAGE}" STREQUAL "AUTO_LINKAGE") OR ("${LINKAGE}" STREQUAL "STATIC")) - set(USE_${NAME} ON) - set(USE_STATIC_${NAME} ON) - list(APPEND STATIC_LIBRARIES ${${NAME}_STATIC_LIB}) - message(STATUS "Adding static external library ${NAME} (${${NAME}_STATIC_LIB}) to dependencies of ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}.") - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND ADDITIONAL_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - message(STATUS "Adding include path for ${NAME} to static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_STATIC_INCLUDE_DIR}") - endif() - - if(${${NAME}_STATIC_LIB} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS) - list(APPEND ${PUBLIC_STATIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND PUBLIC_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - endif() - else() - list(APPEND ${PRIVATE_STATIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) - if(${NAME}_STATIC_INCLUDE_DIR) - list(APPEND PRIVATE_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) - endif() - endif() - - # add Qt resources of static library for exporting it - if(${NAME}_QT_RESOURCES) - message(STATUS "Adding ${${NAME}_QT_RESOURCES} to STATIC_LIBRARIES_QT_RESOURCES for ${META_PROJECT_NAME}.") - list(APPEND STATIC_LIBRARIES_QT_RESOURCES ${${NAME}_QT_RESOURCES}) - endif() - - elseif((${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB) AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE" AND (NOT ${NAME}_STATIC_LIB OR (NOT STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (NOT STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${LINKAGE}" STREQUAL "SHARED"))) - set(USE_${NAME} ON) - set(USE_SHARED_${NAME} ON) - if(NOT ${NAME}_DYNAMIC_LIB) - set(${NAME}_DYNAMIC_LIB ${${NAME}_SHARED_LIB}) - endif() - list(APPEND STATIC_LIBRARIES ${${NAME}_DYNAMIC_LIB}) - message(STATUS "Adding dynamic external library ${NAME} (${${NAME}_DYNAMIC_LIB}) to dependencies of static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}.") - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND ADDITIONAL_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - message(STATUS "Adding include path for ${NAME} to static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_DYNAMIC_INCLUDE_DIR}") - endif() - - if(${${NAME}_DYNAMIC_LIB} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS) - list(APPEND ${PUBLIC_STATIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND PUBLIC_STATIC_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - endif() - else() - list(APPEND ${PRIVATE_STATIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) - if(${NAME}_DYNAMIC_INCLUDE_DIR) - list(APPEND PRIVATE_STATIC_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) - endif() - endif() - else() - if(${NAME}_REQUIRED) - message(FATAL_ERROR "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") - else() - message(WARNING "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") - endif() - endif() - endmacro() - - macro(link_against_library NAME LINKAGE REQUIRED) - link_against_library_varnames("${NAME}" "${LINKAGE}" "${REQUIRED}" - PRIVATE_LIBRARIES PUBLIC_LIBRARIES PRIVATE_STATIC_LIBRARIES PUBLIC_STATIC_LIBRARIES - ) - endmacro() - - macro(link_tests_against_library NAME LINKAGE REQUIRED) - link_against_library_varnames("${NAME}" "${LINKAGE}" "${REQUIRED}" - TEST_LIBRARIES TEST_LIBRARIES STATIC_TEST_LIBRARIES STATIC_TEST_LIBRARIES - ) - endmacro() - - macro(find_external_library NAME LINKAGE REQUIRED) - set(${NAME}_DYNAMIC_INCLUDE_DIR NOTFOUND CACHE PATH "${NAME} include dir (dynamic)") - set(${NAME}_DYNAMIC_LIB NOTFOUND CACHE FILEPATH "${NAME} lib (dynamic)") - set(${NAME}_STATIC_INCLUDE_DIR NOTFOUND CACHE PATH "${NAME} include dir (static)") - set(${NAME}_STATIC_LIB NOTFOUND CACHE FILEPATH "${NAME} lib (static)") - - save_default_library_suffixes() - - if(NOT ${NAME}_DYNAMIC_LIB) - configure_dynamic_library_suffixes() - find_library(DETECTED_${NAME}_DYNAMIC_LIB ${NAME}) - set(${NAME}_DYNAMIC_LIB ${DETECTED_${NAME}_DYNAMIC_LIB} CACHE FILEPATH "${NAME} lib (dynamic)" FORCE) - endif() - - if(NOT ${NAME}_STATIC_LIB) - configure_static_library_suffixes() - find_library(DETECTED_${NAME}_STATIC_LIB ${NAME}) - set(${NAME}_STATIC_LIB ${DETECTED_${NAME}_STATIC_LIB} CACHE FILEPATH "${NAME} lib (static)" FORCE) - endif() - - restore_default_library_suffixes() - endmacro() - - macro(use_external_library NAME LINKAGE REQUIRED) - find_external_library("${NAME}" "${LINKAGE}" "${REQUIRED}") - link_against_library("${NAME}" "${LINKAGE}" "${REQUIRED}") - endmacro() - - function(use_external_library_from_package_dynamic NAME PKGNAME INCLUDE_VAR LIBRARY_VAR COMPAT_VERSION) - # internally used by find_external_library_from_package to find dynamic libraries - configure_dynamic_library_suffixes() - find_package(${PKGNAME} ${COMPAT_VERSION}) - set(${NAME}_DYNAMIC_INCLUDE_DIR ${${INCLUDE_VAR}} CACHE PATH "${NAME} include dir (dynamic)" FORCE) - set(${NAME}_DYNAMIC_LIB ${${LIBRARY_VAR}} CACHE FILEPATH "${NAME} lib (dynamic)" FORCE) - endfunction() - - function(use_external_library_from_package_static NAME PKGNAME INCLUDE_VAR LIBRARY_VAR COMPAT_VERSION) - # internally used by find_external_library_from_package to find static libraries - configure_static_library_suffixes() - find_package(${PKGNAME} ${COMPAT_VERSION}) - set(${NAME}_STATIC_INCLUDE_DIR ${${INCLUDE_VAR}} CACHE PATH "${NAME} include dir (static)" FORCE) - set(${NAME}_STATIC_LIB ${${LIBRARY_VAR}} CACHE FILEPATH "${NAME} lib (static)" FORCE) - endfunction() - - macro(find_external_library_from_package NAME PKGNAME VERSION INCLUDE_VAR LIBRARY_VAR LINKAGE REQUIRED) - # handle specified VERSION - if("${VERSION}" STREQUAL "ANY_VERSION") - set(${NAME}_COMPATIBLE_VERSION "") - else() - set(${NAME}_COMPATIBLE_VERSION ${VERSION}) - endif() - - # use the find_library approach first because it is less buggy when trying to detect static libraries - # caveat: this way include dirs are not detected - however those are mostly the the default anyways and - # can also be set manually by the user in case the auto-detection is not sufficient - find_external_library("${NAME}" "${LINKAGE}" OPTIONAL) - - # fall back to actual use of find_package - # use separate functions to get a new scope - save_default_library_suffixes() - if(NOT ${NAME}_DYNAMIC_LIB) - use_external_library_from_package_dynamic(${NAME} ${PKGNAME} ${INCLUDE_VAR} "${LIBRARY_VAR}" "${${NAME}_COMPATIBLE_VERSION}") - endif() - if(NOT ${NAME}_STATIC_LIB) - use_external_library_from_package_static(${NAME} ${PKGNAME} ${INCLUDE_VAR} "${LIBRARY_VAR}" "${${NAME}_COMPATIBLE_VERSION}") - endif() - restore_default_library_suffixes() - endmacro() - - macro(use_external_library_from_package NAME PKGNAME VERSION INCLUDE_VAR LIBRARY_VAR LINKAGE REQUIRED) - find_external_library_from_package("${NAME}" "${PKGNAME}" "${VERSION}" "${INCLUDE_VAR}" "${LIBRARY_VAR}" "${LINKAGE}" "${REQUIRED}") - link_against_library("${NAME}" "${LINKAGE}" "${REQUIRED}") - endmacro() - - macro(use_iconv LINKAGE REQUIRED) - set(FORCE_EXTERNAL_ICONV OFF CACHE PATH "whether to force usage of external iconv (rather than the using the one bundled with glibc)") - if(NOT FORCE_EXTERNAL_ICONV) - # check whether iconv exists in standard lib - include(CheckFunctionExists) - check_function_exists(iconv HAS_ICONV) - endif() - if(NOT FORCE_EXTERNAL_ICONV AND HAS_ICONV) - message(STATUS "Using iconv from the standard library for ${META_PROJECT_NAME}.") - else() - # find external iconv library - use_external_library(iconv ${LINKAGE} ${REQUIRED}) - endif() - endmacro() - - set(THIRD_PARTY_MODULE_LOADED YES) +# prevent multiple inclusion +if(DEFINED THIRD_PARTY_MODULE_LOADED) + return() endif() +set(THIRD_PARTY_MODULE_LOADED YES) + +macro(save_default_library_suffixes) + set(DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) +endmacro() + +macro(restore_default_library_suffixes) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES}) + unset(DEFAULT_CMAKE_FIND_LIBRARY_SUFFIXES) +endmacro() + +macro(configure_static_library_suffixes) + # allows to look for static libraries in particular + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + endif() +endmacro() + +macro(configure_dynamic_library_suffixes) + # allows to look for dynamic libraries in particular + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .dll .dll.a) + elseif(APPLE) + set(CMAKE_FIND_LIBRARY_SUFFIXES .dylib .so) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .so) + endif() +endmacro() + +macro(link_against_library_varnames NAME LINKAGE REQUIRED PRIVATE_LIBRARIES_VARNAME PUBLIC_LIBRARIES_VARNAME PRIVATE_STATIC_LIBRARIES_VARNAME PUBLIC_STATIC_LIBRARIES_VARNAME) + # determine whether the library is required or optional + # FIXME: improve passing required argument + if("${REQUIRED}" STREQUAL "OPTIONAL") + set(${NAME}_REQUIRED "NO") + elseif("${REQUIRED}" STREQUAL "REQUIRED") + set(${NAME}_REQUIRED "REQUIRED") + else() + message(FATAL_ERROR "Invalid use of link_against_library; must specify either REQUIRED or OPTIONAL.") + endif() + + # add library to list of libraries to link against when building dynamic libraries or applications + # - prefer dynamic lib if linkage not explicitely specified + if(${NAME}_STATIC_LIB AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE" AND ((NOT (${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB)) OR (STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${LINKAGE}" STREQUAL "STATIC"))) + set(USE_${NAME} ON) + set(USE_STATIC_${NAME} ON) + list(APPEND LIBRARIES ${${NAME}_STATIC_LIB}) + message(STATUS "Linking ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} statically against external library ${NAME} (${${NAME}_STATIC_LIB}).") + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND ADDITIONAL_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + message(STATUS "Adding include path for ${NAME} to ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_STATIC_INCLUDE_DIR}") + endif() + + if(${${NAME}_STATIC_LIB} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS) + list(APPEND ${PUBLIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND PUBLIC_SHARED_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + endif() + else() + list(APPEND ${PRIVATE_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND PRIVATE_SHARED_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + endif() + endif() + + # add Qt resources of static library to be enabled + if(${NAME}_QT_RESOURCES) + message(STATUS "Adding ${${NAME}_QT_RESOURCES} to LIBRARIES_QT_RESOURCES for ${META_PROJECT_NAME}.") + list(APPEND LIBRARIES_QT_RESOURCES ${${NAME}_QT_RESOURCES}) + endif() + + elseif((${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB) AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE") OR ("${LINKAGE}" STREQUAL "SHARED"))) + set(USE_${NAME} ON) + set(USE_SHARED_${NAME} ON) + if(NOT ${NAME}_DYNAMIC_LIB) + set(${NAME}_DYNAMIC_LIB ${${NAME}_SHARED_LIB}) + endif() + list(APPEND LIBRARIES ${${NAME}_DYNAMIC_LIB}) + message(STATUS "Linking ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} dynamically against external library ${NAME} (${${NAME}_DYNAMIC_LIB}).") + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND ADDITIONAL_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + message(STATUS "Adding include path for ${NAME} to ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_DYNAMIC_INCLUDE_DIR}") + endif() + + if(${${NAME}_DYNAMIC_LIB} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS) + list(APPEND ${PUBLIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND PUBLIC_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + endif() + else() + list(APPEND ${PRIVATE_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND PRIVATE_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + endif() + endif() + else() + if(${NAME}_REQUIRED) + message(FATAL_ERROR "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") + else() + message(WARNING "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") + endif() + endif() + + # add library to list of libraries to be provided as transitive dependencies when building static libraries + # - prefer static lib if linkage not explicitely specified + if(${NAME}_STATIC_LIB AND ("${LINKAGE}" STREQUAL "AUTO_LINKAGE") OR ("${LINKAGE}" STREQUAL "STATIC")) + set(USE_${NAME} ON) + set(USE_STATIC_${NAME} ON) + list(APPEND STATIC_LIBRARIES ${${NAME}_STATIC_LIB}) + message(STATUS "Adding static external library ${NAME} (${${NAME}_STATIC_LIB}) to dependencies of ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}.") + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND ADDITIONAL_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + message(STATUS "Adding include path for ${NAME} to static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_STATIC_INCLUDE_DIR}") + endif() + + if(${${NAME}_STATIC_LIB} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_STATIC_LIB_DEPENDS) + list(APPEND ${PUBLIC_STATIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND PUBLIC_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + endif() + else() + list(APPEND ${PRIVATE_STATIC_LIBRARIES_VARNAME} ${${NAME}_STATIC_LIB}) + if(${NAME}_STATIC_INCLUDE_DIR) + list(APPEND PRIVATE_STATIC_INCLUDE_DIRS ${${NAME}_STATIC_INCLUDE_DIR}) + endif() + endif() + + # add Qt resources of static library for exporting it + if(${NAME}_QT_RESOURCES) + message(STATUS "Adding ${${NAME}_QT_RESOURCES} to STATIC_LIBRARIES_QT_RESOURCES for ${META_PROJECT_NAME}.") + list(APPEND STATIC_LIBRARIES_QT_RESOURCES ${${NAME}_QT_RESOURCES}) + endif() + + elseif((${NAME}_DYNAMIC_LIB OR ${NAME}_SHARED_LIB) AND (("${LINKAGE}" STREQUAL "AUTO_LINKAGE" AND (NOT ${NAME}_STATIC_LIB OR (NOT STATIC_LINKAGE AND "${META_PROJECT_TYPE}" STREQUAL "application") OR (NOT STATIC_LIBRARY_LINKAGE AND ("${META_PROJECT_TYPE}" STREQUAL "" OR "${META_PROJECT_TYPE}" STREQUAL "library")))) OR ("${LINKAGE}" STREQUAL "SHARED"))) + set(USE_${NAME} ON) + set(USE_SHARED_${NAME} ON) + if(NOT ${NAME}_DYNAMIC_LIB) + set(${NAME}_DYNAMIC_LIB ${${NAME}_SHARED_LIB}) + endif() + list(APPEND STATIC_LIBRARIES ${${NAME}_DYNAMIC_LIB}) + message(STATUS "Adding dynamic external library ${NAME} (${${NAME}_DYNAMIC_LIB}) to dependencies of static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}.") + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND ADDITIONAL_SHARED_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + message(STATUS "Adding include path for ${NAME} to static ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}: ${${NAME}_DYNAMIC_INCLUDE_DIR}") + endif() + + if(${${NAME}_DYNAMIC_LIB} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS OR ${NAME} IN_LIST META_PUBLIC_SHARED_LIB_DEPENDS) + list(APPEND ${PUBLIC_STATIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND PUBLIC_STATIC_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + endif() + else() + list(APPEND ${PRIVATE_STATIC_LIBRARIES_VARNAME} ${${NAME}_DYNAMIC_LIB}) + if(${NAME}_DYNAMIC_INCLUDE_DIR) + list(APPEND PRIVATE_STATIC_INCLUDE_DIRS ${${NAME}_DYNAMIC_INCLUDE_DIR}) + endif() + endif() + else() + if(${NAME}_REQUIRED) + message(FATAL_ERROR "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") + else() + message(WARNING "External library ${NAME} required by ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} is not available for the specified linkage ${LINKAGE}.") + endif() + endif() +endmacro() + +macro(link_against_library NAME LINKAGE REQUIRED) + link_against_library_varnames("${NAME}" "${LINKAGE}" "${REQUIRED}" + PRIVATE_LIBRARIES PUBLIC_LIBRARIES PRIVATE_STATIC_LIBRARIES PUBLIC_STATIC_LIBRARIES + ) +endmacro() + +macro(link_tests_against_library NAME LINKAGE REQUIRED) + link_against_library_varnames("${NAME}" "${LINKAGE}" "${REQUIRED}" + TEST_LIBRARIES TEST_LIBRARIES STATIC_TEST_LIBRARIES STATIC_TEST_LIBRARIES + ) +endmacro() + +macro(find_external_library NAME LINKAGE REQUIRED) + set(${NAME}_DYNAMIC_INCLUDE_DIR NOTFOUND CACHE PATH "${NAME} include dir (dynamic)") + set(${NAME}_DYNAMIC_LIB NOTFOUND CACHE FILEPATH "${NAME} lib (dynamic)") + set(${NAME}_STATIC_INCLUDE_DIR NOTFOUND CACHE PATH "${NAME} include dir (static)") + set(${NAME}_STATIC_LIB NOTFOUND CACHE FILEPATH "${NAME} lib (static)") + + save_default_library_suffixes() + + if(NOT ${NAME}_DYNAMIC_LIB) + configure_dynamic_library_suffixes() + find_library(DETECTED_${NAME}_DYNAMIC_LIB ${NAME}) + set(${NAME}_DYNAMIC_LIB ${DETECTED_${NAME}_DYNAMIC_LIB} CACHE FILEPATH "${NAME} lib (dynamic)" FORCE) + endif() + + if(NOT ${NAME}_STATIC_LIB) + configure_static_library_suffixes() + find_library(DETECTED_${NAME}_STATIC_LIB ${NAME}) + set(${NAME}_STATIC_LIB ${DETECTED_${NAME}_STATIC_LIB} CACHE FILEPATH "${NAME} lib (static)" FORCE) + endif() + + restore_default_library_suffixes() +endmacro() + +macro(use_external_library NAME LINKAGE REQUIRED) + find_external_library("${NAME}" "${LINKAGE}" "${REQUIRED}") + link_against_library("${NAME}" "${LINKAGE}" "${REQUIRED}") +endmacro() + +function(use_external_library_from_package_dynamic NAME PKGNAME INCLUDE_VAR LIBRARY_VAR COMPAT_VERSION) + # internally used by find_external_library_from_package to find dynamic libraries + configure_dynamic_library_suffixes() + find_package(${PKGNAME} ${COMPAT_VERSION}) + set(${NAME}_DYNAMIC_INCLUDE_DIR ${${INCLUDE_VAR}} CACHE PATH "${NAME} include dir (dynamic)" FORCE) + set(${NAME}_DYNAMIC_LIB ${${LIBRARY_VAR}} CACHE FILEPATH "${NAME} lib (dynamic)" FORCE) +endfunction() + +function(use_external_library_from_package_static NAME PKGNAME INCLUDE_VAR LIBRARY_VAR COMPAT_VERSION) + # internally used by find_external_library_from_package to find static libraries + configure_static_library_suffixes() + find_package(${PKGNAME} ${COMPAT_VERSION}) + set(${NAME}_STATIC_INCLUDE_DIR ${${INCLUDE_VAR}} CACHE PATH "${NAME} include dir (static)" FORCE) + set(${NAME}_STATIC_LIB ${${LIBRARY_VAR}} CACHE FILEPATH "${NAME} lib (static)" FORCE) +endfunction() + +macro(find_external_library_from_package NAME PKGNAME VERSION INCLUDE_VAR LIBRARY_VAR LINKAGE REQUIRED) + # handle specified VERSION + if("${VERSION}" STREQUAL "ANY_VERSION") + set(${NAME}_COMPATIBLE_VERSION "") + else() + set(${NAME}_COMPATIBLE_VERSION ${VERSION}) + endif() + + # use the find_library approach first because it is less buggy when trying to detect static libraries + # caveat: this way include dirs are not detected - however those are mostly the the default anyways and + # can also be set manually by the user in case the auto-detection is not sufficient + find_external_library("${NAME}" "${LINKAGE}" OPTIONAL) + + # fall back to actual use of find_package + # use separate functions to get a new scope + save_default_library_suffixes() + if(NOT ${NAME}_DYNAMIC_LIB) + use_external_library_from_package_dynamic(${NAME} ${PKGNAME} ${INCLUDE_VAR} "${LIBRARY_VAR}" "${${NAME}_COMPATIBLE_VERSION}") + endif() + if(NOT ${NAME}_STATIC_LIB) + use_external_library_from_package_static(${NAME} ${PKGNAME} ${INCLUDE_VAR} "${LIBRARY_VAR}" "${${NAME}_COMPATIBLE_VERSION}") + endif() + restore_default_library_suffixes() +endmacro() + +macro(use_external_library_from_package NAME PKGNAME VERSION INCLUDE_VAR LIBRARY_VAR LINKAGE REQUIRED) + find_external_library_from_package("${NAME}" "${PKGNAME}" "${VERSION}" "${INCLUDE_VAR}" "${LIBRARY_VAR}" "${LINKAGE}" "${REQUIRED}") + link_against_library("${NAME}" "${LINKAGE}" "${REQUIRED}") +endmacro() + +macro(use_iconv LINKAGE REQUIRED) + set(FORCE_EXTERNAL_ICONV OFF CACHE PATH "whether to force usage of external iconv (rather than the using the one bundled with glibc)") + if(NOT FORCE_EXTERNAL_ICONV) + # check whether iconv exists in standard lib + include(CheckFunctionExists) + check_function_exists(iconv HAS_ICONV) + endif() + if(NOT FORCE_EXTERNAL_ICONV AND HAS_ICONV) + message(STATUS "Using iconv from the standard library for ${META_PROJECT_NAME}.") + else() + # find external iconv library + use_external_library(iconv ${LINKAGE} ${REQUIRED}) + endif() +endmacro() diff --git a/cmake/modules/Doxygen.cmake b/cmake/modules/Doxygen.cmake index 9c74f58..48c815a 100644 --- a/cmake/modules/Doxygen.cmake +++ b/cmake/modules/Doxygen.cmake @@ -3,78 +3,79 @@ if(NOT BASIC_PROJECT_CONFIG_DONE) endif() option(NO_DOXYGEN "whether creation of Doxygen targets is disabled (enabled by default)" OFF) - if(NOT NO_DOXYGEN) - # find doxygen.h template - include(TemplateFinder) - find_template_file("doxygen" CPP_UTILITIES DOXYGEN_TEMPLATE_FILE) + return() +endif() - # find executables - find_program(DOXYGEN_BIN doxygen) - find_program(PERL_BIN perl) - find_program(DIA_BIN dia) - if(DIA_BIN) - set(HAVE_DIA "YES") - else() - set(HAVE_DIA "NO") - endif() - find_program(DOT_BIN dot) - if(DOT_BIN) - set(HAVE_DOT "YES") - else() - set(HAVE_DOT "NO") - endif() +# find doxygen.h template +include(TemplateFinder) +find_template_file("doxygen" CPP_UTILITIES DOXYGEN_TEMPLATE_FILE) - if(NOT DOXYGEN_BIN) - message(WARNING "Doxygen not found, unable to add target for generating API documentation for ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}") - else() - # load cached configuration and other variables - set(DOXY_LANGUAGE "English" CACHE STRING "specifies the language of the API documentation generated with Doxygen") - set(DOXY_CUSTOM_CONFIG "" CACHE STRING "specifies extra options for Doxygen") - set(DOXY_NUMBER "${META_APP_VERSION}") - set(DOXY_INPUT_FILES - ${HEADER_FILES} ${SRC_FILES} ${TEST_HEADER_FILES} ${TEST_SRC_FILES} ${WIDGETS_HEADER_FILES} ${WIDGETS_SRC_FILES} - ${QML_HEADER_FILES} ${QML_SRC_FILES} ${DOC_FILES} ${DOC_ONLY_FILES} +# find executables +find_program(DOXYGEN_BIN doxygen) +find_program(PERL_BIN perl) +find_program(DIA_BIN dia) +if(DIA_BIN) + set(HAVE_DIA "YES") +else() + set(HAVE_DIA "NO") +endif() +find_program(DOT_BIN dot) +if(DOT_BIN) + set(HAVE_DOT "YES") +else() + set(HAVE_DOT "NO") +endif() + +if(NOT DOXYGEN_BIN) + message(WARNING "Doxygen not found, unable to add target for generating API documentation for ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}") + return() +endif() + +# load cached configuration and other variables +set(DOXY_LANGUAGE "English" CACHE STRING "specifies the language of the API documentation generated with Doxygen") +set(DOXY_CUSTOM_CONFIG "" CACHE STRING "specifies extra options for Doxygen") +set(DOXY_NUMBER "${META_APP_VERSION}") +set(DOXY_INPUT_FILES + ${HEADER_FILES} ${SRC_FILES} ${TEST_HEADER_FILES} ${TEST_SRC_FILES} ${WIDGETS_HEADER_FILES} ${WIDGETS_SRC_FILES} + ${QML_HEADER_FILES} ${QML_SRC_FILES} ${DOC_FILES} ${DOC_ONLY_FILES} +) +set(DOXY_PATH_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/") +list(GET DOC_FILES 0 DOXY_MAIN_PAGE_FILE) +set(DOXY_MAIN_PAGE_FILE "${DOXY_PATH_PREFIX}${DOXY_MAIN_PAGE_FILE}") + +# convert DOXY_INPUT_FILES to whitespace-separated list +include(ListToString) +list_to_string(" " "\"${DOXY_PATH_PREFIX}" "\"" "${DOXY_INPUT_FILES}" DOXY_INPUT_FILES_WHITESPACE_SEPARATED) + +# generate Doxygen configuration +configure_file( + "${DOXYGEN_TEMPLATE_FILE}" + "${CMAKE_CURRENT_BINARY_DIR}/doxygen.config" +) + +# add target for generating API documentation +add_custom_target("${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_apidoc" + COMMAND "${DOXYGEN_BIN}" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.config" + SOURCES ${DOXY_INPUT_FILES} +) +if(NOT TARGET apidoc) + add_custom_target(apidoc) +endif() +add_dependencies(apidoc "${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_apidoc") + +# add install target for API documentation +if(NOT META_NO_INSTALL_TARGETS AND ENABLE_INSTALL_TARGETS) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/api-doc" + DESTINATION "share/${META_PROJECT_NAME}" + COMPONENT api-doc + OPTIONAL + ) + if(NOT TARGET install-api-doc) + add_custom_target(install-api-doc + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=api-doc -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" ) - set(DOXY_PATH_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/") - list(GET DOC_FILES 0 DOXY_MAIN_PAGE_FILE) - set(DOXY_MAIN_PAGE_FILE "${DOXY_PATH_PREFIX}${DOXY_MAIN_PAGE_FILE}") - - # convert DOXY_INPUT_FILES to whitespace-separated list - include(ListToString) - list_to_string(" " "\"${DOXY_PATH_PREFIX}" "\"" "${DOXY_INPUT_FILES}" DOXY_INPUT_FILES_WHITESPACE_SEPARATED) - - # generate Doxygen configuration - configure_file( - "${DOXYGEN_TEMPLATE_FILE}" - "${CMAKE_CURRENT_BINARY_DIR}/doxygen.config" - ) - - # add target for generating API documentation - add_custom_target("${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_apidoc" - COMMAND "${DOXYGEN_BIN}" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.config" - SOURCES ${DOXY_INPUT_FILES} - ) - if(NOT TARGET apidoc) - add_custom_target(apidoc) - endif() - add_dependencies(apidoc "${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX}_apidoc") - - # add install target for API documentation - if(NOT META_NO_INSTALL_TARGETS AND ENABLE_INSTALL_TARGETS) - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/api-doc" - DESTINATION "share/${META_PROJECT_NAME}" - COMPONENT api-doc - OPTIONAL - ) - if(NOT TARGET install-api-doc) - add_custom_target(install-api-doc - COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=api-doc -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" - ) - endif() - endif() - - message(STATUS "Generating target for generating API documentation for ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} with Doxygen") - endif() endif() + +message(STATUS "Generating target for generating API documentation for ${TARGET_PREFIX}${META_PROJECT_NAME}${TARGET_SUFFIX} with Doxygen") diff --git a/cmake/modules/ShellCompletion.cmake b/cmake/modules/ShellCompletion.cmake index 3242bde..a93910c 100644 --- a/cmake/modules/ShellCompletion.cmake +++ b/cmake/modules/ShellCompletion.cmake @@ -4,34 +4,35 @@ endif() option(SHELL_COMPLETION_ENABLED "controls whether shell completion is enabled in general" ON) option(BASH_COMPLETION_ENABLED "controls whether shell completion for bash is enabled" ON) - -if(SHELL_COMPLETION_ENABLED) - # add bash completion (currently the only supported shell completion) - if(BASH_COMPLETION_ENABLED) - # find bash-completion.sh template - include(TemplateFinder) - find_template_file("bash-completion.sh" CPP_UTILITIES BASH_COMPLETION_TEMPLATE_FILE) - - # generate wrapper script for bash completion - configure_file( - "${BASH_COMPLETION_TEMPLATE_FILE}" - "${CMAKE_CURRENT_BINARY_DIR}/bash-completion/completions/${META_PROJECT_NAME}" - @ONLY - ) - - # add install target bash completion - if(NOT META_NO_INSTALL_TARGETS AND ENABLE_INSTALL_TARGETS) - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bash-completion/completions" - DESTINATION "share/bash-completion" - COMPONENT bash-completion - ) - if(NOT TARGET install-bash-completion) - add_custom_target(install-bash-completion - COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=bash-completion -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" - ) - endif() - endif() - - message(STATUS "Generating files for bash completion.") - endif() +if(NOT SHELL_COMPLETION_ENABLED) + return() +endif() + +# add bash completion (currently the only supported shell completion) +if(BASH_COMPLETION_ENABLED) + # find bash-completion.sh template + include(TemplateFinder) + find_template_file("bash-completion.sh" CPP_UTILITIES BASH_COMPLETION_TEMPLATE_FILE) + + # generate wrapper script for bash completion + configure_file( + "${BASH_COMPLETION_TEMPLATE_FILE}" + "${CMAKE_CURRENT_BINARY_DIR}/bash-completion/completions/${META_PROJECT_NAME}" + @ONLY + ) + + # add install target bash completion + if(NOT META_NO_INSTALL_TARGETS AND ENABLE_INSTALL_TARGETS) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bash-completion/completions" + DESTINATION "share/bash-completion" + COMPONENT bash-completion + ) + if(NOT TARGET install-bash-completion) + add_custom_target(install-bash-completion + COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=bash-completion -P "${CMAKE_BINARY_DIR}/cmake_install.cmake" + ) + endif() + endif() + + message(STATUS "Generating files for bash completion.") endif() diff --git a/cmake/modules/TemplateFinder.cmake b/cmake/modules/TemplateFinder.cmake index 9d263b3..1bddda5 100644 --- a/cmake/modules/TemplateFinder.cmake +++ b/cmake/modules/TemplateFinder.cmake @@ -1,22 +1,23 @@ -if(NOT DEFINED TEMPLATE_FINDER_LOADED) - - function(find_template_file FILE_NAME PROJECT_VAR_NAME OUTPUT_VAR) - if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in") - # check own source directory - set(${OUTPUT_VAR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in" PARENT_SCOPE) - message(STATUS "Using template for ${FILE_NAME} from own (${META_PROJECT_NAME}) source directory.") - elseif(EXISTS "${${PROJECT_VAR_NAME}_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in") - # check sources of project - set(${OUTPUT_VAR} "${${PROJECT_VAR_NAME}_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in" PARENT_SCOPE) - message(STATUS "Using template for ${FILE_NAME} from ${PROJECT_VAR_NAME} source directory.") - elseif(EXISTS "${${PROJECT_VAR_NAME}_CONFIG_DIRS}/templates/${FILE_NAME}.in") - # check installed version of project - set(${OUTPUT_VAR} "${${PROJECT_VAR_NAME}_CONFIG_DIRS}/templates/${FILE_NAME}.in" PARENT_SCOPE) - message(STATUS "Using template for ${FILE_NAME} from ${PROJECT_VAR_NAME} installation.") - else() - message(FATAL_ERROR "Template for ${FILE_NAME} file can not be located.") - endif() - endfunction() - - set(TEMPLATE_FINDER_LOADED YES) +# prevent multiple inclusion +if(DEFINED TEMPLATE_FINDER_LOADED) + return() endif() +set(TEMPLATE_FINDER_LOADED YES) + +function(find_template_file FILE_NAME PROJECT_VAR_NAME OUTPUT_VAR) + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in") + # check own source directory + set(${OUTPUT_VAR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in" PARENT_SCOPE) + message(STATUS "Using template for ${FILE_NAME} from own (${META_PROJECT_NAME}) source directory.") + elseif(EXISTS "${${PROJECT_VAR_NAME}_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in") + # check sources of project + set(${OUTPUT_VAR} "${${PROJECT_VAR_NAME}_SOURCE_DIR}/cmake/templates/${FILE_NAME}.in" PARENT_SCOPE) + message(STATUS "Using template for ${FILE_NAME} from ${PROJECT_VAR_NAME} source directory.") + elseif(EXISTS "${${PROJECT_VAR_NAME}_CONFIG_DIRS}/templates/${FILE_NAME}.in") + # check installed version of project + set(${OUTPUT_VAR} "${${PROJECT_VAR_NAME}_CONFIG_DIRS}/templates/${FILE_NAME}.in" PARENT_SCOPE) + message(STATUS "Using template for ${FILE_NAME} from ${PROJECT_VAR_NAME} installation.") + else() + message(FATAL_ERROR "Template for ${FILE_NAME} file can not be located.") + endif() +endfunction() diff --git a/cmake/modules/WindowsResources.cmake b/cmake/modules/WindowsResources.cmake index 5028175..a9dfbc8 100644 --- a/cmake/modules/WindowsResources.cmake +++ b/cmake/modules/WindowsResources.cmake @@ -6,53 +6,55 @@ if(NOT BASIC_PROJECT_CONFIG_DONE) message(FATAL_ERROR "Before including the WindowsResources module, the LibraryConfig/ApplicationConfig module must be included.") endif() -option(WINDOWS_RESOURCES_ENABLED "controls Windows resources are enabled" ON) -option(WINDOWS_ICON_ENABLED "controls Windows icon is enabled" ON) +option(WINDOWS_RESOURCES_ENABLED "controls whether Windows resources are enabled" ON) +option(WINDOWS_ICON_ENABLED "controls whether Windows icon is enabled" ON) -if(MINGW AND WINDOWS_RESOURCES_ENABLED) - # find rc template - include(TemplateFinder) - find_template_file("windows.rc" CPP_UTILITIES RC_TEMPLATE_FILE) - - # create Windows icon from png with ffmpeg if available - unset(WINDOWS_ICON_PATH) - unset(WINDOWS_ICON_RC_ENTRY) - if(WINDOWS_ICON_ENABLED) - find_program(FFMPEG_BIN ffmpeg avconv) - if(FFMPEG_BIN) - if(NOT PNG_ICON_PATH) - set(PNG_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/128x128/apps/${META_PROJECT_NAME}.png") - set(USING_DEFAULT_PNG_ICON_PATH true) - endif() - if(PNG_ICON_NO_CROP) - unset(PNG_ICON_CROP) - elseif(NOT PNG_ICON_CROP) - # default cropping - set(PNG_ICON_CROP "iw-20:ih-20:10:10") - endif() - if(EXISTS "${PNG_ICON_PATH}") - set(WINDOWS_ICON_PATH "${CMAKE_CURRENT_BINARY_DIR}/resources/${META_PROJECT_NAME}.ico") - set(WINDOWS_ICON_RC_ENTRY "IDI_ICON1 ICON DISCARDABLE \"${WINDOWS_ICON_PATH}\"") - add_custom_command( - OUTPUT "${WINDOWS_ICON_PATH}" - COMMAND ${FFMPEG_BIN} -y -i "${PNG_ICON_PATH}" -vf crop=${PNG_ICON_CROP},scale=64:64 "${WINDOWS_ICON_PATH}" - ) - message(STATUS "Generating Windows icon from \"${PNG_ICON_PATH}\" via ${FFMPEG_BIN}.") - elseif(NOT USING_DEFAULT_PNG_ICON_PATH) - message(FATAL_ERROR "The specified PNG_ICON_PATH \"${PNG_ICON_PATH}\" is invalid.") - endif() - unset(USING_DEFAULT_PNG_ICON_PATH) - endif(FFMPEG_BIN) - endif() - - # create Windows rc file from template - configure_file( - "${RC_TEMPLATE_FILE}" - "${CMAKE_CURRENT_BINARY_DIR}/resources/windows.rc" - ) - # set windres as resource compiler - list(APPEND RES_FILES "${CMAKE_CURRENT_BINARY_DIR}/resources/windows.rc") - set(CMAKE_RC_COMPILER_INIT windres) - set(CMAKE_RC_COMPILE_OBJECT " -O coff -i -o ") - enable_language(RC) +if(NOT MINGW OR NOT WINDOWS_RESOURCES_ENABLED) + return() endif() + +# find rc template +include(TemplateFinder) +find_template_file("windows.rc" CPP_UTILITIES RC_TEMPLATE_FILE) + +# create Windows icon from png with ffmpeg if available +unset(WINDOWS_ICON_PATH) +unset(WINDOWS_ICON_RC_ENTRY) +if(WINDOWS_ICON_ENABLED) + find_program(FFMPEG_BIN ffmpeg avconv) + if(FFMPEG_BIN) + if(NOT PNG_ICON_PATH) + set(PNG_ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/resources/icons/hicolor/128x128/apps/${META_PROJECT_NAME}.png") + set(USING_DEFAULT_PNG_ICON_PATH true) + endif() + if(PNG_ICON_NO_CROP) + unset(PNG_ICON_CROP) + elseif(NOT PNG_ICON_CROP) + # default cropping + set(PNG_ICON_CROP "iw-20:ih-20:10:10") + endif() + if(EXISTS "${PNG_ICON_PATH}") + set(WINDOWS_ICON_PATH "${CMAKE_CURRENT_BINARY_DIR}/resources/${META_PROJECT_NAME}.ico") + set(WINDOWS_ICON_RC_ENTRY "IDI_ICON1 ICON DISCARDABLE \"${WINDOWS_ICON_PATH}\"") + add_custom_command( + OUTPUT "${WINDOWS_ICON_PATH}" + COMMAND ${FFMPEG_BIN} -y -i "${PNG_ICON_PATH}" -vf crop=${PNG_ICON_CROP},scale=64:64 "${WINDOWS_ICON_PATH}" + ) + message(STATUS "Generating Windows icon from \"${PNG_ICON_PATH}\" via ${FFMPEG_BIN}.") + elseif(NOT USING_DEFAULT_PNG_ICON_PATH) + message(FATAL_ERROR "The specified PNG_ICON_PATH \"${PNG_ICON_PATH}\" is invalid.") + endif() + unset(USING_DEFAULT_PNG_ICON_PATH) + endif() +endif() + +# create Windows rc file from template +configure_file( + "${RC_TEMPLATE_FILE}" + "${CMAKE_CURRENT_BINARY_DIR}/resources/windows.rc" +) +# set windres as resource compiler +list(APPEND RES_FILES "${CMAKE_CURRENT_BINARY_DIR}/resources/windows.rc") +set(CMAKE_RC_COMPILER_INIT windres) +set(CMAKE_RC_COMPILE_OBJECT " -O coff -i -o ") +enable_language(RC)