diff --git a/CMakeLists.txt b/CMakeLists.txt index 03ad72e8a..155ceb28b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,9 @@ project(libtorrent set (SOVERSION "9") list(APPEND CMAKE_MODULE_PATH ${libtorrent_SOURCE_DIR}/cmake/Modules) -include(FeatureSummary) include(GNUInstallDirs) include(GeneratePkgConfig) +include(LibtorrentMacros) set(sources web_connection_base @@ -165,55 +165,14 @@ set(ed25519_sources set(includes include ed25519/src) -function(list_prepend _listName _prefix) - string(REGEX REPLACE "([^;]+)" "${_prefix}\\1" _tmp_list "${${_listName}}") - set (${_listName} "${_tmp_list}" PARENT_SCOPE) -endfunction() - list_prepend(sources "src/") list_prepend(kademlia_sources "src/kademlia/") list_prepend(ed25519_sources "ed25519/src/") -function(target_optional_compile_definitions _target _scope) - set(options FEATURE) - set(oneValueArgs NAME DESCRIPTION DEFAULT) - set(multiValueArgs ENABLED DISABLED) - cmake_parse_arguments(TOCD ${options} "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - option(${TOCD_NAME} "${TOCD_DESCRIPTION}" ${TOCD_DEFAULT}) - if (${${TOCD_NAME}}) - target_compile_definitions(${_target} ${_scope} ${TOCD_ENABLED}) - else() - target_compile_definitions(${_target} ${_scope} ${TOCD_DISABLED}) - endif() - if(${TOCD_FEATURE}) - add_feature_info(${TOCD_NAME} ${TOCD_NAME} "${TOCD_DESCRIPTION}") - endif() -endfunction() - -macro(feature_option _name _description _default) - option(${_name} "${_description}" ${_default}) - add_feature_info(${_name} ${_name} "${_description}") -endmacro() - # these options control target creation and thus have to be declared before the add_library() call feature_option(BUILD_SHARED_LIBS "build libtorrent as a shared library" ON) feature_option(static_runtime "build libtorrent with static runtime" OFF) -macro(find_public_dependency _name) - find_package(${_name} ${ARGN}) - string(TOUPPER "${_name}" _name_uppercased) - if (${_name}_FOUND OR ${_name_uppercased}_FOUND) - # Dependencies to be used below for generating Config.cmake file - # We don't need the 'REQUIRED' argument there - set(_args "${_name}") - list(APPEND _args "${ARGN}") - list(REMOVE_ITEM _args "REQUIRED") - list(REMOVE_ITEM _args "") # just in case - string(REPLACE ";" " " _args "${_args}") - list(APPEND _package_dependencies "${_args}") - endif() -endmacro() - find_public_dependency(Threads REQUIRED) if(static_runtime) @@ -319,6 +278,7 @@ option(tcmalloc "link against google performance tools tcmalloc" OFF) # 1. With C++11 onward, we require Boost system component, with C++03 we need chrono and random components too # 2. When building against boost 1.66 and newer, C++11 is required. +set(minimal_required_cxx_standard 98) # For the first requirement we do: set(required_boost_components system) if (NOT cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES) @@ -331,20 +291,14 @@ target_link_libraries(torrent-rasterbar PUBLIC ${Boost_SYSTEM_LIBRARY}) # now test the second requirement: if (Boost_VERSION VERSION_GREATER_EQUAL 106600) + set(minimal_required_cxx_standard 11) if (NOT cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES) message(FATAL_ERROR "When building against boost 1.66 and newer, C++11 is required,\n" "and your compiler does not support that") endif() endif() -# selecting C++14/11 mode if available -if (cxx_std_14 IN_LIST CMAKE_CXX_COMPILE_FEATURES) - target_compile_features(torrent-rasterbar PUBLIC cxx_std_14) - message(STATUS "Building in C++14 mode") -elseif(cxx_std_11 IN_LIST CMAKE_CXX_COMPILE_FEATURES) - target_compile_features(torrent-rasterbar PUBLIC cxx_std_11) - message(STATUS "Building in C++11 mode") -endif() +select_cxx_standard(torrent-rasterbar ${minimal_required_cxx_standard}) target_link_libraries(torrent-rasterbar PUBLIC ${Boost_LIBRARIES}) diff --git a/Makefile.am b/Makefile.am index 4aa50bcf3..49c3f97e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,6 +123,7 @@ EXTRA_DIST = \ README.rst \ cmake/Modules/FindLibGcrypt.cmake \ cmake/Modules/GeneratePkgConfig.cmake \ + cmake/Modules/LibtorrentMacros.cmake \ cmake/Modules/ucm_flags.cmake \ cmake/Modules/GeneratePkgConfig/generate-pkg-config.cmake.in \ cmake/Modules/GeneratePkgConfig/pkg-config.cmake.in \ diff --git a/cmake/Modules/LibtorrentMacros.cmake b/cmake/Modules/LibtorrentMacros.cmake new file mode 100644 index 000000000..6690efe67 --- /dev/null +++ b/cmake/Modules/LibtorrentMacros.cmake @@ -0,0 +1,102 @@ +# Various helper function and macros for building libtorrent + +include(FeatureSummary) + +# macro for issuing option() and add_feature_info() in a single call. +# Synopsis: +# feature_option( ) +macro(feature_option _name _description _default) + option(${_name} "${_description}" ${_default}) + add_feature_info(${_name} ${_name} "${_description}") +endmacro() + +# function to add a simple build option which controls compile definition(s) for a target. +# Synopsis: +# target_optional_compile_definitions( [FEATURE] +# NAME DESCRIPTION DEFAULT +# [ENABLED [enabled_compile_definitions...]] +# [DISABLED [disabled_compile_defnitions...]] +# ) +# NAME, DESCRIPTION and DEFAULT are passed to option() call +# if FEATURE is given, they are passed to add_feature_info() +# ENABLED lists compile definitions that will be set on when option is enabled, +# DISABLED lists definitions that will be set otherwise +function(target_optional_compile_definitions _target _scope) + set(options FEATURE) + set(oneValueArgs NAME DESCRIPTION DEFAULT) + set(multiValueArgs ENABLED DISABLED) + cmake_parse_arguments(TOCD ${options} "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + option(${TOCD_NAME} "${TOCD_DESCRIPTION}" ${TOCD_DEFAULT}) + if (${${TOCD_NAME}}) + target_compile_definitions(${_target} ${_scope} ${TOCD_ENABLED}) + else() + target_compile_definitions(${_target} ${_scope} ${TOCD_DISABLED}) + endif() + if(${TOCD_FEATURE}) + add_feature_info(${TOCD_NAME} ${TOCD_NAME} "${TOCD_DESCRIPTION}") + endif() +endfunction() + +# a helper macro that calls find_package() and appends the package (if found) to the +# _package_dependencies list, which can be used later to generate package config file +macro(find_public_dependency _name) + find_package(${_name} ${ARGN}) + string(TOUPPER "${_name}" _name_uppercased) + if (${_name}_FOUND OR ${_name_uppercased}_FOUND) + # Dependencies to be used below for generating Config.cmake file + # We don't need the 'REQUIRED' argument there + set(_args "${_name}") + list(APPEND _args "${ARGN}") + list(REMOVE_ITEM _args "REQUIRED") + list(REMOVE_ITEM _args "") # just in case + string(REPLACE ";" " " _args "${_args}") + list(APPEND _package_dependencies "${_args}") + endif() +endmacro() + +function(_cxx_standard_to_year _yearVar _std) + if (${_std} GREATER 97) + math(EXPR _year "1900 + ${_std}") + else() + math(EXPR _year "2000 + ${_std}") + endif() + set(${_yearVar} ${_year} PARENT_SCOPE) +endfunction() + +function(select_cxx_standard _target _minimal_supported_version) + message(STATUS "Compiler default is C++${CMAKE_CXX_STANDARD_DEFAULT}") + # make the CXX_STANDARD property public to ensure it makes it into the pkg-config file + get_target_property(_std ${_target} CXX_STANDARD) + # RC_1_1 still supports C++98, which is lower version than C++11. Thus we convert std + # version to year value and compare years + _cxx_standard_to_year(minimal_supported_version_year ${_minimal_supported_version}) + # if it is unset, select the default if it is sufficient or the ${_minimal_supported_version} + if (NOT ${_std}) + _cxx_standard_to_year(std_default_year ${CMAKE_CXX_STANDARD_DEFAULT}) + if (${std_default_year} GREATER_EQUAL ${minimal_supported_version_year}) + set(_std ${CMAKE_CXX_STANDARD_DEFAULT}) + else() + set(_std ${_minimal_supported_version}) + endif() + else() + _cxx_standard_to_year(std_year ${_std}) + if (${std_year} LESS ${minimal_supported_version_year}) + message(SEND_ERROR "Sorry, C++${_std} is not supported by libtorrent with the given Boost version") + message(FATAL_ERROR "The minimal supported C++ standard version is C++${_minimal_supported_version}") + endif() + endif() + + if (cxx_std_${_std} IN_LIST CMAKE_CXX_COMPILE_FEATURES) + # force this standard + target_compile_features(${_target} PUBLIC cxx_std_${_std}) + else() + message(FATAL_ERROR "Requested C++ standard version (${_std}) is not supported by the compiler") + endif() + + message(STATUS "Building in C++${_std} mode") +endfunction() + +function(list_prepend _listName _prefix) + string(REGEX REPLACE "([^;]+)" "${_prefix}\\1" _tmp_list "${${_listName}}") + set (${_listName} "${_tmp_list}" PARENT_SCOPE) +endfunction()