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 → 构建 → 安装 → 打包

参考资源

相关推荐
爱笑的眼睛112 小时前
深入HarmonyOS USB设备管理:从基础到高级开发
华为·harmonyos
ifeng09182 小时前
HarmonyOS远程真机调试实战:云测与设备管控技巧
华为·harmonyos
爱笑的眼睛112 小时前
HarmonyOS应用开发深度解析:@State状态管理的进阶技巧
华为·harmonyos
流影ng3 小时前
【HarmonyOS】状态管理V2
华为·harmonyos
哦***77 小时前
华为FreeBuds Pro5:星闪连接和星闪音频有啥区别?
华为·音频
Kisang.13 小时前
【HarmonyOS】性能优化——组件的封装与复用
华为·性能优化·typescript·harmonyos·鸿蒙
ifeng091815 小时前
HarmonyOS网络请求优化实战:智能缓存、批量处理与竞态处理
网络·缓存·harmonyos
HMSCore21 小时前
【FAQ】HarmonyOS SDK 闭源开放能力 — Notification Kit
harmonyos
HarmonyOS_SDK21 小时前
【FAQ】HarmonyOS SDK 闭源开放能力 — Account Kit
harmonyos