• 我为什么更推荐你使用cmake编译grpc程序?


    事情源于我最近在使用gRPC库,在编译时下意识使用了makefile编译,然后,编译时报错找不到库文件。

    makefile 文件:

    CC = g++
    CFLAGS = -std=c++11 -I. -I/usr/local/include -L/usr/localb
    GFLAGS = -lgrpc++ -lgrpc -lprotobuf -lpthread -lz -lgpr
    
    all: measurement_client measurement_server
    
    measurement_client: client.cpp measurement.grpc.pb.cc
    	$(CC) $(CFLAGS) -o measurement_client client.cpp measurement.grpc.pb.cc $(GFLAGS)
    
    measurement_server: server.cpp measurement.grpc.pb.cc
    	$(CC) $(CFLAGS) -o measurement_server server.cpp measurement.grpc.pb.cc $(GFLAGS)
    
    run_server:
    	./measurement_server
    
    run_client:
    	./measurement_client
    
    clean:
    	rm -f measurement_client measurement_server
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在编译时报错一些库未定义:
    ![[TXYXKM`851N63V7SRX98E%V.png]]![[CBQGJRNZ0L8M{ I 7 I7 I7UQBVV3.png]]![[SP]]VXW3A_M9SJW5JOPV7K9.png]]

    从这里看到缺失的都是它自己的一些库依赖。

    然后就开始了漫长的查找过程,期间发现使用的是静态库,尝试编译成动态库,发现反而让库文件彻底混乱损坏了。

    这里写一个列表,这是gRPC 需要的依赖库文件,可以看看有多少:

    $ ls
    cmake                          libabsl_log_severity.a          libabsl_throw_delegate.a  libgrpc.a                  libgrpc_plugin_support.a  libssl.a
    libabsl_bad_optional_access.a  libabsl_raw_logging_internal.a  libaddress_sorting.a      libgrpc++.a                libgrpcpp_channelz.a      libupb.a
    libabsl_base.a                 libabsl_spinlock_wait.a         libcares.a                libgrpc++_alts.a           libgrpc++_reflection.a    libz.a
    libabsl_dynamic_annotations.a  libabsl_strings.a               libcrypto.a               libgrpc_cronet.a           libgrpc_unsecure.a        pkgconfig
    libabsl_int128.a               libabsl_strings_internal.a      libgpr.a                  libgrpc++_error_details.a  libgrpc++_unsecure.a
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    你可以尝试使用这个makefile

    # Protobuf - 必须为 Protobuf3
    PROTOBUF_HOME=/usr/local/protobuf
    PROTOBUF_INCL=-I${PROTOBUF_HOME}/include
    PROTOBUF_LIB=${PROTOBUF_HOME}/lib/libprotobuf.a ${PROTOBUF_HOME}/lib/libprotobuf-lite.a
    
    # gRPC
    GRPC_HOME=/usr/local
    GRPC_INCL=-I${GRPC_HOME}/include
    ABSL_LIB=${GRPC_HOME}/lib/libabsl_strings.a ${GRPC_HOME}/lib/libabsl_strings_internal.a ${GRPC_HOME}/lib/libabsl_throw_delegate.a ${GRPC_HOME}/lib/libabsl_base.a
    GRPC_LIB=${ABSL_LIB} ${GRPC_HOME}/lib/libgpr.a ${GRPC_HOME}/lib/libgrpc++.a ${GRPC_HOME}/lib/libgrpc.a ${GRPC_HOME}/lib/libupb.a ${GRPC_HOME}/lib/libssl.a ${GRPC_HOME}/lib/libcrypto.a ${GRPC_HOME}/lib/libcares.a ${GRPC_HOME}/lib/libaddress_sorting.a
    
    INCLS=${GRPC_INCL} ${PROTOBUF_INCL}
    LIBS=-pthread -ldl -lrt -lz -Wl,--start-group ${GRPC_LIB} ${PROTOBUF_LIB} -Wl,--end-group
    
    .PHONY: build
    build:
    	g++ -std=c++11 -Wno-deprecated-declarations -o test test.cpp ../grpc/common.pb.cc ../grpc/proxy.pb.cc ../grpc/proxy.grpc.pb.cc -I../grpc ${INCLS} $(LIBS)
    
    .PHONY: clean
    clean:
    	rm -f test
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    上述的“-Wno-deprecated-declarations”是为消除下列编译警告:

    /usr/local/include/grpcpp/impl/codegen/proto_utils.h:52:32: 警告:不建议使用‘int google::protobuf::MessageLite::ByteSize() const(声明于 /usr/local/include/google/protobuf/message_lite.h:402):Please use ByteSizeLong() instead [-Wdeprecated-declarations]
    
    • 1

    因为库实在有点多,为避免因为静态库顺序的坑,直接使用了“–start-group”和“–end-group”忽略顺序关系。建议使用CMake或automake编译,以省去处理依赖的麻烦。

    以下是官方给出的 cmake 更加的简洁:

    # Copyright 2018 gRPC authors.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    # cmake build file for C++ DeviceData example.
    # Assumes protobuf and gRPC have been installed using cmake.
    # See cmake_externalproject/CMakeLists.txt for all-in-one cmake build
    # that automatically builds all the dependencies before building DeviceData.
    
    cmake_minimum_required(VERSION 3.5.1)
    
    project(DeviceData C CXX)
    
    include(../cmake/common.cmake)
    
    # Proto file
    get_filename_component(dev_proto "../../protos/DeviceData.proto" ABSOLUTE)
    get_filename_component(dev_proto_path "${dev_proto}" PATH)
    
    # Generated sources
    set(dev_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/DeviceData.pb.cc")
    set(dev_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/DeviceData.pb.h")
    set(dev_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/DeviceData.grpc.pb.cc")
    set(dev_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/DeviceData.grpc.pb.h")
    add_custom_command(
          OUTPUT "${dev_proto_srcs}" "${dev_proto_hdrs}" "${dev_grpc_srcs}" "${dev_grpc_hdrs}"
          COMMAND ${_PROTOBUF_PROTOC}
          ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
            --cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
            -I "${dev_proto_path}"
            --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
            "${dev_proto}"
          DEPENDS "${dev_proto}")
    
    # Include generated *.pb.h files
    include_directories("${CMAKE_CURRENT_BINARY_DIR}")
    
    # dev_grpc_proto
    add_library(dev_grpc_proto
      ${dev_grpc_srcs}
      ${dev_grpc_hdrs}
      ${dev_proto_srcs}
      ${dev_proto_hdrs})
    target_link_libraries(dev_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}
        dev_grpc_proto
        ${_REFLECTION}
        ${_GRPC_GRPCPP}
        ${_PROTOBUF_LIBPROTOBUF})
    endforeach()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    其中引用的上级cmake 为common.cmake

    # Copyright 2018 gRPC authors.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    # cmake build file for C++ route_guide example.
    # Assumes protobuf and gRPC have been installed using cmake.
    # See cmake_externalproject/CMakeLists.txt for all-in-one cmake build
    # that automatically builds all the dependencies before building route_guide.
    
    cmake_minimum_required(VERSION 3.5.1)
    
    set (CMAKE_CXX_STANDARD 11)
    
    if(MSVC)
      add_definitions(-D_WIN32_WINNT=0x600)
    endif()
    
    find_package(Threads REQUIRED)
    
    if(GRPC_AS_SUBMODULE)
      # One way to build a projects that uses gRPC is to just include the
      # entire gRPC project tree via "add_subdirectory".
      # This approach is very simple to use, but the are some potential
      # disadvantages:
      # * it includes gRPC's CMakeLists.txt directly into your build script
      #   without and that can make gRPC's internal setting interfere with your
      #   own build.
      # * depending on what's installed on your system, the contents of submodules
      #   in gRPC's third_party/* might need to be available (and there might be
      #   additional prerequisites required to build them). Consider using
      #   the gRPC_*_PROVIDER options to fine-tune the expected behavior.
      #
      # A more robust approach to add dependency on gRPC is using
      # cmake's ExternalProject_Add (see cmake_externalproject/CMakeLists.txt).
    
      # Include the gRPC's cmake build (normally grpc source code would live
      # in a git submodule called "third_party/grpc", but this example lives in
      # the same repository as gRPC sources, so we just look a few directories up)
      add_subdirectory(../../.. ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL)
      message(STATUS "Using gRPC via add_subdirectory.")
    
      # After using add_subdirectory, we can now use the grpc targets directly from
      # this build.
      set(_PROTOBUF_LIBPROTOBUF libprotobuf)
      set(_REFLECTION grpc++_reflection)
      if(CMAKE_CROSSCOMPILING)
        find_program(_PROTOBUF_PROTOC protoc)
      else()
        set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
      endif()
      set(_GRPC_GRPCPP grpc++)
      if(CMAKE_CROSSCOMPILING)
        find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
      else()
        set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)
      endif()
    elseif(GRPC_FETCHCONTENT)
      # Another way is to use CMake's FetchContent module to clone gRPC at
      # configure time. This makes gRPC's source code available to your project,
      # similar to a git submodule.
      message(STATUS "Using gRPC via add_subdirectory (FetchContent).")
      include(FetchContent)
      FetchContent_Declare(
        grpc
        GIT_REPOSITORY https://github.com/grpc/grpc.git
        # when using gRPC, you will actually set this to an existing tag, such as
        # v1.25.0, v1.26.0 etc..
        # For the purpose of testing, we override the tag used to the commit
        # that's currently under test.
        GIT_TAG        vGRPC_TAG_VERSION_OF_YOUR_CHOICE)
      FetchContent_MakeAvailable(grpc)
    
      # Since FetchContent uses add_subdirectory under the hood, we can use
      # the grpc targets directly from this build.
      set(_PROTOBUF_LIBPROTOBUF libprotobuf)
      set(_REFLECTION grpc++_reflection)
      set(_PROTOBUF_PROTOC $<TARGET_FILE:protoc>)
      set(_GRPC_GRPCPP grpc++)
      if(CMAKE_CROSSCOMPILING)
        find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
      else()
        set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)
      endif()
    else()
      # This branch assumes that gRPC and all its dependencies are already installed
      # on this system, so they can be located by find_package().
    
      # Find Protobuf installation
      # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.
      set(protobuf_MODULE_COMPATIBLE TRUE)
      find_package(Protobuf CONFIG REQUIRED)
      message(STATUS "Using protobuf ${Protobuf_VERSION}")
    
      set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
      set(_REFLECTION gRPC::grpc++_reflection)
      if(CMAKE_CROSSCOMPILING)
        find_program(_PROTOBUF_PROTOC protoc)
      else()
        set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
      endif()
    
      # Find gRPC installation
      # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
      find_package(gRPC CONFIG REQUIRED)
      message(STATUS "Using gRPC ${gRPC_VERSION}")
    
      set(_GRPC_GRPCPP gRPC::grpc++)
      if(CMAKE_CROSSCOMPILING)
        find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
      else()
        set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
      endif()
    endif()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    分享一个有趣的 学习链接:https://xxetb.xet.tech/s/HY8za

  • 相关阅读:
    SpringWeb(SpringMVC)
    HS-ResNet: Hierarchical-Split Block on Convolutional Neural Network
    groovy:SimpleDateFormat 打印当前时间
    淘宝API详情接口调用示例
    Scala学习:类和对象
    【无标题】
    软考高级系统分析师考试2022论文考了些啥?改为二选一
    【开源微服务项目】论如何在微服务中优雅的实现Redis序列化配置
    postman高阶脚本
    Retrofit2 完全解析 探索与okhttp之间的关系
  • 原文地址:https://blog.csdn.net/qq_29111047/article/details/134496375