Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GCC 10.1 support #158

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

GCC 10.1 support #158

wants to merge 5 commits into from

Conversation

dutow
Copy link

@dutow dutow commented Jul 19, 2020

This pull requests adds GCC support on top of @mmha's CMake pull request.

I cherry picked his commit to the current master branch for this, I will rebase my pull request once that PR is merged.

I opened this for now only so my changes can be reviewed.

As I explained in my last commit message GCC 10.1 seems to have remaining bugs causing test failures. I found workarounds for some of them, but I had to completely remove one testcase for GCC (not supported syntax), and leave a test failure as is (missing destructor call). Otherwise the library seems to be working.

mmha and others added 5 commits July 18, 2020 20:18
Starting with GCC 10.1, GCC/libstdc++ supports coroutines, but includes
them in their final location in <coroutine>.

This commit generalizes the location of the header, and the name of the
types (either in the std or std::experimental namespace), so that both
the current Clang/MSVC and the GCC approach can be supported.

This should also guarantee that both current and later Clang/MSVC
releases will be supported by the library.
While clang uses the -fcoroutines-ts flag to add support for the
Coroutines TS, GCC uses the -fcoroutines flag.

This commit refactors the cmake finder to support both.
* Included missing headers
* Disabled a testcase for GCC that uses a syntax not supported by
  GCC10.1
* Reordered a class so GCC is able to find a data member
After these changes, there's one failure remaining with GCC 10.1, where
it doesn't call a destructor for an object, and calls another later than
it should.

Other tests required workarounds for bugs in the GCC coroutine
implementation, but were possible to fix with minor code modifications.
@dutow dutow marked this pull request as draft July 19, 2020 20:34
@nanoric
Copy link

nanoric commented Aug 14, 2020

Great job!
When can this be merged?

Copy link
Owner

@lewissbaker lewissbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for the PR!
CMake and GCC support have been requested by several people.
My apologies for taking so long to review.

A few minor things to address:

  • Some accidental changes of std::experimental::filesystem to cppcoro::filesystem (which will break the Windows builds)
  • Missing reexport of std::noop_coroutine()
  • There is some debug spam still in test/counted.hpp
  • I'm not sure that some of the workarounds to get tests passing with GCC 10.1 are worthwhile.
    GCC 10.1 coroutines support was quite broken.
    I'd probably recommend requiring GCC 10.2 as a minimum compiler version for use with cppcoro.

Also, it would be good to hook up the CI configs to exercise the CMake builds to avoid regressions.
This can be deferred to a later PR though.


find_package_handle_standard_args(CppcoroCoroutines
REQUIRED_VARS Coroutines_LIBRARY_SUPPORT Coroutines_COMPILER_SUPPORT
FAIL_MESSAGE "Verify that the compiler and the standard library both support the Coroutines TS")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe reword to also be inclusive of C++20 coroutines, not just Coroutines TS?
"... both support either C++20 coroutines or the Coroutines TS"


