cmake_minimum_required(VERSION 3.21) project(coroutine LANGUAGES CXX VERSION 2.0.0) option(BUILD_SHARED_LIBS "https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html" ON) option(CMAKE_BUILD_TYPE "https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html" "Debug") option(BUILD_TESTING "Build test program" OFF) option(WITH_GCD "Build with GCD(libdispatch)" OFF) # set(CMAKE_C_STANDARD 17) # set(CMAKE_CXX_STANDARD 20) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS true) include(GNUInstallDirs) message(STATUS "system: ${CMAKE_SYSTEM}") message(STATUS "build_type: ${CMAKE_BUILD_TYPE}") message(STATUS "paths:") message(STATUS " - ${CMAKE_INSTALL_PREFIX}") message(STATUS " - ${PROJECT_SOURCE_DIR}") message(STATUS " - ${PROJECT_BINARY_DIR}") message(STATUS) message(STATUS "compiler:") message(STATUS " - ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") message(STATUS " - ${CMAKE_CXX_COMPILER}") message(STATUS) message(STATUS "cmake:") message(STATUS " - ${CMAKE_VERSION}") message(STATUS " - ${CMAKE_COMMAND}") message(STATUS " - ${CMAKE_TOOLCHAIN_FILE}") message(STATUS " - ${CMAKE_GENERATOR}") message(STATUS " - ${CMAKE_BUILD_TOOL}") message(STATUS) # get_filename_component(CMAKE_COROUTINES_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/FindCoroutines.cmake ABSOLUTE) # if(NOT EXISTS ${CMAKE_COROUTINES_MODULE_PATH}) # file(DOWNLOAD https://raw.githubusercontent.com/facebookexperimental/libunifex/main/cmake/FindCoroutines.cmake # ${CMAKE_COROUTINES_MODULE_PATH} # EXPECTED_HASH SHA256=0129305dd3d030de21684543fec9b1e7b0af7a67ed1bad4348c3259ecfb20cef # ) # endif() list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) # # Known STL-Compiler issues # - https://github.com/microsoft/STL, issue 100 # if(CMAKE_CXX_COMPILER_ID MATCHES Clang AND WIN32) message(WARNING "clang-cl won't work with ") endif() find_package(Coroutines REQUIRED) find_package(Threads REQUIRED) # Threads::Threads find_package(fmt CONFIG REQUIRED) # fmt::fmt-header-only find_package(spdlog CONFIG REQUIRED) # spdlog::spdlog_header_only # see https://github.com/microsoft/GSL/tree/v4.0.0 # check https://github.com/microsoft/vcpkg ms-gsl # find_package(Microsoft.GSL 4.0 CONFIG REQUIRED) # Microsoft.GSL::GSL add_library(coro_cpp17 src/coro.hpp src/coro.cpp) add_library(coro_cpp20 src/coro.hpp src/coro.cpp) add_library(coro_latest src/coro.hpp src/coro.cpp) add_library(coro_action17 SHARED src/action.hpp src/action.cpp) add_library(coro_action20 SHARED src/action.hpp src/action.cpp) if(MSVC) add_library(coro_clangcl INTERFACE) target_compile_definitions(coro_clangcl INTERFACE __cpp_impl_coroutine=201902L _DOWNLEVEL_COROUTINES_SUPPORTED ) if(CMAKE_CXX_COMPILER_ID MATCHES Clang) target_compile_options(coro_cpp17 PRIVATE "SHELL:/clang:-std=c++20" "SHELL:/clang:-fcoroutines-ts") target_compile_options(coro_action17 PRIVATE "SHELL:/clang:-std=c++20") target_link_libraries(coro_action17 PRIVATE coro_cpp17 coro_clangcl) target_link_libraries(coro_action20 PRIVATE coro_cpp20 coro_clangcl) else() target_compile_options(coro_cpp17 PUBLIC /std:c++17 /await PRIVATE /Zc:__cplusplus) target_compile_options(coro_action17 PRIVATE /Zc:__cplusplus) target_link_libraries(coro_action17 PRIVATE coro_cpp17) target_link_libraries(coro_action20 PRIVATE coro_cpp20) endif() target_compile_options(coro_cpp20 PUBLIC /std:c++20 PRIVATE /Zc:__cplusplus) target_compile_options(coro_latest PUBLIC /std:c++latest PRIVATE /Zc:__cplusplus) target_compile_options(coro_action20 PRIVATE /Zc:__cplusplus) elseif(CMAKE_CXX_COMPILER_ID MATCHES Clang) target_compile_options(coro_cpp17 PUBLIC -std=c++17 -fcoroutines-ts) target_compile_options(coro_cpp20 PUBLIC -std=c++20) target_compile_options(coro_latest PUBLIC -std=c++2b) target_link_libraries(coro_action17 PRIVATE coro_cpp17) target_link_libraries(coro_action20 PRIVATE coro_cpp20) elseif(CMAKE_CXX_COMPILER_ID MATCHES GNU) # ... endif() if(WITH_GCD) # libdispatch if(APPLE) find_library(DISPATCH_LIBPATH NAMES CoreFoundation REQUIRED) elseif(WIN32) find_library(DISPATCH_LIBPATH NAMES dispatch REQUIRED) find_library(BLOCKS_RUNTIME_LIBPATH NAMES BlocksRuntime REQUIRED) endif() add_library(coro_gcd17 SHARED src/gcd.hpp src/gcd.cpp) set_target_properties(coro_gcd17 PROPERTIES CXX_STANDARD 17) target_include_directories(coro_gcd17 PRIVATE src) target_link_libraries(coro_gcd17 PRIVATE ${DISPATCH_LIBPATH} ${BLOCKS_RUNTIME_LIBPATH} coro_cpp17 coro_action17 spdlog::spdlog) endif() return() string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) list(APPEND headers src/coroutine/frame.h src/coroutine/${system_name}.h ) add_library(coroutine ${headers} # src/frame.cpp # src/${system_name}.cpp src/libmain.cpp ) set_target_properties(coroutine PROPERTIES PUBLIC_HEADER "${headers}" WINDOWS_EXPORT_ALL_SYMBOLS true CXX_STANDARD_REQUIRED true CXX_STANDARD 20 ) target_include_directories(coroutine PUBLIC $ $ ) target_link_libraries(coroutine PRIVATE Threads::Threads fmt::fmt-header-only spdlog::spdlog_header_only ) # compiler options / macro hints if(CMAKE_CXX_COMPILER_ID MATCHES Clang) if(WIN32) # 'target_compile_options' removes duplicated -Xclang directive. # avoide the removal using cmake flag variable target_compile_options(coroutine PUBLIC "/clang:-std=c++20" # c++2b for experiment? PRIVATE "/clang:-fms-compatibility-version=1900" # -Wall -Wextra -ferror-limit=5 ) # clang 13: `__cpp_coroutines` macro is 201703L. `__cpp_lib_coroutine` is NOT defined target_compile_definitions(coroutine PUBLIC # force feature activation. # see https://github.com/llvm/llvm-project/blob/release/13.x/clang/lib/Frontend/InitPreprocessor.cpp __cpp_impl_coroutine=201902L # make define __cpp_lib_coroutine # see https://github.com/microsoft/STL, issue 1730, 2510 _DOWNLEVEL_COROUTINES_SUPPORTED ) elseif(UNIX OR APPLE) target_compile_options(coroutine PUBLIC -stdlib=libc++ -fcoroutines-ts ) endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES GNU) target_compile_options(coroutine PUBLIC -fcoroutines ) target_link_libraries(coroutine PUBLIC stdc++ ) elseif(MSVC) # select between C++ Coroutines TS & C++ 20 Coroutines # if(support_intrinsic_builtin AND has_coroutine) # target_compile_options(coroutine # PUBLIC # /std:c++20 # ) # else() # target_compile_options(coroutine # PUBLIC # /std:c++17 /await # ) # endif() # see https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus target_compile_options(coroutine PRIVATE /Zc:__cplusplus /JMC- ) endif() # compile definition and linkage if(WIN32) target_compile_definitions(coroutine PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX ) elseif(CMAKE_SYSTEM_NAME MATCHES Linux) if(ANDROID) target_link_libraries(coroutine PUBLIC ${ANDROID_STL} # expect c++_shared ) else() target_link_libraries(coroutine PUBLIC rt ) endif() elseif(UNIX OR APPLE) target_link_libraries(coroutine PUBLIC c++ ) endif() install(TARGETS coroutine EXPORT coroutine-config PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # # export declared cmake targets # # 'coroutine-targets' is indeed better name, but without using 'configure_file()' # the exporting step will be more complicated for non-CMake users. # just merge all contents into the file 'coroutine-config.cmake' # install(EXPORT ${PROJECT_NAME}-config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME} # share/coroutine ) # # generate/install config & version info # include(CMakePackageConfigHelpers) set(VERSION_FILE_PATH ${CMAKE_BINARY_DIR}/cmake/${PROJECT_NAME}-config-version.cmake) write_basic_package_version_file(${VERSION_FILE_PATH} VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES ${VERSION_FILE_PATH} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME} # share/coroutine ) # # for testing, CTest will be used # if(NOT BUILD_TESTING) message(STATUS "Test is disabled.") return() endif() enable_testing() find_package(Catch2 2.13 CONFIG REQUIRED) # Catch2::Catch2 # create a test exe with the given name ... add_executable(coroutine_test_suite test/test_main.cpp test/test_action.cpp ) set_target_properties(coroutine_test_suite PROPERTIES CXX_STANDARD 20 CXX_STANDARD_REQUIRED true ) # target_compile_definitions(coroutine_test_suite # PRIVATE # CATCH_CONFIG_FAST_COMPILE # ) target_link_libraries(coroutine_test_suite PRIVATE Catch2::Catch2 coroutine ) if(coroutine_IS_TOP_LEVEL) install(TARGETS coroutine_test_suite DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() add_test(NAME test_exception COMMAND coroutine_test_suite "[exception]") # create_ctest( article_russian_roulette coroutine_portable ) # # # # # # # # # # , # # if(APPLE) add_test(NAME test_dispatch COMMAND coroutine_test_suite "[dispatch]") endif() # # # # # # if(CMAKE_CXX_COMPILER_ID MATCHES GNU) message(WARNING "using gcc: the compiler may not work for current code") endif()