Build Qt with gRPC using cmake in Linux
-
Hi, may I know how to build Qt with gRPC using cmake?
FYI, I had executed gRPC C++ (https://grpc.io/docs/languages/cpp/quickstart/) examples successfully. When I combine it into Qt application (Qt Quick Application), undefined reference to gRPC error occurs. So may I know the correct way to build Qt with gRPC? I found a qtprotobuf repo in https://github.com/semlanik/qtprotobuf but may I know is there any alternative way to do it without using this repo? Thank you.
-
@JJLim said in Build Qt with gRPC using cmake in Linux:
So may I know the correct way to build Qt with gRPC?
Don't you mean build your Qt app with gRPC and not Qt itself?
Please show what you did and what exact errors you got. -
@jsulm Hi, thank you for your reply. FYI, I hope that I can build a Qt app itself without using the SDK in qt but seems like the progress is not so good. I created a QtQuick Qml application. Then, I combine the cmakelist of grpc in helloworld example with qt. The overall cmake file is as follow.
cmake_minimum_required(VERSION 3.14) project(try5 VERSION 0.1 LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) ###################################################Combine here############################################### include(./common.cmake) # Proto file get_filename_component(hw_proto "./helloworld.proto" ABSOLUTE) get_filename_component(hw_proto_path "${hw_proto}" PATH) # Generated sources set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc") set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h") set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc") set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h") add_custom_command( OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" COMMAND ${_PROTOBUF_PROTOC} ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}" --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" "${hw_proto}" DEPENDS "${hw_proto}") # Include generated *.pb.h files include_directories("${CMAKE_CURRENT_BINARY_DIR}") # hw_grpc_proto add_library(hw_grpc_proto ${hw_grpc_srcs} ${hw_grpc_hdrs} ${hw_proto_srcs} ${hw_proto_hdrs}) target_link_libraries(hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF}) # Targets greeter_[async_](client|server) foreach(_target greeter_client greeter_server greeter_callback_client greeter_callback_server greeter_async_client greeter_async_client2 greeter_async_server) add_executable(${_target} "${_target}.cc") target_link_libraries(${_target} hw_grpc_proto ${_REFLECTION} ${_GRPC_GRPCPP} ${_PROTOBUF_LIBPROTOBUF}) endforeach() ################################################################################################################ find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED) set(PROJECT_SOURCES main.cpp qml.qrc ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(try5 MANUAL_FINALIZATION ${PROJECT_SOURCES} ) else() if(ANDROID) add_library(try5 SHARED ${PROJECT_SOURCES} ) else() add_executable(try5 ${PROJECT_SOURCES} ) endif() endif() target_compile_definitions(try5 PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>) target_link_libraries(try5 PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick) set_target_properties(try5 PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} ) if(QT_VERSION_MAJOR EQUAL 6) qt_import_qml_plugins(try5) qt_finalize_executable(try5) endif()
However, I cannot import gRPC library in main.cpp
This is the first method I had tried. I not sure how to "bind" gRPC into qt, even though I manually copy the required folder into the same level dir, it can detect the gRPC folder, but the result is undefined error as shown below.
jj@jj-HP-Pavilion-g4-Notebook-PC:~/Desktop/qt/hello$ cmake . -- The C compiler identification is GNU 9.3.0 -- The CXX compiler identification is GNU 9.3.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Looking for pthread.h -- Looking for pthread.h - found -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed -- Looking for pthread_create in pthreads -- Looking for pthread_create in pthreads - not found -- Looking for pthread_create in pthread -- Looking for pthread_create in pthread - found -- Found Threads: TRUE CMake Warning (dev) at /usr/lib/cmake/protobuf/protobuf-options.cmake:6 (option): Policy CMP0077 is not set: option() honors normal variables. Run "cmake --help-policy CMP0077" for policy details. Use the cmake_policy command to set the policy and suppress this warning. For compatibility with older versions of CMake, option is clearing the normal variable 'protobuf_MODULE_COMPATIBLE'. Call Stack (most recent call first): /usr/lib/cmake/protobuf/protobuf-config.cmake:2 (include) common.cmake:101 (find_package) CMakeLists.txt:14 (include) This warning is for project developers. Use -Wno-dev to suppress it. -- Using protobuf 3.15.8.0 -- Using gRPC 1.38.0 -- Configuring done CMake Warning (dev) in CMakeLists.txt: Policy CMP0071 is not set: Let AUTOMOC and AUTOUIC process GENERATED files. Run "cmake --help-policy CMP0071" for policy details. Use the cmake_policy command to set the policy and suppress this warning. For compatibility, CMake is excluding the GENERATED source file(s): "/home/jj/Desktop/qt/hello/helloworld.grpc.pb.cc" "/home/jj/Desktop/qt/hello/helloworld.grpc.pb.h" "/home/jj/Desktop/qt/hello/helloworld.pb.cc" "/home/jj/Desktop/qt/hello/helloworld.pb.h" from processing by AUTOMOC and AUTOUIC. If any of the files should be processed, set CMP0071 to NEW. If any of the files should not be processed, explicitly exclude them by setting the source file property SKIP_AUTOGEN: set_property(SOURCE file.h PROPERTY SKIP_AUTOGEN ON) This warning is for project developers. Use -Wno-dev to suppress it. -- Generating done -- Build files have been written to: /home/jj/Desktop/qt/hello jj@jj-HP-Pavilion-g4-Notebook-PC:~/Desktop/qt/hello$ make -j4 Scanning dependencies of target hw_grpc_proto_autogen Scanning dependencies of target hello_autogen [ 3%] Automatic MOC and UIC for target hello [ 6%] Automatic MOC and UIC for target hw_grpc_proto [ 6%] Built target hello_autogen [ 6%] Built target hw_grpc_proto_autogen [ 9%] Automatic RCC for qml.qrc Scanning dependencies of target hw_grpc_proto Scanning dependencies of target hello [ 12%] Building CXX object CMakeFiles/hw_grpc_proto.dir/hw_grpc_proto_autogen/mocs_compilation.cpp.o [ 15%] Building CXX object CMakeFiles/hello.dir/hello_autogen/mocs_compilation.cpp.o [ 18%] Building CXX object CMakeFiles/hello.dir/main.cpp.o [ 21%] Building CXX object CMakeFiles/hw_grpc_proto.dir/helloworld.grpc.pb.cc.o [ 25%] Building CXX object CMakeFiles/hello.dir/hello_autogen/EWIEGA46WW/qrc_qml.cpp.o [ 28%] Building CXX object CMakeFiles/hw_grpc_proto.dir/helloworld.pb.cc.o [ 31%] Linking CXX static library libhw_grpc_proto.a [ 37%] Linking CXX executable hello [ 37%] Built target hw_grpc_proto Scanning dependencies of target greeter_async_client_autogen Scanning dependencies of target greeter_async_server_autogen Scanning dependencies of target greeter_async_client2_autogen [ 40%] Automatic MOC and UIC for target greeter_async_client [ 43%] Automatic MOC and UIC for target greeter_async_server [ 46%] Automatic MOC and UIC for target greeter_async_client2 [ 46%] Built target greeter_async_client_autogen [ 46%] Built target greeter_async_server_autogen [ 46%] Built target greeter_async_client2_autogen Scanning dependencies of target greeter_client_autogen Scanning dependencies of target greeter_server_autogen Scanning dependencies of target greeter_async_client2 [ 50%] Automatic MOC and UIC for target greeter_client [ 53%] Automatic MOC and UIC for target greeter_server [ 53%] Built target greeter_client_autogen [ 56%] Building CXX object CMakeFiles/greeter_async_client2.dir/greeter_async_client2_autogen/mocs_compilation.cpp.o [ 56%] Built target greeter_server_autogen [ 59%] Building CXX object CMakeFiles/greeter_async_client2.dir/greeter_async_client2.cc.o Scanning dependencies of target greeter_async_server Scanning dependencies of target greeter_async_client [ 62%] Building CXX object CMakeFiles/greeter_async_server.dir/greeter_async_server_autogen/mocs_compilation.cpp.o [ 65%] Building CXX object CMakeFiles/greeter_async_client.dir/greeter_async_client_autogen/mocs_compilation.cpp.o [ 68%] Building CXX object CMakeFiles/greeter_async_server.dir/greeter_async_server.cc.o /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: in function `RunServer()': main.cpp:(.text+0x6c): undefined reference to `grpc::EnableDefaultHealthCheckService(bool)' /usr/bin/ld: main.cpp:(.text+0x71): undefined reference to `grpc::reflection::InitProtoReflectionServerBuilderPlugin()' /usr/bin/ld: main.cpp:(.text+0x80): undefined reference to `grpc::ServerBuilder::ServerBuilder()' /usr/bin/ld: main.cpp:(.text+0x8f): undefined reference to `grpc::InsecureServerCredentials()' /usr/bin/ld: main.cpp:(.text+0xae): undefined reference to `grpc::ServerBuilder::AddListeningPort(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<grpc::ServerCredentials>, int*)' /usr/bin/ld: main.cpp:(.text+0xd6): undefined reference to `grpc::ServerBuilder::RegisterService(grpc::Service*)' /usr/bin/ld: main.cpp:(.text+0xef): undefined reference to `grpc::ServerBuilder::BuildAndStart()' /usr/bin/ld: main.cpp:(.text+0x168): undefined reference to `grpc::ServerBuilder::~ServerBuilder()' /usr/bin/ld: main.cpp:(.text+0x203): undefined reference to `grpc::ServerBuilder::~ServerBuilder()' /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: in function `helloworld::HelloReply::set_message(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)': main.cpp:(.text._ZN10helloworld10HelloReply11set_messageEONSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_ZN10helloworld10HelloReply11set_messageEONSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x53): undefined reference to `google::protobuf::internal::ArenaStringPtr::Set(google::protobuf::internal::ArenaStringPtr::EmptyDefault, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, google::protobuf::Arena*)' /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: in function `GreeterServiceImpl::SayHello(grpc::ServerContext*, helloworld::HelloRequest const*, helloworld::HelloReply*)': main.cpp:(.text._ZN18GreeterServiceImpl8SayHelloEPN4grpc13ServerContextEPKN10helloworld12HelloRequestEPNS3_10HelloReplyE[_ZN18GreeterServiceImpl8SayHelloEPN4grpc13ServerContextEPKN10helloworld12HelloRequestEPNS3_10HelloReplyE]+0xb5): undefined reference to `grpc::Status::OK' /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: in function `GreeterServiceImpl::GreeterServiceImpl()': main.cpp:(.text._ZN18GreeterServiceImplC2Ev[_ZN18GreeterServiceImplC5Ev]+0x18): undefined reference to `helloworld::Greeter::Service::Service()' /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: in function `GreeterServiceImpl::~GreeterServiceImpl()': main.cpp:(.text._ZN18GreeterServiceImplD2Ev[_ZN18GreeterServiceImplD5Ev]+0x2a): undefined reference to `helloworld::Greeter::Service::~Service()' /usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o:(.data.rel.ro._ZTI18GreeterServiceImpl[_ZTI18GreeterServiceImpl]+0x10): undefined reference to `typeinfo for helloworld::Greeter::Service' collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/hello.dir/build.make:126: hello] Error 1 make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/hello.dir/all] Error 2 make[1]: *** Waiting for unfinished jobs.... [ 71%] Building CXX object CMakeFiles/greeter_async_client.dir/greeter_async_client.cc.o [ 75%] Linking CXX executable greeter_async_server [ 78%] Linking CXX executable greeter_async_client [ 81%] Linking CXX executable greeter_async_client2 [ 81%] Built target greeter_async_server [ 81%] Built target greeter_async_client [ 81%] Built target greeter_async_client2 make: *** [Makefile:84: all] Error 2 jj@jj-HP-Pavilion-g4-Notebook-PC:~/Desktop/qt/hello$
-
@JJLim This has nothing to do with Qt.
What you seem to do is to add gRPC source code into your project. Don't do that.
First build gRPC using same compiler you use for your Qt apps and then simply add gRPC as a dependency to your project.Also, since you're on Linux you also may simply install gRPC using the packet system of your Linux distribution, no need to build it by yourself.
-
@jsulm Thank you for your advices. I am still trying on this method, figuring out the correct method to write the cmakelists.txt. BTW, may I know what is the gRPC dependency, are they the autogen files by protoc?
Bcuz I saw some articles that we need to add a lot of gRPC library into qt project, I am confuse about this. The picture below referred to this statement
https://www.cnblogs.com/MakeView660/p/11532192.html This is the article link, it is using windows. This makes me struggle which one is the correct path that I need to include in Linux.
-
Yup, I am using gRPC provided by Linux distro, since I want to focus on C++, so I install gRPC based on the instructions from https://grpc.io/docs/languages/cpp/quickstart/
However, I am wondering how to include gRPC package into qt project that is created by using Qt Creator IDE.
-
Hi,
Once you build and installed the gRPC libraries and tools then use the libraries as any other C++ dependency.
-
@jack-reemoon sorry because you use gRPC instead of rest service?
Thanks