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

Added CMake build system #110

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.13)
project(cppcoro LANGUAGES CXX)

set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(CTest)

add_subdirectory(lib)
if(BUILD_TESTING)
add_subdirectory(test)
endif()

export(EXPORT cppcoroTargets
FILE "${PROJECT_BINARY_DIR}/cppcoro/cppcoroTargets.cmake"
NAMESPACE cppcoro::)
configure_file(cmake/cppcoroConfig.cmake
"${PROJECT_BINARY_DIR}/cppcoro/cppcoroConfig.cmake"
COPYONLY)

set(config_package_location lib/cmake/cppcoro)
install(DIRECTORY include
DESTINATION .
COMPONENT Devel)
install(FILES cmake/FindCppcoroCoroutines.cmake
DESTINATION ${config_package_location}
COMPONENT Devel)
install(EXPORT cppcoroTargets
FILE cppcoroTargets.cmake
NAMESPACE cppcoro::
DESTINATION ${config_package_location})
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/cppcoro/cppcoroConfig.cmake
DESTINATION ${config_package_location}
COMPONENT Devel)
68 changes: 66 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2859,18 +2859,20 @@ Given a type, `S`, that implements the `DelayedScheduler` and an instance, `s` o

The cppcoro library supports building under Windows with Visual Studio 2017 and Linux with Clang 5.0+.

