autoconf 工具 OpenHarmony PC 适配指南

目录

工具简介

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 包含以下主要工具:

  1. autoconf :从 configure.ac 生成 configure 脚本
  2. autoheader :生成 config.h.in 模板文件
  3. autom4te:M4 宏处理器,autoconf 的核心引擎
  4. autoreconf:自动运行 autoconf、autoheader、automake 等工具
  5. autoscan :扫描源代码,生成初始的 configure.ac
  6. autoupdate :更新旧的 configure.ac 到新版本
  7. ifnames:列出 C/C++ 源代码中使用的预处理器符号

主要功能

Autoconf 的主要功能包括:

  1. 配置脚本生成 :从 configure.ac 生成可移植的 configure 脚本
  2. 系统特性检测:自动检测编译器、库、头文件、函数等系统特性
  3. 条件编译支持 :生成 config.h 文件,支持条件编译
  4. 交叉编译支持:支持交叉编译到不同平台
  5. 宏系统:提供丰富的 M4 宏库,用于检测各种系统特性
  6. 版本管理:支持软件包版本管理和依赖检查
  7. 安装路径配置:支持灵活的安装路径配置
  8. 功能开关 :支持 --enable-*--disable-* 选项

工作流程

复制代码
configure.ac (M4 宏) 
    ↓
autoconf (M4 处理器)
    ↓
configure (Shell 脚本)
    ↓
./configure (运行)
    ↓
config.h, Makefile (生成)

使用场景

Autoconf 在以下场景中特别有用:

  1. GNU 软件包开发:符合 GNU 编码标准的软件包
  2. 跨平台项目:需要在多种 Unix 系统上构建的项目
  3. 开源项目:需要标准化的配置和构建流程的项目
  4. 复杂依赖管理:需要检测和配置复杂依赖关系的项目
  5. 构建系统现代化:将旧的手写配置脚本迁移到现代构建系统

基本使用方法

典型工作流程

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

  1. 创建 configure.ac:定义项目配置和系统检测
  2. 运行 autoconf :生成 configure 脚本
  3. 运行 autoheader :生成 config.h.in(可选)
  4. 运行 ./configure :配置项目,生成 config.hMakefile
  5. 运行 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 构建系统:

  1. bootstrapautoreconf :生成 configure 脚本(开发版本)
  2. configure :配置构建环境,生成 Makefile
  3. make:编译源代码和生成工具
  4. 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 脚本不存在,还需要先运行 bootstrapautoreconf 生成它。

解决方案

在构建脚本中添加生成 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。同时缺少创建安装目录的步骤。

解决方案
  1. 修正变量名 :将所有 TREE_INSTALL_HNP_PATH 改为 AUTOCONF_INSTALL_HNP_PATH
  2. 创建安装目录:在 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 包)。在交叉编译场景中,我们通常不需要构建文档,因为:

  1. 文档不是运行时必需的
  2. 交叉编译环境可能缺少文档构建工具
  3. 文档可以在主机系统上单独构建
解决方案

跳过文档构建,修改 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"

脚本关键点说明

  1. 环境变量设置:设置安装路径和 PREFIX
  2. 目录创建:确保安装目录存在
  3. 配置清理:清理之前的构建配置
  4. configure 生成
    • 优先使用 autoreconf(不检查 m4 版本)
    • 如果失败,再尝试 bootstrap
    • 提供清晰的错误信息
  5. m4 版本处理
    • 自动查找 Homebrew 安装的 m4
    • 检查系统 m4 版本是否满足要求
    • 将找到的 m4 添加到 PATH
  6. configure 运行:配置交叉编译环境
  7. 文档跳过
    • 设置 MAKEINFO=trueHELP2MAN=true
    • 使用 awk 安全地处理多行变量定义
    • 清空 INFO_DEPSdist_man_MANS 变量
    • all-am 目标中移除文档和 man 依赖
  8. 构建和安装:编译并安装到指定目录
  9. 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

总结

适配要点

  1. Autotools 构建系统 :Autoconf 使用标准的 Autotools 构建流程,需要先运行 autoreconfbootstrap 生成 configure 脚本

  2. m4 版本要求:Autoconf 需要 GNU M4 1.4.8 或更高版本(推荐 1.4.16+)

    • 优先使用 autoreconf 生成 configure(不检查 m4 版本)
    • 运行 configure 时需要满足版本要求的 m4
    • 自动查找并使用 Homebrew 安装的 m4
  3. 交叉编译配置 :使用 --host=aarch64-linux-gnu 作为目标平台(autotools 不认识 aarch64-linux-ohos

  4. 文档构建跳过:交叉编译时通常不需要构建文档和 man 页面,需要:

    • 设置 MAKEINFO=trueHELP2MAN=true
    • 使用 awk 安全地处理多行变量定义
    • 清空 INFO_DEPSdist_man_MANS 变量
    • all-am 目标中移除文档和 man 依赖
  5. Makefile 修改安全 :使用 awk 处理多行变量定义,避免破坏 Makefile 语法

适用场景

Autoconf 的 OpenHarmony 适配适用于:

  • 需要构建使用 Autotools 的项目
  • 开发符合 GNU 编码标准的软件包
  • 需要跨平台构建支持的项目
  • 构建系统现代化改造

经验总结

  1. autoreconf vs bootstrap :优先使用 autoreconf,因为它不检查 m4 版本,可以避免版本问题

  2. m4 版本管理 :自动查找并使用更新的 m4 版本,确保 configure 能够正常运行

  3. 文档构建:交叉编译时跳过文档构建是常见做法,可以避免工具依赖问题

  4. 多行变量处理 :使用 awk 而不是 sed 处理 Makefile 中的多行变量定义,避免语法错误

  5. 错误处理:为所有关键步骤添加错误处理,确保构建失败时能够及时发现问题

  6. 变量命名 :使用项目特定的变量名(如 AUTOCONF_INSTALL_HNP_PATH),避免与其他项目冲突

  7. 构建顺序:确保正确的构建顺序:清理 → 生成 configure → 查找 m4 → 运行 configure → 修改 Makefile → 构建 → 安装 → 打包

参考资源

相关推荐
遇到困难睡大觉哈哈2 小时前
HarmonyOS —— Remote Communication Kit 拦截器(Interceptor)高阶定制能力笔记
笔记·华为·harmonyos
遇到困难睡大觉哈哈3 小时前
HarmonyOS —— Remote Communication Kit 定制处理行为(ProcessingConfiguration)速记笔记
笔记·华为·harmonyos
氤氲息3 小时前
鸿蒙 ArkTs 的WebView如何与JS交互
javascript·交互·harmonyos
遇到困难睡大觉哈哈3 小时前
HarmonyOS支付接入证书准备与生成指南
华为·harmonyos
赵浩生3 小时前
鸿蒙技术干货10:鸿蒙图形渲染基础,Canvas绘图与自定义组件实战
harmonyos
赵浩生3 小时前
鸿蒙技术干货9:deviceInfo 设备信息获取与位置提醒 APP 整合
harmonyos
BlackWolfSky4 小时前
鸿蒙暂未归类知识记录
华为·harmonyos
L、2186 小时前
Flutter 与开源鸿蒙(OpenHarmony):跨平台开发的新未来
flutter·华为·开源·harmonyos
L、2187 小时前
Flutter 与 OpenHarmony 深度融合实践:打造跨生态高性能应用(进阶篇)
javascript·flutter·华为·智能手机·harmonyos