Compile&Link

编译和链接

起因

最近使用到一个简易RPC库,依赖项只有消息队列ZeroMQ,对应库名字是zmq

目录结构如下

├── buttonrpc.hpp
├── CMakeLists.txt
├── example
│   ├── main_client.cpp
│   └── main_server.cpp
├── README.md
└── Serializer.hpp

在自定义的头文件中buttonrpc.hpp中用到了zmq库,我使用apt下载下来。

其中CMakeLists.txt文件内容如下

cmake_minimum_required(VERSION 3.23)
project(buttonrpc_cpp14)
set(CMAKE_CXX_STANDARD 14)
include_directories(.) //添加头文件的查找路径,这样example目录下的cpp可以直接引入头文件而非完整路径。

add_executable(buttonrpc_cpp14 example/main_client.cpp)

CMakeLists.txt的配置是没问题的,但使用CLionIDE编译运行时出现如下链接错误。

/usr/bin/ld: CMakeFiles/buttonrpc_cpp14.dir/example/main_client.cpp.o: in function `zmq::error_t::error_t()':
/usr/include/zmq.hpp:292: undefined reference to `zmq_errno'

在次这前,我一直以为是只要引入头文件即可使用其内容。

然而事实是,需要链接。

知识梳理

编译链接生成可执行文件实际需要四个步骤,以及他们对应的g++命令

  • 预处理(pre-process)g++ -E Preprocess only; do not compile, assemble or link.
  • 编译 (Compile)g++ -S Compile only; do not assemble or link.
  • 汇编(assemble)g++ -c Compile and assemble, but do not link.
  • 链接 (link)g++ -l Place the output into file.

他们处理之后的文件后缀分别为

  • g++ -E main.cpp > main.i 预处理后的文件 linux下以.i为后缀名,这个过程只激活预处理,不生成文件,因此你需要把它重定向到一个输出文件里 。
  • g++ -S main.cpp 生成main.s汇编文件。
  • g++ -c main.cpp生成main.o含机器指令的目标文件。
  • g++ main.o 链接相关文件并生成 a.out (可使用-o指定文件名字)可执行文件。

一般,直接使用g++ -c编译所有文件,然后使用g++ -o进行链接。

如果需要链接一些第三方库,需要g++ -o -l -l后面接库名。

实际上,C++标准库也是需要链接的,g++会默认链接它们,无须显式链接。

静态库和动态库

静态库

命名规则:

  • Linux:libxxx.a
  • window: libxxx.lib

制作:

gcc -c file1.c file2.c
ar rcs libxxx.a file1.o file2.o

动态库

命名规则:

  • Linux:libxxx.so
  • windows: libxxx.dll

制作

gcc -c -fpic file1.c file2.c
gcc -shared file1.o file2.o -o - libxxx.so

编译后需要修改文件或环境变量。

工作原理

  • 静态库工作gcc链接时会把静态库中的代码打包到可执行文件中。
  • 动态库gcc链接时,动态库的代码不会被打包到可执行文件中。
    • 当程序启动后,动态库会被动态加载到内存中,通过ldd file命令检查动态库依赖关系
    • 系统的动态载入器获取依赖库的绝对路径。对于elf格式的可执行程序,是由ld_linux.so来完成。
    • 先后检查文件的DT_RPATHH - > LD_LIBRARY_PATH->etc/ld.so.cache文件列表->lib->/usr/lib目录后载入内存

对比

静态 动态
优点 打包、加载速度快、打包无需提供静态库、移植方便 可以实现进程中资源共享、更新、部署、发布简单
缺点 消耗系统资源,浪费内存。更新、部署、发布麻烦 加载速度慢、发布程序时需要提供依赖的动态库

Compile&Link
https://messenger1th.github.io/2024/07/24/Articles/Compile&Link/
作者
Epoch
发布于
2024年7月24日
许可协议