This library makes use of the [Cake build system](https://github.com/lewissbaker/cake) (no, not the [C# one](http://cakebuild.net/)).
This library makes use of either the [Cake build system](https://github.com/lewissbaker/cake) (no, not the [C# one](http://cakebuild.net/)) or CMake.

The cake build system is checked out automatically as a git submodule so you don't need to download or install it separately.

## Building on Windows

This library currently requires Visual Studio 2017 or later and the Windows 10 SDK.

Support for Clang ([#3](https://github.com/lewissbaker/cppcoro/issues/3)) and Linux ([#15](https://github.com/lewissbaker/cppcoro/issues/15)) is planned.
Support for Linux ([#15](https://github.com/lewissbaker/cppcoro/issues/15)) is planned.

### Prerequisites

The CMakeLists requires version 3.13 or later.

The Cake build-system is implemented in Python and requires Python 2.7 to be installed.

Ensure Python 2.7 interpreter is in your PATH and available as 'python'.
Expand Down Expand Up @@ -2903,6 +2905,68 @@ c:\Code\cppcoro> git submodule update --init --recursive

### Building from the command-line

#### With CMake

Cppcoro follows the usual CMake workflow with no custom options added. Notable [standard CMake options](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html):

| Flag | Description | Default Value |
|----------------------|------------------------------|------------------------|
| BUILD_TESTING | Build the unit tests | ON |
| BUILD_SHARED_LIBS | Build as a shared library | OFF |
| CMAKE_BUILD_TYPE | Build as `Debug`/`Release` | <empty> |
| CMAKE_INSTALL_PREFIX | Where to install the library | `/usr/local` (on Unix) |

CMake also respects the [conventional environment variables](https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html):

| Environment Variable | Description |
|----------------------|-------------------------------|
| CXX | Path to the C++ compiler |
| CXXFLAGS | C++ compiler flags to prepend |
| LDFLAGS | Linker flags to prepend |

Example:

```bash
cd <this/repo>
mkdir build
cd build
export CXX=clang++
export CXXFLAGS="-stdlib=libc++ -march=native"
export LDFLAGS="-stdlib=libc++ -fuse-ld=lld -Wl,--gdb-index"
cmake .. [-GNinja] -DCMAKE_INSTALL_PREFIX=$HOME/.local -DBUILD_SHARED_LIBS=ON
ninja # or make -jN
ninja test # Run the tests
ninja install
```

The CMake build scripts will also install a `cppcoroConfig.cmake` file for consumers to use.
It will check at the consumer site that coroutines are indeed supported by the system and enable the appropriate compiler flag for Clang or MSVC, respectively.
Assuming cppcoro has been installed to `$HOME/.local` like in the example above it can be consumed like this:

```cmake
find_package(cppcoro REQUIRED)
add_executable(app main.cpp)
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_GNU_FLAG
-- Performing Test Coroutines_SUPPORTS_GNU_FLAG - Success
-- Looking for C++ include coroutine
-- Looking for C++ include coroutine - not found
-- Looking for C++ include experimental/coroutine
-- Looking for C++ include experimental/coroutine - found
-- Configuring done
-- Generating done
# ...
```

#### With Cake

To build from the command-line just run 'cake.bat' in the workspace root.

eg.
Expand Down
Empty file added cmake/CMakeLists.txt
Empty file.
36 changes: 36 additions & 0 deletions cmake/FindCppcoroCoroutines.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
include(CheckCXXCompilerFlag)
include(CheckIncludeFileCXX)
include(FindPackageHandleStandardArgs)

check_cxx_compiler_flag(/await Coroutines_SUPPORTS_MS_FLAG)
check_cxx_compiler_flag(-fcoroutines-ts Coroutines_SUPPORTS_GNU_FLAG)
Copy link
Owner

Choose a reason for hiding this comment

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

I think that since the adoption of coroutines into C++20 that clang (trunk?) now also enables coroutines when -std=c++2a is enabled.

if(Coroutines_SUPPORTS_MS_FLAG OR Coroutines_SUPPORTS_GNU_FLAG)
set(Coroutines_COMPILER_SUPPORT ON)
endif()

if(Coroutines_SUPPORTS_MS_FLAG)
check_include_file_cxx("coroutine" Coroutines_STANDARD_LIBRARY_SUPPORT "/await")
check_include_file_cxx("experimental/coroutine" Coroutines_EXPERIMENTAL_LIBRARY_SUPPORT "/await")
elseif(Coroutines_SUPPORTS_GNU_FLAG)
check_include_file_cxx("coroutine" Coroutines_STANDARD_LIBRARY_SUPPORT "-fcoroutines-ts")
check_include_file_cxx("experimental/coroutine" Coroutines_EXPERIMENTAL_LIBRARY_SUPPORT "-fcoroutines-ts")
endif()

if(Coroutines_EXPERIMENTAL_LIBRARY_SUPPORT OR Coroutines_STANDARD_LIBRARY_SUPPORT)
set(Coroutines_LIBRARY_SUPPORT ON)
endif()

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")

if(NOT CppcoroCoroutines_FOUND OR TARGET cppcoro::coroutines)
return()
endif()

add_library(cppcoro::coroutines INTERFACE IMPORTED)
if(Coroutines_SUPPORTS_MS_FLAG)
target_compile_options(cppcoro::coroutines INTERFACE /await)
Copy link
Owner

Choose a reason for hiding this comment

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

Under msvc optimised x64 builds we also want to add the "/await:heapelide" flag to take advantage of the coroutine frame heap-elision optimisations.

elseif(Coroutines_SUPPORTS_GNU_FLAG)
target_compile_options(cppcoro::coroutines INTERFACE -fcoroutines-ts)
endif()
6 changes: 6 additions & 0 deletions cmake/cppcoroConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})

include(CMakeFindDependencyMacro)
find_dependency(CppcoroCoroutines QUIET REQUIRED)

include("${CMAKE_CURRENT_LIST_DIR}/cppcoroTargets.cmake")
168 changes: 168 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
set(includes
awaitable_traits.hpp
is_awaitable.hpp
async_auto_reset_event.hpp
async_manual_reset_event.hpp
async_generator.hpp
async_mutex.hpp
async_latch.hpp
async_scope.hpp
broken_promise.hpp
cancellation_registration.hpp
cancellation_source.hpp
cancellation_token.hpp
task.hpp
sequence_barrier.hpp
sequence_traits.hpp
single_producer_sequencer.hpp
multi_producer_sequencer.hpp
shared_task.hpp
shared_task.hpp
single_consumer_event.hpp
single_consumer_async_auto_reset_event.hpp
sync_wait.hpp
task.hpp
io_service.hpp
config.hpp
on_scope_exit.hpp
file_share_mode.hpp
file_open_mode.hpp
file_buffering_mode.hpp
file.hpp
fmap.hpp
when_all.hpp
when_all_ready.hpp
resume_on.hpp
schedule_on.hpp
generator.hpp
readable_file.hpp
recursive_generator.hpp
writable_file.hpp
read_only_file.hpp
write_only_file.hpp
read_write_file.hpp
file_read_operation.hpp
file_write_operation.hpp
static_thread_pool.hpp
)
list(TRANSFORM includes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/")

set(netIncludes
ip_address.hpp
ip_endpoint.hpp
ipv4_address.hpp
ipv4_endpoint.hpp
ipv6_address.hpp
ipv6_endpoint.hpp
socket.hpp
)
list(TRANSFORM netIncludes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/net/")

set(detailIncludes
void_value.hpp
when_all_ready_awaitable.hpp
when_all_counter.hpp
when_all_task.hpp
get_awaiter.hpp
is_awaiter.hpp
any.hpp
sync_wait_task.hpp
unwrap_reference.hpp
lightweight_manual_reset_event.hpp
)
list(TRANSFORM detailIncludes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/detail/")

set(privateHeaders
cancellation_state.hpp
socket_helpers.hpp
auto_reset_event.hpp
spin_wait.hpp
spin_mutex.hpp
)

set(sources
async_auto_reset_event.cpp
async_manual_reset_event.cpp
async_mutex.cpp
cancellation_state.cpp
cancellation_token.cpp
cancellation_source.cpp
cancellation_registration.cpp
lightweight_manual_reset_event.cpp
ip_address.cpp
ip_endpoint.cpp
ipv4_address.cpp
ipv4_endpoint.cpp
ipv6_address.cpp
ipv6_endpoint.cpp
static_thread_pool.cpp
auto_reset_event.cpp
spin_wait.cpp
spin_mutex.cpp
)

if(WIN32)
set(win32DetailIncludes
win32.hpp
win32_overlapped_operation.hpp
)
list(TRANSFORM win32DetailIncludes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/detail/")
list(APPEND detailIncludes ${win32DetailIncludes})

set(win32NetIncludes
socket.hpp
socket_accept_operation.hpp
socket_connect_operation.hpp
socket_disconnect_operation.hpp
socket_recv_operation.hpp
socket_recv_from_operation.hpp
socket_send_operation.hpp
socket_send_to_operation.hpp
)
list(TRANSFORM win32NetIncludes PREPEND "${PROJECT_SOURCE_DIR}/include/cppcoro/net/")
list(APPEND netIncludes ${win32NetIncludes})

set(win32Sources
win32.cpp
io_service.cpp
file.cpp
readable_file.cpp
writable_file.cpp
read_only_file.cpp
write_only_file.cpp
read_write_file.cpp
file_read_operation.cpp
file_write_operation.cpp
socket_helpers.cpp
socket.cpp
socket_accept_operation.cpp
socket_connect_operation.cpp
socket_disconnect_operation.cpp
socket_send_operation.cpp
socket_send_to_operation.cpp
socket_recv_operation.cpp
socket_recv_from_operation.cpp
)
list(APPEND sources ${win32Sources})
endif()

add_library(cppcoro
${includes}
${netIncludes}
${detailIncludes}
${privateHeaders}
${sources}
)

target_include_directories(cppcoro PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_compile_features(cppcoro PUBLIC cxx_std_20)

find_package(CppcoroCoroutines REQUIRED)
target_link_libraries(cppcoro PUBLIC cppcoro::coroutines)

install(TARGETS cppcoro EXPORT cppcoroTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
49 changes: 49 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
add_library(doctest::doctest INTERFACE IMPORTED)
target_include_directories(doctest::doctest INTERFACE doctest)

find_package(Threads REQUIRED)

add_executable(run
counted.hpp
io_service_fixture.hpp

main.cpp
counted.cpp
generator_tests.cpp
recursive_generator_tests.cpp
async_generator_tests.cpp
async_auto_reset_event_tests.cpp
async_manual_reset_event_tests.cpp
async_mutex_tests.cpp
async_latch_tests.cpp
cancellation_token_tests.cpp
task_tests.cpp
sequence_barrier_tests.cpp
shared_task_tests.cpp
sync_wait_tests.cpp
single_consumer_async_auto_reset_event_tests.cpp
single_producer_sequencer_tests.cpp
multi_producer_sequencer_tests.cpp
when_all_tests.cpp
when_all_ready_tests.cpp
ip_address_tests.cpp
ip_endpoint_tests.cpp
ipv4_address_tests.cpp
ipv4_endpoint_tests.cpp
ipv6_address_tests.cpp
ipv6_endpoint_tests.cpp
static_thread_pool_tests.cpp
)

if(WIN32)
target_sources(run PRIVATE
scheduling_operator_tests.cpp
io_service_tests.cpp
file_tests.cpp
socket_tests.cpp
)
endif()

target_link_libraries(run PRIVATE cppcoro Threads::Threads)

add_test(NAME test COMMAND run)