CMake静态库

前言

我们知道 c.cpp c. hh 两个文件会经过编译,然后生成机器码文件,
而静态库的作用就是保存机器码,一方面是保证了安全性,另一方面是不用再次编译(但是跨平台肯定是不行的)

如何生成静态库

add_library(静态库名字 STATIC 静态库.cpp文件)
add_library(add_static STATIC add.cpp)

静态库的完整过程

  1. 编译 add.cpp 生成静态库: 当通过命令添加一个库时,CMake 会为适用的源文件生成一个编译指令 add_library(add_static STATIC add.cpp)。在这种情况下,它将 add.cpp 编译文件并创建一个名为 add_static 的静态库(在 Windows 上通常是 add_static.lib,在 Unix-like 系统中是 libadd_static.a)。

  2. 编译 main.cpp 生成对象文件: add_executable(main main.cpp) 命令告诉 CMake 对 main.cpp 文件进行编译,生成一个对象文件 main.o( 或 main.obj)。

  3. 将静态库 add_static 链接到最终的可执行文件 main 确保在 CMake 创建最终的可执行文件时,它会链接之前编译的静态库 add_static.lib。这其中包括了查找和解析函数调用,比如 add() 函数,因为它在静态库 add_static.lib 中定义。这个链接过程涉及到把的 main.cpp 文件编译成可执行文件

这样,生成的可执行文件 main 就包含了 add_static 库中所有必需的代码,这意味着在调用函数 add() 时不需要再有任何其它的库依赖。

编译和链接的具体命令取决于使用的编译器和平台。如果正在使用 GCC,则它可能会类似于:

1
2
3
4
g++ -c add.cpp -o add.o                    # 编译生成add.o
ar rcs libadd_static.a add.o # 通过静态库归档器创建静态库
g++ -c main.cpp -o main.o # 编译生成main.o
g++ main.o -L. -ladd_static -o main # 链接生成main可执行文件

这里,-L. 告诉编译器在当前目录下查找库(-L 指定库的搜索路径),而 -ladd_static 指定静态库名称(lib 不包括前缀和后缀 .a.lib)。

正确建立的 CMake 项目会让这个过程自动化,所以通常不需要手动运行编译和链接命令。只需要在构建目录中运行以下 CMake 命令:

1
2
cmake ..
make

或使用 CMake 生成适用于选择的 IDE 的工程。

CMake 后台进行的具体编译和链接命令对于最终用户通常是透明的,除非有错误发生或者需要调试 CMake 本身的问题。如果想看到 CMake 执行 make 的具体命令,可以在命令行中增加的选项,如:VERBOSE=1

1
make VERBOSE=1

这将打印出每个编译和链接阶段的具体命令。

静态库结构

[Pasted image 20231223002434.png]

[Pasted image 20231223004758.png]
以下是一个简单的示意,说明了这些组件是如何集成在静态库中的:

1
2
3
4
5
6
7
8
9
10
11
12
13
[静态库 libadd_static.a 或 add_static.lib]
|
|-- [对象文件 add1.o]
| |-- 函数 add1 的机器代码
| |-- 符号表(包含函数 add1 的信息)
|
|-- [对象文件 add2.o]
| |-- 函数 add2 的机器代码
| |-- 符号表(包含函数 add2 的信息)
|
|-- ... (其他对象文件和它们的代码)
|
|-- [符号索引] (可选,用于快速查找符号)

当链接器创建最终的可执行文件或另一个库时,如果需要使用静态库中的函数或变量,链接器会在静态库的符号表中查找相应的符号,并将对应的机器代码链接到最终的产物中。