autoconf 命令 #
autoconf
是 GNU 构建系统的一部分,用于生成自动配置脚本(通常命名为configure
),这些脚本可以自动检测系统特性并适应不同的平台环境,从而使软件包能够在各种 Unix 类系统上编译。
语法 #
autoconf [选项]... [模板文件]
如果没有指定模板文件,默认使用configure.ac
或旧式的configure.in
。
常用选项 #
选项 | 描述 |
---|---|
-h, --help |
显示帮助信息 |
-V, --version |
显示版本信息 |
-v, --verbose |
启用详细输出 |
-f, --force |
强制更新所有生成的文件 |
-W 类别 |
报告指定类别的警告 |
-B 目录 |
将目录添加到搜索路径的开头 |
-I 目录 |
将目录添加到搜索路径 |
-o 文件 |
将输出保存到指定文件而不是configure |
-t 文件 |
更新文件的时间戳 |
--include=目录 |
将目录添加到搜索路径(同-I) |
--prepend-include=目录 |
将目录添加到搜索路径的开头(同-B) |
--warnings=类别 |
报告指定类别的警告(同-W) |
--trace=宏 |
报告宏的使用情况 |
--initialization |
跟踪 autoconf 的初始化过程 |
基本用法 #
1. 生成配置脚本 #
autoconf
这将读取configure.ac
(或configure.in
)文件,并生成configure
脚本。
2. 使用详细输出 #
autoconf -v
3. 强制重新生成 #
autoconf -f
4. 指定输出文件 #
autoconf -o my-configure
5. 指定模板文件 #
autoconf my-configure.ac
configure.ac 基本结构 #
configure.ac
是 autoconf 的主要输入文件,包含了一系列宏调用,用于生成configure
脚本。以下是一个基本的configure.ac
文件结构:
# 初始化autoconf,指定包名称和版本
AC_INIT([mypackage], [1.0], [[email protected]])
# 检查基本程序
AC_PROG_CC
AC_PROG_INSTALL
# 检查头文件
AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
# 检查库函数
AC_CHECK_FUNCS([malloc strdup])
# 检查类型定义
AC_TYPE_SIZE_T
# 配置输出文件
AC_CONFIG_FILES([Makefile src/Makefile])
# 生成配置头文件
AC_CONFIG_HEADERS([config.h])
# 完成配置
AC_OUTPUT
常用宏 #
1. 初始化和设置 #
宏 | 描述 |
---|---|
AC_INIT(包名, 版本, 错误报告地址) |
初始化 autoconf |
AC_CONFIG_SRCDIR(唯一文件) |
指定源目录中的唯一文件,用于 sanity 检查 |
AC_CONFIG_HEADERS(文件) |
指定要生成的配置头文件 |
AC_CONFIG_FILES(文件...) |
指定要生成的文件列表 |
AC_CONFIG_AUX_DIR(目录) |
指定辅助构建工具的目录 |
AC_CONFIG_MACRO_DIR(目录) |
指定宏文件的目录 |
AC_PREREQ(版本) |
指定所需的 autoconf 最低版本 |
AC_CANONICAL_HOST |
确定主机系统类型 |
AC_CANONICAL_TARGET |
确定目标系统类型 |
AC_PREFIX_DEFAULT(前缀) |
设置默认安装前缀 |
AC_OUTPUT |
生成配置文件并结束配置脚本 |
2. 程序和工具检查 #
宏 | 描述 |
---|---|
AC_PROG_CC |
检查 C 编译器 |
AC_PROG_CXX |
检查 C++编译器 |
AC_PROG_F77 |
检查 Fortran 77 编译器 |
AC_PROG_FC |
检查 Fortran 编译器 |
AC_PROG_INSTALL |
检查 install 程序 |
AC_PROG_MAKE_SET |
检查 make 程序 |
AC_PROG_RANLIB |
检查 ranlib 程序 |
AC_PROG_AWK |
检查 awk 程序 |
AC_PROG_SED |
检查 sed 程序 |
AC_PROG_YACC |
检查 yacc 程序 |
AC_PROG_LEX |
检查 lex 程序 |
AC_CHECK_PROG(变量, 程序, 值-如果找到, 值-如果未找到, [路径]) |
检查特定程序 |
AC_PATH_PROG(变量, 程序, 值-如果未找到, [路径]) |
检查程序并返回完整路径 |
3. 库和函数检查 #
宏 | 描述 |
---|---|
AC_CHECK_LIB(库, 函数, [动作-如果找到], [动作-如果未找到]) |
检查库中的函数 |
AC_CHECK_FUNCS(函数列表, [动作-如果找到], [动作-如果未找到]) |
检查函数是否存在 |
AC_REPLACE_FUNCS(函数列表) |
检查函数,如果不存在则使用替代实现 |
AC_LIBOBJ(文件) |
添加文件到要编译的对象文件列表 |
AC_SEARCH_LIBS(函数, 库列表, [动作-如果找到], [动作-如果未找到]) |
在库列表中搜索函数 |
4. 头文件和结构检查 #
宏 | 描述 |
---|---|
AC_CHECK_HEADERS(头文件列表, [动作-如果找到], [动作-如果未找到]) |
检查头文件是否存在 |
AC_CHECK_HEADER(头文件, [动作-如果找到], [动作-如果未找到]) |
检查单个头文件 |
AC_HEADER_STDC |
检查 ANSI C 头文件 |
AC_STRUCT_TIMEZONE |
检查时区结构 |
AC_CHECK_MEMBERS([结构.成员], [动作-如果找到], [动作-如果未找到]) |
检查结构成员 |
5. 类型检查 #
宏 | 描述 |
---|---|
AC_TYPE_SIZE_T |
检查 size_t 类型 |
AC_TYPE_PID_T |
检查 pid_t 类型 |
AC_TYPE_OFF_T |
检查 off_t 类型 |
AC_TYPE_SIGNAL |
检查信号处理程序返回类型 |
AC_CHECK_TYPES(类型列表, [动作-如果找到], [动作-如果未找到]) |
检查类型是否存在 |
AC_CHECK_SIZEOF(类型, [默认]) |
检查类型的大小 |
6. 系统特性检查 #
宏 | 描述 |
---|---|
AC_SYS_LARGEFILE |
检查大文件支持 |
AC_FUNC_ALLOCA |
检查 alloca 函数 |
AC_FUNC_MALLOC |
检查 malloc 函数 |
AC_FUNC_REALLOC |
检查 realloc 函数 |
AC_FUNC_MMAP |
检查 mmap 函数 |
AC_CHECK_DECLS(符号列表, [动作-如果声明], [动作-如果未声明]) |
检查符号是否已声明 |
7. 输出和消息 #
宏 | 描述 |
---|---|
AC_MSG_CHECKING(特性描述) |
打印正在检查特性的消息 |
AC_MSG_RESULT(结果) |
打印检查结果 |
AC_MSG_NOTICE(消息) |
打印通知消息 |
AC_MSG_ERROR(错误消息, [退出状态=1]) |
打印错误消息并退出 |
AC_MSG_WARN(警告消息) |
打印警告消息 |
AC_MSG_FAILURE(错误消息, [退出状态=1]) |
打印错误消息并退出 |
8. 变量和条件 #
宏 | 描述 |
---|---|
AC_DEFINE(变量, 值, [描述]) |
定义 C 预处理器宏 |
AC_DEFINE_UNQUOTED(变量, 值, [描述]) |
定义 C 预处理器宏,展开 shell 变量 |
AC_SUBST(变量, [值]) |
替换输出文件中的变量 |
AC_ARG_ENABLE(特性, 帮助字符串, [动作-如果给定], [动作-如果未给定]) |
添加–enable-特性选项 |
AC_ARG_WITH(包, 帮助字符串, [动作-如果给定], [动作-如果未给定]) |
添加–with-包选项 |
AS_IF(测试1, [动作1], [测试2], [动作2], ..., [否则动作]) |
条件执行 |
AS_CASE(字符串, [模式1], [动作1], ..., [默认动作]) |
基于模式匹配执行动作 |
高级用法 #
1. 自定义宏 #
可以在aclocal.m4
文件或m4
目录中定义自定义宏:
# 定义检查特定库版本的宏
AC_DEFUN([MY_CHECK_LIB_VERSION],
[
AC_MSG_CHECKING([for $1 version >= $2])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <$1.h>]],
[[#if $1_VERSION < $2
#error Version too old
#endif
]])],
[
AC_MSG_RESULT([yes])
$3
],
[
AC_MSG_RESULT([no])
$4
])
])
2. 条件配置 #
# 添加--enable-debug选项
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug], [enable debug mode])],
[], [enable_debug=no])
# 根据选项设置编译标志
AS_IF([test "x$enable_debug" = xyes],
[CFLAGS="$CFLAGS -g -O0 -DDEBUG"],
[CFLAGS="$CFLAGS -O2"])
3. 检查外部包 #
# 添加--with-zlib选项
AC_ARG_WITH([zlib],
[AS_HELP_STRING([--with-zlib=DIR], [use zlib in DIR])],
[], [with_zlib=yes])
# 检查zlib
AS_IF([test "x$with_zlib" != xno],
[
AS_IF([test "x$with_zlib" != xyes],
[
CPPFLAGS="$CPPFLAGS -I$with_zlib/include"
LDFLAGS="$LDFLAGS -L$with_zlib/lib"
])
AC_CHECK_HEADERS([zlib.h], [], [AC_MSG_ERROR([zlib.h not found])])
AC_CHECK_LIB([z], [inflate], [], [AC_MSG_ERROR([zlib not found])])
])
4. 生成多个输出文件 #
# 配置多个输出文件
AC_CONFIG_FILES([
Makefile
src/Makefile
doc/Makefile
tests/Makefile
])
5. 使用 autoheader 生成配置头文件 #
# 在configure.ac中
AC_CONFIG_HEADERS([config.h])
# 定义配置选项
AC_DEFINE([HAVE_FEATURE], [1], [Define if feature is available])
然后运行:
autoheader
autoconf
6. 使用 autoscan 生成 configure.ac 模板 #
autoscan
这将生成configure.scan
文件,可以将其重命名为configure.ac
并进行编辑。
完整构建系统示例 #
1. 目录结构 #
project/
├── configure.ac
├── Makefile.am
├── src/
│ ├── Makefile.am
│ ├── main.c
│ └── utils.c
└── include/
└── utils.h
2. configure.ac #
# 初始化autoconf
AC_INIT([myproject], [1.0], [[email protected]])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
# 初始化automake
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
# 检查程序
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_MAKE_SET
# 检查库和头文件
AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
AC_CHECK_FUNCS([malloc strdup])
AC_CHECK_LIB([m], [sqrt])
# 添加选项
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug], [enable debug mode])],
[], [enable_debug=no])
AS_IF([test "x$enable_debug" = xyes],
[CFLAGS="$CFLAGS -g -O0 -DDEBUG"],
[CFLAGS="$CFLAGS -O2"])
# 配置输出文件
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
src/Makefile
])
# 完成配置
AC_OUTPUT
3. Makefile.am(顶层) #
SUBDIRS = src
dist_doc_DATA = README.md
4. src/Makefile.am #
bin_PROGRAMS = myprogram
myprogram_SOURCES = main.c utils.c
myprogram_CPPFLAGS = -I$(top_srcdir)/include
5. 构建步骤 #
# 生成aclocal.m4
aclocal
# 生成config.h.in
autoheader
# 生成configure脚本
autoconf
# 生成Makefile.in文件
automake --add-missing
# 配置项目
./configure
# 构建项目
make
# 安装项目
make install
实用示例 #
1. 检查特定版本的编译器 #
AC_PREREQ([2.69])
AC_INIT([myproject], [1.0])
# 检查C编译器
AC_PROG_CC
AC_LANG([C])
# 检查GCC版本
AS_IF([test "x$GCC" = xyes],
[
AC_MSG_CHECKING([if GCC version is >= 4.8])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#error GCC version is too old
#endif
]],
[[]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
AC_MSG_ERROR([GCC version must be at least 4.8])
])
])
AC_OUTPUT
2. 检查系统特性并适配代码 #
AC_INIT([myproject], [1.0])
AC_CONFIG_HEADERS([config.h])
# 检查大小端
AC_C_BIGENDIAN(
[AC_DEFINE([IS_BIG_ENDIAN], [1], [Define if system is big endian])],
[AC_DEFINE([IS_LITTLE_ENDIAN], [1], [Define if system is little endian])])
# 检查类型大小
AC_CHECK_SIZEOF([int])
AC_CHECK_SIZEOF([long])
AC_CHECK_SIZEOF([void *])
# 检查特定函数
AC_CHECK_FUNCS([mmap posix_memalign])
AC_OUTPUT
3. 配置可选功能 #
AC_INIT([myproject], [1.0])
AC_CONFIG_HEADERS([config.h])
# 添加可选功能
AC_ARG_ENABLE([feature1],
[AS_HELP_STRING([--enable-feature1], [enable feature1 support])],
[], [enable_feature1=no])
AC_ARG_ENABLE([feature2],
[AS_HELP_STRING([--enable-feature2], [enable feature2 support])],
[], [enable_feature2=no])
# 根据选项配置
AS_IF([test "x$enable_feature1" = xyes],
[AC_DEFINE([HAVE_FEATURE1], [1], [Define if feature1 is enabled])])
AS_IF([test "x$enable_feature2" = xyes],
[
# 检查feature2所需的库
AC_CHECK_LIB([feature2], [feature2_func], [],
[AC_MSG_ERROR([feature2 requested but library not found])])
AC_DEFINE([HAVE_FEATURE2], [1], [Define if feature2 is enabled])
])
AC_OUTPUT
4. 跨平台配置 #
AC_INIT([myproject], [1.0])
AC_CONFIG_HEADERS([config.h])
# 检查系统类型
AC_CANONICAL_HOST
# 根据系统类型配置
case $host_os in
linux*)
AC_DEFINE([OS_LINUX], [1], [Define if on Linux])
;;
darwin*)
AC_DEFINE([OS_MACOS], [1], [Define if on macOS])
;;
mingw*|cygwin*|msys*)
AC_DEFINE([OS_WINDOWS], [1], [Define if on Windows])
;;
*)
AC_MSG_WARN([Unsupported operating system: $host_os])
;;
esac
AC_OUTPUT
5. 检查外部依赖 #
AC_INIT([myproject], [1.0])
AC_CONFIG_HEADERS([config.h])
# 检查pkg-config
PKG_PROG_PKG_CONFIG
# 检查libpng
PKG_CHECK_MODULES([PNG], [libpng >= 1.6.0],
[
AC_DEFINE([HAVE_LIBPNG], [1], [Define if libpng is available])
],
[
AC_MSG_WARN([libpng not found, PNG support will be disabled])
])
# 将标志添加到Makefile
AC_SUBST([PNG_CFLAGS])
AC_SUBST([PNG_LIBS])
AC_OUTPUT
常见问题排查 #
1. 找不到宏 #
错误:
configure.ac:10: error: possibly undefined macro: AM_INIT_AUTOMAKE
解决方案:
# 添加automake宏
AC_CONFIG_MACRO_DIR([m4])
# 确保运行aclocal时包含正确的目录
2. 缺少文件 #
错误:
configure: error: cannot find install-sh, install.sh, or shtool in build-aux "."/build-aux
解决方案:
# 指定辅助目录
AC_CONFIG_AUX_DIR([build-aux])
# 运行automake --add-missing来创建缺少的文件
3. 版本不兼容 #
错误:
warning: The macro `AC_HELP_STRING' is obsolete.
解决方案:
# 使用新的宏
# 旧: AC_HELP_STRING([--enable-feature], [description])
# 新: AS_HELP_STRING([--enable-feature], [description])
4. 缺少 m4 目录 #
错误:
configure.ac:8: warning: cannot find macro directory 'm4'
解决方案:
# 创建m4目录
mkdir -p m4
与其他自动化构建工具的比较 #
工具 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
autoconf | 广泛支持、成熟、强大的系统检测 | 语法复杂、学习曲线陡峭 | 需要广泛兼容性的 Unix/Linux 项目 |
CMake | 跨平台、现代语法、IDE 支持 | 不如 autoconf 在 Unix 系统上灵活 | 跨平台项目、需要 IDE 集成 |
Meson | 快速、简单、现代 | 相对较新、不如 autoconf 成熟 | 新项目、注重构建速度 |
SCons | Python 语法、灵活 | 构建速度较慢 | Python 项目、需要高度定制的构建系统 |
提示和技巧 #
1. 使用 autoreconf 简化流程 #
# 一步完成所有autotools步骤
autoreconf -i
2. 使用宏包 #
# 在configure.ac中
# 使用gettext宏
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.19])
# 使用libtool宏
LT_INIT
3. 调试 configure 脚本 #
# 运行configure时启用shell调试
sh -x ./configure
4. 使用 config.site 文件 #
创建~/.config.site
文件来设置默认选项:
# 默认启用调试
enable_debug=yes
# 默认安装前缀
prefix=/opt/local
5. 使用 AC_CONFIG_COMMANDS 执行自定义命令 #
AC_CONFIG_COMMANDS([stamp-h], [date > stamp-h])