namespace cppcoro {
template<typename Promise=void>
using coroutine_handle = std::coroutine_handle<Promise>;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also one place that makes use of std::experimental::noop_coroutine() (round_robin_scheduler.hpp) which also needs to be made available if it's provided by the platform headers.

It should be supported by all <coroutine> headers (since that's required by the C++20 spec).
However, compilers that just implemented the coroutines TS may not have it (e.g. early versions of clang and all MSVC versions).

We may need some kind of detection/macro to enable this (or maybe we can use feature-macros to detect it?)

#include <experimental/coroutine>
#include <cppcoro/coroutine.hpp>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like this include is needed.
Remove it instead?

#include <experimental/coroutine>
#include <cppcoro/coroutine.hpp>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly here, include seems to be unused. Maybe just remove this include?

@@ -61,7 +61,7 @@ namespace cppcoro
public:
round_robin_scheduler() noexcept
: m_index(0)
, m_noop(std::experimental::noop_coroutine())
, m_noop(cppcoro::noop_coroutine())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The noop_coroutine() function has not been exported from cppcoro yet.

Comment on lines +385 to +387
// GCC 10.1 workaround: "co_yield start++ always returns the same value, resulting in an infinite loop
// ((++start)-1) seems to have the same issue, while ++start works, but breaks the test
start++;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC 10.1 had a large number of coroutine bugs. I wouldn't recommend it for any coroutine code in production.
This issue should hopefully have been fixed in 10.2, although I'm not sure whether this particular issue was reported.

Possibly related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95017 or https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95599 ?

Comment on lines +123 to +124
// GCC 10.1 workaround: GCC doesn't generate any code for a for loop with only a co_await in it
[](){}();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed in GCC 10.2.
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95017

Comment on lines +180 to +181
// GCC 10.1 performs 2 copies
CHECK(counted::copy_construction_count >= 1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed in GCC 10.2
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95350

@@ -112,6 +112,9 @@ TEST_CASE("when_all() with all task types")

CHECK(a == "foo");
CHECK(b.id == 0);
// GCC 10.1 fails this check: at this point there are 3 objects alive
// * One will be destructed later
// * One object is completely leaked
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I wonder why this one is failing.
There were a few destructor-related bugs I found in 10.1 most of which should be fixed in 10.2.
Have you tested this with 10.2 to see if it passes?

namespace fs = std::experimental::filesystem;
namespace fs = cppcoro::filesystem;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidental search+replace change?

I couldn't see any changes that would have reexported std::experimental::filesystem under cppcoro.
Also see other headers: file.hpp/cpp, read_write_file.hpp/cpp, read_only_file.hpp/cpp, write_only_file.hpp/cpp

@OleksandrKvl
Copy link

OleksandrKvl commented Aug 26, 2020

I've done similar CMake+GCC support for local experiments and implemented several things differently, not quite clean though.
Consider replacing for co_await with manual implementation because it hasn't been approved for C++20. Also, why cppcoroConfig.cmake and FindCppcoroCoroutines.cmake are needed there? IIRC, they should be generated outside of project directory where others can reach them. Here's my installation part:

include(GNUInstallDirs)

# install headers
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../include/cppcoro 
    TYPE INCLUDE
)

# install binary
install(TARGETS cppcoro_lib
    EXPORT coro
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

# install config for find_package()
install(EXPORT coro
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cppcoro
    NAMESPACE cppcoro::
    FILE cppcoroConfig.cmake
)

# generate export file
export(EXPORT coro
    NAMESPACE cppcoro::
    FILE cppcoroExport.cmake
)

It's usually good to set default CMAKE_BUILD_TYPE to Release. People then can use canonical CMake installation mkdir build && cd build && cmake .. && cmake --build . && cmake --install .

@GIGte GIGte mentioned this pull request Aug 27, 2020
@pbrady
Copy link

pbrady commented Sep 8, 2020

Just want to say that I'm excited about this.

@dutow
Copy link
Author

dutow commented Sep 9, 2020

@OleksandrKvl the cmake files are from #110, I didn't change those. And I'm not sure if defaulting to release is a good idea, as that would effect multi-buildtype IDE setups also (like visual studio or xcode). If a projects wants to set a default build type correctly, it usually requires several conditions (don't do anything if using a multi config generator ; use debug if the .git directory is present ; use relwithdebinfo otherwise)

@lewissbaker I'll updat my PR based on your comments, but do you have plans about #110? As currently this PR includes that commit too.

@lewissbaker
Copy link
Owner

I've added some comments to #110.
Perhaps @OleksandrKvl 's comments above could be added to that PR and CMake-related discussion moved there?

@dutow Would it be possible to separate this PR out into just the code-changes needed for GCC support and not have it build upon the CMake changes, so that they can be merged independently?

@dutow
Copy link
Author

dutow commented Oct 10, 2020

@lewissbaker Then we don't have a build system I'm actually familiar with. Cake seems to be a custom tool written by you, and the cake script currently forces clang on linux/osx. Seems like adding gcc there would require more changes than the cmake script (adding a config to choose the compiler, then refactoring the entire linux/darwin section to handle both clang and gcc)

Also, then we'll have to add d99be58 to the cmake pullrequest instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants