仓库里没有的版本号、需要打开某个特殊编译选项、官方只给了 tar.gz 源码包——碰到这些情况,就得走源码编译这条路。./configure、make、make install三步是主角,但每一步到底在干嘛、缺依赖报什么错、装完怎么卸载,这篇按真实流程走一遍。
一、什么时候才需要源码编译
包管理器能装就尽量别编译。源码编译适合这几种情况:
- 仓库版本太旧,软件要新版本;
- 需要打开仓库包没编进去的功能;
- 官方根本没出 .deb/.rpm,只给源码;
- 想把软件装到自定义路径。
代价是:编译完的软件,包管理器不认识,以后升级、卸载都得手动来。
二、整体流程一张图
下载源码包 → 解压 → ./configure → make → make install 校验依赖 生成Makefile 编译 安装到系统每一步都可能失败,定位问题时顺着这个顺序往上找。
三、第一步:下载并解压
以一个典型的 autoconf 项目为例:
wgethttps://example.com/app-1.2.0.tar.gztar-xzfapp-1.2.0.tar.gzcdapp-1.2.0解压后先看一眼 README 和 INSTALL 文件,作者写的编译说明往往比网上教程准。
四、第二步:./configure
它在干嘛
configure是一个 shell 脚本,跑一遍它会自动探测:编译器在哪、系统有没有 zlib、头文件路径对不对,最后根据探测结果生成Makefile。
常用选项
| 选项 | 作用 |
|---|---|
--prefix=路径 | 指定安装位置,默认/usr/local |
--enable-功能 | 打开某个功能 |
--disable-功能 | 关掉某个功能 |
--with-库=路径 | 指定依赖库位置 |
--help | 列出所有可用选项 |
示例与预期输出
./configure--prefix=/usr/local/app --enable-feature-xxx预期输出(节选):
checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes checking for gcc... gcc checking whether the C compiler works... yes checking for zlib.h... yes checking for library containing deflate... -lz configure: creating ./config.status config.status: creating Makefile跑到一半报configure: error: please install xxx,就是缺依赖。Ubuntu 上装编译依赖通常是sudo apt install build-essential,RHEL 系是sudo dnf groupinstall "Development Tools"。
五、第三步:make
它在干嘛
make读 Makefile,按依赖关系调用 gcc 把 .c 文件编成 .o,再链接成可执行文件。这一步不碰系统目录,失败了随便重来,不影响现有系统。
常用选项
| 选项 | 作用 |
|---|---|
make -j$(nproc) | 多核并行编译,速度快很多 |
make clean | 清空上次编译产物,重新编 |
示例与预期输出
make-j$(nproc)预期输出(节选):
CC src/main.o CC src/utils.o CC src/config.o LD app报gcc: command not found就是没装编译器;报某个.h: No such file or directory就是缺开发头文件,Ubuntu 上对应的包通常叫libxxx-dev,RHEL 上叫xxx-devel。
六、第四步:make install
它在干嘛
把编译好的可执行文件、库、配置文件拷到--prefix指定的目录。这一步要写系统目录,所以要 sudo。
示例与预期输出
sudomakeinstall预期输出(节选):
install -m 755 app /usr/local/app/bin/app install -m 644 conf/app.conf /usr/local/app/etc/ installing man page to /usr/local/app/share/man/man1装完后,可执行文件在/usr/local/app/bin/。如果敲app提示 command not found,是因为/usr/local/app/bin不在PATH里,要么用完整路径,要么把它加进/etc/profile.d/。
七、怎么卸载和清理
make install不会把文件登记进 dpkg/rpm 数据库,所以 apt、dnf 找不到它。卸载方式看项目:
- 回到源码目录跑
sudo make uninstall——多数项目支持; - 不支持的,就手动删
--prefix目录。这也是为什么前面强烈建议用--prefix指定独立路径,别用默认/usr,否则删的时候会和系统文件混在一起。
源码目录本身在编译完可以整个删掉,不影响已经 install 的文件。
八、知识扩展:为什么编译这么吃环境
很多人第一次编译卡在"缺这个头文件、缺那个库"上,原因是开发环境和运行环境是分开的。系统里装了zlib运行库(.so),不代表装了zlib开发包(头文件.h和链接文件)。运行库只够让现成软件跑起来,编译新软件必须有开发包。
Ubuntu 上命名规则是libxxx-dev,比如zlib1g-dev;RHEL 系是xxx-devel,比如zlib-devel。报错信息里出现zlib.h: No such file or directory,照着这个规则找包名基本不会错。
另外make -j$(nproc)里的nproc是当前 CPU 核数,并行编译能把编译时间从半小时压到几分钟。小机器上别写死-j8,4 核机器用-j$(nproc)才是通用写法。