目录
- 工具简介
- 主要功能
- 使用场景
- 基本使用方法
- [OpenHarmony 适配过程](#OpenHarmony 适配过程)
- 遇到的问题及解决方案
- [问题 1: Makefile 不存在](#问题 1: Makefile 不存在)
- [问题 2: 变量名错误](#问题 2: 变量名错误)
- [问题 3: bootstrap 失败 - m4 版本太旧](#问题 3: bootstrap 失败 - m4 版本太旧)
- [问题 4: configure 时 m4 版本检查失败](#问题 4: configure 时 m4 版本检查失败)
- [问题 5: 缺少 makeinfo 工具](#问题 5: 缺少 makeinfo 工具)
- [问题 6: 缺少 help2man 工具](#问题 6: 缺少 help2man 工具)
- 构建脚本详解
- 验证和测试
- 总结
工具简介
GNU Autoconf 是一个可扩展的 M4 宏包,用于生成 shell 脚本来自动配置软件源代码包。这些脚本可以在无需手动干预的情况下,使软件包适应多种类 Unix 系统。
基本信息
- 项目名称: GNU Autoconf
- 版本: 2.72 (开发快照)
- 官方网站: https://www.gnu.org/software/autoconf/
- 许可证: GPL v3+ (带例外条款)
- 构建系统: Autotools (autoconf/automake)
- 编程语言: Perl, Shell, M4
设计理念
Autoconf 从模板文件创建配置脚本,模板文件以 M4 宏调用的形式列出软件包可以使用的操作系统特性。Autoconf 的目标是:
- 可移植性:生成的 configure 脚本可以在多种 Unix 系统上工作
- 自动化:自动检测系统特性和功能
- 自包含:生成的 configure 脚本是自包含的,用户不需要安装 Autoconf
- 可扩展性:通过 M4 宏系统可以轻松扩展功能
核心组件
Autoconf 包含以下主要工具:
- autoconf :从
configure.ac生成configure脚本 - autoheader :生成
config.h.in模板文件 - autom4te:M4 宏处理器,autoconf 的核心引擎
- autoreconf:自动运行 autoconf、autoheader、automake 等工具
- autoscan :扫描源代码,生成初始的
configure.ac - autoupdate :更新旧的
configure.ac到新版本 - ifnames:列出 C/C++ 源代码中使用的预处理器符号
主要功能
Autoconf 的主要功能包括:
- 配置脚本生成 :从
configure.ac生成可移植的configure脚本 - 系统特性检测:自动检测编译器、库、头文件、函数等系统特性
- 条件编译支持 :生成
config.h文件,支持条件编译 - 交叉编译支持:支持交叉编译到不同平台
- 宏系统:提供丰富的 M4 宏库,用于检测各种系统特性
- 版本管理:支持软件包版本管理和依赖检查
- 安装路径配置:支持灵活的安装路径配置
- 功能开关 :支持
--enable-*和--disable-*选项
工作流程
configure.ac (M4 宏)
↓
autoconf (M4 处理器)
↓
configure (Shell 脚本)
↓
./configure (运行)
↓
config.h, Makefile (生成)
使用场景
Autoconf 在以下场景中特别有用:
- GNU 软件包开发:符合 GNU 编码标准的软件包
- 跨平台项目:需要在多种 Unix 系统上构建的项目
- 开源项目:需要标准化的配置和构建流程的项目
- 复杂依赖管理:需要检测和配置复杂依赖关系的项目
- 构建系统现代化:将旧的手写配置脚本迁移到现代构建系统
基本使用方法
典型工作流程
bash
# 1. 从源代码仓库检出(如果是开发版本)
git clone https://git.savannah.gnu.org/git/autoconf.git
cd autoconf
# 2. 生成 configure 脚本(开发版本需要)
./bootstrap
# 或者使用 autoreconf
autoreconf -i
# 3. 配置构建环境
./configure --prefix=/usr/local
# 4. 编译
make
# 5. 运行测试(可选)
make check
# 6. 安装
make install
基本命令
bash
# 生成 configure 脚本
autoconf
# 生成 config.h.in
autoheader
# 自动运行所有需要的工具
autoreconf -i
# 扫描源代码生成初始 configure.ac
autoscan
# 更新旧的 configure.ac
autoupdate
# 查看帮助
autoconf --help
在项目中使用 Autoconf
- 创建
configure.ac:定义项目配置和系统检测 - 运行
autoconf:生成configure脚本 - 运行
autoheader:生成config.h.in(可选) - 运行
./configure:配置项目,生成config.h和Makefile - 运行
make:编译项目
OpenHarmony 适配过程
项目结构
autoconf/
├── bootstrap # 引导脚本(生成 configure)
├── configure.ac # Autoconf 配置文件
├── Makefile.am # Automake 输入文件
├── bin/ # 二进制文件目录
│ ├── autoconf.in # autoconf Perl 脚本模板
│ ├── autoheader.in # autoheader Perl 脚本模板
│ ├── autom4te.in # autom4te Perl 脚本模板
│ ├── autoreconf.in # autoreconf Perl 脚本模板
│ ├── autoscan.in # autoscan Perl 脚本模板
│ ├── autoupdate.in # autoupdate Perl 脚本模板
│ └── ifnames.in # ifnames Perl 脚本模板
├── lib/ # 库文件目录
│ ├── autoconf/ # Autoconf M4 宏文件
│ ├── Autom4te/ # Autom4te Perl 模块
│ └── m4sugar/ # M4sugar 宏库
├── doc/ # 文档目录
│ ├── autoconf.texi # Texinfo 文档源
│ └── standards.texi # GNU 编码标准文档
├── man/ # Man 页面模板
├── tests/ # 测试套件
├── build_ohos.sh # OpenHarmony 构建脚本
└── hnp.json # HNP 配置文件
构建系统
Autoconf 使用 Autotools 构建系统:
- bootstrap 或 autoreconf :生成
configure脚本(开发版本) - configure :配置构建环境,生成
Makefile - make:编译源代码和生成工具
- make install:安装到指定目录
适配步骤
1. 创建构建脚本
创建 build_ohos.sh 脚本,配置 OpenHarmony 交叉编译环境:
bash
#!/bin/bash
# ============================================================================
# build_ohos.sh - autoconf HarmonyOS 构建脚本
# ============================================================================
# autoconf 使用 autotools 构建系统
# ============================================================================
export AUTOCONF_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/autoconf.org/autoconf_1.0.0
sys_prefix=${PREFIX}
export PREFIX=${AUTOCONF_INSTALL_HNP_PATH}
2. 生成 configure 脚本
检查并生成 configure 脚本(如果不存在):
bash
# 优先尝试 autoreconf(不检查 m4 版本)
if [ -f "configure.ac" ] && command -v autoreconf >/dev/null 2>&1; then
echo "Using autoreconf to generate configure script..."
autoreconf -i
elif [ -f "bootstrap" ]; then
./bootstrap
fi
3. 查找并使用更新的 m4
Autoconf 需要 GNU M4 1.4.8 或更高版本(推荐 1.4.16+)。如果系统 m4 版本太旧,需要查找并使用更新的版本:
bash
# 查找 Homebrew 安装的 m4
if [ -f "/opt/homebrew/Cellar/m4/1.4.20/bin/m4" ]; then
export PATH="/opt/homebrew/Cellar/m4/1.4.20/bin:${PATH}"
fi
4. 运行 configure
配置构建环境,使用 aarch64-linux-gnu 作为 host:
bash
./configure \
--prefix=${AUTOCONF_INSTALL_HNP_PATH} \
--host=aarch64-linux-gnu \
--enable-static \
--disable-shared \
CC="${CC}" \
CXX="${CXX}" \
CFLAGS="${CFLAGS}" \
CXXFLAGS="${CXXFLAGS}" \
LDFLAGS="${LDFLAGS}"
遇到的问题及解决方案
问题 1: Makefile 不存在
错误现象
There seems to be no Makefile in this directory.
You must run ./configure before running 'make'.
make: *** [abort-due-to-no-makefile] Error 1
问题分析
Autoconf 使用 Autotools 构建系统,需要先运行 configure 脚本生成 Makefile。如果 configure 脚本不存在,还需要先运行 bootstrap 或 autoreconf 生成它。
解决方案
在构建脚本中添加生成 configure 脚本的逻辑:
bash
# 生成 configure 脚本(如果不存在)
if [ ! -f "configure" ]; then
# 优先尝试 autoreconf(不检查 m4 版本)
if [ -f "configure.ac" ] && command -v autoreconf >/dev/null 2>&1; then
echo "Using autoreconf to generate configure script..."
autoreconf -i || {
echo "Warning: autoreconf failed, trying bootstrap..."
if [ -f "bootstrap" ]; then
./bootstrap || {
echo "Error: bootstrap failed"
exit 1
}
fi
}
elif [ -f "bootstrap" ]; then
./bootstrap || {
echo "Error: bootstrap failed"
exit 1
}
fi
fi
问题 2: 变量名错误
错误现象
cp: /hnp.json: Read-only file system
realpath unsuccess. path=-o
source dir path=-o is invalid.
tar: autoconf_1.0.0: Cannot stat: No such file or directory
问题分析
构建脚本中使用了错误的变量名 TREE_INSTALL_HNP_PATH,应该使用 AUTOCONF_INSTALL_HNP_PATH。同时缺少创建安装目录的步骤。
解决方案
- 修正变量名 :将所有
TREE_INSTALL_HNP_PATH改为AUTOCONF_INSTALL_HNP_PATH - 创建安装目录:在 configure 之前创建安装目录
bash
# 创建安装目录
mkdir -p ${AUTOCONF_INSTALL_HNP_PATH} || {
echo "Error: Failed to create installation directory"
exit 1
}
问题 3: bootstrap 失败 - m4 版本太旧
错误现象
bootstrap: m4 (GNU M4 1.4.6) is too old
Error: bootstrap failed
问题分析
系统的 m4 版本(1.4.6)太旧,而 autoconf 的 bootstrap 脚本需要 GNU M4 1.4.8 或更高版本(推荐 1.4.16+)。bootstrap 脚本在运行时会检查 m4 版本。
解决方案
优先使用 autoreconf 而不是 bootstrap,因为 autoreconf 不检查 m4 版本:
bash
# 优先尝试 autoreconf(不检查 m4 版本)
if [ -f "configure.ac" ] && command -v autoreconf >/dev/null 2>&1; then
echo "Using autoreconf to generate configure script..."
autoreconf -i || {
echo "Warning: autoreconf failed, trying bootstrap..."
# 如果 autoreconf 失败,再尝试 bootstrap
if [ -f "bootstrap" ]; then
./bootstrap || {
echo "Error: bootstrap failed"
echo "Note: bootstrap requires GNU M4 1.4.8 or later (recommended 1.4.16+)"
echo "Current m4 version: $(m4 --version 2>&1 | head -1)"
echo "Please install a newer version of m4 or use autoreconf"
exit 1
}
fi
}
关键点:
autoreconf不检查 m4 版本,可以避免版本检查问题- 如果
autoreconf失败,再尝试bootstrap作为后备方案 - 提供清晰的错误信息,指导用户安装更新的 m4
问题 4: configure 时 m4 版本检查失败
错误现象
checking for GNU M4 that supports accurate traces... configure: error: no acceptable m4 could be found in $PATH.
GNU M4 1.4.8 or later is required; 1.4.16 or newer is recommended.
问题分析
configure 脚本在运行时检查 m4 版本,发现系统的 m4(1.4.6)不满足要求。虽然 autoreconf 可以生成 configure 脚本,但运行 configure 时仍然需要满足版本要求的 m4。
解决方案
在运行 configure 之前,查找并使用更新的 m4(如 Homebrew 安装的版本):
bash
# 查找并使用更新的 m4(如果可用)
# Homebrew 安装的 m4 通常是 keg-only,需要手动添加到 PATH
M4_PATH=""
if [ -f "/opt/homebrew/Cellar/m4/1.4.20/bin/m4" ]; then
M4_PATH="/opt/homebrew/Cellar/m4/1.4.20/bin"
elif [ -f "/opt/homebrew/opt/m4/bin/m4" ]; then
M4_PATH="/opt/homebrew/opt/m4/bin"
elif command -v m4 >/dev/null 2>&1; then
M4_VERSION=$(m4 --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [ -n "$M4_VERSION" ]; then
# 检查版本是否 >= 1.4.8
MAJOR=$(echo "$M4_VERSION" | cut -d. -f1)
MINOR=$(echo "$M4_VERSION" | cut -d. -f2)
PATCH=$(echo "$M4_VERSION" | cut -d. -f3)
if [ "$MAJOR" -gt 1 ] || ([ "$MAJOR" -eq 1 ] && [ "$MINOR" -gt 4 ]) || ([ "$MAJOR" -eq 1 ] && [ "$MINOR" -eq 4 ] && [ "$PATCH" -ge 8 ]); then
M4_PATH="$(dirname $(command -v m4))"
fi
fi
fi
# 如果找到更新的 m4,添加到 PATH
if [ -n "$M4_PATH" ]; then
export PATH="${M4_PATH}:${PATH}"
echo "Using m4 from: ${M4_PATH}"
m4 --version | head -1
fi
关键点:
- 优先查找 Homebrew 安装的 m4(通常在
/opt/homebrew/Cellar/m4/或/opt/homebrew/opt/m4/bin/) - 检查系统 m4 版本是否满足要求(>= 1.4.8)
- 将找到的 m4 添加到 PATH 前面,确保
configure使用正确的版本
问题 5: 缺少 makeinfo 工具
错误现象
/Users/jianguo/HarmonyOSPC/build/code/autoconf/build-aux/missing: line 85: makeinfo: command not found
WARNING: 'makeinfo' is missing on your system.
make: *** [doc/standards.info] Error 127
问题分析
Autoconf 在构建时会尝试生成 info 格式的文档,这需要 makeinfo 工具(属于 Texinfo 包)。在交叉编译场景中,我们通常不需要构建文档,因为:
- 文档不是运行时必需的
- 交叉编译环境可能缺少文档构建工具
- 文档可以在主机系统上单独构建
解决方案
跳过文档构建,修改 Makefile 移除文档依赖:
bash
# 跳过文档构建(交叉编译时不需要文档,且缺少 makeinfo)
# 设置 MAKEINFO 为空命令,避免调用 makeinfo
export MAKEINFO=true
# 修改 Makefile 跳过文档目标
if [ -f "Makefile" ]; then
# 使用 awk 更安全地处理多行 INFO_DEPS 变量定义
awk '
/^INFO_DEPS = / {
print "INFO_DEPS = "
in_info_deps = 1
next
}
in_info_deps && (/^\t/ || /^[ \t]+/) {
# 跳过制表符或空格开头的续行(Makefile 多行变量定义的续行)
next
}
in_info_deps {
# 遇到非续行,结束 INFO_DEPS 定义
in_info_deps = 0
}
{ print }
' Makefile > Makefile.tmp && mv Makefile.tmp Makefile
# 移除 all-am 目标中的文档依赖
sed -i '' 's/ $(INFO_DEPS)//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/autoconf\.info doc\/standards\.info//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/autoconf\.info//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/standards\.info//g' Makefile 2>/dev/null || true
# 注释掉 doc 相关的 info 文件规则
sed -i '' 's/^\(doc\/.*\.info:\)/#\1/g' Makefile 2>/dev/null || true
fi
关键点:
- 使用
awk安全地处理多行变量定义,避免破坏 Makefile 语法 - 清空
INFO_DEPS变量,移除所有文档依赖 - 注释掉所有
doc/*.info相关的构建规则
问题 6: 缺少 help2man 工具
错误现象
/Users/jianguo/HarmonyOSPC/build/code/autoconf/build-aux/missing: line 85: help2man: command not found
WARNING: 'help2man' is missing on your system.
make[1]: *** [man/autoconf.1] Error 127
问题分析
Autoconf 在构建时会尝试生成 man 页面,这需要 help2man 工具。help2man 用于从程序的 --help 和 --version 输出自动生成 man 页面。在交叉编译场景中,我们通常不需要构建 man 页面。
解决方案
跳过 man 页面构建:
bash
# 设置 HELP2MAN 为空命令,避免调用 help2man
export HELP2MAN=true
# 修改 Makefile 跳过 man 页面目标
if [ -f "Makefile" ]; then
# 使用 awk 处理多行 dist_man_MANS 变量定义
awk '
/^dist_man_MANS = / {
print "dist_man_MANS = "
in_man_mans = 1
next
}
in_man_mans && (/^\t/ || /^[ \t]+/) {
# 跳过制表符或空格开头的续行
next
}
in_man_mans {
# 遇到非续行,结束 dist_man_MANS 定义
in_man_mans = 0
}
{ print }
' Makefile > Makefile.tmp && mv Makefile.tmp Makefile
# 移除 all-am 目标中的 man 依赖
sed -i '' 's/ $(MANS)//g' Makefile 2>/dev/null || true
# 注释掉 man 相关的规则
sed -i '' 's/^\(man\/.*\.1:\)/#\1/g' Makefile 2>/dev/null || true
fi
关键点:
- 设置
HELP2MAN=true避免调用 help2man - 使用
awk安全地清空dist_man_MANS变量 - 从
all-am目标中移除$(MANS)依赖 - 注释掉所有
man/*.1相关的构建规则
构建脚本详解
完整的 build_ohos.sh 脚本如下:
bash
#!/bin/bash
# ============================================================================
# build_ohos.sh - autoconf HarmonyOS 构建脚本
# ============================================================================
# autoconf 使用 autotools 构建系统
# ============================================================================
export AUTOCONF_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/autoconf.org/autoconf_1.0.0
sys_prefix=${PREFIX}
export PREFIX=${AUTOCONF_INSTALL_HNP_PATH}
echo "${PREFIX}"
# 创建安装目录
mkdir -p ${AUTOCONF_INSTALL_HNP_PATH} || {
echo "Error: Failed to create installation directory"
exit 1
}
# 清理之前的配置(如果存在)
if [ -f "Makefile" ]; then
make distclean || true
fi
rm -f config.status config.cache config.log
# 生成 configure 脚本(如果不存在)
if [ ! -f "configure" ]; then
# 优先尝试 autoreconf(不检查 m4 版本)
if [ -f "configure.ac" ] && command -v autoreconf >/dev/null 2>&1; then
echo "Using autoreconf to generate configure script..."
autoreconf -i || {
echo "Warning: autoreconf failed, trying bootstrap..."
# 如果 autoreconf 失败,尝试 bootstrap
if [ -f "bootstrap" ]; then
./bootstrap || {
echo "Error: bootstrap failed"
echo "Note: bootstrap requires GNU M4 1.4.8 or later (recommended 1.4.16+)"
echo "Current m4 version: $(m4 --version 2>&1 | head -1)"
echo "Please install a newer version of m4 or use autoreconf"
exit 1
}
else
echo "Error: autoreconf failed and bootstrap not found"
exit 1
fi
}
elif [ -f "bootstrap" ]; then
echo "Using bootstrap to generate configure script..."
./bootstrap || {
echo "Error: bootstrap failed"
echo "Note: bootstrap requires GNU M4 1.4.8 or later (recommended 1.4.16+)"
echo "Current m4 version: $(m4 --version 2>&1 | head -1)"
echo "Please install a newer version of m4:"
echo " macOS: brew install m4"
echo " Or try using autoreconf if available"
exit 1
}
elif [ -f "configure.ac" ]; then
autoreconf -i || {
echo "Error: autoreconf failed"
exit 1
}
else
echo "Error: No configure script, bootstrap, or configure.ac found"
exit 1
fi
fi
# 查找并使用更新的 m4(如果可用)
# Homebrew 安装的 m4 通常是 keg-only,需要手动添加到 PATH
M4_PATH=""
if [ -f "/opt/homebrew/Cellar/m4/1.4.20/bin/m4" ]; then
M4_PATH="/opt/homebrew/Cellar/m4/1.4.20/bin"
elif [ -f "/opt/homebrew/opt/m4/bin/m4" ]; then
M4_PATH="/opt/homebrew/opt/m4/bin"
elif command -v m4 >/dev/null 2>&1; then
M4_VERSION=$(m4 --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [ -n "$M4_VERSION" ]; then
# 检查版本是否 >= 1.4.8
MAJOR=$(echo "$M4_VERSION" | cut -d. -f1)
MINOR=$(echo "$M4_VERSION" | cut -d. -f2)
PATCH=$(echo "$M4_VERSION" | cut -d. -f3)
if [ "$MAJOR" -gt 1 ] || ([ "$MAJOR" -eq 1 ] && [ "$MINOR" -gt 4 ]) || ([ "$MAJOR" -eq 1 ] && [ "$MINOR" -eq 4 ] && [ "$PATCH" -ge 8 ]); then
M4_PATH="$(dirname $(command -v m4))"
fi
fi
fi
# 如果找到更新的 m4,添加到 PATH
if [ -n "$M4_PATH" ]; then
export PATH="${M4_PATH}:${PATH}"
echo "Using m4 from: ${M4_PATH}"
m4 --version | head -1
fi
# 运行 configure
./configure \
--prefix=${AUTOCONF_INSTALL_HNP_PATH} \
--host=aarch64-linux-gnu \
--enable-static \
--disable-shared \
CC="${CC}" \
CXX="${CXX}" \
CFLAGS="${CFLAGS}" \
CXXFLAGS="${CXXFLAGS}" \
LDFLAGS="${LDFLAGS}" || {
echo "Error: configure failed"
if [ -z "$M4_PATH" ]; then
echo ""
echo "Note: configure requires GNU M4 1.4.8 or later"
echo "Current m4 version: $(m4 --version 2>&1 | head -1)"
echo "Please install a newer version of m4:"
echo " macOS: brew install m4"
echo " Then add to PATH: export PATH=\"/opt/homebrew/opt/m4/bin:\$PATH\""
fi
exit 1
}
# 跳过文档构建(交叉编译时不需要文档,且缺少 makeinfo)
# 设置 MAKEINFO 为空命令,避免调用 makeinfo
export MAKEINFO=true
# 设置 HELP2MAN 为空命令,避免调用 help2man
export HELP2MAN=true
# 修改 Makefile 跳过文档和 man 页面目标
if [ -f "Makefile" ]; then
# 使用 awk 更安全地处理多行 INFO_DEPS 变量定义
awk '
/^INFO_DEPS = / {
print "INFO_DEPS = "
in_info_deps = 1
next
}
in_info_deps && (/^\t/ || /^[ \t]+/) {
# 跳过制表符或空格开头的续行(Makefile 多行变量定义的续行)
next
}
in_info_deps {
# 遇到非续行,结束 INFO_DEPS 定义
in_info_deps = 0
}
{ print }
' Makefile > Makefile.tmp && mv Makefile.tmp Makefile
# 使用 awk 处理多行 dist_man_MANS 变量定义
awk '
/^dist_man_MANS = / {
print "dist_man_MANS = "
in_man_mans = 1
next
}
in_man_mans && (/^\t/ || /^[ \t]+/) {
# 跳过制表符或空格开头的续行
next
}
in_man_mans {
# 遇到非续行,结束 dist_man_MANS 定义
in_man_mans = 0
}
{ print }
' Makefile > Makefile.tmp && mv Makefile.tmp Makefile
# 移除 all-am 目标中的文档和 man 依赖
sed -i '' 's/ $(INFO_DEPS)//g' Makefile 2>/dev/null || true
sed -i '' 's/ $(MANS)//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/autoconf\.info doc\/standards\.info//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/autoconf\.info//g' Makefile 2>/dev/null || true
sed -i '' 's/ doc\/standards\.info//g' Makefile 2>/dev/null || true
# 注释掉 doc 相关的 info 文件规则
sed -i '' 's/^\(doc\/.*\.info:\)/#\1/g' Makefile 2>/dev/null || true
# 注释掉 man 相关的规则
sed -i '' 's/^\(man\/.*\.1:\)/#\1/g' Makefile 2>/dev/null || true
fi
# 构建(跳过文档)
make VERBOSE=1 -j$(sysctl -n hw.ncpu 2>/dev/null || echo 4) || {
echo "Error: make failed"
exit 1
}
# 安装
make install || {
echo "Error: make install failed"
exit 1
}
# 复制 HNP 配置文件
cp hnp.json ${AUTOCONF_INSTALL_HNP_PATH}/ || {
echo "Error: failed to copy hnp.json"
exit 1
}
# 打包
if [ -d "${AUTOCONF_INSTALL_HNP_PATH}" ]; then
pushd ${AUTOCONF_INSTALL_HNP_PATH}/../ > /dev/null || {
echo "Error: pushd failed"
export PREFIX=${sys_prefix}
exit 1
}
${HNP_TOOL} pack -i ${AUTOCONF_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/ || {
echo "Error: HNP pack failed"
popd > /dev/null
export PREFIX=${sys_prefix}
exit 1
}
tar -zvcf ${ARCHIVE_PATH}/ohos_autoconf_1.0.0.tar.gz autoconf_1.0.0/ || {
echo "Error: tar failed"
popd > /dev/null
export PREFIX=${sys_prefix}
exit 1
}
popd > /dev/null
else
echo "Error: Installation directory does not exist: ${AUTOCONF_INSTALL_HNP_PATH}"
export PREFIX=${sys_prefix}
exit 1
fi
# 恢复 PREFIX
export PREFIX=${sys_prefix}
echo "Build completed successfully!"
echo "Output files:"
echo " - ${ARCHIVE_PATH}/autoconf.hnp"
echo " - ${ARCHIVE_PATH}/ohos_autoconf_1.0.0.tar.gz"
脚本关键点说明
- 环境变量设置:设置安装路径和 PREFIX
- 目录创建:确保安装目录存在
- 配置清理:清理之前的构建配置
- configure 生成 :
- 优先使用
autoreconf(不检查 m4 版本) - 如果失败,再尝试
bootstrap - 提供清晰的错误信息
- 优先使用
- m4 版本处理 :
- 自动查找 Homebrew 安装的 m4
- 检查系统 m4 版本是否满足要求
- 将找到的 m4 添加到 PATH
- configure 运行:配置交叉编译环境
- 文档跳过 :
- 设置
MAKEINFO=true和HELP2MAN=true - 使用
awk安全地处理多行变量定义 - 清空
INFO_DEPS和dist_man_MANS变量 - 从
all-am目标中移除文档和 man 依赖
- 设置
- 构建和安装:编译并安装到指定目录
- HNP 打包:生成 HNP 格式包和 tar.gz 压缩包
验证和测试
构建验证
构建成功后,检查生成的文件:
bash
# 检查 HNP 包
ls -lh output/autoconf.hnp
# 检查 tar.gz 包
ls -lh output/ohos_autoconf_1.0.0.tar.gz
# 检查安装目录
ls -R ${AUTOCONF_INSTALL_HNP_PATH}
功能测试
在 OpenHarmony 设备上测试 autoconf:
bash
# 检查版本
autoconf --version
# 检查帮助
autoconf --help
# 测试其他工具
autoheader --version
autom4te --version
autoreconf --version
autoscan --version
autoupdate --version
ifnames --version
使用示例
在 OpenHarmony 项目中使用 autoconf:
bash
# 1. 创建 configure.ac
cat > configure.ac << 'EOF'
AC_INIT([hello], [1.0])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
EOF
# 2. 运行 autoconf
autoconf
# 3. 运行 configure
./configure
# 4. 编译
make
总结
适配要点
-
Autotools 构建系统 :Autoconf 使用标准的 Autotools 构建流程,需要先运行
autoreconf或bootstrap生成configure脚本 -
m4 版本要求:Autoconf 需要 GNU M4 1.4.8 或更高版本(推荐 1.4.16+)
- 优先使用
autoreconf生成 configure(不检查 m4 版本) - 运行
configure时需要满足版本要求的 m4 - 自动查找并使用 Homebrew 安装的 m4
- 优先使用
-
交叉编译配置 :使用
--host=aarch64-linux-gnu作为目标平台(autotools 不认识aarch64-linux-ohos) -
文档构建跳过:交叉编译时通常不需要构建文档和 man 页面,需要:
- 设置
MAKEINFO=true和HELP2MAN=true - 使用
awk安全地处理多行变量定义 - 清空
INFO_DEPS和dist_man_MANS变量 - 从
all-am目标中移除文档和 man 依赖
- 设置
-
Makefile 修改安全 :使用
awk处理多行变量定义,避免破坏 Makefile 语法
适用场景
Autoconf 的 OpenHarmony 适配适用于:
- 需要构建使用 Autotools 的项目
- 开发符合 GNU 编码标准的软件包
- 需要跨平台构建支持的项目
- 构建系统现代化改造
经验总结
-
autoreconf vs bootstrap :优先使用
autoreconf,因为它不检查 m4 版本,可以避免版本问题 -
m4 版本管理 :自动查找并使用更新的 m4 版本,确保
configure能够正常运行 -
文档构建:交叉编译时跳过文档构建是常见做法,可以避免工具依赖问题
-
多行变量处理 :使用
awk而不是sed处理 Makefile 中的多行变量定义,避免语法错误 -
错误处理:为所有关键步骤添加错误处理,确保构建失败时能够及时发现问题
-
变量命名 :使用项目特定的变量名(如
AUTOCONF_INSTALL_HNP_PATH),避免与其他项目冲突 -
构建顺序:确保正确的构建顺序:清理 → 生成 configure → 查找 m4 → 运行 configure → 修改 Makefile → 构建 → 安装 → 打包