在Linux下为g++链接三方库


概述

最近在学习Boost网络库,一开始使用的版本是apt源带的1.74.0,大概是20年左右的版本,后面想了一下太老了,同时想配合gcc13体验一下协程,就去下了最新的Boost 1.85.0, 然后在安装的时候没有选择默认安装位置(之前不知道吃大亏),而是自定义了一个地方,这样能够让我们多版本使用,但是无法像之前直接丝滑的#include使用,同时又不想像维护第三方一样每次都写CMakeList,于是怎么让g++(or gcc)识别库就成了一个问题。

Boost

这里选择的方法是使用在.zshrc中export环境变量的方法来使用,下面分别来看这三变量的作用:

  • BOOST_ROOT:实际上可有可无,主要是在CMakeList中使用find_package查找boost时使用
  • CPLUS_INCLUDE_PATH: g++查找头文件包含处
  • LD_LIBRARY_PATH: 动态库连接地址

常用的话可以直接加在.zshrc中避免繁杂的编写。

Protobuf

只能说太折磨了,本来想着一开始或许像Boost一样给他安装完就行了,没想到复杂程度翻了好几个倍,而且还需要像之前一样使用不指定路径直接使用,好在最后折磨了几个小时终于配好了。网上有关的资料实在是太少,最后还是只能靠自己分析出来,果然make your hands dirty才是让工程能力上升的好方式。而且其实最后的答案也并不意外,但是如果没有人跟你说的话自己需要碰壁很久(还是之前boost太好配置形成路径依赖了)。

如果你只想快速使用,而不需要太新的版本的话那么可以直接通过下面两个命令快速安装学习使用。

sudo apt install protobuf-compiler
sudo apt install libprotobuf-dev

至于怎么安装,安装Protobuf可是一大乐子,这里只说如果安装在其他路径而非默认路径怎么添加到我们需要的环境中,在安装完后,需要添加对应的环境(重点),找到一些测试的demo,同时生成对应的pb文件,后面我们就需要编译了,首先大概率是这种情况:

其实一点不意外

好的,然后去网络上查找,发现原来需要 -lprotobuf,加上试试,然后会发现ld找不到protobuf库,那么如果说手动指定链接的库能否成功?

成功了

尝试echo一下$LD_LIBRARY_PATH,发现是有对应库的地址的,那么说明问题并不在动态库上,链接有问题而不是动态库,那么只剩下是静态库的问题了,首先添加一下静态库的地址:

  • 第一个用于执行protoc
  • 第二个命令用于寻找pkgconfig,主要用于CMakeLists
  • 剩下的分别是头文件包含,静态库动态库连接地址

终于可以不用手动指定链接地址了

CMake中使用

与Boost不同,Boost在设置完环境变量后的使用基本跟std差不多,可以无感使用非常丝滑,但是Protobuf不行,并且Protobuf一般在中大型项目里面我们才会使用(一般要配合CMakeLists),那么怎么在CMakeLists里面使用就成了关键。

  • 方法一:手动指定

    set(Protobuf_PREFIX_PATH
        "/home/joytsing/makeInstall/protobuf3.21.12/include"            
        "/home/joytsing/makeInstall/protobuf3.21.12/lib"             
        "/home/joytsing/makeInstall/protobuf3.21.12/bin" )
    list(APPEND CMAKE_PREFIX_PATH "${Protobuf_PREFIX_PATH}")
    find_package(Protobuf REQUIRED)

  • 方法二:利用PkgConfig

    find_package(PkgConfig)
    pkg_search_module(Protobuf REQUIRED protobuf)

注意,这个方法有缺陷,没法使用protobuf_generate_cpp这些原生指令,简单的工程可以用方法2,复杂的最好就不要用了。

在引入库之后就可以正常使用了,可喜可贺。

find_package(Protobuf REQUIRED)  #查找protobuf包

include_directories(${Protobuf_INCLUDE_DIRS})  #添加头文件,其实这一步在我们添加完CPLUS_INCLUDE是不需要的

add_executable(exe main.cpp test.pb.cc) # 在用file(GLOB_RECURSE)的时候一定要注意是*.cc,找*.cpp无法编译

target_link_libraries(exe ${PROTOBUF_LIBRARIES})  #一定要连接库文件

一些疑惑

其实我挺奇怪为什么boost不需要像Protobuf一样在使用g++命令的时候手动链接,同时不需要添加静态库的地址(最后还是为了以防万一把boost的静态链接给加上了)。

后记

最好不要把protobuf加到全局里面去配置,大概率会跟grpc冲突。


评论
  目录