大纲
前言
本文将介绍 CMake 如何编译和链接静态库和动态库。
C/C++ 项目编译的介绍
编译的流程
C++ 的编译和链接过程通常分为四个主要阶段:预处理、编译、汇编和链接。每个阶段都有特定的任务,最终生成可执行文件。这些阶段的流程如下:
- 预处理:处理
#include
、#define
等指令,生成纯文本代码。 - 编译:将代码转换成汇编代码。
- 汇编:将汇编代码转换成机器代码,生成目标文件。
- 链接:将目标文件和库文件组合,生成可执行文件。
编译的命令
步骤 | 命令 |
---|
1. 预处理 | gcc -E hello.c -o hello.i |
2. 编译到汇编代码 | gcc -S hello.c -o hello.s |
3. 汇编到目标代码(机器语言) | gcc -c hello.s -o hello.o |
4. 链接,生成可执行文件 | gcc hello.o -o hello |
以上四个步骤,可以合成一个步骤,直接编译链接成可执行的目标文件 | gcc hello.c -o hello |
静态库与动态库的介绍
静态库的介绍
静态库的概念
- 静态库基本可以理解为源码编译后的二进制代码,也就是多个编译后的目标文件的集合
- Windows 平台编译后的目标文件的文件名后缀为
.obj
,而 Linux 或者 MacOS 平台的文件名后缀为 .o
- 引用开源项目的静态库时,必须注意遵守开源协议,也就是针对相应的静态库是否获得了使用授权
静态库的文件名规则
- Windows 平台:以
.lib
为文件名后缀,比如 xlog.lib
,或者代表 Debug 版本的 xlog_d.lib
- Liunx 平台(Ubuntu、Android、HarmonyOS):以
lib
为文件名前缀,并且以 .a
为文件名后缀,比如 libxlog.a
- MacOS 平台:以
lib
为文件名前缀,并且以 .a
为文件名后缀,比如 libxlog.a
动态库的介绍
- 动态库的文件名规则
- Windows 平台:
- 第一类文件,以
.lib
为文件名后缀,比如 xlog.lib
,存放的是函数地址索引 - 第二类文件,以
.dll
为文件名后缀,比如 xlog.dll
,存放的是函数二进制代码
- Liunx 平台(Ubuntu、Android、HarmonyOS):以
lib
为文件名前缀,并且以 .so
为文件名后缀,比如 libxlog.so
- MacOS 平台:以
lib
为文件名前缀,并且以 .dylib
为文件名后缀,比如 libxlog.dylib
头文件的作用
- 函数名称和参数类型(用于索引查找函数地址)
- 不引用,可以自己直接声明函数
- 知道函数名称后,就可以调用系统 API 查找函数
CMake 编译与链接静态库
代码下载
完整的 CMake 案例代码可以从 这里 下载得到。
CMake 编译静态库
这里将演示如何使用 CMake 编译生成 C/C++ 项目的静态库。
1 2 3 4 5
| cmake_lib └── xlog ├── CMakeLists.txt ├── xlog.cpp └── xlog.h
|
1 2 3 4 5 6 7 8 9 10 11
| #ifndef XLOG_H #define XLOG_H
class XLog {
public: XLog();
};
#endif
|
1 2 3 4 5 6 7 8
| #include <iostream> #include "xlog.h"
using namespace std;
XLog::XLog() { cout << "Create XLog Instance" << endl; }
|
xlog
目录下的 CMakeLists.txt
文件
1 2 3 4 5 6 7 8
| # 指定CMake版本号 cmake_minimum_required(VERSION 3.15)
# 指定项目名称 project(xlog)
# 编译生成静态库 add_library(xlog STATIC xlog.cpp xlog.h)
|
1 2 3 4 5 6 7 8
| cd xlog
cmake -S . -B build
cmake --build build
|
系统平台 | 编译生成的静态库文件 |
---|
Windows | xlog.lib |
Linux | libxlog.a |
MacOS | libxlog.a |
CMake 链接静态库
通过上面的步骤使用 CMake 编译生成 C/C++ 项目的静态库后,这里将演示如何使用 CMake 链接 C/C++ 项目的静态库,最终编译生成可执行文件。
1 2 3 4 5 6 7 8
| cmake_lib ├── test_xlog │ ├── CMakeLists.txt │ └── test_xlog.cpp └── xlog ├── CMakeLists.txt ├── xlog.cpp └── xlog.h
|
1 2 3 4 5 6 7 8 9 10 11
| #ifndef XLOG_H #define XLOG_H
class XLog {
public: XLog();
};
#endif
|
1 2 3 4 5 6 7 8
| #include <iostream> #include "xlog.h"
using namespace std;
XLog::XLog() { cout << "Create XLog Instance" << endl; }
|
xlog
目录下的 CMakeLists.txt
文件
1 2 3 4 5 6 7 8
| # 指定CMake版本号 cmake_minimum_required(VERSION 3.15)
# 指定项目名称 project(xlog)
# 编译生成静态库 add_library(xlog STATIC xlog.cpp xlog.h)
|
test_xlog
目录下的 test_xlog.cpp
源文件
1 2 3 4 5 6 7 8 9 10
| #include <iostream> #include "xlog.h"
using namespace std;
int main() { XLog log; cout << "test xlog" << endl; return 0; }
|
test_xlog
目录下的 CMakeLists.txt
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 指定CMake的版本号 cmake_minimum_required(VERSION 3.15)
# 指定项目名称 project(test_log)
# 指定头文件的搜索路径 include_directories("../xlog")
# 指定静态库的搜索路径 link_directories("../xlog/build")
# 编译生成可执行文件 add_executable(test_xlog test_xlog.cpp)
# 指定需要链接的静态库 target_link_libraries(test_xlog xlog)
|
1 2 3 4 5 6 7 8
| cd test_xlog
cmake -S . -B build
cmake --build build
|
系统平台 | 编译生成的可执行文件 |
---|
Windows | test_xlog.exe |
Linux | test_xlog |
MacOS | test_xlog |
CMake 编译与链接动态库
代码下载
完整的 CMake 案例代码可以从 这里 下载得到。
CMake 编译动态库
这里将演示如何使用 CMake 编译生成 C/C++ 项目的动态库。
1 2 3 4 5
| cmake_dylib ├── CMakeLists.txt └── xlog ├── xlog.cpp └── xlog.h
|
1 2 3 4 5 6 7 8 9 10 11
| #ifndef XLOG_H #define XLOG_H
class XLog {
public: XLog();
};
#endif
|
1 2 3 4 5 6 7 8
| #include <iostream> #include "xlog.h"
using namespace std;
XLog::XLog() { cout << "Create XLog Instance" << endl; }
|
cmake_dylib
目录下的 CMakeLists.txt
文件
1 2 3 4 5 6 7 8
| # 指定 CMake 的版本号 cmake_minimum_required(VERSION 3.15)
# 指定项目名称 project(xlog)
# 编译生成动态库 add_library(xlog SHARED xlog/xlog.cpp)
|
1 2 3 4 5 6 7 8
| cd cmake_dylib
cmake -S . -B build
cmake --build build
|
系统平台 | 编译生成的动态库文件 |
---|
Windows | xlog.lib, xlog.dll |
Linux | libxlog.so |
MacOS | libxlog.dylib |
CMake 链接动态库
通过上面的步骤使用 CMake 编译生成 C/C++ 项目的动态库后,这里将演示如何使用 CMake 链接 C/C++ 项目的动态库,最终编译生成可执行文件。
1 2 3 4 5 6 7
| cmake_dylib ├── CMakeLists.txt ├── test_xlog │ └── test_xlog.cpp └── xlog ├── xlog.cpp └── xlog.h
|
1 2 3 4 5 6 7 8 9 10 11
| #ifndef XLOG_H #define XLOG_H
class XLog {
public: XLog();
};
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #ifndef XLOG_H #define XLOG_H
#ifndef _WIN32 #define XCPP_API #else #ifdef xlog_EXPORTS #define XCPP_API __declspec(dllexport) #else #define XCPP_API __declspec(dllimport) #endif #endif
class XCPP_API XLog {
public: XLog();
};
#endif
|
test_xlog
目录下的 test_xlog.cpp
源文件
1 2 3 4 5 6 7 8 9 10
| #include <iostream> #include "xlog.h"
using namespace std;
int main() { XLog log; cout << "test xlog" << endl; return 0; }
|
cmake_dylib
目录下的 CMakeLists.txt
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 指定 CMake 的版本号 cmake_minimum_required(VERSION 3.15)
# 指定项目名称 project(xlog)
# 指定头文件的搜索路径 include_directories("xlog")
# 编译生成动态库,通常会自带预处理变量 xlog_EXPORTS add_library(xlog SHARED xlog/xlog.cpp)
# 编译生成可执行文件 add_executable(test_xlog test_xlog/test_xlog.cpp xlog)
# 指定需要链接的动态库 target_link_libraries(test_xlog xlog)
|
提示
CMake 在编译的时候,会将动态库的文件路径写死,如果需要使用相对路径,可以使用类似 -Wl, -rpath, /opt/mker/poco/lib
这样的参数来实现。
1 2 3 4 5 6 7 8
| cd cmake_dylib
cmake -S . -B build
cmake --build build
|
系统平台 | 编译生成的可执行文件 |
---|
Windows | test_xlog.exe |
Linux | test_xlog |
MacOS | test_xlog |