diff --git a/CMakeLists.txt b/CMakeLists.txt index bd2a5a8..a525854 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ set(ASYNCIO_VERSION 1.0.6) option(BUILD_SAMPLES "Build asyncio samples" ON) option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) +option(BUILD_MODULES "Build asyncio modules" OFF) if (BUILD_SHARED_LIBS AND MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) @@ -24,32 +25,32 @@ find_package(libuv CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) add_library( - asyncio - src/uv.cpp - src/io.cpp - src/fs.cpp - src/time.cpp - src/poll.cpp - src/pipe.cpp - src/thread.cpp - src/signal.cpp - src/stream.cpp - src/buffer.cpp - src/channel.cpp - src/process.cpp - src/task.cpp - src/event_loop.cpp - src/net/net.cpp - src/net/dns.cpp - src/net/tls.cpp - src/net/dgram.cpp - src/net/stream.cpp - src/http/url.cpp - src/http/request.cpp - src/http/websocket.cpp - src/sync/mutex.cpp - src/sync/event.cpp - src/sync/condition.cpp + asyncio + src/uv.cpp + src/io.cpp + src/fs.cpp + src/time.cpp + src/poll.cpp + src/pipe.cpp + src/thread.cpp + src/signal.cpp + src/stream.cpp + src/buffer.cpp + src/channel.cpp + src/process.cpp + src/task.cpp + src/event_loop.cpp + src/net/net.cpp + src/net/dns.cpp + src/net/tls.cpp + src/net/dgram.cpp + src/net/stream.cpp + src/http/url.cpp + src/http/request.cpp + src/http/websocket.cpp + src/sync/mutex.cpp + src/sync/event.cpp + src/sync/condition.cpp ) if (WIN32) @@ -57,73 +58,73 @@ if (WIN32) endif () target_include_directories( - asyncio - PUBLIC - $ - $ + asyncio + PUBLIC + $ + $ ) target_link_libraries( - asyncio - PRIVATE - $<$:Crypt32> - PUBLIC - zero::zero - ZLIB::ZLIB - OpenSSL::SSL - OpenSSL::Crypto - CURL::libcurl - nlohmann_json::nlohmann_json - $,libuv::uv_a,libuv::uv> + asyncio + PRIVATE + $<$:Crypt32> + PUBLIC + zero::zero + ZLIB::ZLIB + OpenSSL::SSL + OpenSSL::Crypto + CURL::libcurl + nlohmann_json::nlohmann_json + $,libuv::uv_a,libuv::uv> ) add_library(asyncio-main STATIC src/main.cpp) target_link_libraries(asyncio-main PUBLIC asyncio) install( - DIRECTORY - include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ${EXCLUDE_HEADERS} + DIRECTORY + include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ${EXCLUDE_HEADERS} ) install( - TARGETS asyncio - EXPORT ${PROJECT_NAME}Targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + TARGETS asyncio + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install( - TARGETS asyncio-main - EXPORT ${PROJECT_NAME}Targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + TARGETS asyncio-main + EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( - EXPORT ${PROJECT_NAME}Targets - NAMESPACE ${PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) configure_package_config_file( - cmake/${PROJECT_NAME}-config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + cmake/${PROJECT_NAME}-config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - VERSION ${ASYNCIO_VERSION} - COMPATIBILITY SameMajorVersion + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION ${ASYNCIO_VERSION} + COMPATIBILITY SameMajorVersion ) install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ) if (BUILD_SAMPLES) @@ -133,3 +134,7 @@ endif () if (BUILD_TESTING) add_subdirectory(test) endif () + +if (BUILD_MODULES) + add_subdirectory(modules) +endif () diff --git a/README.md b/README.md index d4f5f29..9f4ab9d 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ Based on the `libuv` event loop, use C++20 stackless `coroutines` to implement n - Lessons learned from `JavaScript`'s `Promise.all`, `Promise.any`, `Promise.race`, etc., subtask management methods. - Lessons learned from `Golang`'s `WaitGroup` dynamic task management groups. - Built-in call stack tracing allows for better debugging and analysis. +- Support for C++20 modules.

(back to top)

diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt new file mode 100644 index 0000000..bce9e19 --- /dev/null +++ b/modules/CMakeLists.txt @@ -0,0 +1,29 @@ + +add_library(asyncio_module) + +target_sources(asyncio_module + PUBLIC + FILE_SET CXX_MODULES FILES + asyncio.cppm + asyncio.http.cppm + asyncio.net.cppm + asyncio.sync.cppm +) + +target_compile_features(asyncio_module PUBLIC cxx_std_20) + +target_include_directories(asyncio_module PUBLIC + $ + $ +) + +add_library(asyncio::module ALIAS asyncio_module) + +# Installation +install(TARGETS asyncio_module + EXPORT ${PROJECT_NAME}Targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/asyncio/modules +) \ No newline at end of file diff --git a/modules/asyncio.cppm b/modules/asyncio.cppm new file mode 100644 index 0000000..03bdf4b --- /dev/null +++ b/modules/asyncio.cppm @@ -0,0 +1,197 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +export module asyncio; + +export import :http; +export import :net; +export import :sync; + +export namespace asyncio { + namespace binary { + using asyncio::binary::readLE; + using asyncio::binary::readBE; + using asyncio::binary::writeLE; + using asyncio::binary::writeBE; + } + + using asyncio::BufReader; + using asyncio::BufWriter; + using asyncio::BufReaderError; + + using asyncio::ChannelCore; + using asyncio::Sender; + using asyncio::Receiver; + using asyncio::Channel; + using asyncio::channel; + using asyncio::TrySendError; + using asyncio::SendSyncError; + using asyncio::SendError; + using asyncio::TryReceiveError; + using asyncio::ReceiveSyncError; + using asyncio::ReceiveError; + using asyncio::ChannelError; + + using asyncio::EventLoop; + using asyncio::run; + using asyncio::reschedule; + + using asyncio::File; + using asyncio::open; + using asyncio::read; + using asyncio::readString; + using asyncio::write; + using asyncio::absolute; + using asyncio::canonical; + using asyncio::weaklyCanonical; + using asyncio::relative; + using asyncio::proximate; + using asyncio::copy; + using asyncio::copyFile; + using asyncio::copySymlink; + using asyncio::createDirectory; + using asyncio::createDirectories; + using asyncio::createHardLink; + using asyncio::createSymlink; + using asyncio::createDirectorySymlink; + using asyncio::currentPath; + using asyncio::exists; + using asyncio::equivalent; + using asyncio::fileSize; + using asyncio::hardLinkCount; + using asyncio::lastWriteTime; + using asyncio::permissions; + using asyncio::readSymlink; + using asyncio::remove; + using asyncio::removeAll; + using asyncio::rename; + using asyncio::resizeFile; + using asyncio::space; + using asyncio::status; + using asyncio::symlinkStatus; + using asyncio::temporaryDirectory; + using asyncio::isBlockFile; + using asyncio::isCharacterFile; + using asyncio::isDirectory; + using asyncio::isEmpty; + using asyncio::isFIFO; + using asyncio::isOther; + using asyncio::isRegularFile; + using asyncio::isSocket; + using asyncio::isSymlink; + using asyncio::DirectoryEntry; + using asyncio::Asynchronous; + using asyncio::readDirectory; + using asyncio::walkDirectory; + + using asyncio::FileDescriptor; + using asyncio::IFileDescriptor; + using asyncio::ICloseable; + using asyncio::IHalfCloseable; + using asyncio::IReader; + using asyncio::IWriter; + using asyncio::ISeekable; + using asyncio::IBufReader; + using asyncio::IBufWriter; + using asyncio::copy; + using asyncio::StringReader; + using asyncio::StringWriter; + using asyncio::BytesReader; + using asyncio::BytesWriter; + using asyncio::IOError; + + using asyncio::Pipe; + using asyncio::PipeListener; + + using asyncio::Poll; + + using asyncio::Process; + using asyncio::ExitStatus; + using asyncio::Output; + using asyncio::ChildProcess; + using asyncio::Command; + using asyncio::PseudoConsole; + + using asyncio::Promise; + + using asyncio::Signal; + + using asyncio::Stream; + using asyncio::Listener; + + namespace task { + using asyncio::task::Awaitable; + using asyncio::task::NoExceptAwaitable; + using asyncio::task::TaskGroup; + using asyncio::task::Frame; + using asyncio::task::CancellableFuture; + using asyncio::task::CancellableTask; + using asyncio::task::Cancelled; + using asyncio::task::Lock; + using asyncio::task::Unlock; + using asyncio::task::cancelled; + using asyncio::task::lock; + using asyncio::task::unlock; + using asyncio::task::callback_result_t; + using asyncio::task::Task; + using asyncio::task::Promise; + using asyncio::task::all_ranges_future_t; + using asyncio::task::all_ranges_value_t; + using asyncio::task::all_ranges_error_t; + using asyncio::task::all; + using asyncio::task::all_varaidic_future_t; + using asyncio::task::all_variadic_value_t; + using asyncio::task::all_variadic_error_t; + using asyncio::task::all_settled_ranges_future_t; + using asyncio::task::all_settled_ranges_value_t; + using asyncio::task::allSettled; + using asyncio::task::all_settled_variadic_future_t; + using asyncio::task::all_settled_variadic_value_t; + using asyncio::task::any_ranges_future_t; + using asyncio::task::any_ranges_value_t; + using asyncio::task::any_ranges_error_t; + using asyncio::task::any; + using asyncio::task::any_variadic_future_t; + using asyncio::task::any_variadic_value_t; + using asyncio::task::any_variadic_error_t; + using asyncio::task::race_ranges_future_t; + using asyncio::task::race_ranges_value_t; + using asyncio::task::race_ranges_error_t; + using asyncio::task::race; + using asyncio::task::race_variadic_future_t; + using asyncio::task::race_variadic_value_t; + using asyncio::task::race_variadic_error_t; + using asyncio::task::from; + using asyncio::task::spawn; + using asyncio::task::Error; + } + + using asyncio::toThread; + using asyncio::toThreadPool; + using asyncio::ToThreadPoolError; + + using asyncio::timeout; + using asyncio::TimeoutError; + + namespace uv { + using asyncio::uv::expected; + using asyncio::uv::Handle; + using asyncio::uv::Error; + } +} diff --git a/modules/asyncio.http.cppm b/modules/asyncio.http.cppm new file mode 100644 index 0000000..07c4d44 --- /dev/null +++ b/modules/asyncio.http.cppm @@ -0,0 +1,47 @@ +module; + +#include +#include +#include + +export module asyncio:http; + +export namespace asyncio::http { + using asyncio::http::Connection; + using asyncio::http::Requests; + using asyncio::http::Response; + using asyncio::http::TLSConfig; + using asyncio::http::Options; + using asyncio::http::CURLError; + using asyncio::http::CURLMError; + + using asyncio::http::urlEscape; + using asyncio::http::urlUnescape; + using asyncio::http::URL; + using asyncio::http::operator<=>; + using asyncio::http::operator==; + + namespace ws { + using asyncio::http::ws::CloseCode; + using asyncio::http::ws::CloseCodeCategory; + using asyncio::http::ws::make_error_code; + using asyncio::http::ws::Opcode; + using asyncio::http::ws::InternalMessage; + using asyncio::http::ws::Message; + using asyncio::http::ws::Header; + using asyncio::http::ws::Frame; + using asyncio::http::ws::Compressor; + using asyncio::http::ws::Decompressor; + using asyncio::http::ws::DeflateConfig; + using asyncio::http::ws::DeflateExtension; + using asyncio::http::ws::WebSocket; + } +} + +export namespace zero { + using zero::scan; +} + +export namespace fmt { + using fmt::formatter; +} diff --git a/modules/asyncio.net.cppm b/modules/asyncio.net.cppm new file mode 100644 index 0000000..67ec927 --- /dev/null +++ b/modules/asyncio.net.cppm @@ -0,0 +1,74 @@ +module; + +#include +#include +#include +#include +#include + +export module asyncio:net; + +export namespace asyncio::net { + using asyncio::net::UDPSocket; + + using asyncio::net::getAddressInfo; + using asyncio::net::lookupIP; + + using asyncio::net::IPv4; + using asyncio::net::IPv6; + using asyncio::net::IP; + using asyncio::net::LOCALHOST_IPV4; + using asyncio::net::BROADCAST_IPV4; + using asyncio::net::UNSPECIFIED_IPV4; + using asyncio::net::LOCALHOST_IPV6; + using asyncio::net::UNSPECIFIED_IPV6; + using asyncio::net::IPv4Address; + using asyncio::net::IPv6Address; + using asyncio::net::UnixAddress; + using asyncio::net::IPAddress; + using asyncio::net::Address; + using asyncio::net::SocketAddress; + using asyncio::net::operator==; + using asyncio::net::ipAddressFrom; + using asyncio::net::addressFrom; + using asyncio::net::socketAddressFrom; + using asyncio::net::IEndpoint; + using asyncio::net::ISocket; + using asyncio::net::copyBidirectional; + using asyncio::net::ParseAddressError; + + using asyncio::net::TCPStream; + using asyncio::net::TCPListener; + #ifdef _WIN32 + using asyncio::net::NamedPipeStream; + using asyncio::net::NamedPipeListener; + #else + using asyncio::net::UnixStream; + using asyncio::net::UnixListener; + #endif + + namespace tls { + using asyncio::net::tls::openSSLError; + #ifdef __linux__ + using asyncio::net::tls::systemCABundle; + #endif + using asyncio::net::tls::expected; + using asyncio::net::tls::Version; + using asyncio::net::tls::Certificate; + using asyncio::net::tls::PrivateKey; + using asyncio::net::tls::CertKeyPair; + using asyncio::net::tls::Context; + using asyncio::net::tls::ClientConfig; + using asyncio::net::tls::ServerConfig; + using asyncio::net::tls::Config; + using asyncio::net::tls::TLS; + using asyncio::net::tls::connect; + using asyncio::net::tls::accept; + using asyncio::net::tls::OpenSSLError; + using asyncio::net::tls::TLSError; + } +} + +export namespace fmt { + using fmt::formatter; +} diff --git a/modules/asyncio.sync.cppm b/modules/asyncio.sync.cppm new file mode 100644 index 0000000..710bfbb --- /dev/null +++ b/modules/asyncio.sync.cppm @@ -0,0 +1,15 @@ +module; + +#include +#include +#include + +export module asyncio:sync; + +export namespace asyncio::sync { + using asyncio::sync::Condition; + + using asyncio::sync::Event; + + using asyncio::sync::Mutex; +}