Skip to content

Commit f6fb710

Browse files
committed
CMake: leave C++ standard selection to the user
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.
1 parent cdf7622 commit f6fb710

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2952,10 +2952,10 @@ target_link_libraries(app PRIVATE cppcoro::cppcoro)
29522952
```bash
29532953
$ cmake . -Dcppcoro_ROOT=$HOME/.local
29542954
# ...
2955-
-- Performing Test Coroutines_SUPPORTS_MS_FLAG
2956-
-- Performing Test Coroutines_SUPPORTS_MS_FLAG - Failed
2957-
-- Performing Test Coroutines_SUPPORTS_COROUTINES_FLAG
2958-
-- Performing Test Coroutines_SUPPORTS_COROUTINES_FLAG - Success
2955+
-- Performing Test _CXX_COROUTINES_SUPPORTS_MS_FLAG
2956+
-- Performing Test _CXX_COROUTINES_SUPPORTS_MS_FLAG - Failed
2957+
-- Performing Test _CXX_COROUTINES_SUPPORTS_CORO_FLAG
2958+
-- Performing Test _CXX_COROUTINES_SUPPORTS_CORO_FLAG - Success
29592959
-- Looking for C++ include coroutine
29602960
-- Looking for C++ include coroutine - not found
29612961
-- Looking for C++ include experimental/coroutine

cmake/FindCoroutines.cmake

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ if(TARGET std::coroutines)
100100
return()
101101
endif()
102102

103+
include(CheckCXXCompilerFlag)
103104
include(CMakePushCheckState)
104105
include(CheckIncludeFileCXX)
105106
include(CheckCXXSourceCompiles)
@@ -108,13 +109,16 @@ cmake_push_check_state()
108109

109110
set(CMAKE_REQUIRED_QUIET ${Coroutines_FIND_QUIETLY})
110111

111-
# All of our tests required C++17 or later
112-
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")
113-
set(_CXX_COROUTINES_STD17 "/std:c++17")
114-
set(_CXX_COROUTINES_AWAIT "/await")
115-
else()
116-
set(_CXX_COROUTINES_STD17 "-std=c++17")
117-
set(_CXX_COROUTINES_AWAIT "-fcoroutines-ts")
112+
check_cxx_compiler_flag(/await _CXX_COROUTINES_SUPPORTS_MS_FLAG)
113+
check_cxx_compiler_flag(-fcoroutines-ts _CXX_COROUTINES_SUPPORTS_TS_FLAG)
114+
check_cxx_compiler_flag(-fcoroutines _CXX_COROUTINES_SUPPORTS_CORO_FLAG)
115+
116+
if(_CXX_COROUTINES_SUPPORTS_MS_FLAG)
117+
set(_CXX_COROUTINES_EXTRA_FLAGS "/await")
118+
elseif(_CXX_COROUTINES_SUPPORTS_TS_FLAG)
119+
set(_CXX_COROUTINES_EXTRA_FLAGS "-fcoroutines-ts")
120+
elseif(_CXX_COROUTINES_SUPPORTS_CORO_FLAG)
121+
set(_CXX_COROUTINES_EXTRA_FLAGS "-fcoroutines")
118122
endif()
119123

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

143147
if(find_final)
144148
check_include_file_cxx("coroutine" _CXX_COROUTINES_HAVE_HEADER)
149+
if(NOT _CXX_COROUTINES_HAVE_HEADER)
150+
cmake_push_check_state()
151+
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
152+
check_include_file_cxx("coroutine" _CXX_COROUTINES_HAVE_HEADER_WITH_FLAG)
153+
set(_CXX_COROUTINES_HAVE_HEADER ${_CXX_COROUTINES_HAVE_HEADER_WITH_FLAG})
154+
cmake_pop_check_state()
155+
endif()
145156
mark_as_advanced(_CXX_COROUTINES_HAVE_HEADER)
146157
if(_CXX_COROUTINES_HAVE_HEADER)
147158
# We found the non-experimental header. Don't bother looking for the
@@ -154,6 +165,13 @@ endif()
154165

155166
if(find_experimental)
156167
check_include_file_cxx("experimental/coroutine" _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
168+
if(NOT _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
169+
cmake_push_check_state()
170+
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
171+
check_include_file_cxx("experimental/coroutine" _CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER_WITH_FLAG)
172+
set(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER ${_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER_WITH_FLAG})
173+
cmake_pop_check_state()
174+
endif()
157175
mark_as_advanced(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER)
158176
else()
159177
set(_CXX_COROUTINES_HAVE_EXPERIMENTAL_HEADER FALSE)
@@ -188,7 +206,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)
188206
int result;
189207
present get_return_object() { return present{*this}; }
190208
@CXX_COROUTINES_NAMESPACE@::suspend_never initial_suspend() { return {}; }
191-
@CXX_COROUTINES_NAMESPACE@::suspend_always final_suspend() { return {}; }
209+
@CXX_COROUTINES_NAMESPACE@::suspend_always final_suspend() noexcept { return {}; }
192210
void return_value(int i) { result = i; }
193211
void unhandled_exception() {}
194212
};
@@ -223,7 +241,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)
223241

224242
if(NOT CXX_COROUTINES_NO_AWAIT_NEEDED)
225243
# Add the -fcoroutines-ts (or /await) flag
226-
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_STD17} ${_CXX_COROUTINES_AWAIT}")
244+
set(CMAKE_REQUIRED_FLAGS "${_CXX_COROUTINES_EXTRA_FLAGS}")
227245
check_cxx_source_compiles("${code}" CXX_COROUTINES_AWAIT_NEEDED)
228246
set(can_link ${CXX_COROUTINES_AWAIT_NEEDED})
229247
endif()
@@ -235,7 +253,7 @@ if(CXX_COROUTINES_HAVE_COROUTINES)
235253
if(CXX_COROUTINES_NO_AWAIT_NEEDED)
236254
# Nothing to add...
237255
elseif(CXX_COROUTINES_AWAIT_NEEDED)
238-
target_compile_options(std::coroutines INTERFACE ${_CXX_COROUTINES_AWAIT})
256+
target_compile_options(std::coroutines INTERFACE ${_CXX_COROUTINES_EXTRA_FLAGS})
239257
endif()
240258
else()
241259
set(CXX_COROUTINES_HAVE_COROUTINES FALSE)
@@ -247,5 +265,5 @@ cmake_pop_check_state()
247265
set(Coroutines_FOUND ${_found} CACHE BOOL "TRUE if we can compile and link a program using std::coroutines" FORCE)
248266

249267
if(Coroutines_FIND_REQUIRED AND NOT Coroutines_FOUND)
250-
message(FATAL_ERROR "Cannot compile simple program using std::coroutines")
268+
message(FATAL_ERROR "Cannot compile simple program using std::coroutines. Is C++17 or later activated?")
251269
endif()

lib/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ target_include_directories(cppcoro PUBLIC
159159
$<INSTALL_INTERFACE:include>)
160160
target_compile_features(cppcoro PUBLIC cxx_std_20)
161161

162-
find_package(Coroutines REQUIRED)
162+
find_package(Coroutines COMPONENTS Experimental Final REQUIRED)
163163
target_link_libraries(cppcoro PUBLIC std::coroutines)
164164

165165
install(TARGETS cppcoro EXPORT cppcoroTargets

0 commit comments

Comments
 (0)