generic CMake on Linux
jwinarske opened this issue · 21 comments
I'm hitting multiple issues using generic CMake (no package managers) on Fedora 36 and Ubuntu 22. I can make it work with changes.
Are you open to CMake changes/PRs?
Sure, I am also happy to look into it myself if you want. I personally use Ubuntu 20.04 + vcpkg with GCC and Clang just fine.
I am particularly interested in having asio-grpc CMake install work properly on all systems (ASIO_GRPC_INSTALL) along with the CMake options (e.g. ASIO_GRPC_USE_BOOST_CONTAINER). When it comes to compiling the tests and examples then I do not expect things to work without vcpkg, but if they can be made to work without significant changes then I am happy to integrate them.
It's fairly straight forward to replicate. Either Ubutnu 22 or Fedora 36, with stock version of CMake.
I use CLion for projects, which behaves the same as CMake at command line.
In all my use cases vcpkg
or other would never be used, only generic CMake.
Ok, I was able to spot that asio-grpc gets mis-installed by some CMake generators which cause memory_resource.hpp
to be incorrect (does not affect any released version of asio-grpc though). I fixed that on master now. Aside from that the following Dockerfile:
FROM ubuntu:22.04
RUN apt-get update &&\
apt-get install --no-install-recommends -y -q \
libgrpc++-dev \
protobuf-compiler-grpc \
libprotobuf-dev \
libboost-all-dev \
git \
build-essential \
pkg-config \
ca-certificates \
cmake
RUN git clone https://github.com/Tradias/asio-grpc.git --depth 1 /asio-grpc
RUN cd /asio-grpc &&\
cmake -Bbuild . -DCMAKE_INSTALL_PREFIX=/out &&\
cmake --build build --target install
COPY ./src /src
WORKDIR /src
RUN cmake -Bbuild . -DCMAKE_PREFIX_PATH=/out -DCMAKE_POSITION_INDEPENDENT_CODE=on &&\
cmake --build build
ENTRYPOINT ["/src/build/test"]
and src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(test)
find_package(PkgConfig)
pkg_check_modules(protobuf REQUIRED IMPORTED_TARGET protobuf)
add_executable(protobuf::protoc IMPORTED)
find_program(PROTOC_EXECUTABLE protoc)
set_target_properties(protobuf::protoc PROPERTIES IMPORTED_LOCATION
"${PROTOC_EXECUTABLE}")
add_executable(gRPC::grpc_cpp_plugin IMPORTED)
find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
set_target_properties(
gRPC::grpc_cpp_plugin PROPERTIES IMPORTED_LOCATION
"${GRPC_CPP_PLUGIN_EXECUTABLE}")
pkg_check_modules(grpc++ REQUIRED IMPORTED_TARGET grpc++)
pkg_check_modules(grpc REQUIRED IMPORTED_TARGET grpc)
find_package(Boost REQUIRED)
set(ASIO_GRPC_DISABLE_AUTOLINK on)
find_package(asio-grpc CONFIG REQUIRED)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE asio-grpc::asio-grpc Boost::headers PkgConfig::protobuf
PkgConfig::grpc++ PkgConfig::grpc)
asio_grpc_protobuf_generate(
GENERATE_GRPC
TARGET
test
IMPORT_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}"
PROTOS
"${CMAKE_CURRENT_SOURCE_DIR}/helloworld/helloworld.proto")
target_compile_features(test PRIVATE cxx_std_20)
with src/main.cpp and src/helloworld/helloworld.proto works fine. Using pkg-config makes things a bit clumpsy and I highly recommend using a more recent version of gRPC, the one provided by Ubuntu is only 1.30.2 (from Jul 18, 2020).
I'll take a look at this.
I tend to prefer CMAKE_STAGING_PREFIX=$(pwd)/out/usr
over setting CMAKE_INSTALL_PREFIX
, as it correctly manages rpath, and in above case the install is technically a staged install.
Is 20 a hard requirement? It would be useful to see some analysis between using 17 vs 20. Picking up 20 just for the co-routine convenience is a hard sell for many.
I appreciate the assistance.
Thank you for looking into it.
I didn't know about CMAKE_STAGING_PREFIX
, seems interesting.
No, C++17 is fully supported. Looks like I have just have to be very careful with any example/tutorial code that I share anywhere 😁 to not give false impressions.
Documenting the recommended pattern to use your library with C++17 would be helpful. Maybe even a dedicated example with a subfolder named as such.
Another is clang-tidy compliance. CLion has this enabled by default.
Also a platform agnostic way to set some common flags I tend to always use:
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON)
I'm evaluating high perf gRPC/Flutter solutions for Automotive Grade Linux.
I'm also interested in using your library to replace the manual code in this library:
https://github.com/jwinarske/aasdk
Asio-grpc provides the glue-code between the async gRPC API (grpc::CompletionQueue) and a backend for expressing and composing asynchronous operations. Three such backends are available: Boost.Asio, standalone Asio and libunifex. It does not dictate how those backends are to be used and it is often best to see their respective documentations for more information.
Assuming that you are mostly interested in client-side code, you can find an example that uses Boost.Asio+Boost.Coroutine for a generic unary RPC here: https://github.com/Tradias/asio-grpc/blob/master/example/generic-client.cpp#L49-L53. In fact, you can take any C++20 coroutine example and replace co_spawn with spawn and use_awaitable with yield_context and it becomes C++17 compatible. For instance the helloworld client:
asio::spawn(
grpc_context,
[&](const asio::yield_context& yield)
{
// ...
status = RPC::request(grpc_context, stub, client_context, request, response, yield);
},
asio::detached);
For best possible performance you would probably be looking at using libunifex though, e.g. this server-streaming example. It can seem a bit overwhelming at first. I recommend taking a look at the standardization proposal and related talks from cppcon and other conferences to learn more. Note that libunifex requires C++20 when using MSVC but C++17 otherwise.
I am excited to see your interest coming from an Automotive Grade Linux background.
@Tradias Great info. I studied up on libunifex, and it looks like a good fit. I will have validated the CMake changes in the next couple of days. Many thanks!
@jwinarske have you made progress on your validation? Any additional issues or pain points that I can help with?
Libunifex doesn't seem to have any recent commit. @Tradias is asio-grpc with libunifex stable to use in production?
Libunifex is part of facebookexperimental:
This project is still evolving and should be considered experimental in nature. No guarantee is made for API or ABI stability.
However according to facebookexperimental/libunifex#214
Most of Facebook's mobile apps on the major platforms now use libunifex.
And additionally:
It will probably never guarantee ABI stability. As parts of libunifex get standardized, I expect we'll declare those parts API-stable. That's probably all we're likely to guarantee, though.
Unfortunately libunifex requires a kernel version (5.6 or later) and it will not be available until RHEL 9.2. Can you please make a release available that can compile examples (tests not needed - I was able to compile all the tests) with C++ 20 or 17?
@smahapatra1 I am not sure I understand.
The current master branch will simply not create CMake targets that need libunifex when it cannot be found.
Any previous releases can be configured with ASIO_GRPC_ENABLE_CPP20_TESTS_AND_EXAMPLES=off
to prevent the searching for- and creation of libunifex related targets.
I am surprised to hear that you managed to compile tests but not examples because both utilize libunifex in similar fashion.
@smahapatra1 I am not sure I understand.
The current master branch will simply not create CMake targets that need libunifex when it cannot be found. Any previous releases can be configured with
ASIO_GRPC_ENABLE_CPP20_TESTS_AND_EXAMPLES=off
to prevent the searching for- and creation of libunifex related targets.I am surprised to hear that you managed to compile tests but not examples because both utilize libunifex in similar fashion.
Sorry, I was not clear. I am using tradias-asio-grpc-2.4.0 with -DASIO_GRPC_INSTALL=ON -DASIO_GRPC_DISABLE_AUTOLINK=OFF -DASIO_GRPC_USE_BOOST_CONTAINER=ON -DASIO_GRPC_BUILD_TESTS=ON -DASIO_GRPC_ENABLE_CPP20_TESTS_AND_EXAMPLES=ON.
This fails with message:
-- Checking for module 'unifex'
-- Package 'unifex', required by 'virtual:world', not found
-- Configuring incomplete, errors occurred!
If I remove CPP20_TESTS_AND_EXAMPLES=ON but keep the rest (including ASIO_GRPC_BUILD_TESTS=ON), I can build it.
My goal is to turn off testing (after first successful test) and build the library and examples (but without unifex) so that I can learn from the examples. I can't use libunifex.
ok, that should work in the next release where libunifex is treated as an optional dependency during example/test build + you can enable examples only with ASIO_GRPC_BUILD_EXAMPLES=on
.
Also note that ASIO_GRPC_DISABLE_AUTOLINK
has no effect when configuring asio-grpc. It is meant to be used before find_package(asio-grpc)
/add_subdirectory(asio-grpc)
.
@smahapatra1 asio-grpc v2.5.0 has been released with:
Add a new CMake option called ASIO_GRPC_BUILD_EXAMPLES which enables compilation of just examples without tests. Also, libunifex is now treated as an optional dependency.
See release notes: https://github.com/Tradias/asio-grpc/releases/tag/v2.5.0 but use v2.5.1 in production.
@Tradias Looking at this again. For the foreseeable future I'm only interested in libunifex support. Is there a feasible combo for your libunifex examples and C++ 17?
Hi, thanks for checking back in. I am excited to hear that you are interested in libunifex. There are currently two examples:
I hope your affords with libunifex are going well. Since the initial question in this issue has been resolved, I will close it. Please do not hesitate to create a new one if you have any more questions.