CMake使用外部动态库/静态库和头文件

一、准备工作

在博文《使用CMake构建静态库和动态库》中已经介绍了libhello动态库的构建和安装,现在我们看看如何使用这个外部动态库。

本文中的示例前提是已经安装了libhello.so共享库。

二、新建一个新的CMake工程

创建一个新的名为usehellolib的CMake工程,在main.cpp中使用libhello.so中提供的函数say_hello().

main.cpp

#include <iostream>
#include "hello.hpp"

int main(int, char**) {
    say_hello();
}

工程根目录下的CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.0.0)
project(usehellolib VERSION 0.1.0)

add_subdirectory(src)

# 以下内容非必须
include(CTest)
enable_testing()

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

src 目录下的 CMakeLists.txt内容如下:

add_executable(usehellolib main.cpp)

整个工程的目录结构看起来是这样的:

20230101212438

三、开始构建

按照惯例,到build目录下进行构建

cd build
cmake ..
make

此时会发现报错了,提示找不到hello.hpp

20230101212658

hello.hpp 位于/usr/include/hello 目录中,并没有位于系统标准的头文件路径, 为了让我们的工程能够找到hello.hpp,我们需要引入一个新的指令INCLUDE_DIRECTORIES:

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)

这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的后面,你可以通过两种方式来进行控制搜索路径添加的方式:

  • CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过 SET 这个 cmake 变量为 on,可以
    将添加的头文件搜索路径放在已有路径的前面。
  • 通过 AFTER 或者 BEFORE 参数,也可以控制是追加还是置前。

现在我们在 src/CMakeLists.txt 中添加一个头文件搜索路径,方式很简单,加入

INCLUDE_DIRECTORIES(/usr/include/hello)

20230101213311

进入build目录重新构建,发现找不到头文件的错误已经消失,但是出现了一个新错误:

20230101213236

这是因为我们并没有 link 到共享库 libhello 上。

四、为target添加共享库

我们现在需要完成的任务是将目标文件链接到 libhello,这里我们需要引入两个新的指令
LINK_DIRECTORIES 和 TARGET_LINK_LIBRARIES。

LINK_DIRECTORIES 的全部语法是:

LINK_DIRECTORIES(directory1 directory2 ...)

这个指令非常简单,添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可执行二进制,在编译时就需要指定一下这些共享库的路径。这个例子中我们没有用到这个指令。

TARGET_LINK_LIBRARIES 的全部语法是:

TARGET_LINK_LIBRARIES(target library1
    <debug | optimized> library2
    ...)

这个指令可以用来为 target 添加需要链接的共享库,本例中target是一个可执行文件,但是同样可以用于为自己编写的共享库添加共享库链接。

为了解决上面遇到的函数未定义错误,我们向 src/CMakeLists.txt 中添加如下指令:

TARGET_LINK_LIBRARIES(main hello)
也可以写成
TARGET_LINK_LIBRARIES(main libhello.so)

20230101214207

重新构建,这时我们就得到了一个连接到libhello的可执行程序usehellolib,位于build/src目录:

20230101214520

执行看是否能运行成功, 发现仍然有报错:

./usehellolib: error while loading shared libraries: libhello.so.1: cannot open shared object file: No such file or directory

20230101215501

可是文件明明是存在的:
20230101215639

我们来看看ldconfig这个程序,位于/sbin下,它的作用是将文件/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache以供使用,因此当安装完一些库文件,或者修改/etc/ld.so.conf增加了库的新的搜索路径,需要运行一下ldconfig,使所有的库文件都被缓存到文件/etc/ld.so.cache中,如果没做,可能会找不到刚安装的库。

执行一下ldconfig

ldconfig

如果是普通用户的话,需要使用sudo

20230101221409

再次执行程序,此时已经可以正常运行:

20230101221539

检查一下程序的链接情况,可以看到确实链接了libhello共享库:

20230101221759

五、链接静态库

那么如何链接到静态库呢? 很简单,只需要将
TARGET_LINK_LIBRRARIES 指令修改为:
TARGET_LINK_LIBRARIES(usehellolib libhello.a)

重新构建并查看链接情况:

20230101223755

猜你喜欢

转载自blog.csdn.net/hubing_hust/article/details/128516750