我最近在尝试手写线程池,尽管还有很多改进的地方,但用来学习本节内容足够了。
构建静态库和动态库
光是构建静态库和动态库还不够, 还需要指定生成路径,这样别人使用你的库文件将相当方便(后面你就知道了)。
先看看如何构建静态库和动态库。
1 |
|
对于安装路径、头文件安装路径、静态库安装路径、动态库安装路径已在上节介绍。
这里重点讲 install 的配置,即用户在终端使用 install 命令就能生成提前配置好的安装路径。
1 |
|
因此,我们的重点关注静态库和动态库以及头文件的安装路径,那我们先设置路径和配置生成库文件的命令。
1 |
|
但如果我们希望用户应用 install 命令来把这些文件全部放在安装路径下,就还需要继续往下配置。
下面的配置中有些新参数在前面没有介绍,比如:DESTINATION、ARCHIVE、RUNTIME、LIBRARY。
1 |
|
对出现的新参数,下面用列表来展示:
目标文件 | 内容 | 安装目录变量 | 默认安装文件夹 |
---|---|---|---|
ARCHIVE | 静态库 | ${CMAKE_INSTALL_LIBDIR}) | lib |
LIBRARY | 动态库 | ${CMAKE_INSTALL_LIBDIR}) | lib |
RUNTIME | 可执行二进制文件 | ${CMAKE_INSTALL_BINDIR} | bin |
还有非常关键的指令:DESTINATION <dir>
即指定磁盘上要安装文件的目录。<dir>
应为相对路径。 绝对路径是允许的,但不建议使用。
下面开始整个静态库和动态库的构建和安装过程,最后再看看安装情况。
1 |
|
效果:
以后用户想要使用这个库,就只需要把 YThreadPool_x86 拷贝到自己的项目文件中。
然后在 CMakeLists.txt 中找到所需库文件和头文件即可,这也是下面要演示的内容,即如何使用链接静态库和动态库。
链接静态库和动态库
link_directories 用来指定库的路径,那么后续使用 link_libraries 或 target_link_libraries 搜索库文件的时候,也就只需要传入库文件名称即可。
link_directories 不会进行层级搜索。它只会将指定的目录添加到链接器的搜索路径中,而不会自动搜索该目录下的子目录。也就是说,如果你使用 link_directories(${CMAKE_SOURCE_DIR}/lib)
,链接器只会查找 ${CMAKE_SOURCE_DIR}/lib
目录中的库文件,不会查找 lib
目录中的子目录。
如果你需要链接某个子目录中的库,必须显式地使用 link_directories
指定那个子目录,或者使用 target_link_libraries
直接指定库的完整路径。
(一)链接静态库
1 |
|
如果是系统提供的静态库,填写静态库名称即可。
如果是第三方静态库,需要给出具体路径才行(但我们一般选择 link_directories 方法找到库文件的位置)。
注意:因为静态库是在编译可执行程序之前要存在的一个文件,因此我们的link_libraries
语法 务必 在 add_executable
语法之前。
(二)链接动态库
1 |
|
我们需要指定链接的目标,因为我们是要动态加载的,因此必须指定加载到哪个应用程序中,因此target参数是可执行程序的名称。
注意:因为动态库是在编译可执行程序之后要存在的一个文件,因此我们的target_link_libraries
语法 务必 在 add_executable
语法之后。
关键字 | 说明 | 传递方式 |
---|---|---|
PRIVATE | 目标链接到库,但不会传递给依赖此目标的其他目标 | 链接库仅对当前目标可见 |
PUBLIC | 目标链接到库,并且依赖此目标的其他目标也会链接到该库 | 链接库对当前目标和依赖此目标的所有目标都可见 |
INTERFACE | 目标本身不会链接到库,但任何依赖此目标的目标会链接到该库。适用于仅在接口需要的库 | 链接库对依赖此目标的所有目标可见,但对当前目标不可见 |
如上这种讲法还是不太好理解,下面用实例说明:
1 |
|
A
链接到 libA
,但只有 A
自己能看到 libA
,所以 libA
不会传递给 B
或 C
。
B
链接到 A
,并且这个链接关系是 PUBLIC
,所以 B
和 C
都能看到 A
。
C
链接到 B
,但这种链接关系是 INTERFACE
,所以 C
能看到 B
的接口,但 B
实际上没有链接到其他库。
下面我就具体演示,把静态库和动态库一并引入,实际情景中你可能只需要静态库或动态库即可。
1 |
|