automake 工具 OpenHarmony PC 适配指南
目录
- 工具简介
- 主要功能
- 使用场景
- 基本使用方法
- OpenHarmony 适配过程
- 项目结构
- 构建系统
- 适配步骤
- 遇到的问题及解决方案
- 问题 1: Makefile 不存在
- 问题 2: 变量名错误
- 问题 3: 缺少 makeinfo 工具
- 问题 4: Makefile 语法错误
- 问题 5: amhello 示例构建失败
- 构建脚本详解
- 验证和测试
- 总结
工具简介
GNU Automake是一个 Makefile 生成器,旨在实现可移植性并符合 GNU 编码标准中的 Makefile 变量和目标规范。
基本信息
- 项目名称: GNU Automake
- 版本: 1.18.1 (开发快照)
- 官方网站: https://www.gnu.org/software/automake/
- 许可证: GPL v2+
- 构建系统: Autotools (autoconf/automake)
- 编程语言: Perl
| 项目名称 | automake |
|---|---|
| 开源协议 | GPL-2.0-or-later |
| 源码版本 | 1.18.1 |
| 目标平台 | aarch64-linux-ohos |
| 依赖项 | OpenHarmony SDK、Autotools (autoconf, automake) |
| 操作系统平台 | OpenHarmony PC |
| 源码地址 | https://git.savannah.gnu.org/git/automake.git |
设计理念
Automake 是一个 Perl 脚本,输入文件是Makefile.am,输出文件是Makefile.in,这些文件用于 Autoconf。Automake 要求开发者在configure.ac中完成某些配置。
Automake 的目标是:
- 可移植性:生成的 Makefile 可以在多种 Unix 系统上工作
- 符合标准:遵循 GNU 编码标准
- 自动化:减少手动编写和维护 Makefile 的工作量
- 功能丰富:支持多种构建场景(库、程序、测试、文档等)
主要功能
Automake 的主要功能包括:
- Makefile 生成:从
Makefile.am生成符合 GNU 标准的Makefile.in - 依赖跟踪:自动处理源代码依赖关系
- 安装规则:自动生成安装和卸载规则
- 分发支持:支持
make dist和make distcheck创建源代码分发包 - 测试支持:支持
make check运行测试套件 - 文档构建:支持构建 info、HTML、PDF 等格式的文档
- 库支持:支持构建静态库和共享库
- 交叉编译:支持交叉编译到不同平台
aclocal 工具
Automake 包还包含aclocal程序,用于根据configure.ac的内容生成aclocal.m4。它作为扩展和维护 autoconf 的机制,允许其他包作者编写可以被 aclocal 自动使用的 m4 宏。
使用场景
Automake 在以下场景中特别有用:
- GNU 软件包开发:符合 GNU 编码标准的软件包
- 跨平台项目:需要在多种 Unix 系统上构建的项目
- 复杂构建系统:需要处理多个目录、库、程序和测试的项目
- 开源项目:需要标准化的构建和安装流程的项目
- 构建系统现代化:将旧的手写 Makefile 迁移到现代构建系统
基本使用方法
典型工作流程
# 1. 从源代码仓库检出(如果是开发版本)gitclone https://git.savannah.gnu.org/git/automake.gitcdautomake# 2. 生成 configure 脚本(开发版本需要)./bootstrap# 3. 配置构建环境./configure--prefix=/usr/local# 4. 编译make# 5. 运行测试(可选)makecheck# 6. 安装makeinstall基本命令
# 生成 Makefile.inautomake --add-missing# 生成 aclocal.m4aclocal# 查看帮助automake--helpaclocal--help在项目中使用 Automake
- 创建
configure.ac:定义项目配置 - 创建
Makefile.am:定义构建规则 - 运行
aclocal:生成aclocal.m4 - 运行
autoconf:生成configure脚本 - 运行
automake:生成Makefile.in - 运行
./configure:生成Makefile - 运行
make:编译项目
OpenHarmony 适配过程
项目结构
automake/ ├── bootstrap # 引导脚本(生成 configure) ├── configure.ac # Autoconf 配置文件 ├── Makefile.am # Automake 输入文件 ├── bin/ # 二进制文件目录 │ ├── automake.in # automake Perl 脚本模板 │ └── aclocal.in # aclocal Perl 脚本模板 ├── lib/ # 库文件目录 │ ├── Automake/ # Automake Perl 模块 │ └── am/ # Makefile.am 片段 ├── doc/ # 文档目录 │ ├── automake.texi # Texinfo 文档源 │ └── amhello/ # 示例项目 ├── m4/ # m4 宏文件 ├── t/ # 测试套件 ├── build_ohos.sh # OpenHarmony 构建脚本 └── hnp.json # HNP 配置文件构建系统
Automake 使用 Autotools 构建系统:
- bootstrap:生成
configure脚本(开发版本) - configure:配置构建环境,生成
Makefile - make:编译源代码和生成工具
- make install:安装到指定目录
适配步骤
1. 创建构建脚本
创建build_ohos.sh脚本,配置 OpenHarmony 交叉编译环境:
#!/bin/bash# ============================================================================# build_ohos.sh - automake HarmonyOS 构建脚本# ============================================================================# automake 使用 autotools 构建系统# ============================================================================exportAUTOMAKE_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/automake.org/automake_1.0.0sys_prefix=${PREFIX}exportPREFIX=${AUTOMAKE_INSTALL_HNP_PATH}2. 生成 configure 脚本
检查并生成configure脚本(如果不存在):
# 生成 configure 脚本(如果不存在)if[!-f"configure"];thenif[-f"bootstrap"];then./bootstrap||{echo"Error: bootstrap failed"exit1}elif[-f"configure.ac"];thenautoreconf-i||{echo"Error: autoreconf failed"exit1}elseecho"Error: No configure script, bootstrap, or configure.ac found"exit1fifi3. 运行 configure
配置构建环境,使用aarch64-linux-gnu作为 host(因为 autotools 不认识aarch64-linux-ohos):
./configure\--prefix=${AUTOMAKE_INSTALL_HNP_PATH}\--host=aarch64-linux-gnu\--enable-static\--disable-shared\CC="${CC}"\CXX="${CXX}"\CFLAGS="${CFLAGS}"\CXXFLAGS="${CXXFLAGS}"\LDFLAGS="${LDFLAGS}"注意:--enable-static和--disable-shared选项会被 configure 警告为未识别的选项,但不影响构建。
移植环境说明:该命令基于build配置框架进行移植编译,环境搭建可以参考文章《开源软件鸿蒙化适配与构建指南(交叉编译)》,主要是ohos sdk的下载配置和build配置框架的下载使用说明。
遇到的问题及解决方案
问题 1: Makefile 不存在
错误现象
GNUmakefile:23: There seems to be no Makefile in this directory. GNUmakefile:24: You must run ./configure before running 'make'. GNUmakefile:25: *** Fatal Error. Stop.问题分析
Automake 使用 Autotools 构建系统,需要先运行configure脚本生成Makefile。如果configure脚本不存在,还需要先运行bootstrap或autoreconf生成它。
解决方案
在构建脚本中添加生成configure脚本的逻辑:
# 生成 configure 脚本(如果不存在)if[!-f"configure"];thenif[-f"bootstrap"];then./bootstrap||{echo"Error: bootstrap failed"exit1}elif[-f"configure.ac"];thenautoreconf-i||{echo"Error: autoreconf failed"exit1}fifi# 运行 configure./configure--prefix=${AUTOMAKE_INSTALL_HNP_PATH}--host=aarch64-linux-gnu...问题 2: 变量名错误
错误现象
cp: /hnp.json: Read-only file system realpath unsuccess. path=-o source dir path=-o is invalid. tar: automake_1.0.0: Cannot stat: No such file or directory问题分析
构建脚本中使用了错误的变量名TREE_INSTALL_HNP_PATH,应该使用AUTOMAKE_INSTALL_HNP_PATH。同时缺少创建安装目录的步骤。
解决方案
- 修正变量名:将所有
TREE_INSTALL_HNP_PATH改为AUTOMAKE_INSTALL_HNP_PATH - 创建安装目录:在 configure 之前创建安装目录
# 创建安装目录mkdir-p${AUTOMAKE_INSTALL_HNP_PATH}||{echo"Error: Failed to create installation directory"exit1}问题 3: 缺少 makeinfo 工具
错误现象
/Users/jianguo/HarmonyOSPC/build/code/automake/lib/missing: line 85: makeinfo: command not found WARNING: 'makeinfo' is missing on your system. make: *** [doc/automake-history.info] Error 127问题分析
Automake 在构建时会尝试生成 info 格式的文档,这需要makeinfo工具(属于 Texinfo 包)。在交叉编译场景中,我们通常不需要构建文档,因为:
- 文档不是运行时必需的
- 交叉编译环境可能缺少文档构建工具
- 文档可以在主机系统上单独构建
解决方案
跳过文档构建,修改 Makefile 移除文档依赖:
# 跳过文档构建(交叉编译时不需要文档,且缺少 makeinfo)# 设置 MAKEINFO 为空命令,避免调用 makeinfoexportMAKEINFO=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&&mvMakefile.tmp Makefile# 移除 all-am 目标中的文档依赖sed-i'''s/ $(INFO_DEPS)//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake\.info doc\/automake-history\.info//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake\.info//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake-history\.info//g'Makefile2>/dev/null||true# 注释掉 doc 相关的 info 文件规则sed-i'''s/^\(doc\/.*\.info:\)/#\1/g'Makefile2>/dev/null||truefi关键点:
- 使用
awk安全地处理多行变量定义,避免破坏 Makefile 语法 - 清空
INFO_DEPS变量,移除所有文档依赖 - 注释掉所有
doc/*.info相关的构建规则
问题 4: Makefile 语法错误
错误现象
Makefile:216: *** commands commence before first target. Stop.问题分析
在使用sed修改INFO_DEPS变量时,只替换了第一行,留下了以制表符开头的续行,导致 Makefile 语法错误。Makefile 中的多行变量定义格式如下:
INFO_DEPS = \ $(srcdir)/doc/automake.info \ $(srcdir)/doc/automake-history.info如果只替换第一行,会留下:
INFO_DEPS = $(srcdir)/doc/automake-history.info这会导致 Makefile 解析错误,因为制表符开头的行会被解释为命令,但前面没有目标。
解决方案
使用awk安全地处理多行变量定义:
# 使用 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&&mvMakefile.tmp Makefile关键点:
- 识别
INFO_DEPS =行 - 跳过所有以制表符或空格开头的续行
- 遇到非续行时结束处理
- 将多行定义替换为单行空定义
INFO_DEPS =
问题 5: amhello 示例构建失败
错误现象
Wide character in print at ./doc/help2man line 668. Wide character in print at ./doc/help2man line 668. doc/amhello-1.0.tar.gz: recipe failed. See file '/Users/jianguo/HarmonyOSPC/build/code/automake/doc/amhello/amhello-output.tmp' for details make: *** [doc/amhello-1.0.tar.gz] Error 1问题分析
amhello是 Automake 提供的示例项目,用于演示如何使用 Automake。构建amhello-1.0.tar.gz时,会调用help2man生成 man 页面,但遇到了字符编码问题。在交叉编译场景中,我们不需要构建示例项目。
解决方案
跳过amhello示例的构建:
# 注释掉 amhello-1.0.tar.gz 的构建规则sed-i'''s|^\($(srcdir)/doc/amhello-1\.0\.tar\.gz:\)|#\1|g'Makefile2>/dev/null||true# 清空 dist_doc_DATA 变量(移除 amhello-1.0.tar.gz)sed-i'''s|^dist_doc_DATA = .*|dist_doc_DATA = |'Makefile2>/dev/null||true# 从 DATA 变量中移除 dist_doc_DATA(如果存在)sed-i'''s| $(dist_doc_DATA)||g'Makefile2>/dev/null||true# 注释掉 amhello 相关的规则(避免构建示例文档)sed-i'''s|^\(doc/amhello.*:\)|#\1|g'Makefile2>/dev/null||true关键点:
- 注释掉
amhello-1.0.tar.gz的构建规则 - 清空
dist_doc_DATA变量 - 从
DATA变量中移除dist_doc_DATA的引用
构建脚本详解
完整的build_ohos.sh脚本如下:
#!/bin/bash# ============================================================================# build_ohos.sh - automake HarmonyOS 构建脚本# ============================================================================# automake 使用 autotools 构建系统# ============================================================================exportAUTOMAKE_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/automake.org/automake_1.0.0sys_prefix=${PREFIX}exportPREFIX=${AUTOMAKE_INSTALL_HNP_PATH}echo"${PREFIX}"# 创建安装目录mkdir-p${AUTOMAKE_INSTALL_HNP_PATH}||{echo"Error: Failed to create installation directory"exit1}# 清理之前的配置(如果存在)if[-f"Makefile"];thenmakedistclean||truefirm-fconfig.status config.cache config.log# 生成 configure 脚本(如果不存在)if[!-f"configure"];thenif[-f"bootstrap"];then./bootstrap||{echo"Error: bootstrap failed"exit1}elif[-f"configure.ac"];thenautoreconf-i||{echo"Error: autoreconf failed"exit1}elseecho"Error: No configure script, bootstrap, or configure.ac found"exit1fifi# 运行 configure./configure\--prefix=${AUTOMAKE_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"exit1}# 跳过文档构建(交叉编译时不需要文档,且缺少 makeinfo)# 设置 MAKEINFO 为空命令,避免调用 makeinfoexportMAKEINFO=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&&mvMakefile.tmp Makefile# 移除 all-am 目标中的文档依赖sed-i'''s/ $(INFO_DEPS)//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake\.info doc\/automake-history\.info//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake\.info//g'Makefile2>/dev/null||truesed-i'''s/ doc\/automake-history\.info//g'Makefile2>/dev/null||true# 注释掉 doc 相关的 info 文件规则sed-i'''s/^\(doc\/.*\.info:\)/#\1/g'Makefile2>/dev/null||true# 注释掉 amhello-1.0.tar.gz 的构建规则sed-i'''s|^\($(srcdir)/doc/amhello-1\.0\.tar\.gz:\)|#\1|g'Makefile2>/dev/null||true# 清空 dist_doc_DATA 变量(移除 amhello-1.0.tar.gz)sed-i'''s|^dist_doc_DATA = .*|dist_doc_DATA = |'Makefile2>/dev/null||true# 从 DATA 变量中移除 dist_doc_DATA(如果存在)sed-i'''s| $(dist_doc_DATA)||g'Makefile2>/dev/null||true# 注释掉 amhello 相关的规则(避免构建示例文档)sed-i'''s|^\(doc/amhello.*:\)|#\1|g'Makefile2>/dev/null||truefi# 构建(跳过文档)makeVERBOSE=1-j$(sysctl-nhw.ncpu2>/dev/null||echo4)||{echo"Error: make failed"exit1}# 安装makeinstall||{echo"Error: make install failed"exit1}# 复制 HNP 配置文件cphnp.json${AUTOMAKE_INSTALL_HNP_PATH}/||{echo"Error: failed to copy hnp.json"exit1}# 打包if[-d"${AUTOMAKE_INSTALL_HNP_PATH}"];thenpushd${AUTOMAKE_INSTALL_HNP_PATH}/../>/dev/null||{echo"Error: pushd failed"exportPREFIX=${sys_prefix}exit1}${HNP_TOOL}pack-i${AUTOMAKE_INSTALL_HNP_PATH}-o${ARCHIVE_PATH}/||{echo"Error: HNP pack failed"popd>/dev/nullexportPREFIX=${sys_prefix}exit1}tar-zvcf${ARCHIVE_PATH}/ohos_automake_1.0.0.tar.gz automake_1.0.0/||{echo"Error: tar failed"popd>/dev/nullexportPREFIX=${sys_prefix}exit1}popd>/dev/nullelseecho"Error: Installation directory does not exist:${AUTOMAKE_INSTALL_HNP_PATH}"exportPREFIX=${sys_prefix}exit1fi# 恢复 PREFIXexportPREFIX=${sys_prefix}echo"Build completed successfully!"echo"Output files:"echo" -${ARCHIVE_PATH}/automake.hnp"echo" -${ARCHIVE_PATH}/ohos_automake_1.0.0.tar.gz"脚本关键点说明
- 环境变量设置:设置安装路径和 PREFIX
- 目录创建:确保安装目录存在
- 配置清理:清理之前的构建配置
- configure 生成:如果不存在,通过
bootstrap或autoreconf生成 - configure 运行:配置交叉编译环境
- 文档跳过:使用
awk和sed修改 Makefile 跳过文档构建 - 构建和安装:编译并安装到指定目录
- HNP 打包:生成 HNP 格式包和 tar.gz 压缩包
验证和测试
构建验证
构建成功后,检查生成的文件:
# 检查 HNP 包ls-lhoutput/automake.hnp# 检查 tar.gz 包ls-lhoutput/ohos_automake_1.0.0.tar.gz# 检查安装目录ls-R${AUTOMAKE_INSTALL_HNP_PATH}功能测试
在 OpenHarmony 设备上测试 automake:
# 检查版本automake--version# 检查帮助automake--help# 测试 aclocalaclocal--version使用示例
在 OpenHarmony 项目中使用 automake:
# 1. 创建 Makefile.amcat>Makefile.am<<'EOF' bin_PROGRAMS = hello hello_SOURCES = hello.c EOF# 2. 运行 automakeautomake --add-missing# 3. 运行 configure./configure# 4. 编译make总结
适配要点
Autotools 构建系统:Automake 使用标准的 Autotools 构建流程,需要先运行
bootstrap或autoreconf生成configure脚本交叉编译配置:使用
--host=aarch64-linux-gnu作为目标平台(autotools 不认识aarch64-linux-ohos)文档构建跳过:交叉编译时通常不需要构建文档,需要:
- 设置
MAKEINFO=true避免调用 makeinfo - 使用
awk安全地处理多行变量定义 - 清空
INFO_DEPS变量 - 注释掉所有文档相关的构建规则
- 设置
示例项目跳过:跳过
amhello示例项目的构建,避免字符编码问题Makefile 修改安全:使用
awk处理多行变量定义,避免破坏 Makefile 语法
适用场景
Automake 的 OpenHarmony 适配适用于:
- 需要构建使用 Autotools 的项目
- 开发符合 GNU 编码标准的软件包
- 需要跨平台构建支持的项目
- 构建系统现代化改造
经验总结
多行变量处理:使用
awk而不是sed处理 Makefile 中的多行变量定义,避免语法错误文档构建:交叉编译时跳过文档构建是常见做法,可以避免工具依赖问题
错误处理:为所有关键步骤添加错误处理,确保构建失败时能够及时发现问题
变量命名:使用项目特定的变量名(如
AUTOMAKE_INSTALL_HNP_PATH),避免与其他项目冲突构建顺序:确保正确的构建顺序:清理 → 生成 configure → 运行 configure → 修改 Makefile → 构建 → 安装 → 打包
参考资源
- Automake 官方网站
- GNU Autotools 文档
- OpenHarmony Native Package (HNP) 文档
- 项目代码仓
- PC代码仓
- PC社区
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
