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

Add initial support for GRPC++ #568

Merged
merged 21 commits into from
Jun 20, 2024
Merged
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
3 changes: 2 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ But RPP is header-only library, so, without enabling any extra options is just c
- `RPP_BUILD_TESTS` - (ON/OFF) build unit tests (default OFF)
- `RPP_BUILD_EXAMPLES` - (ON/OFF) build examples of usage of RPP (default OFF)
- `RPP_BUILD_SFML_CODE` - (ON/OFF) build RPP code related to SFML or not (default OFF) - requires SFML to be installed
- `RPP_BUILD_QT_CODE` - (ON/OFF) build RPPQT related code (examples/tests)(rppqt module doesn't requires this one) (default OFF) - requires QT5/6 to be installed
- `RPP_BUILD_QT_CODE` - (ON/OFF) build QT related code (examples/tests)(rppqt module doesn't requires this one) (default OFF) - requires QT5/6 to be installed
- `RPP_BUILD_GRPC_CODE` - (ON/OFF) build GRPC related code (examples/tests)(rppgrpc module doesn't requires this one) (default OFF) - requires grpc++/protobuf to be installed

By default, it provides rpp and rppqt INTERFACE modules.

Expand Down
30 changes: 19 additions & 11 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@
"RPP_BUILD_QT_CODE" : "ON"
}
},
{
"name" : "build-grpc",
"hidden": true,
"cacheVariables": {
"RPP_BUILD_GRPC_CODE" : "ON"
}
},
{
"name" : "use-conan",
"hidden": true,
Expand All @@ -149,6 +156,7 @@
},
{
"name": "build-dir",
"hidden": true,
"binaryDir": "${sourceDir}/build"
},

Expand All @@ -160,7 +168,7 @@
},
{
"name": "ci-coverage-gcc",
"inherits": ["ci-build", "build-tests", "build-qt", "ci-unix", "ci-gcc"],
"inherits": ["ci-build", "build-tests", "build-qt", "build-grpc", "ci-unix", "ci-gcc"],
"cacheVariables": {
"RPP_ENABLE_COVERAGE": "ON",
"CMAKE_CXX_FLAGS": "-O0 -g --coverage -fkeep-inline-functions -fkeep-static-functions -fprofile-arcs -ftest-coverage -fno-inline -fno-omit-frame-pointer -fno-optimize-sibling-calls",
Expand All @@ -171,7 +179,7 @@
},
{
"name": "ci-coverage-clang",
"inherits": ["ci-build", "build-tests", "build-qt", "ci-unix", "ci-clang"],
"inherits": ["ci-build", "build-tests", "build-qt", "build-grpc", "ci-unix", "ci-clang"],
"cacheVariables": {
"RPP_ENABLE_COVERAGE": "ON",
"CMAKE_CXX_FLAGS": "-fprofile-instr-generate -fcoverage-mapping",
Expand All @@ -189,51 +197,51 @@
},
{
"name": "ci-sanitize-asan",
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "ci-unix", "ci-clang"],
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "build-grpc", "ci-unix", "ci-clang"],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1"
}
},
{
"name": "ci-sanitize-lsan",
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "ci-unix", "ci-clang"],
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "build-grpc", "ci-unix", "ci-clang"],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=leak -fno-omit-frame-pointer -g -O1"
}
},
{
"name": "ci-sanitize-msan",
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "ci-unix", "ci-clang"],
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "build-grpc", "ci-unix", "ci-clang"],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=memory -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -g -O2"
}
},
{
"name": "ci-sanitize-ubsan",
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "ci-unix", "ci-clang"],
"inherits": ["ci-build", "build-tests", "build-benchmarks", "build-qt", "build-grpc", "ci-unix", "ci-clang"],
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=undefined"
}
},
{
"name": "ci-macos-tests",
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-sfml", "ci-unix"]
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-grpc", "build-sfml", "ci-unix"]
},
{
"name": "ci-ubuntu-clang-tests",
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-sfml", "ci-unix", "ci-clang", "cppcheck", "clang-tidy"]
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-grpc", "build-sfml", "ci-unix", "ci-clang", "cppcheck", "clang-tidy"]
},
{
"name": "ci-ubuntu-gcc-tests",
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-sfml", "ci-unix", "ci-gcc", "cppcheck", "clang-tidy"]
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-grpc", "build-sfml", "ci-unix", "ci-gcc", "cppcheck", "clang-tidy"]
},
{
"name": "ci-windows-tests",
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-sfml", "ci-win64"]
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-grpc", "build-sfml", "ci-win64"]
},
{
"name": "ci-ubuntu-clang-tests-no-checks",
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-sfml", "ci-unix", "ci-clang" ]
"inherits": ["ci-build", "build-tests", "build-examples", "build-qt", "build-grpc", "build-sfml", "ci-unix", "ci-clang" ]
},


Expand Down
4 changes: 3 additions & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,7 @@ INPUT = src/rpp \
src/extensions \
src/examples/rpp/doxygen \
src/examples/rppqt/doxygen \
src/examples/rppgrpc/doxygen \
docs

