Makefile.am的例子
Makefile.am 的例子
这篇用“能直接抄走改”的方式,整理 Automake 常见写法。
如果你已经会写 Makefile,这篇重点是:如何把规则写进 Makefile.am,再由 Autotools 生成可移植构建系统。
1. 先理解三层关系
configure.ac:定义项目配置逻辑(检测依赖、生成哪些 Makefile)。Makefile.am:声明各目录编译/安装规则。configure + make:生成Makefile.in/Makefile后执行构建。
一句话:configure.ac 管“配置”,Makefile.am 管“目标与安装”。
2. 最小项目结构示例
1 | myapp/ |
顶层 configure.ac:
1 | AC_INIT([myapp], [1.0.0], [you@example.com]) |
顶层 Makefile.am:
1 | SUBDIRS = src |
src/Makefile.am:
1 | bin_PROGRAMS = myapp |
3. 常见变量命名规则(最重要)
Automake 大量语义都在变量名里:
bin_PROGRAMS:安装到$(bindir)的可执行文件。lib_LTLIBRARIES:安装到$(libdir)的 libtool 库。noinst_LIBRARIES:仅构建,不安装。*_SOURCES:目标的源码列表。*_CPPFLAGS / *_CFLAGS / *_LDFLAGS:目标级编译/链接参数。
示例:
1 | bin_PROGRAMS = appctl |
4. 安装脚本、配置文件、数据文件
很多人把 mkdir/cp 写在 SPEC %install,更推荐先在 Makefile.am 描述好。
4.1. 安装脚本
1 | scriptdir = $(libexecdir)/myapp/scripts |
4.2. 安装配置/数据
1 | myconfdir = $(sysconfdir)/myapp |
说明:
dist_:文件已存在于源码树,且会进入make dist包。nodist_:文件构建时生成,不在源码树静态存在。
5. 生成文件用 nodist_(很常见)
例如模板 version.h.in 在构建时生成 version.h:
1 | BUILT_SOURCES = version.h |
6. 多目录构建与顺序
顶层用 SUBDIRS 控制构建顺序:
1 | SUBDIRS = lib src tools |
如果是条件构建:
1 | if BUILD_TESTS |
对应条件通常在 configure.ac 用 AM_CONDITIONAL 定义。
7. 单元测试与 make check
推荐把测试接入 Automake 标准入口:
1 | check_PROGRAMS = test_core |
这样可以统一执行:
1 | make check |
8. 自定义目标与 .PHONY
Makefile.am 里也可以加自定义命令:
1 |
|
用 .PHONY 避免和同名文件冲突。
9. 一个“中型项目”片段示例
1 | ACLOCAL_AMFLAGS = -I m4 |
这个片段对应你原文里的典型场景:
- 多目录编译。
- 安装 service/script/pkgconfig。
- 用条件开关控制 tests。
10. 与 SPEC 配合的建议
当 Makefile.am 写好安装规则后,SPEC %install 可简化为:
1 | %install |
SPEC %files 只需声明安装结果路径,不再手工 cp 文件,维护成本会低很多。
11. 常见坑
- 变量名拼错后缀(如把
_DATA写成_DATAS)。 - 忘记把生成文件放到
BUILT_SOURCES,并行编译时容易失败。 SUBDIRS顺序不对导致依赖库先后错误。- 脚本放错变量(
SCRIPTSvsDATA)造成权限不符合预期。
12. 我的建议
- 安装语义尽量前移到
Makefile.am,不要堆在 SPEC 里。 - 先写最小可运行目录,再增量拆分子目录和条件编译。
- 每次改规则都跑一遍:
autoreconf -fi && ./configure && make && make install DESTDIR=/tmp/pkgroot。
这样可以尽早验证“构建成功”与“安装路径正确”是不是同时成立。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 因受!
评论