diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5569428..3515f770 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,13 @@ project(mp-units VERSION 2.2.0 LANGUAGES CXX) set(projectPrefix MP_UNITS_) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +include(CheckCXXFeatureSupported) +include(AddMPUnitsModule) +include(GNUInstallDirs) + +# project options option(${projectPrefix}BUILD_CXX_MODULES "Add C++ modules to the list of default targets" OFF) message(STATUS "${projectPrefix}BUILD_CXX_MODULES: ${${projectPrefix}BUILD_CXX_MODULES}") @@ -34,21 +41,39 @@ message(STATUS "${projectPrefix}AS_SYSTEM_HEADERS: ${${projectPrefix}AS_SYSTEM_H option(${projectPrefix}USE_FMTLIB "Enables usage of fmtlib instead of the 'std::format' facilities" OFF) message(STATUS "${projectPrefix}USE_FMTLIB: ${${projectPrefix}USE_FMTLIB}") -list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +# C++ features +check_cxx_feature_supported(__cpp_explicit_this_parameter ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED) +check_cxx_feature_supported("__cpp_constexpr >= 202211L" ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS) -include(AddMPUnitsModule) -include(GNUInstallDirs) +if(${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED) + message(STATUS "API/ABI: `quantity_spec` uses explicit `this` parameter in its definition") +else() + message(STATUS "API/ABI: `quantity_spec` uses CRTP in its definition") +endif() +if(${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS) + message(STATUS "API/ABI: `unit_symbol()` returns `std::string_view`") +else() + message(STATUS "API/ABI: `unit_symbol()` returns `fixed_string`") +endif() + +# C++ modules if(${projectPrefix}BUILD_CXX_MODULES) + if(CMAKE_VERSION VERSION_LESS "3.28.1") + message(FATAL_ERROR, "CMake versions before 3.28.1 do not support C++ modules properly") + endif() + cmake_minimum_required(VERSION 3.28.1) + + # # none of the below seems to work + # cmake_policy(VERSION 3.28.1) + # cmake_policy(SET CMP0155 NEW) + set(${projectPrefix}TARGET_SCOPE "PUBLIC") else() set(${projectPrefix}TARGET_SCOPE "INTERFACE") endif() -if(${projectPrefix}AS_SYSTEM_HEADERS) - set(unitsAsSystem SYSTEM) -endif() - +# components/modules add_subdirectory(core) add_subdirectory(systems) diff --git a/src/cmake/CheckCXXFeatureSupported.cmake b/src/cmake/CheckCXXFeatureSupported.cmake new file mode 100644 index 00000000..43d1b39b --- /dev/null +++ b/src/cmake/CheckCXXFeatureSupported.cmake @@ -0,0 +1,119 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#[=======================================================================[.rst: +CheckCXXFeatureSupported +------------------------ + +Check if a C++ feature is supported. + +.. command:: check_cxx_feature_supported + + .. code-block:: cmake + + check_cxx_feature_supported( ) + + Check that the ```` is true and store the result in a ````. + +The following variables may be set before calling this macro to modify +the way the check is run: + +.. include:: /module/CMAKE_REQUIRED_FLAGS.txt + +.. include:: /module/CMAKE_REQUIRED_DEFINITIONS.txt + +.. include:: /module/CMAKE_REQUIRED_INCLUDES.txt + +.. include:: /module/CMAKE_REQUIRED_LINK_OPTIONS.txt + +.. include:: /module/CMAKE_REQUIRED_LIBRARIES.txt + +.. include:: /module/CMAKE_REQUIRED_QUIET.txt + +For example: + +.. code-block:: cmake + + include(CheckCXXFeatureSupported) + + check_cxx_feature_supported(__cpp_explicit_this_parameter EXPLICIT_THIS_PARAMETER_SUPPORTED) + check_cxx_feature_supported("__cpp_constexpr >= 202211L" STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS) +#]=======================================================================] + +include_guard(GLOBAL) + +macro(CHECK_CXX_FEATURE_SUPPORTED CONDITION VARIABLE) + if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") + set(_CFS_SOURCE "/* */\n") + set(MACRO_CHECK_FEATURE_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) + if(CMAKE_REQUIRED_LINK_OPTIONS) + set(CHECK_FEATURE_EXISTS_LINK_OPTIONS + LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS}) + else() + set(CHECK_FEATURE_EXISTS_LINK_OPTIONS) + endif() + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_FEATURE_EXISTS_LIBS + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_FEATURE_EXISTS_LIBS) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CMAKE_FEATURE_EXISTS_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CMAKE_FEATURE_EXISTS_INCLUDES) + endif() + string(APPEND _CFS_SOURCE + "#include \n") + string(APPEND _CFS_SOURCE " +int main() +{ + static_assert(${CONDITION}); +}\n") + + if(NOT CMAKE_REQUIRED_QUIET) + message(CHECK_START "Checking C++ feature test macro '${CONDITION}'") + endif() + try_compile(${VARIABLE} + SOURCE_FROM_VAR "CheckFeatureExists.cxx" _CFS_SOURCE + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_FEATURE_EXISTS_LINK_OPTIONS} + ${CHECK_FEATURE_EXISTS_LIBS} + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FEATURE_EXISTS_FLAGS} + "${CMAKE_FEATURE_EXISTS_INCLUDES}" + ) + if(${VARIABLE}) + if(NOT CMAKE_REQUIRED_QUIET) + message(CHECK_PASS "SUCCESS") + endif() + set(${VARIABLE} 1 CACHE INTERNAL "C++ feature test macro '${CONDITION}' supported") + else() + if(NOT CMAKE_REQUIRED_QUIET) + message(CHECK_FAIL "FAIL") + endif() + set(${VARIABLE} "" CACHE INTERNAL "C++ feature test macro '${CONDITION}' supported") + endif() + unset(_CFS_SOURCE) + endif() +endmacro()