Skip to content

Commit

Permalink
CMake: leave C++ standard selection to the user
Browse files Browse the repository at this point in the history
FindCoroutines.cmake tried to figure out the correct flags to use
coroutines. However, with MSVC 16.8 this is impossible. MSVC 16.8
supports both the coroutines-ts with its experimental headers
and experimental namespace as well as the C++20 coroutines.
The user can select the coroutines-ts with the /await flag and
the C++20 coroutines with /std:c++latest. Only the user can know
what she wants.
This patch changes the logic in FindCoroutines.cmake to basically:
If it does not compile without (/await|-fcoroutines-ts),
try adding (/await|-fcoroutines-ts) to the compiler flags.
  • Loading branch information
andreasbuhr committed Oct 21, 2020
1 parent cdf7622 commit f6fb710
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2952,10 +2952,10 @@ target_link_libraries(app PRIVATE cppcoro::cppcoro)
```bash
$ cmake . -Dcppcoro_ROOT=$HOME/.local
# ...
-- Performing Test Coroutines_SUPPORTS_MS_FLAG
-- Performing Test Coroutines_SUPPORTS_MS_FLAG - Failed
-- Performing Test Coroutines_SUPPORTS_COROUTINES_FLAG
-- Performing Test Coroutines_SUPPORTS_COROUTINES_FLAG - Success
-- Performing Test _CXX_COROUTINES_SUPPORTS_MS_FLAG
-- Performing Test _CXX_COROUTINES_SUPPORTS_MS_FLAG - Failed
-- Performing Test _CXX_COROUTINES_SUPPORTS_CORO_FLAG
-- Performing Test _CXX_COROUTINES_SUPPORTS_CORO_FLAG - Success
-- Looking for C++ include coroutine
-- Looking for C++ include coroutine - not found
-- Looking for C++ include experimental/coroutine
Expand Down
40 changes: 29 additions & 11 deletions cmake/FindCoroutines.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ if(TARGET std::coroutines)
return()
endif()

include(CheckCXXCompilerFlag)
include(CMakePushCheckState)
include(CheckIncludeFileCXX)
include(CheckCXXSourceCompiles)
Expand All @@ -108,13 +109,16 @@ cmake_push_check_state()

set(CMAKE_REQUIRED_QUIET ${Coroutines_FIND_QUIETLY})

# All of our tests required C++17 or later
if(("x${CMAKE_CXX_COMPILER_ID}" MATCHES "x.*Clang" AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
set(_CXX_COROUTINES_STD17 "/std:c++17")
set(_CXX_COROUTINES_AWAIT "/await")
else()
set(_CXX_COROUTINES_STD17 "-std=c++17")
set(_CXX_COROUTINES_AWAIT "-fcoroutines-ts")
check_cxx_compiler_flag(/await _CXX_COROUTINES_SUPPORTS_MS_FLAG)
check_cxx_compiler_flag(-fcoroutines-ts _CXX_COROUTINES_SUPPORTS_TS_FLAG)
check_cxx_compiler_flag(-fcoroutines _CXX_COROUTINES_SUPPORTS_CORO_FLAG)

if(_CXX_COROUTINES_SUPPORTS_MS_FLAG)
set(_CXX_COROUTINES_EXTRA_FLAGS "/await")
elseif(_CXX_COROUTINES_SUPPORTS_TS_FLAG)
set(_CXX_COROUTINES_EXTRA_FLAGS "-fcoroutines-ts")
elseif(_CXX_COROUTINES_SUPPORTS_CORO_FLAG)
set(_CXX_COROUTINES_EXTRA_FLAGS "-fcoroutines")
endif()

# Normalize and check the component list we were given
Expand Down Expand Up @@ -142,6 +146,13 @@ endif()

if(find_final)
check_include_file_cxx("coroutine" _CXX_COROUTINES_HAVE_HEADER)
if(NOT _CXX_COROUTINES_HAVE_HEADER)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
check_include_file_cxx("coroutine" _CXX_COROUTINES_HAVE_HEADER_WITH_FLAG)
set(_CXX_COROUTINES_HAVE_HEADER ${_CXX_COROUTINES_HAVE_HEADER_WITH_FLAG})
cmake_pop_check_state()
endif()
mark_as_advanced(_CXX_COROUTINES_HAVE_HEADER)
if(_CXX_COROUTINES_HAVE_HEADER)
# We found the non-experimental header. Don't bother looking for the
Expand All @@ -154,6 +165,13 @@ endif()

if(find_experimental)
check_include_file_cxx("experimental/coroutine" _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
if(NOT _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
check_include_file_cxx("experimental/coroutine" _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER_WITH_FLAG)
set(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER ${_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER_WITH_FLAG})
cmake_pop_check_state()
endif()
mark_as_advanced(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
else()
set(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER FALSE)
Expand Down Expand Up @@ -188,7 +206,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)
int result;
present get_return_object() { return present{*this}; }
@CXX_COROUTINES_NAMESPACE@::suspend_never initial_suspend() { return {}; }
@CXX_COROUTINES_NAMESPACE@::suspend_always final_suspend() { return {}; }
@CXX_COROUTINES_NAMESPACE@::suspend_always final_suspend() noexcept { return {}; }
void return_value(int i) { result = i; }
void unhandled_exception() {}
};
Expand Down Expand Up @@ -223,7 +241,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)

if(NOT CXX_COROUTINES_NO_AWAIT_NEEDED)
# Add the -fcoroutines-ts (or /await) flag
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_STD17} ${_CXX_COROUTINES_AWAIT}")
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
check_cxx_source_compiles("${code}" CXX_COROUTINES_AWAIT_NEEDED)
set(can_link ${CXX_COROUTINES_AWAIT_NEEDED})
endif()
Expand All @@ -235,7 +253,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)
if(CXX_COROUTINES_NO_AWAIT_NEEDED)
# Nothing to add...
elseif(CXX_COROUTINES_AWAIT_NEEDED)
target_compile_options(std::coroutines INTERFACE ${_CXX_COROUTINES_AWAIT})
target_compile_options(std::coroutines INTERFACE ${_CXX_COROUTINES_EXTRA_FLAGS})
endif()
else()
set(CXX_COROUTINES_HAVE_COROUTINES FALSE)
Expand All @@ -247,5 +265,5 @@ cmake_pop_check_state()
set(Coroutines_FOUND ${_found} CACHE BOOL "TRUE if we can compile and link a program using std::coroutines" FORCE)

if(Coroutines_FIND_REQUIRED AND NOT Coroutines_FOUND)
message(FATAL_ERROR "Cannot compile simple program using std::coroutines")
message(FATAL_ERROR "Cannot compile simple program using std::coroutines. Is C++17 or later activated?")
endif()
2 changes: 1 addition & 1 deletion lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ target_include_directories(cppcoro PUBLIC
$<INSTALL_INTERFACE:include>)
target_compile_features(cppcoro PUBLIC cxx_std_20)

find_package(Coroutines REQUIRED)
find_package(Coroutines COMPONENTS Experimental Final REQUIRED)
target_link_libraries(cppcoro PUBLIC std::coroutines)

install(TARGETS cppcoro EXPORT cppcoroTargets
Expand Down

0 comments on commit f6fb710

Please sign in to comment.