CMake 链接第三方库的方式

前 言

项目中经常会使用第三方库,因此编译时会需要去链接这些库,这里介绍几种链接第三方库的方式。编译使用 CMake,第三方库以 protobuf 3.20.1 为例。

说 明

库的安装
protobuf 可以通过 apt-get 来安装也可以通过源码编译安装。

如果使用 apt-get 来安装,相关的文件会安装到/usr/bin (执行文件)、 /usr/lib (库文件)、/usr/include (头文件)中。当然,不同的Linux版本安装路径可能会不同,但这些路径默认都会在系统的环境变量中,因此编译时一般直接链接 protobuf 即可。

如果自己使用源码编译安装,安装的路径可能不在环境变量中。以下的几种方式均是手动安装且安装路径在 /usr/loacl/protocbuf 下的示例。
Ps:当然也可以将安装路径添加到环境变量里来解决问题,本文主要是介绍不同的链接方式。

实 现

1. 简单方式
最简单的方式就是使用 include_directories 包含头文件路径以及使用 link_directories 指定库搜索路径,如下:

# 包含头文件路径
include_directories(/usr/local/protobuf/include)
# 指定库搜索路径
link_directories(/usr/local/protobuf/lib)

add_executable(Demo demo.cpp)

# 链接 protobuf,同时需要链接 pthread
target_link_libraries(Demo protobuf pthread)

2. find_package
find_package 可以帮助我们找到第三方库的相关依赖,详细内容可以参考官方文档:cmake find_package
find_package 会在以下路径(优先级由上往下)查找:

<package>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
PATH

我们可以设置 <package>_DIR 值,或者将查找路径添加到 CMAKE_PREFIX_PATH 中,实现如下:

# 定义查找路径
set(Protobuf_PREFIX_PATH "/usr/local/protobuf")
# 添加到 CMAKE_PREFIX_PATH
list(APPEND CMAKE_PREFIX_PATH "${Protobuf_PREFIX_PATH}")
# 查找 Protobuf
find_package(Protobuf REQUIRED)

# 包含头文件
include_directories(${Protobuf_INCLUDE_DIR})

add_executable(Demo demo.cpp)

# 链接选项
target_link_libraries(Demo ${Protobuf_LIBRARIES} pthread)

3. pkg-config
pkg-config 是通过库提供的 .pc 文件来定位库的各种路径。首先需要安装 pkg-config

sudo apt-get install pkg-config

接着我们需要让 pkg-config 能够找到 protobuf.pc 文件。
有两种方式:

  • 1.在手动安装 protobuf 的路径 /usr/local/protobuf/lib/pkgconfig 下可以找到提供的 .pc 文件,将其拷贝到 pkg-config 默认搜索路径 /usr/lib/pkgconfig
  • 2.将路径 /usr/local/protobuf/lib/pkgconfig 添加到环境变量 PKG_CONFIG_PATH

最后在CMake中使用 pkg-config 查找库并链接

find_package(PkgConfig)
# pkg_search_module(自定义名  必需项  查找库名)
pkg_search_module(Protobuf REQUIRED protobuf)

include_directories(${Protobuf_INCLUDEDIR})
link_directories(${Protobuf_LIBDIR})

add_executable(Demo demo.cpp)

target_link_libraries(Demo protobuf pthread)

使用的变量 ${Protobuf_INCLUDEDIR}${Protobuf_LIBDIR} 是根据我们自定义名以及 .pc 中定义的变量而来,查看 protobuf.pc 内容如下:

prefix=/usr/local/protobuf                                                                                                                                        
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: Protocol Buffers
Description: Google's Data Interchange Format
Version: 3.20.1
Libs: -L${libdir} -lprotobuf
Libs.private: -lz 

Cflags: -I${includedir}
Conflicts: protobuf-lite

文中定义了库路径 libdir 和头文件路径 includedir

问 题

在第二种方式中提到,可以设置 <package>_DIR 的路径且其优先级最高。根据 find_package 的原理,其是寻找路径下的 <package>Config.cmake 文件来获取库信息。

手动安装 protobuf 情况下,在编译路径中可以找到 cmake 文件夹,其中包含了关键文件 protobuf-config.cmakeprotobuf-config.cmake(可能带有 .in 后缀)
设置该路径为 <package>_DIR,实现如下:

# /root/cyh/protobuf/build/protobuf-3.20.1 为我编译的路径
set(protobuf_DIR "/root/cyh/protobuf/build/protobuf-3.20.1/cmake")
find_package(Protobuf REQUIRED)

此时,CMake报错:

CMake Error at /usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:137 (message):
  Could NOT find Protobuf (missing: Protobuf_INCLUDE_DIR)
Call Stack (most recent call first):
  /usr/share/cmake-3.10/Modules/FindPackageHandleStandardArgs.cmake:378 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-3.10/Modules/FindProtobuf.cmake:543 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  CMakeLists.txt:8 (find_package)

使用 CONFIG 模式查找

find_package(Protobuf REQUIRED CONFIG)

CMake报错:

CMake Error at CMakeLists.txt:8 (find_package):
Could not find a package configuration file provided by "Protobuf" with any
of the following names:

    ProtobufConfig.cmake
    protobuf-config.cmake

奇怪的是,报错提示找不到的 protobuf-config.cmake 文件确实在指定目录中。
参考了几个讨论:

还是没能解决问题,于是改用上文设置安装路径到 CMAKE_PREFIX_PATH 的方式解决。
欢迎大佬留言指点!


GitHub Blog 同步更新

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容