# This tag can be used to specify the character encoding of the source files
Expand Down Expand Up @@ -1078,7 +1079,8 @@ EXCLUDE_SYMBOLS =
# command).

EXAMPLE_PATH = src/examples/rpp/doxygen \
src/examples/rppqt/doxygen
src/examples/rppqt/doxygen \
src/examples/rppgrpc/doxygen

# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
Expand Down
82 changes: 60 additions & 22 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ macro(rpp_handle_3rdparty TARGET_NAME)
set_target_properties(${TARGET_NAME} PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:${TARGET_NAME},INTERFACE_INCLUDE_DIRECTORIES>)
endmacro()

macro(rpp_fetch_library_extended NAME URL TAG TARGET_NAME)
Include(FetchContent)
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build SHARED libraries")

Set(FETCHCONTENT_QUIET FALSE)

FetchContent_Declare(
${NAME}
GIT_REPOSITORY ${URL}
GIT_TAG ${TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
GIT_SUBMODULES ""
)

FetchContent_MakeAvailable(${NAME})
rpp_handle_3rdparty(${TARGET_NAME})
endmacro()

macro(rpp_fetch_library NAME URL TAG)
find_package(${NAME} QUIET)
if (NOT ${NAME}_FOUND)
message("-- RPP: Fetching ${NAME}...")
rpp_fetch_library_extended(${NAME} ${URL} ${TAG} ${NAME})
endif()
endmacro()

# ===================== SFML =======================
if (RPP_BUILD_SFML_CODE AND RPP_BUILD_EXAMPLES)
find_package(SFML COMPONENTS graphics system window REQUIRED)
Expand Down Expand Up @@ -42,32 +69,43 @@ if (RPP_BUILD_QT_CODE AND (RPP_BUILD_TESTS OR RPP_BUILD_EXAMPLES))
endmacro()
endif()

macro(rpp_fetch_library_extended NAME URL TAG TARGET_NAME)
Include(FetchContent)
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build SHARED libraries")
# ========================== GRPC ====================================
if (RPP_BUILD_GRPC_CODE AND (RPP_BUILD_TESTS OR RPP_BUILD_EXAMPLES))
find_package(Protobuf CONFIG REQUIRED)
find_package(gRPC CONFIG REQUIRED)

Set(FETCHCONTENT_QUIET FALSE)
rpp_handle_3rdparty(gRPC::grpc++)
rpp_handle_3rdparty(protobuf::protobuf)

FetchContent_Declare(
${NAME}
GIT_REPOSITORY ${URL}
GIT_TAG ${TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
GIT_SUBMODULES ""
)
macro(rpp_add_proto_target TARGET FILES)
add_library(${TARGET} STATIC ${FILES})

FetchContent_MakeAvailable(${NAME})
rpp_handle_3rdparty(${TARGET_NAME})
endmacro()
target_link_libraries(${TARGET}
PUBLIC
gRPC::grpc++
protobuf::libprotobuf
${grpc_LIBRARIES_TARGETS}
)

macro(rpp_fetch_library NAME URL TAG)
find_package(${NAME} QUIET)
if (NOT ${NAME}_FOUND)
message("-- RPP: Fetching ${NAME} from ${URL} by ${TAG}...")
rpp_fetch_library_extended(${NAME} ${URL} ${TAG} ${NAME})
endif()
endmacro()
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION )
protobuf_generate(TARGET ${TARGET} OUT_VAR PROTO_FILES LANGUAGE cpp )

protobuf_generate(
TARGET ${TARGET}
LANGUAGE grpc
OUT_VAR GRPC_PROTO_FILES
# PROTOC_OUT_DIR "${PROTO_BINARY_DIR}"
PLUGIN protoc-gen-grpc=${grpc_cpp_plugin_location}
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc)


set_target_properties(${TARGET} PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:${TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
set_target_properties(${TARGET} PROPERTIES CXX_CLANG_TIDY "")
set_target_properties(${TARGET} PROPERTIES CXX_CPPCHECK "")
endmacro()
endif()

# ==================== RXCPP =======================
if (RPP_BUILD_RXCPP AND RPP_BUILD_BENCHMARKS)
Expand Down
6 changes: 6 additions & 0 deletions cmake/install-rules.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ install(
DIRECTORY
src/rpp
src/extensions/rppqt
src/extensions/rppgrpc
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT
Expand All @@ -25,6 +26,11 @@ install(
EXPORT RPPTargets
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rppqt"
)
install(
TARGETS rppgrpc
EXPORT RPPTargets
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/rppgrpc"
)

write_basic_package_version_file(
"${package}ConfigVersion.cmake"
Expand Down
4 changes: 4 additions & 0 deletions cmake/variables.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ endfunction()
# ------------ Options to tweak ---------------------
option(RPP_BUILD_SFML_CODE "Enable SFML support in examples/code." OFF)
option(RPP_BUILD_QT_CODE "Enable QT support in examples/code." OFF)
option(RPP_BUILD_GRPC_CODE "Enable grpc++ support in examples/code." OFF)

if (RPP_DEVELOPER_MODE)
option(RPP_BUILD_TESTS "Build unit tests tree." OFF)
Expand All @@ -100,6 +101,9 @@ if (RPP_DEVELOPER_MODE)
if (RPP_BUILD_BENCHMARKS)
set(CONAN_ARGS "${CONAN_ARGS};-o rpp/*:with_benchmarks=True")
endif()
if (RPP_BUILD_GRPC_CODE)
set(CONAN_ARGS "${CONAN_ARGS};-o rpp/*:with_grpc=True")
endif()
endif()

if(RPP_ENABLE_COVERAGE)
Expand Down
8 changes: 4 additions & 4 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def requirements(self):
if self.options.with_sfml:
self.requires("sfml/2.6.1", options={"audio": False})

# if self.options.with_grpc:
# self.requires("grpc/1.54.3", transitive_libs=True, transitive_headers=True)
# self.requires("protobuf/3.21.12")
# self.requires("libmount/2.39", override=True)
if self.options.with_grpc:
self.requires("grpc/1.54.3", transitive_libs=True, transitive_headers=True)
self.requires("protobuf/3.21.12")
self.requires("libmount/2.39", override=True)

if self.options.with_cmake:
self.tool_requires("cmake/3.29.3")
4 changes: 4 additions & 0 deletions src/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ add_subdirectory(rpp)
if(RPP_BUILD_QT_CODE)
add_subdirectory(rppqt)
endif()

if (RPP_BUILD_GRPC_CODE)
add_subdirectory(rppgrpc)
endif()
2 changes: 2 additions & 0 deletions src/examples/rppgrpc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# add_subdirectory(communication)
add_subdirectory(doxygen)
9 changes: 9 additions & 0 deletions src/examples/rppgrpc/communication/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
set(TARGET rppgrpc_communication)

rpp_add_proto_target(${TARGET}_proto protocol.proto)

add_executable(${TARGET}_server server.cpp)
target_link_libraries(${TARGET}_server PRIVATE ${TARGET}_proto rppgrpc)

add_executable(${TARGET}_client client.cpp)
target_link_libraries(${TARGET}_client PRIVATE ${TARGET}_proto rppgrpc)
78 changes: 78 additions & 0 deletions src/examples/rppgrpc/communication/client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <rpp/rpp.hpp>

#include <grpc++/create_channel.h>
#include <rppgrpc/rppgrpc.hpp>

#include "protocol.grpc.pb.h"
#include "protocol.pb.h"


int main()
{
auto channel = grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials());
if (!channel)
{
std::cout << "NO CHANNEL" << std::endl;
return 0;
}
auto stub = TestService::NewStub(channel);
if (!stub)
{
std::cout << "NO STUB" << std::endl;
return 0;
}

std::array<grpc::ClientContext, 3> ctx{};
auto d = rpp::composite_disposable_wrapper::make();

rpp::subjects::publish_subject<std::string> bidi_requests{};
rpp::subjects::publish_subject<Response> bidi_responses{};
bidi_responses.get_observable().subscribe(d, [](const Response& v) {
std::cout << "[BidireactionalResponse]: " << v.ShortDebugString() << std::endl;
});

rppgrpc::add_client_reactor(&TestService::StubInterface::async_interface::Bidirectional,
*stub->async(),
&ctx[0],
bidi_requests.get_observable()
| rpp::ops::take_while([](const std::string& v) { return v != "0"; })
| rpp::ops::map([](const std::string& v) {
Request i{};
i.set_value(std::string{"BidiRequest "} + v);
return i;
}),
bidi_responses.get_observer());

rppgrpc::add_client_reactor(&TestService::StubInterface::async_interface::ClientSide,
*stub->async(),
&ctx[1],
bidi_responses.get_observable()
| rpp::ops::map([](const Response& response) {
Request request{};
request.set_value(std::string{"ClientSideRequest "} + response.value());
return request;
}),
rpp::make_lambda_observer(d, [](const Response& v) {
std::cout << "[ClientsideResponse]: " << v.ShortDebugString() << std::endl;
}));
Request req{};
rppgrpc::add_client_reactor(&TestService::StubInterface::async_interface::ServerSide,
*stub->async(),
&ctx[2],
&req,
rpp::make_lambda_observer(d, [](const Response& v) {
std::cout << "[ServerSideResponse]: " << v.ShortDebugString() << std::endl;
}));

std::cout << "SUBSCRIBED" << std::endl;

std::string in{};
while (!d.is_disposed())
{
std::getline(std::cin, in);
bidi_requests.get_observer().on_next(in);
in.clear();
}

return 0;
}
15 changes: 15 additions & 0 deletions src/examples/rppgrpc/communication/protocol.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";

message Request {
string Value = 1;
}

message Response {
string Value = 1;
}

service TestService {
rpc ServerSide(Request) returns (stream Response) {}
rpc ClientSide(stream Request) returns (Response) {}
rpc Bidirectional(stream Request) returns (stream Response) {}
}
Loading
Loading