大白编译——autotools与cmake
发布于2025-07-20 01:58:56,更新于2025-07-20 23:49:39,标签:devops 文章会持续修订,转载请注明来源地址:https://meethigher.top/blog之前记录了通过autotools编译rpm包与deb包的步骤。参考小白编译——rpm包与deb包 - 言成言成啊
一、跨平台编译
1.1 背景
本节参考
- Autotools Tutorial
- Using GNU Autotools:强烈建议亲自阅读一遍,可以借助AI学习
1.1.1 跨平台困扰
在C中,头文件(.h)只负责“声明”,具体的实现放到“库文件”里。不同系统“库文件”示例如下
- 静态库
- Linux: libc.a
- Windows: format.lib
- 动态库
- Linux: libc.so
- Windows: msvcrt.dll
C语言跨平台时不兼容的主要来源
- 函数不存在
- 如
strtod()
,为C标准库函数,但是老版libc
根本没有对应实现
- 如
- 函数有不同的名字
strchr()
vsindex()
,strchr()
为C标准库函数,但是在老版libc
只有index()
,两者作用相同。
- 原型差异
- 老系统只有
int setpgrp(void)
,新系统只有int setpgrp(int,int)
。
- 老系统只有
- 行为差异
malloc(0)
返回值不确定。
- 所在库不同
pow()
的实现可能在libm.so
或libc.so
。
- 头文件差异
- 历史原因,有些系统会针对头文件进行补充,导致其他平台没有。
1.1.2 解决办法
如何实现一个可移植的软件包?让同一份源代码能在不同系统上无修改地编译、运行。
三种应对办法
- 大量
#if/#else
→ 代码凌乱,不推荐。 - 替换宏(
#define fseeko ...
)→ 推荐。 - 替换函数(提供缺失函数的兼容实现)→ 推荐。
替换宏示例,来自 coreutils-5.2.1
的 system.h
。
1 |
|
开发者不关心系统是否提供,放心使用fseeko
替换函数示例,来自GNU C library
,即libc.so
1 | char *strdup(const char *s) { |
此处多插一嘴。Golang标准库如何实现零运行时依赖的可执行程序的?
答:每个可执行文件都包含了完整的运行时库和标准库
1.1.3 autotools由来
1991 年起,人们开始写 shell 脚本自动探测系统特征。这就是 autotools
中的configure
脚本的由来。它主要负责
- 检测系统是否具备所需的库、函数、工具
- 根据开发者写的检测指令,生成
config.h
。比如开发者要检测AC_CHECK_FUNCS([strdup])
,那么config.h
检测到存在,会写入#define HAVE_STRDUP 1
- 生成适合本系统的 Makefile
configure
是Autotools
的一部分,Autotools
还涉及到两个工具Autoconf
和Automake
Autoconf
- 用于从开发者编写的
configure.ac
文件生成configure
脚本。
- 用于从开发者编写的
Automake
- 用于从开发者编写的
Makefile.am
文件生成Makefile.in
文件。Makefile.in
文件是configure
脚本的输入,用于生成最终的Makefile
。
- 用于从开发者编写的
不过在实际使用中,一行autoreconf -fi
即包含了Autoconf
和Automake
的两个操作。Autotools
整体流程如下图
对于用户来说,只需记住三板斧:./configure && make && make install
1.2 autotools与cmake对比
autotools(经典老兵)与cmake(新一代工具链)的优劣对比
- autotools
- 优点:轻量,在Linux上零依赖运行,只要
/bin/sh
+make
- 缺点:跨平台编译体验不好。比如在
Windows
上编译。
- 优点:轻量,在Linux上零依赖运行,只要
- cmake:使用
c++
重新实现了整套逻辑,不依赖shell
- 优点:跨平台体验更佳。用户在多个平台,使用一套命令即可完成编译。
- 缺点:需要安装
CMake
二、编译实战
下面以两个示例,记录使用autotools
和cmake
进行编译的过程。
我有一个源码文件main.c,需要将其编译成Linux可执行程序。
1 | // src/main.c |
autotools与cmake的源码(meethigher/autotools-vs-cmake: 以一个入门级程序,简单比较autotools与cmake两者的编译区别)结构如下,
1 | ├─hello-autotools |
分别使用两种工具在Debian12
上面进行编译。
参考
2.1 autotools
安装预置的编译环境
1 | apt -y install autoconf make gcc |
进入到项目中进行编译
1 | # 生成 configure |
2.2 cmake
安装预置的编译环境
1 | apt -y install cmake gcc |
进入到项目中进行编译
1 | # 将编译的内容全部放置到gaga目录。 |