diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..d7d85abf9b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,67 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +cmake_minimum_required(VERSION 3.5) + +set(BOOST_CMAKE FALSE) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" + "${CMAKE_CURRENT_LIST_DIR}/cmake/packages" + "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/share/modules/cmake") + +include(CMDeploy) +include(CMConfig) +include(CMSetupVersion) + +cm_setup_version(VERSION 1.74.0) + +option(BUILD_TESTS "Build unit tests" FALSE) + +if("${CMAKE_WORKSPACE_NAME}" STREQUAL "boost") + set(BOOST_CMAKE TRUE) + + cm_project(random WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + find_package(${CMAKE_WORKSPACE_NAME}_core) + find_package(${CMAKE_WORKSPACE_NAME}_config) + find_package(${CMAKE_WORKSPACE_NAME}_math) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} "src/random_device.cpp") + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME ${CURRENT_PROJECT_NAME}) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE ${CMAKE_WORKSPACE_NAME}::core) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE ${CMAKE_WORKSPACE_NAME}::config) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE ${CMAKE_WORKSPACE_NAME}::math) + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE + ${CMAKE_WORKSPACE_NAME}::multiprecision) + +else() + cm_workspace(boost SOURCES_DIR "${CMAKE_CURRENT_LIST_DIR}") + + find_package(Boost REQUIRED) + + cm_project(random WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME}) + + add_library(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} "src/random_device.cpp") + set_property(TARGET ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PROPERTY EXPORT_NAME ${CURRENT_PROJECT_NAME}) + + target_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE ${Boost_LIBRARIES}) + target_include_directories(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} PRIVATE + $ + $ + + ${Boost_INCLUDE_DIR}) +endif() + +cm_deploy(TARGETS ${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + INCLUDE ${CURRENT_SOURCES_DIR}/include + NAMESPACE ${CMAKE_WORKSPACE_NAME}::) + +if(BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt new file mode 100644 index 0000000000..1f0da6fe26 --- /dev/null +++ b/cmake/modules/CMakeLists.txt @@ -0,0 +1,15 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +cmake_minimum_required (VERSION 3.5) + +install(DIRECTORY share/modules/cmake DESTINATION cm) + +enable_testing() +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR}) +add_subdirectory(test) diff --git a/cmake/modules/share/modules/cmake/CMConfig.cmake b/cmake/modules/share/modules/cmake/CMConfig.cmake new file mode 100644 index 0000000000..6eb1a3fa13 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMConfig.cmake @@ -0,0 +1,202 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) +include(CMFuture) +enable_testing() + +function(contains_path FILEPATH SUBPATH RESULT) + file(RELATIVE_PATH PATH "${SUBPATH}" "${FILEPATH}") + if(${PATH} MATCHES "\\.\\./") + set(${RESULT} FALSE PARENT_SCOPE) + else() + set(${RESULT} TRUE PARENT_SCOPE) + endif() +endfunction() + +function(add_subdirectories INPUT_DIRECTORY) + set(options) + set(oneValueArgs SUBMODULE_DEFINITION_HEADER) + set(multiValueArgs EXCLUDE_DIRS EXCLUDE_LIBS) + + set(INCLUDED_DIRS) + set(INCLUDED_LIBS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + file(GLOB_RECURSE LIBS ${INPUT_DIRECTORY}/*CMakeLists.txt) + + if(PARSE_EXCLUDE_DIRS) + set(EXCLUDED_DIRS) + + foreach(ITERATOR ${LIBS}) + foreach(DIR_ITERATOR IN LISTS PARSE_EXCLUDE_DIRS) + contains_path(${ITERATOR} ${DIR_ITERATOR} CONTAINS) + if(${CONTAINS}) + list(APPEND EXCLUDED_DIRS ${ITERATOR}) + endif() + endforeach() + endforeach() + + list(REMOVE_ITEM LIBS ${EXCLUDED_DIRS}) + endif() + + foreach(lib ${LIBS}) + file(READ ${lib} CONTENT) + if(PARSE_SUBMODULE_DEFINITION_HEADER) + if("${CONTENT}" MATCHES ${PARSE_SUBMODULE_DEFINITION_HEADER}) + get_filename_component(LIB_DIR ${lib} DIRECTORY) + get_filename_component(LIB_NAME ${LIB_DIR} NAME) + if(PARSE_EXCLUDE_LIBS OR PARSE_EXCLUDE_DIRS) + if(NOT "${LIB_NAME}" IN_LIST PARSE_EXCLUDE_LIBS AND NOT "${LIB_DIR}" IN_LIST PARSE_EXCLUDE_DIRS) + list(APPEND INCLUDED_LIBS ${LIB_NAME}) + list(APPEND INCLUDED_DIRS ${LIB_DIR}) + add_subdirectory(${LIB_DIR}) + endif() + else() + list(APPEND INCLUDED_LIBS ${LIB_NAME}) + list(APPEND INCLUDED_DIRS ${LIB_DIR}) + add_subdirectory(${LIB_DIR}) + endif() + endif() + else() + get_filename_component(LIB_DIR ${lib} DIRECTORY) + get_filename_component(LIB_NAME ${LIB_DIR} NAME) + if(PARSE_EXCLUDE_LIBS OR PARSE_EXCLUDE_DIRS) + if(NOT "${LIB_NAME}" IN_LIST PARSE_EXCLUDE_LIBS AND NOT "${LIB_DIR}" IN_LIST PARSE_EXCLUDE_DIRS) + list(APPEND INCLUDED_LIBS ${LIB_NAME} PARENT_SCOPE) + list(APPEND INCLUDED_DIRS ${LIB_DIR} PARENT_SCOPE) + add_subdirectory(${LIB_DIR}) + endif() + else() + + list(APPEND INCLUDED_LIBS ${LIB_NAME} PARENT_SCOPE) + list(APPEND INCLUDED_DIRS ${LIB_DIR} PARENT_SCOPE) + add_subdirectory(${LIB_DIR}) + endif() + endif() + endforeach() + + set(INCLUDED_DIRS ${INCLUDED_DIRS} PARENT_SCOPE) + set(INCLUDED_LIBS ${INCLUDED_LIBS} PARENT_SCOPE) +endfunction() + +function(cm_project INPUT_PROJECT_NAME) + set(options) + set(oneValueArgs DESCRIPTION VERSION WORKSPACE_NAME) + set(multiValueArgs LANGUAGES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to workspace(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + if(PARSE_WORKSPACE_NAME) + if(PARSE_VERSION AND PARSE_LANGUAGES AND PARSE_DESCRIPTION) + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME} + VERSION ${PARSE_VERSION} + DESCRIPTION ${PARSE_DESCRIPTION} + LANGUAGES ${PARSE_LANGUAGES}) + elseif(PARSE_LANGUAGES) + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME} ${PARSE_LANGUAGES}) + else() + project(${INPUT_WORKSPACE_NAME}_${INPUT_PROJECT_NAME}) + endif() + endif() + + set(CURRENT_PROJECT_NAME ${INPUT_PROJECT_NAME} PARENT_SCOPE) + set(CMAKE_PROJECT_NAME ${CMAKE_PROJECT_NAME} PARENT_SCOPE) + set(PROJECT_NAME ${INPUT_PROJECT_NAME} PARENT_SCOPE) + + string(TOUPPER ${INPUT_PROJECT_NAME} UPPER_PROJECT_NAME) + set(CURRENT_UPPER_PROJECT_NAME ${UPPER_PROJECT_NAME} PARENT_SCOPE) + + if(PARSE_WORKSPACE_NAME) + file(RELATIVE_PATH RELATIVE_DIR ${CMAKE_WORKSPACE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + + set(CURRENT_SOURCES_DIR ${CMAKE_WORKSPACE_SOURCES_DIR}/${RELATIVE_DIR} PARENT_SCOPE) + set(CURRENT_TEST_SOURCES_DIR ${CMAKE_WORKSPACE_SOURCES_DIR}/${RELATIVE_DIR}/test PARENT_SCOPE) + endif() +endfunction() + +function(cm_workspace WORKSPACE_NAME) + set(options) + set(oneValueArgs DESCRIPTION VERSION SOURCES_DIR) + set(multiValueArgs LANGUAGES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to workspace(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + project(${WORKSPACE_NAME} ${PARSE_VERSION} ${PARSE_DESCRIPTION} ${PARSE_LANGUAGES}) + set(PROJECT_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_PROJECT_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_NAME ${WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_LIST ${CMAKE_WORKSPACE_LIST} ${CMAKE_WORKSPACE_NAME} PARENT_SCOPE) + set(CMAKE_WORKSPACE_DIR ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) + string(TOUPPER ${WORKSPACE_NAME} UPPER_WORKSPACE_NAME) + set(CMAKE_UPPER_WORKSPACE_NAME ${UPPER_WORKSPACE_NAME} PARENT_SCOPE) + + if(PARSE_SOURCES_DIR) + set(CMAKE_WORKSPACE_SOURCES_DIR ${PARSE_SOURCES_DIR} PARENT_SCOPE) + endif() +endfunction() + +function(patch_file INPUT_SOURCE INPUT_PATCH OUTPUT_DIRECTORY) + set(options) + set(oneValueArgs PREFIX_PATCH_NAME POSTFIX_PATCH_NAME) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + find_package(Patch) + if(NOT Patch_FOUND) + message("Patch utulity is not found") + endif() + string(REPLACE ${CURRENT_TEST_SOURCES_DIR} ${CMAKE_CURRENT_BINARY_DIR} OUTPUT_FILE ${INPUT_SOURCE}) + file(COPY ${INPUT_SOURCE} DESTINATION ${OUTPUT_DIRECTORY}) + get_filename_component(SOURCE_FILE_NAME ${INPUT_SOURCE} NAME) + set(NEW_SOURCE_FILE_NAME ${PARSE_PREFIX_PATCH_NAME}${SOURCE_FILE_NAME}) + if(PARSE_POSTFIX_PATCH_NAME) + string(REPLACE . ${PARSE_POSTFIX_PATCH_NAME}. NEW_SOURCE_FILE_NAME ${NEW_SOURCE_FILE_NAME}) + endif() + file(RENAME ${OUTPUT_DIRECTORY}/${SOURCE_FILE_NAME} ${OUTPUT_DIRECTORY}/${NEW_SOURCE_FILE_NAME}) + execute_process(COMMAND patch ${OUTPUT_DIRECTORY}/${NEW_SOURCE_FILE_NAME} ${INPUT_PATCH} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) +endfunction() + +function(patch_directory SOURCES_DIRECTORY PATCHES_DIRECTORY OUTPUT_DIRECTORY) + set(options) + set(oneValueArgs PREFIX_PATCH_NAME POSTFIX_PATCH_NAME) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + find_package(Patch) + if(NOT Patch_FOUND) + message("Patch utulity is not found") + endif() + file(GLOB_RECURSE PATCHES_FILES LIST_DIRECTORIES FALSE ${PATCHES_DIRECTORY}/*.patch) + file(GLOB_RECURSE SOURCES_FILES LIST_DIRECTORIES FALSE ${SOURCES_DIRECTORY}/*) + foreach(PATCH_FILE IN LISTS PATCHES_FILES) + string(REPLACE ".patch" "" SOURCE_FILE_NAME ${PATCH_FILE}) + string(REPLACE ${PATCHES_DIRECTORY} ${SOURCES_DIRECTORY} SOURCE_FILE_NAME ${SOURCE_FILE_NAME}) + list(FIND SOURCES_FILES ${SOURCE_FILE_NAME} SOURCES_FILE_FIND) + if(${SOURCES_FILE_FIND} EQUAL -1) + message(FATAL_ERROR "Source file for patch is not found: " ${PATCH_FILE}) + endif() + list(GET SOURCES_FILES ${SOURCES_FILE_FIND} SOURCE_FILE) + string(REPLACE ${SOURCES_DIRECTORY} ${OUTPUT_DIRECTORY} OUTPUT_FILE_DIRECTORY ${SOURCE_FILE}) + get_filename_component(OUTPUT_FILE_DIRECTORY ${OUTPUT_FILE_DIRECTORY} DIRECTORY) + patch_file(${SOURCE_FILE} ${PATCH_FILE} ${OUTPUT_FILE_DIRECTORY} + PREFIX_PATCH_NAME ${PARSE_PREFIX_PATCH_NAME} POSTFIX_PATCH_NAME ${PARSE_POSTFIX_PATCH_NAME}) + endforeach() +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMDeploy.cmake b/cmake/modules/share/modules/cmake/CMDeploy.cmake new file mode 100644 index 0000000000..4fc048c9c1 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMDeploy.cmake @@ -0,0 +1,49 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(CMPkgConfig) +include(CMInstallTargets) +include(CMExport) + +function(cm_deploy) + set(options SKIP_HEADER_INSTALL) + set(oneValueArgs NAMESPACE COMPATIBILITY) + set(multiValueArgs TARGETS INCLUDE) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_SKIP_HEADER_INSTALL) + cm_install_targets(TARGETS ${PARSE_TARGETS} INCLUDE ${PARSE_INCLUDE} SKIP_HEADER_INSTALL) + else() + cm_install_targets(TARGETS ${PARSE_TARGETS} INCLUDE ${PARSE_INCLUDE} ) + endif() + + cm_auto_pkgconfig(TARGET ${PARSE_TARGETS}) + cm_auto_export(TARGETS ${PARSE_TARGETS} NAMESPACE ${PARSE_NAMESPACE} COMPATIBILITY ${PARSE_COMPATIBILITY}) + + foreach(TARGET ${PARSE_TARGETS}) + get_target_property(TARGET_NAME ${TARGET} EXPORT_NAME) + if(NOT TARGET_NAME) + get_target_property(TARGET_NAME ${TARGET} NAME) + endif() + set(EXPORT_LIB_TARGET ${PARSE_NAMESPACE}${TARGET_NAME}) + if(NOT TARGET ${EXPORT_LIB_TARGET}) + add_library(${EXPORT_LIB_TARGET} ALIAS ${TARGET}) + endif() + set_target_properties(${TARGET} PROPERTIES INTERFACE_FIND_PACKAGE_NAME ${PROJECT_NAME}) + if(COMMAND cm_add_rpath) + get_target_property(TARGET_TYPE ${TARGET} TYPE) + if(NOT "${TARGET_TYPE}" STREQUAL "INTERFACE_LIBRARY") + cm_add_rpath("$") + endif() + endif() + cm_shadow_notify(${EXPORT_LIB_TARGET}) + cm_shadow_notify(${TARGET}) + endforeach() + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMExport.cmake b/cmake/modules/share/modules/cmake/CMExport.cmake new file mode 100644 index 0000000000..e3477c8751 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMExport.cmake @@ -0,0 +1,154 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) +include(WriteBasicConfigVersionFile) + +function(cm_get_target_package_source OUT_VAR TARGET) + set(RESULT) + if(TARGET ${TARGET}) + get_property(TARGET_ALIAS TARGET ${TARGET} PROPERTY ALIASED_TARGET) + if(TARGET_ALIAS) + set(TARGET ${TARGET_ALIAS}) + endif() + get_property(TARGET_IMPORTED TARGET ${TARGET} PROPERTY IMPORTED) + if(TARGET_IMPORTED OR TARGET_ALIAS) + get_property(TARGET_FIND_PACKAGE_NAME TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_NAME) + if(NOT TARGET_FIND_PACKAGE_NAME) + message(SEND_ERROR "The target ${TARGET_FIND_PACKAGE_NAME} does not have information about find_package() call.") + endif() + set(PKG_NAME ${TARGET_FIND_PACKAGE_NAME}) + get_property(TARGET_FIND_PACKAGE_VERSION TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_VERSION) + if(TARGET_FIND_PACKAGE_VERSION) + set(PKG_NAME "${PKG_NAME} ${TARGET_FIND_PACKAGE_VERSION}") + endif() + get_property(TARGET_FIND_PACKAGE_EXACT TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_EXACT) + if(TARGET_FIND_PACKAGE_EXACT) + set(PKG_NAME "${PKG_NAME} ${TARGET_FIND_PACKAGE_EXACT}") + endif() + set(RESULT "${PKG_NAME}") + # get_property(TARGET_FIND_PACKAGE_REQUIRED TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_REQUIRED) + # get_property(TARGET_FIND_PACKAGE_QUIETLY TARGET ${TARGET} PROPERTY INTERFACE_FIND_PACKAGE_QUIETLY) + endif() + else() + if("${TARGET}" MATCHES "::") + set(TARGET_NAME "$") + else() + set(TARGET_NAME "${TARGET}") + endif() + cm_shadow_exists(HAS_TARGET ${TARGET}) + set(RESULT "$<${HAS_TARGET}:$>") + endif() + set(${OUT_VAR} "${RESULT}" PARENT_SCOPE) +endfunction() + +function(cm_auto_export) + set(options) + set(oneValueArgs NAMESPACE EXPORT NAME COMPATIBILITY) + set(multiValueArgs TARGETS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UPPER) + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + set(TARGET_FILE ${PROJECT_NAME_LOWER}-targets) + if(PARSE_EXPORT) + set(TARGET_FILE ${PARSE_EXPORT}) + endif() + set(CONFIG_NAME ${PACKAGE_NAME_LOWER}-config) + set(TARGET_VERSION ${PROJECT_VERSION}) + + set(BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) + set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) + set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + set(CONFIG_PACKAGE_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/${PACKAGE_NAME_LOWER}) + + set(CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}.cmake") + + set(CONFIG_FILE_CONTENT " +include(CMakeFindDependencyMacro) +") + + if(PARSE_TARGETS) + # Add dependencies + foreach(TARGET ${PARSE_TARGETS}) + get_property(TARGET_LIBS TARGET ${TARGET} PROPERTY INTERFACE_LINK_LIBRARIES) + foreach(LIB ${TARGET_LIBS}) + cm_get_target_package_source(PKG_SRC ${LIB}) + set(HAS_PKG_SRC "$") + string(APPEND CONFIG_FILE_CONTENT "# $<$:Skip >Library: ${LIB}\n") + string(APPEND CONFIG_FILE_CONTENT "$<${HAS_PKG_SRC}:find_dependency(${PKG_SRC})>\n") + endforeach() + endforeach() + # Compute targets imported name + set(EXPORT_LIB_TARGETS) + foreach(TARGET ${PARSE_TARGETS}) + get_target_property(TARGET_NAME ${TARGET} EXPORT_NAME) + if(NOT TARGET_NAME) + get_target_property(TARGET_NAME ${TARGET} NAME) + endif() + set(EXPORT_LIB_TARGET_${TARGET} ${PARSE_NAMESPACE}${TARGET_NAME}) + list(APPEND EXPORT_LIB_TARGETS ${EXPORT_LIB_TARGET_${TARGET}}) + endforeach() + # Export custom properties + set(EXPORT_PROPERTIES) + foreach(TARGET ${PARSE_TARGETS}) + # TODO: Make this a property: the custom properties to be exported + foreach(PROPERTY INTERFACE_PKG_CONFIG_NAME) + set(PROP "$") + set(EXPORT_PROPERTIES "${EXPORT_PROPERTIES} +$<$:set_target_properties(${EXPORT_LIB_TARGET_${TARGET}} PROPERTIES ${PROPERTY} ${PROP})> +") + endforeach() + endforeach() + string(APPEND CONFIG_FILE_CONTENT " +include(\"\${CMAKE_CURRENT_LIST_DIR}/${TARGET_FILE}.cmake\") +include(\"\${CMAKE_CURRENT_LIST_DIR}/properties-${TARGET_FILE}.cmake\") +") + endif() + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/properties-${TARGET_FILE}.cmake CONTENT "${EXPORT_PROPERTIES}") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/properties-${TARGET_FILE}.cmake DESTINATION ${CONFIG_PACKAGE_INSTALL_DIR}) + + file(GENERATE OUTPUT "${CONFIG_FILE}" CONTENT "${CONFIG_FILE_CONTENT}") + + set(COMPATIBILITY_ARG SameMajorVersion) + if(PARSE_COMPATIBILITY) + set(COMPATIBILITY_ARG ${PARSE_COMPATIBILITY}) + endif() + write_basic_config_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}-version.cmake + VERSION ${TARGET_VERSION} + COMPATIBILITY ${COMPATIBILITY_ARG} + ) + + set(NAMESPACE_ARG) + if(PARSE_NAMESPACE) + set(NAMESPACE_ARG "NAMESPACE;${PARSE_NAMESPACE}") + endif() + install(EXPORT ${TARGET_FILE} + DESTINATION + ${CONFIG_PACKAGE_INSTALL_DIR} + ${NAMESPACE_ARG} + ) + + install(FILES + ${CONFIG_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}-version.cmake + DESTINATION + ${CONFIG_PACKAGE_INSTALL_DIR}) + +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMFuture.cmake b/cmake/modules/share/modules/cmake/CMFuture.cmake new file mode 100644 index 0000000000..bab0703866 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMFuture.cmake @@ -0,0 +1,95 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_NAME" + BRIEF_DOCS "The package name that was searched for to create this target" + FULL_DOCS "The package name that was searched for to create this target" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_REQUIRED" + BRIEF_DOCS "true if REQUIRED option was given" + FULL_DOCS "true if REQUIRED option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_QUIETLY" + BRIEF_DOCS "true if QUIET option was given" + FULL_DOCS "true if QUIET option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_EXACT" + BRIEF_DOCS "true if EXACT option was given" + FULL_DOCS "true if EXACT option was given" +) + +define_property(TARGET PROPERTY "INTERFACE_FIND_PACKAGE_VERSION" + BRIEF_DOCS "full requested version string" + FULL_DOCS "full requested version string" +) + +# Custom property to check if target exists +define_property(TARGET PROPERTY "INTERFACE_TARGET_EXISTS" + BRIEF_DOCS "True if target exists" + FULL_DOCS "True if target exists" +) +# Create shadow target to notify that the target exists +macro(cm_shadow_notify TARGET) + if(NOT TARGET _cm_shadow_target_${TARGET}) + add_library(_cm_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL) + endif() + set_target_properties(_cm_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 1) +endmacro() +# Check if target exists by querying the shadow target +macro(cm_shadow_exists OUT TARGET) + if("${TARGET}" MATCHES "^[_a-zA-Z0-9:]+$") + if(NOT TARGET _cm_shadow_target_${TARGET}) + add_library(_cm_shadow_target_${TARGET} INTERFACE IMPORTED GLOBAL) + set_target_properties(_cm_shadow_target_${TARGET} PROPERTIES INTERFACE_TARGET_EXISTS 0) + endif() + set(${OUT} "$") + else() + set(${OUT} "0") + endif() +endmacro() +# Emulate rpath for windows +if(WIN32) + if(NOT COMMAND cm_add_rpath) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(WRITE ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake "set(RPATH)\n") + file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/cm_set_rpath-${CONFIG}.cmake INPUT ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake CONDITION $) + endforeach() + function(cm_add_rpath) + foreach(_RPATH ${ARGN}) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(APPEND ${CMAKE_BINARY_DIR}/cm_set_rpath_pre-${CONFIG}.cmake "list(APPEND RPATH \"${_RPATH}\")\n") + endforeach() + endforeach() + endfunction() + endif() +endif() +# Add library extension to track imported targets +if(NOT COMMAND cm_add_library_ext) + macro(cm_add_library_ext LIB) + set(ARG_LIST "${ARGN}") + if("IMPORTED" IN_LIST ARG_LIST) + if(CMAKE_FIND_PACKAGE_NAME) + set_target_properties(${LIB} PROPERTIES INTERFACE_FIND_PACKAGE_NAME ${CMAKE_FIND_PACKAGE_NAME}) + foreach(TYPE REQUIRED QUIETLY EXACT VERSION) + if(${CMAKE_FIND_PACKAGE_NAME}_FIND_${TYPE}) + set_target_properties(${LIB} PROPERTIES INTERFACE_FIND_PACKAGE_${TYPE} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_${TYPE}}) + endif() + endforeach() + endif() + endif() + endmacro() + + macro(add_library) + _add_library(${ARGN}) + cm_add_library_ext(${ARGN}) + endmacro() + +endif() diff --git a/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake b/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake new file mode 100644 index 0000000000..a5cabd4713 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMIgnorePackage.cmake @@ -0,0 +1,13 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +function(cm_ignore_package NAME) + set(${NAME}_DIR ${CMAKE_BINARY_DIR}/_cm_ignore_packages_/${NAME} CACHE PATH "") + file(WRITE ${${NAME}_DIR}/${NAME}Config.cmake "") +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMInstallTargets.cmake b/cmake/modules/share/modules/cmake/CMInstallTargets.cmake new file mode 100644 index 0000000000..eb447ed2c5 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMInstallTargets.cmake @@ -0,0 +1,50 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) + +function(cm_install_targets) + set(options SKIP_HEADER_INSTALL) + set(oneValueArgs EXPORT) + set(multiValueArgs TARGETS INCLUDE) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(EXPORT_FILE ${PROJECT_NAME_LOWER}-targets) + if(PARSE_EXPORT) + set(EXPORT_FILE ${PARSE_EXPORT}) + endif() + + set(BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) + set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) + set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + + foreach(TARGET ${PARSE_TARGETS}) + foreach(INCLUDE ${PARSE_INCLUDE}) + get_filename_component(INCLUDE_PATH ${INCLUDE} ABSOLUTE) + target_include_directories(${TARGET} INTERFACE $) + endforeach() + target_include_directories(${TARGET} INTERFACE $/${INCLUDE_INSTALL_DIR}>) + endforeach() + + + if(NOT PARSE_SKIP_HEADER_INSTALL) + foreach(INCLUDE ${PARSE_INCLUDE}) + install(DIRECTORY ${INCLUDE}/ DESTINATION ${INCLUDE_INSTALL_DIR}) + endforeach() + endif() + + install(TARGETS ${PARSE_TARGETS} + EXPORT ${EXPORT_FILE} + RUNTIME DESTINATION ${BIN_INSTALL_DIR} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) + +endfunction() + diff --git a/cmake/modules/share/modules/cmake/CMPkgConfig.cmake b/cmake/modules/share/modules/cmake/CMPkgConfig.cmake new file mode 100644 index 0000000000..7057516b19 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMPkgConfig.cmake @@ -0,0 +1,257 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) + +define_property(TARGET PROPERTY "INTERFACE_DESCRIPTION" + BRIEF_DOCS "Description of the target" + FULL_DOCS "Description of the target" +) + +define_property(TARGET PROPERTY "INTERFACE_URL" + BRIEF_DOCS "An URL where people can get more information about and download the package." + FULL_DOCS "An URL where people can get more information about and download the package." +) + +define_property(TARGET PROPERTY "INTERFACE_PKG_CONFIG_REQUIRES" + BRIEF_DOCS "A list of packages required by this package. The versions of these packages may be specified using the comparison operators =, <, >, <= or >=." + FULL_DOCS "A list of packages required by this package. The versions of these packages may be specified using the comparison operators =, <, >, <= or >=." +) + +function(cm_generate_pkgconfig_file) + set(options) + set(oneValueArgs NAME LIB_DIR INCLUDE_DIR DESCRIPTION) + set(multiValueArgs TARGETS CFLAGS LIBS REQUIRES) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(LIB_DIR ${CMAKE_INSTALL_LIBDIR}) + if(PARSE_LIB_DIR) + set(LIB_DIR ${PARSE_LIB_DIR}) + endif() + set(INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) + if(PARSE_INCLUDE_DIR) + set(INCLUDE_DIR ${PARSE_INCLUDE_DIR}) + endif() + + set(LIBS) + set(DESCRIPTION "No description") + if(PARSE_DESCRIPTION) + set(DESCRIPTION ${PARSE_DESCRIPTION}) + endif() + + foreach(TARGET ${PARSE_TARGETS}) + get_property(TARGET_NAME TARGET ${TARGET} PROPERTY NAME) + get_property(TARGET_TYPE TARGET ${TARGET} PROPERTY TYPE) + if(NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + set(LIBS "${LIBS} -l${TARGET_NAME}") + endif() + endforeach() + + if(LIBS OR PARSE_LIBS) + set(LIBS "Libs: -L\${libdir} ${LIBS} ${PARSE_LIBS}") + endif() + + set(PKG_NAME ${PROJECT_NAME}) + if(PARSE_NAME) + set(PKG_NAME ${PARSE_NAME}) + endif() + + file(WRITE ${PKGCONFIG_FILENAME} +" +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=\${prefix} +libdir=\${exec_prefix}/${LIB_DIR} +includedir=\${exec_prefix}/${INCLUDE_DIR} +Name: ${PKG_NAME} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +Cflags: -I\${includedir} ${PARSE_CFLAGS} +${LIBS} +Requires: ${PARSE_REQUIRES} +" + ) + +endfunction() + +function(cm_preprocess_pkgconfig_property VAR TARGET PROP) + get_target_property(OUT_PROP ${TARGET} ${PROP}) + string(REPLACE "$/${CMAKE_INSTALL_INCLUDEDIR}" "\${includedir}" OUT_PROP "${OUT_PROP}") + string(REPLACE "$/${CMAKE_INSTALL_LIBDIR}" "\${libdir}" OUT_PROP "${OUT_PROP}") + string(REPLACE "$" "\${prefix}" OUT_PROP "${OUT_PROP}") + + set(${VAR} ${OUT_PROP} PARENT_SCOPE) + +endfunction() + +function(cm_auto_pkgconfig_each) + set(options) + set(oneValueArgs NAME TARGET) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(LIBS) + set(CFLAGS) + set(REQUIRES) + set(DESCRIPTION "No description") + + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + + set(TARGET) + if(PARSE_TARGET) + set(TARGET ${PARSE_TARGET}) + else() + message(SEND_ERROR "Target is required for auto pkg config") + endif() + + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UPPER) + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + get_property(TARGET_NAME TARGET ${TARGET} PROPERTY NAME) + get_property(TARGET_TYPE TARGET ${TARGET} PROPERTY TYPE) + get_property(TARGET_DESCRIPTION TARGET ${TARGET} PROPERTY INTERFACE_DESCRIPTION) + get_property(TARGET_URL TARGET ${TARGET} PROPERTY INTERFACE_URL) + get_property(TARGET_REQUIRES TARGET ${TARGET} PROPERTY INTERFACE_PKG_CONFIG_REQUIRES) + if(NOT TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") + set(LIBS "${LIBS} -l${TARGET_NAME}") + endif() + + if(TARGET_REQUIRES) + list(APPEND REQUIRES ${TARGET_REQUIRES}) + endif() + + cm_preprocess_pkgconfig_property(LINK_LIBS ${TARGET} INTERFACE_LINK_LIBRARIES) + foreach(LIB ${LINK_LIBS}) + if(TARGET ${LIB}) + get_property(LIB_PKGCONFIG_NAME TARGET ${LIB} PROPERTY INTERFACE_PKG_CONFIG_NAME) + # TODO: Error if this property is missing + if(LIB_PKGCONFIG_NAME) + list(APPEND REQUIRES ${LIB_PKGCONFIG_NAME}) + endif() + else() + if("${LIB}" MATCHES "::") + set(LIB_TARGET_NAME "$") + else() + set(LIB_TARGET_NAME "${LIB}") + endif() + cm_shadow_exists(HAS_LIB_TARGET ${LIB}) + list(APPEND REQUIRES "$<${HAS_LIB_TARGET}:$>") + set(LIBS "${LIBS} $<$:${LIB}>") + endif() + endforeach() + + cm_preprocess_pkgconfig_property(INCLUDE_DIRS ${TARGET} INTERFACE_INCLUDE_DIRECTORIES) + if(INCLUDE_DIRS) + set(CFLAGS "${CFLAGS} $<$:-I$>") + endif() + + cm_preprocess_pkgconfig_property(COMPILE_DEFS ${TARGET} INTERFACE_COMPILE_DEFINITIONS) + if(COMPILE_DEFS) + set(CFLAGS "${CFLAGS} $<$:-D$>") + endif() + + cm_preprocess_pkgconfig_property(COMPILE_OPTS ${TARGET} INTERFACE_COMPILE_OPTIONS) + if(COMPILE_OPTS) + set(CFLAGS "${CFLAGS} $<$:$>") + endif() + + set(CONTENT) + + if(TARGET_DESCRIPTION) + set(DESCRIPTION "${TARGET_DESCRIPTION}") + endif() + + if(TARGET_URL) + set(CONTENT "${CONTENT}\nUrl: ${TARGET_URL}") + endif() + + if(CFLAGS) + set(CONTENT "${CONTENT}\nCflags: ${CFLAGS}") + endif() + + if(LIBS) + set(CONTENT "${CONTENT}\n$<$:Libs: -L\${libdir} ${LIBS}>") + endif() + + if(REQUIRES) + string(REPLACE ";" "," REQUIRES_CONTENT "${REQUIRES}") + set(CONTENT "${CONTENT}\nRequires: ${REQUIRES_CONTENT}") + endif() + + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc CONTENT +" +prefix=${CMAKE_INSTALL_PREFIX} +exec_prefix=\${prefix} +libdir=\${exec_prefix}/${CMAKE_INSTALL_LIBDIR} +includedir=\${exec_prefix}/${CMAKE_INSTALL_INCLUDEDIR} +Name: ${PACKAGE_NAME_LOWER} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +${CONTENT} +" + ) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + set_property(TARGET ${TARGET} PROPERTY INTERFACE_PKG_CONFIG_NAME ${PACKAGE_NAME_LOWER}) +endfunction() + +function(cm_auto_pkgconfig) + set(options) + set(oneValueArgs NAME) + set(multiValueArgs TARGET) # TODO: Rename to TARGETS + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + list(LENGTH PARSE_TARGET TARGET_COUNT) + + if(TARGET_COUNT EQUAL 1) + cm_auto_pkgconfig_each(TARGET ${PARSE_TARGET} NAME ${PARSE_NAME}) + else() + string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) + set(PACKAGE_NAME ${PROJECT_NAME}) + + if(PARSE_NAME) + set(PACKAGE_NAME ${PARSE_NAME}) + endif() + + string(TOLOWER ${PACKAGE_NAME} PACKAGE_NAME_LOWER) + + set(GENERATE_PROJECT_PC On) + foreach(TARGET ${PARSE_TARGET}) + if("${TARGET}" STREQUAL "${PACKAGE_NAME_LOWER}") + set(GENERATE_PROJECT_PC Off) + endif() + cm_auto_pkgconfig_each(TARGET ${TARGET} NAME ${TARGET}) + endforeach() + + string(REPLACE ";" "," REQUIRES "${PARSE_TARGET}") + # TODO: Get description from project + set(DESCRIPTION "No description") + + if(GENERATE_PROJECT_PC) + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_LOWER}.pc CONTENT +" +Name: ${PACKAGE_NAME_LOWER} +Description: ${DESCRIPTION} +Version: ${PROJECT_VERSION} +Requires: ${REQUIRES} +" + ) + endif() + endif() + + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMProperties.cmake b/cmake/modules/share/modules/cmake/CMProperties.cmake new file mode 100644 index 0000000000..56b156a03b --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMProperties.cmake @@ -0,0 +1,105 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2017 Niall Douglas +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# +# +# On MSVC very annoyingly cmake puts /EHsc and /MD(d) into the global flags which means you +# get a warning when you try to disable exceptions or use the static CRT. I hate to use this +# globally imposed solution, but we are going to hack the global flags to use properties to +# determine whether they are on or off +# +# Create custom properties called CXX_EXCEPTIONS, CXX_RTTI and CXX_STATIC_RUNTIME +# These get placed at global, directory and target scopes +foreach(scope GLOBAL DIRECTORY TARGET) + define_property(${scope} PROPERTY "CXX_EXCEPTIONS" INHERITED + BRIEF_DOCS "Enable C++ exceptions, defaults to TRUE at global scope" + FULL_DOCS "Enable C++ exceptions, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_RTTI" INHERITED + BRIEF_DOCS "Enable C++ runtime type information, defaults to TRUE at global scope" + FULL_DOCS "Enable C++ runtime type information, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_STATIC_RUNTIME" INHERITED + BRIEF_DOCS "Enable linking against the static C++ runtime, defaults to FALSE at global scope" + FULL_DOCS "Enable linking against the static C++ runtime, defaults to FALSE at global scope" + ) + define_property(${scope} PROPERTY "CXX_WARNINGS" INHERITED + BRIEF_DOCS "Controls the warning level of compilers, defaults to TRUE at global scope" + FULL_DOCS "Controls the warning level of compilers, defaults to TRUE at global scope" + ) + define_property(${scope} PROPERTY "CXX_WARNINGS_AS_ERRORS" INHERITED + BRIEF_DOCS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" + FULL_DOCS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" + ) + define_property(${scope} PROPERTY "BUILD_SHARED_LIBS" INHERITED + BRIEF_DOCS "Property indicates wether dynamic-linked libraries are going to be built, defaults to + FALSE at global scope" + FULL_DOCS "Property indicates wether dynamic-linked libraries are going to be built, defaults to + FALSE at global scope" + ) +endforeach() +# Set the default for these properties at global scope. If they are not set per target or +# whatever, the next highest scope will be looked up +option(CMAKE_CXX_EXCEPTIONS "Enable C++ exceptions, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_RTTI "Enable C++ runtime type information, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_STATIC_RUNTIME "Enable linking against the static C++ runtime, defaults to FALSE at global scope" FALSE) +option(CMAKE_CXX_WARNINGS "Controls the warning level of compilers, defaults to TRUE at global scope" TRUE) +option(CMAKE_CXX_WARNINGS_AS_ERRORS "Treat warnings as errors and abort compilation on a warning, defaults to FALSE at global scope" FALSE) + +set_property(GLOBAL PROPERTY CXX_EXCEPTIONS ${CMAKE_CXX_EXCEPTIONS}) +set_property(GLOBAL PROPERTY CXX_RTTI ${CMAKE_CXX_RTTI}) +set_property(GLOBAL PROPERTY CXX_STATIC_RUNTIME ${CMAKE_CXX_STATIC_RUNTIME}) +set_property(GLOBAL PROPERTY CXX_WARNINGS ${CMAKE_CXX_WARNINGS}) +set_property(GLOBAL PROPERTY CXX_WARNINGS_AS_ERRORS ${CMAKE_CXX_WARNINGS_AS_ERRORS}) +set_property(GLOBAL PROPERTY BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) + +if(MSVC) + # Purge unconditional use of /MDd, /MD and /EHsc. + foreach(flag + CMAKE_C_FLAGS CMAKE_CXX_FLAGS + CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO + ) + string(REPLACE "/MDd" "" ${flag} "${${flag}}") + string(REPLACE "/MD" "" ${flag} "${${flag}}") + string(REPLACE "/EHsc" "" ${flag} "${${flag}}") + string(REPLACE "/GR" "" ${flag} "${${flag}}") + endforeach() + # Restore those same, but now selected by the properties + add_compile_options( + $<$>,TRUE>:/EHsc> + $<$>,FALSE>:/GR-> + $<$>,FALSE>:$<$:/MDd>$<$>:/MD>> + $<$>,TRUE>:$<$:/MTd>$<$>:/MT>> + $<$>,TRUE>:/W3> + $<$>,FALSE>:/W0> + $<$>,ALL>:/W4> + $<$>,TRUE>:/WX> + ) +else() + add_compile_options( + $<$>,FALSE>:-fno-exceptions> + $<$>,FALSE>:-fno-rtti> + $<$>,TRUE>:-static> + $<$>,TRUE>:-Wall> + $<$>,FALSE>:-w> + $<$>,ALL>:-Wall> + $<$>,ALL>:-pedantic> + $<$>,TRUE>:-Werror> + ) + if(CMAKE_${COMPILER}_COMPILER_ID MATCHES "Clang" OR CMAKE_${COMPILER}_COMPILER_ID MATCHES "AppleClang") + add_compile_options( + $<$>,ALL>:-Weverything> + $<$>,ALL>:-Wno-macro-redefined> + $<$>,ALL>:-Wall> + $<$>,ALL>:-Wno-c++98-compat> + $<$>,ALL>:-Wno-c++98-compat-pedantic> + ) + endif() +endif() \ No newline at end of file diff --git a/cmake/modules/share/modules/cmake/CMSetupVersion.cmake b/cmake/modules/share/modules/cmake/CMSetupVersion.cmake new file mode 100644 index 0000000000..3e68716e40 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMSetupVersion.cmake @@ -0,0 +1,60 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(GNUInstallDirs) +set(CM_HEADER_VERSION_TEMPLATE_FILE "${CMAKE_CURRENT_LIST_DIR}/version.hpp") + +macro(cm_set_parent VAR) + set(${VAR} ${ARGN} PARENT_SCOPE) + set(${VAR} ${ARGN}) +endmacro() + +function(cm_setup_version) + set(options) + set(oneValueArgs VERSION GENERATE_HEADER PARSE_HEADER PREFIX) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + string(TOUPPER ${PROJECT_NAME} PREFIX) + + if(PARSE_PREFIX) + set(PREFIX ${PARSE_PREFIX}) + endif() + + if(PARSE_VERSION) + cm_set_parent(PROJECT_VERSION ${PARSE_VERSION}) + cm_set_parent(${PROJECT_NAME}_VERSION ${PROJECT_VERSION}) + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _version_MAJOR "${PROJECT_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _version_MINOR "${PROJECT_VERSION}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _version_PATCH "${PROJECT_VERSION}") + foreach(level MAJOR MINOR PATCH) + cm_set_parent(${PROJECT_NAME}_VERSION_${level} ${_version_${level}}) + cm_set_parent(PROJECT_VERSION_${level} ${_version_${level}}) + endforeach() + elseif(PARSE_PARSE_HEADER) + foreach(level MAJOR MINOR PATCH) + file(STRINGS ${PARSE_PARSE_HEADER} + _define_${level} + REGEX "#define ${PREFIX}_VERSION_${level}") + string(REGEX MATCH "([0-9]+)" _version_${level} "${_define_${level}}") + # TODO: Check if it is empty + cm_set_parent(${PROJECT_NAME}_VERSION_${level} ${_version_${level}}) + cm_set_parent(PROJECT_VERSION_${level} ${_version_${level}}) + endforeach() + cm_set_parent(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + cm_set_parent(${PROJECT_NAME}_VERSION ${PROJECT_VERSION}) + endif() + # TODO: Get version from the project + + if(PARSE_GENERATE_HEADER) + configure_file("${CM_HEADER_VERSION_TEMPLATE_FILE}" "${PARSE_GENERATE_HEADER}") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PARSE_GENERATE_HEADER}" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + endif() + +endfunction() diff --git a/cmake/modules/share/modules/cmake/CMTest.cmake b/cmake/modules/share/modules/cmake/CMTest.cmake new file mode 100644 index 0000000000..764df19e4f --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMTest.cmake @@ -0,0 +1,240 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +option(BUILD_TESTS "Controls whether to build the tests as part of the main build" FALSE) + +enable_testing() + +foreach(scope GLOBAL DIRECTORY) + define_property(${scope} PROPERTY "ENABLE_TESTS" INHERITED + BRIEF_DOCS "Enable tests" + FULL_DOCS "Enable tests" + ) +endforeach() +option(CMAKE_ENABLE_TESTS "Enable tests" ON) +set_property(GLOBAL PROPERTY ENABLE_TESTS ${CMAKE_ENABLE_TESTS}) + +include(ProcessorCount) +processorcount(_cm_ctest_parallel_level) +set(CTEST_PARALLEL_LEVEL ${_cm_ctest_parallel_level} CACHE STRING "CTest parallel level") + +if(NOT TARGET check) + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C ${CMAKE_CFG_INTDIR} -j ${CTEST_PARALLEL_LEVEL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + + +if(NOT TARGET tests) + add_custom_target(tests COMMENT "Build all tests.") + add_dependencies(check tests) +endif() + +if(NOT TARGET check-${PROJECT_NAME}) + add_custom_target(check-${PROJECT_NAME} COMMAND ${CMAKE_CTEST_COMMAND} -L ${PROJECT_NAME} --output-on-failure -C ${CMAKE_CFG_INTDIR} -j ${CTEST_PARALLEL_LEVEL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +endif() + +if(NOT TARGET tests-${PROJECT_NAME}) + add_custom_target(tests-${PROJECT_NAME} COMMENT "Build all tests for ${PROJECT_NAME}.") + add_dependencies(check-${PROJECT_NAME} tests-${PROJECT_NAME}) +endif() + +function(cm_mark_as_test) + foreach(TEST_TARGET ${ARGN}) + if(NOT BUILD_TESTS) + get_target_property(TEST_TARGET_TYPE ${TEST_TARGET} TYPE) + # We can onle use EXCLUDE_FROM_ALL on build targets + if(NOT "${TEST_TARGET_TYPE}" STREQUAL "INTERFACE_LIBRARY") + set_target_properties(${TEST_TARGET} + PROPERTIES EXCLUDE_FROM_ALL TRUE + ) + endif() + endif() + add_dependencies(tests ${TEST_TARGET}) + add_dependencies(tests-${PROJECT_NAME} ${TEST_TARGET}) + endforeach() +endfunction(cm_mark_as_test) + + +function(cm_create_internal_targets) + if(NOT TARGET _cm_internal_tests-${PROJECT_NAME}) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/_cm_internal_tests-${PROJECT_NAME}.cpp "") + add_library(_cm_internal_tests-${PROJECT_NAME} STATIC ${CMAKE_CURRENT_BINARY_DIR}/_cm_internal_tests-${PROJECT_NAME}.cpp) + cm_mark_as_test(_cm_internal_tests-${PROJECT_NAME}) + endif() +endfunction() + +foreach(scope DIRECTORY TARGET) + define_property(${scope} PROPERTY "CM_TEST_DEPENDENCIES" INHERITED + BRIEF_DOCS "Default test dependencies" + FULL_DOCS "Default test dependencies" + ) +endforeach() + +function(cm_test_link_libraries) + cm_create_internal_targets() + if(BUILD_TESTS) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${ARGN}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${ARGN}) + else() + foreach(TARGET ${ARGN}) + if(TARGET ${TARGET}) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${TARGET}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${TARGET}) + elseif(${TARGET} MATCHES "::") + cm_shadow_exists(HAS_TARGET ${TARGET}) + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES $<${HAS_TARGET}:${TARGET}>) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} $<${HAS_TARGET}:${TARGET}>) + else() + set_property(DIRECTORY APPEND PROPERTY CM_TEST_DEPENDENCIES ${TARGET}) + target_link_libraries(_cm_internal_tests-${PROJECT_NAME} ${TARGET}) + endif() + if(BUILD_SHARED_LIBS) + target_compile_definitions(_cm_internal_tests-${PROJECT_NAME} PRIVATE -DBOOST_TEST_DYN_LINK=1 -DBOOST_TEST_NO_AUTO_LINK=1) + endif() + endforeach() + endif() +endfunction() + +function(cm_target_link_test_libs TARGET) + # target_link_libraries(${TARGET} + # $ + # ) + get_property(DEPS DIRECTORY PROPERTY CM_TEST_DEPENDENCIES) + target_link_libraries(${TARGET} ${DEPS}) +endfunction() + + +function(cm_test) + set(options COMPILE_ONLY WILL_FAIL NO_TEST_LIBS) + set(oneValueArgs NAME SOURCES_PREFIX) + set(multiValueArgs SOURCES CONTENT ARGS) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to cm_test(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + set(SOURCES ${PARSE_SOURCES}) + + if(PARSE_NAME) + set(TEST_NAME ${PARSE_NAME}) + else() + string(MAKE_C_IDENTIFIER "${PROJECT_NAME}_${SOURCES}_test" TEST_NAME) + endif() + + if(PARSE_CONTENT) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated-${TEST_NAME}.cpp "${PARSE_CONTENT}") + set(SOURCES ${CMAKE_CURRENT_BINARY_DIR}/generated-${TEST_NAME}.cpp) + endif() + + if(PARSE_COMPILE_ONLY) + add_library(${TEST_NAME} STATIC EXCLUDE_FROM_ALL ${SOURCES}) + add_test(NAME ${TEST_NAME} + COMMAND ${CMAKE_COMMAND} --build . --target ${TEST_NAME} --config $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + if(PARSE_SOURCES_PREFIX) + target_include_directories(${TEST_NAME} PRIVATE ${PARSE_SOURCES_PREFIX}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) + endif() + + # set_tests_properties(${TEST_NAME} PROPERTIES RESOURCE_LOCK cm_test_compile_only) + else() + add_executable(${TEST_NAME} ${SOURCES}) + cm_mark_as_test(${TEST_NAME}) + if(PARSE_SOURCES_PREFIX) + target_include_directories(${TEST_NAME} PRIVATE ${PARSE_SOURCES_PREFIX}) + else() + target_include_directories(${TEST_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) + endif() + if(WIN32) + foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES} "") + file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}-test-run-${CONFIG}.cmake CONTENT " +include(\"${CMAKE_BINARY_DIR}/cm_set_rpath-$.cmake\") +if(CMAKE_CROSSCOMPILING) +foreach(RP \${RPATH}) + execute_process(COMMAND winepath -w \${RP} OUTPUT_VARIABLE _RPATH) + string(STRIP \"\${_RPATH}\" _RPATH) + set(ENV{WINEPATH} \"\${_RPATH};\$ENV{WINEPATH}\") +endforeach() +else() +set(ENV{PATH} \"\${RPATH};\$ENV{PATH}\") +endif() +execute_process( + COMMAND $ ${PARSE_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE RESULT) +if(NOT RESULT EQUAL 0) + message(FATAL_ERROR \"Test failed\") +endif() +" CONDITION $) + endforeach() + add_test(NAME ${TEST_NAME} COMMAND ${CMAKE_COMMAND} -DCMAKE_CROSSCOMPILING=${CMAKE_CROSSCOMPILING} -P ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}-test-run-$.cmake) + else() + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} ${PARSE_ARGS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + endif() + + if(BUILD_SHARED_LIBS) + target_compile_definitions(${TEST_NAME} PRIVATE -DBOOST_TEST_DYN_LINK=1 -DBOOST_TEST_NO_AUTO_LINK=1) + endif() + + if(PARSE_WILL_FAIL) + set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE) + endif() + set_tests_properties(${TEST_NAME} PROPERTIES LABELS ${PROJECT_NAME}) + if(NOT PARSE_NO_TEST_LIBS) + cm_target_link_test_libs(${TEST_NAME}) + endif() +endfunction(cm_test) + +function(cm_test_header) + set(options STATIC NO_TEST_LIBS) + set(oneValueArgs NAME HEADER) + set(multiValueArgs) + + cmake_parse_arguments(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(PARSE_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to cm_test_header(): \"${PARSE_UNPARSED_ARGUMENTS}\"") + endif() + + if(PARSE_NAME) + set(TEST_NAME ${PARSE_NAME}) + else() + string(MAKE_C_IDENTIFIER "${PROJECT_NAME}_${PARSE_HEADER}_header_test" TEST_NAME) + endif() + + if(PARSE_STATIC) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${TEST_NAME}.cpp + "#include <${PARSE_HEADER}>\nint main() {}\n" + ) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${TEST_NAME}.cpp + "#include <${PARSE_HEADER}>\n" + ) + cm_test(NAME ${TEST_NAME} SOURCES + ${CMAKE_CURRENT_BINARY_DIR}/header-main-include-${TEST_NAME}.cpp + ${CMAKE_CURRENT_BINARY_DIR}/header-static-include-${TEST_NAME}.cpp + ) + else() + cm_test(NAME ${TEST_NAME} CONTENT + "#include <${PARSE_HEADER}>\nint main() {}\n" + ) + endif() + set_tests_properties(${TEST_NAME} PROPERTIES LABELS ${PROJECT_NAME}) +endfunction(cm_test_header) + +macro(cm_add_test_subdirectory) + get_directory_property(_enable_tests_property ENABLE_TESTS) + get_property(_enable_tests_global_property GLOBAL PROPERTY ENABLE_TESTS) + string(TOUPPER "${_enable_tests_property}" _enable_tests_property_upper) + if(_enable_tests_property_upper STREQUAL "OFF" OR _enable_tests_property_upper EQUAL 1) + set(CURRENT_SOURCES_DIR ${CURRENT_SOURCES_DIR}/test) + add_subdirectory(${ARGN}) + endif() +endmacro() diff --git a/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake b/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake new file mode 100644 index 0000000000..4a61031e27 --- /dev/null +++ b/cmake/modules/share/modules/cmake/CMToSnakeCase.cmake @@ -0,0 +1,18 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +function(to_snake_case str var) + # insert an underscore before any upper case letter + # which is not followed by another upper case letter + string(REGEX REPLACE "(.)([A-Z][a-z]+)" "\\1_\\2" value "${str}") + # insert an underscore before any upper case letter + # which is preseded by a lower case letter or number + string(REGEX REPLACE "([a-z0-9])([A-Z])" "\\1_\\2" value "${value}") + string(TOLOWER "${value}" value) + set(${var} "${value}" PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/share/modules/cmake/version.hpp b/cmake/modules/share/modules/cmake/version.hpp new file mode 100644 index 0000000000..116b801ed2 --- /dev/null +++ b/cmake/modules/share/modules/cmake/version.hpp @@ -0,0 +1,18 @@ +//---------------------------------------------------------------------------// +// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef @PREFIX@_GUARD_VERSION_HPP +#define @PREFIX@_GUARD_VERSION_HPP + +#define @PREFIX@_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ +#define @PREFIX@_VERSION_MINOR @PROJECT_VERSION_MINOR@ +#define @PREFIX@_VERSION_PATCH @PROJECT_VERSION_PATCH@ +#define @PREFIX@_VERSION (((@PREFIX@_VERSION_MAJOR) << 24) + ((@PREFIX@_VERSION_MINOR) << 16) + (@PREFIX@_VERSION_PATCH)) + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..b5c24f8bf1 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,154 @@ +#---------------------------------------------------------------------------# +# Copyright (c) 2018-2020 Mikhail Komarov +# Copyright (c) 2018-2020 Alexey Moskvin +# +# Distributed under the Boost Software License, Version 1.0 +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +#---------------------------------------------------------------------------# + +include(CMTest) + +if(BOOST_CMAKE) + find_package(${CMAKE_WORKSPACE_NAME}_filesystem) + find_package(${CMAKE_WORKSPACE_NAME}_test) + find_package(${CMAKE_WORKSPACE_NAME}_math) + find_package(${CMAKE_WORKSPACE_NAME}_multiprecision) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + ${CMAKE_WORKSPACE_NAME}::filesystem + ${CMAKE_WORKSPACE_NAME}::test + ${CMAKE_WORKSPACE_NAME}::math + ${CMAKE_WORKSPACE_NAME}::multiprecision) +else() + find_package(Boost REQUIRED COMPONENTS filesystem unit_test_framework) + + cm_test_link_libraries(${CMAKE_WORKSPACE_NAME}_${CURRENT_PROJECT_NAME} + + $ + + ${Boost_LIBRARIES}) + + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include" + "${CMAKE_CURRENT_BINARY_DIR}/include" + + ${Boost_INCLUDE_DIRS}) +endif() + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_const_mod SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_const_mod.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_generate_canonical SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_generate_canonical.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_random_number_generator SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_random_number_generator.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_random_device SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_random_device.cpp) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_minstd_rand0 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_minstd_rand0.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_minstd_rand SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_minstd_rand.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_rand48 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_rand48.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mt11213b SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mt11213b.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mt19937 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mt19937.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mt19937_64 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mt19937_64.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_mixmax SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_mixmax.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ecuyer1988 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ecuyer1988.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_hellekalek1995 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_hellekalek1995.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_linear_feedback_shift SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_linear_feedback_shift.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_taus88 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_taus88.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_kreutzer1986 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_kreutzer1986.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux3.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux4.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux3_01 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux3_01.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux4_01 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux4_01.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux64_4 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux64_4.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux64_3 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux64_3.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux64_3_01 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux64_3_01.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux64_4_01 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux64_4_01.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux24_base SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux24_base.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux24 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux24.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux48_base SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux48_base.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_ranlux48 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_ranlux48.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_knuth_b SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_knuth_b.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_independent_bits31 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_independent_bits31.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_independent_bits32 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_independent_bits32.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci607 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci607.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci1279 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci1279.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci2281 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci2281.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci3217 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci3217.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci4423 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci4423.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci9689 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci9689.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci19937 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci19937.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci23209 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci23209.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lagged_fibonacci44497 SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lagged_fibonacci44497.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_zero_seed SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_zero_seed.cpp) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_niederreiter_base2_validate SOURCES ${CURRENT_TEST_SOURCES_DIR}/niederreiter_base2_validate.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_sobol_validate SOURCES ${CURRENT_TEST_SOURCES_DIR}/sobol_validate.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_faure_validate SOURCES ${CURRENT_TEST_SOURCES_DIR}/faure_validate.cpp) + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_seed_seq SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_seed_seq.cpp) + + +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_binomial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_binomial.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_binomial_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_binomial_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_poisson SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_poisson.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_poisson_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_poisson_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_discrete SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_discrete.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_discrete_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_discrete_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_gamma SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gamma.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_gamma_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_gamma_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_weibull SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_weibull.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_weibull_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_weibull_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_extreme_value SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_extreme_value.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_extreme_value_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_extreme_value_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_negative_binomial SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_negative_binomial.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_negative_binomial_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_negative_binomial_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_chi_squared SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_chi_squared.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_chi_squared_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_chi_squared_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_fisher_f SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_fisher_f.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_fisher_f_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_fisher_f_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_student_t SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_student_t.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_student_t_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_student_t_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_normal SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_normal.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_normal_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_normal_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_piecewise_constant SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_piecewise_constant.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_piecewise_constant_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_piecewise_constant_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_piecewise_linear SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_piecewise_linear.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_piecewise_linear_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_piecewise_linear_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_exponential SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_exponential.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_exponential_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_exponential_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_bernoulli SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_bernoulli.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_bernoulli_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_bernoulli_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cauchy SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cauchy.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_cauchy_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_cauchy_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_geometric SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_geometric.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_geometric_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_geometric_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lognormal SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lognormal.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_lognormal_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_lognormal_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_triangle SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_triangle.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_triangle_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_triangle_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_int.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_int_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_int_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_real SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_real.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_real_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_real_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_on_sphere SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_on_sphere.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_on_sphere_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_on_sphere_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_smallint SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_smallint.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_uniform_smallint_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_uniform_smallint_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_old_uniform_real SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_old_uniform_real.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_old_uniform_real_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_old_uniform_real_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_old_uniform_int SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_old_uniform_int.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_old_uniform_int_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_old_uniform_int_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_beta SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_beta.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_beta_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_beta_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_laplace SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_laplace.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_laplace_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_laplace_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_non_central_chi_squared SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_non_central_chi_squared.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_non_central_chi_squared_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_non_central_chi_squared_distribution.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_hyperexponential SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_hyperexponential.cpp) +cm_test(NAME ${CURRENT_PROJECT_NAME}_test_test_hyperexponential_distribution SOURCES ${CURRENT_TEST_SOURCES_DIR}/test_hyperexponential_distribution.cpp) + +if(Boost_MULTIPRECISION_FOUND OR TARGET boost_multiprecision) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_multiprecision_int_test SOURCES ${CURRENT_TEST_SOURCES_DIR}/multiprecision_int_test.cpp) + cm_test(NAME ${CURRENT_PROJECT_NAME}_test_multiprecision_float_test SOURCES + ${CURRENT_TEST_SOURCES_DIR}/multiprecision_float_test.cpp) +endif() + +include_directories(${CMAKE_WORKSPACE_SOURCES_DIR}) \ No newline at end of file