目录


1. 背景介绍

1.1 bc 工具简介

bc (Basic Calculator) 是 GNU 项目开发的一个任意精度数值处理语言,类似于 C 语言的语法,支持交互式执行和脚本模式。它提供了强大的数学计算能力,常用于:

  • 精确的数学计算(不受浮点数精度限制)
  • Shell 脚本中的数值处理
  • 科学计算和工程计算
  • 进制转换和数值格式化
  • 数学教学和学习工具
    在这里插入图片描述

1.2 适配目标

将 GNU bc 1.08.2 版本适配到鸿蒙PC(HarmonyOS PC)平台,实现:

  • 交叉编译支持(macOS/Linux → aarch64-linux-ohos)
  • 使用鸿蒙SDK工具链进行编译
  • 生成HNP格式的安装包
  • 生成tar.gz格式的发布包
  • 零外部运行时依赖(静态链接)

1.3 技术栈

  • 编译工具链: OHOS SDK Native LLVM
  • 目标平台: aarch64-linux-ohos
  • 打包格式: HNP (HarmonyOS Native Package)
  • 构建系统: Autotools (autoconf + automake)
  • 链接方式: 静态链接

1.4 基本信息

项目 信息
项目名称 bc (GNU bc)
版本 1.08.2(适配版本)<br>1.08.2(原始版本)
许可证 GPL v3
目标平台 鸿蒙PC (aarch64-linux-ohos)
源码仓库 https://ftp.gnu.org/gnu/bc/
鸿蒙化版本 2025-12-09

项目特点

  • 任意精度计算:支持任意精度的数值计算,不受浮点数精度限制
  • C 语言语法:语法类似 C 语言,易于学习和使用
  • 交互式与脚本模式:支持交互式执行和脚本文件执行
  • 零外部依赖:静态链接,无需外部运行时库
  • 双工具支持:同时提供 bcdc(逆波兰计算器)两个工具

2. 环境准备

2.1 系统要求

  • 开发环境: macOS / Linux / Windows (WSL)
  • 构建工具: autoconf, automake, libtool
  • 鸿蒙SDK: OHOS SDK (包含native工具链)

2.2 SDK安装

  1. 下载SDK
# 下载鸿蒙SDK
cd ~
wget https://cidownload.openharmony.cn/version/Master_Version/ohos-sdk-full_ohos/20250819_020817/version-Master_Version-ohos-sdk-full_ohos-20250819_020817-ohos-sdk-full_ohos.tar.gz

# 解压SDK
tar -zvxf version-Master_Version-ohos-sdk-full_ohos-20250819_020817-ohos-sdk-full_ohos.tar.gz
  1. SDK目录结构
ohos-sdk/
├── native/
│   ├── llvm/bin/          # 编译器工具链
│   ├── sysroot/           # 系统根目录(头文件和库)
│   └── build-tools/       # 构建工具
└── toolchains/
    └── hnpcli            # HNP打包工具

2.3 项目结构

HarmonyOSPC/build/
├── build.sh              # 主构建脚本
├── code/
│   └── bc-1.08.2/        # bc工具源码
│       ├── bc/           # bc主程序源码
│       ├── dc/           # dc计算器源码
│       ├── lib/          # 共享库
│       ├── configure.ac  # Autotools配置
│       ├── build_ohos.sh # 鸿蒙构建脚本
│       └── hnp.json      # HNP包配置
└── output/               # 构建输出目录

3. 项目结构分析

3.1 源码文件分析

bc 采用传统的 Autotools 构建系统,主要组件包括:

bc-1.08.2/
├── bc/              # bc 主程序源码
│   ├── main.c       # 主程序入口
│   ├── execute.c    # 表达式执行
│   └── ...
├── dc/              # dc 计算器源码
│   ├── main.c       # dc主程序
│   └── ...
├── lib/             # 共享库
│   ├── getopt.c     # 命令行参数解析
│   ├── vfprintf.c   # 格式化输出
│   └── number.c     # 数值处理
├── doc/             # 文档和手册页
├── configure.ac     # Autotools配置
├── Makefile.am      # Makefile模板
├── build_ohos.sh    # 鸿蒙构建脚本
└── hnp.json         # HNP 包配置

3.2 构建系统分析

bc 使用 Autotools 构建系统:

  • configure.ac: 定义构建配置和依赖检查
  • Makefile.am: 定义编译规则和安装规则
  • autoreconf: 生成 configure 脚本

3.3 交叉编译配置

3.3.1 构建环境变量设置
# 目标平台
export TARGET_PLATFORM=aarch64-linux-ohos

# 编译器配置
export CC="${OHOS_SDK}/native/llvm/bin/clang"
export CPP="${CC} -E --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"
export AR="${OHOS_SDK}/native/llvm/bin/llvm-ar"
export RANLIB="${OHOS_SDK}/native/llvm/bin/llvm-ranlib"

# 编译选项
export CFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong \
               --target=${TARGET_PLATFORM} -fuse-ld=${LD} --sysroot=${SYSROOT}"

# 链接选项(静态链接)
export LDFLAGS="-fuse-ld=${LD} --target=${TARGET_PLATFORM} \
                --sysroot=${SYSROOT} -static"
3.3.2 Configure 配置
./configure \
    --host=aarch64-unknown-linux-musl \
    --prefix=${BC_INSTALL_HNP_PATH} \
    --without-readline \
    --without-libedit \
    --disable-dc-bang-shell \
    CC="${CC}" \
    CPP="${CPP}" \
    CFLAGS="${CFLAGS}" \
    LDFLAGS="${LDFLAGS} -static"

关键配置说明

  • --host=aarch64-unknown-linux-musl:指定目标平台为 ARM aarch64,使用 musl libc
  • --without-readline --without-libedit:禁用交互式编辑功能,避免外部依赖
  • -static:静态链接,确保零运行时依赖
3.3.3 构建脚本关键步骤

build_ohos.sh 脚本的主要步骤:

  1. 环境检查:检查 autoconf、automake、libtool 等构建工具
  2. 生成 configure:如果从 git 构建,运行 autoreconf -fi
  3. 清理构建:执行 make clean 清理之前的构建产物
  4. 配置交叉编译:运行 configure 配置构建系统
  5. 修复 config.h:修复交叉编译时 configure 未正确设置的宏定义
  6. 编译:执行 make 编译 bc 和 dc
  7. 安装:执行 make install 安装到 HNP 目录
  8. 打包:生成 HNP 包和 tar.gz 压缩包

4. 问题诊断与解决

4.1 问题诊断

在交叉编译过程中,我们遇到了以下主要问题:

  1. config.h 文件创建问题
  2. 交叉编译时宏定义缺失
  3. CPP 环境变量设置问题
  4. 静态链接配置问题

4.2 解决方案

4.2.1 config.h 文件创建问题

问题:configure 执行后,config.h 文件可能没有被正确创建。

解决方案

# 验证并确保 config.h 已创建
if [ ! -f "config.h" ]; then
    echo "Warning: config.h not found, trying to create it..."
    ./config.status --file=config.h 2>&1 || {
        echo "Error: Failed to create config.h"
        exit 1
    }
fi
4.2.2 交叉编译时宏定义缺失

问题:交叉编译时,configure 可能无法正确检测某些系统功能,导致 config.h 中关键宏定义缺失。

解决方案:在构建脚本中添加宏定义修复逻辑:

# 修复 config.h 中缺失的宏定义
echo "Fixing missing macro definitions in config.h..."

# 1. 修复 HAVE_UNISTD_H(避免 proto.h 中的语法错误)
if grep -q "^#undef HAVE_UNISTD_H" config.h 2>/dev/null; then
    echo "  - Fixing HAVE_UNISTD_H..."
    sed -i '' 's/^#undef HAVE_UNISTD_H$/#define HAVE_UNISTD_H 1/' config.h
fi

# 2. 修复 HAVE_VPRINTF(避免 vfprintf.c 编译错误)
if grep -q "^#undef HAVE_VPRINTF" config.h 2>/dev/null; then
    echo "  - Fixing HAVE_VPRINTF..."
    sed -i '' 's/^#undef HAVE_VPRINTF$/#define HAVE_VPRINTF 1/' config.h
fi

# 3. 修复 PACKAGE, VERSION 等宏
if grep -q "^#undef PACKAGE$" config.h 2>/dev/null; then
    echo "  - Fixing PACKAGE, VERSION, BC_COPYRIGHT macros..."
    sed -i '' \
        -e 's/^#undef PACKAGE$/#define PACKAGE "bc"/' \
        -e 's/^#undef PACKAGE_NAME$/#define PACKAGE_NAME "bc"/' \
        -e 's/^#undef PACKAGE_VERSION$/#define PACKAGE_VERSION "1.08.2"/' \
        -e 's/^#undef VERSION$/#define VERSION "1.08.2"/' \
        -e 's/^#undef BC_COPYRIGHT$/#define BC_COPYRIGHT "Copyright (C) 2024 Free Software Foundation, Inc."/' \
        config.h
fi

修复的宏定义

  • HAVE_UNISTD_H:确保 unistd.h 头文件可用,避免 proto.h 中的语法错误
  • HAVE_VPRINTF:确保 vprintf 函数可用,避免 vfprintf.c 编译失败
  • PACKAGE, VERSION, BC_COPYRIGHT:确保程序信息宏定义正确
4.2.3 CPP 环境变量设置

问题:configure 脚本需要 C 预处理器,但默认可能使用 C++ 编译器。

解决方案

# 修复 CPP 环境变量(configure 脚本需要 C 预处理器,而不是 C++ 编译器)
export CPP="${CC} -E --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"

5. 详细修改步骤

5.1 HNP 包配置

hnp.json 配置文件:

{
    "type": "hnp-config",
    "name": "bc",
    "version": "1.08.2",
    "install": {
        "links": [
            {
                "source": "bin/bc",
                "target": "bc"
            },
            {
                "source": "bin/dc",
                "target": "dc"
            }
        ]
    }
}

配置说明

  • name: 包名称(bc)
  • version: 版本号(1.08.2)
  • links: 创建符号链接,将 bin/bcbin/dc 链接到系统 PATH

5.2 安装路径结构

/data/service/hnp/bc.org/bc_1.08.2/
├── bin/
│   ├── bc          # bc 可执行文件
│   └── dc          # dc 可执行文件
├── share/
│   ├── man/man1/
│   │   ├── bc.1    # bc 手册页
│   │   └── dc.1    # dc 手册页
│   └── info/
│       ├── bc.info  # bc info 文档
│       └── dc.info  # dc info 文档
└── hnp.json        # HNP 包配置

5.3 构建脚本关键修改

build_ohos.sh 中的关键修改:

  1. 设置 CPP 环境变量
  2. 修复 config.h 宏定义
  3. 确保静态链接

6. 构建验证

6.1 构建命令

cd /Users/lijiajun/ohos-sdk/HarmonyOSPC/build
SPECIFIC_DIR=bc-1.08.2 ./build.sh --sdk /Users/lijiajun/ohos-sdk

6.2 构建输出

构建成功后,在 output/ 目录下生成:

output/
├── bc.hnp                    # HNP 包文件
└── ohos_bc_1.08.2.tar.gz     # tar.gz 压缩包

6.3 构建日志关键信息

Configuring bc for cross-compilation...
Target platform: aarch64-linux-ohos
Sysroot: /Users/lijiajun/ohos-sdk/native/sysroot

checking for vprintf... yes
checking for getopt_long... yes

Fixing missing macro definitions in config.h...
  - Fixing HAVE_UNISTD_H...
  - Fixing HAVE_VPRINTF...
  - Fixing PACKAGE, VERSION, BC_COPYRIGHT macros...

Building bc...
make -j4

Installing bc...
make install DESTDIR=build_temp

bc and dc installed successfully
Binary file types:
bin/bc: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked
bin/dc: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked

Packing HNP package...
Build completed successfully!

6.4 安装与使用

6.4.1 方式一:使用 HNP 包安装
# 在 鸿蒙PC 上执行
hnp install bc.hnp

# 或使用 tar.gz 包
tar -xzf ohos_bc_1.08.2.tar.gz
cp -r bc_1.08.2/* /data/service/hnp/bc.org/bc_1.08.2/
6.4.2 方式二:手动安装
# 创建安装目录
sudo mkdir -p /data/service/hnp/bc.org/bc_1.08.2/{bin,share/man/man1,share/info}

# 复制文件
sudo cp bc /data/service/hnp/bc.org/bc_1.08.2/bin/
sudo cp dc /data/service/hnp/bc.org/bc_1.08.2/bin/
sudo cp bc.1 /data/service/hnp/bc.org/bc_1.08.2/share/man/man1/
sudo cp dc.1 /data/service/hnp/bc.org/bc_1.08.2/share/man/man1/
sudo cp hnp.json /data/service/hnp/bc.org/bc_1.08.2/

# 设置执行权限
sudo chmod +x /data/service/hnp/bc.org/bc_1.08.2/bin/bc
sudo chmod +x /data/service/hnp/bc.org/bc_1.08.2/bin/dc

# 添加到 PATH
export PATH=$PATH:/data/service/hnp/bc.org/bc_1.08.2/bin
6.4.3 验证安装
# 检查二进制文件
ls -la /data/service/hnp/bc.org/bc_1.08.2/bin/bc
ls -la /data/service/hnp/bc.org/bc_1.08.2/bin/dc

# 检查版本
/data/service/hnp/bc.org/bc_1.08.2/bin/bc --version
/data/service/hnp/bc.org/bc_1.08.2/bin/dc --version

# 测试基本功能
echo "2 + 2" | bc
echo "4" | dc

7. 使用示例

7.1 基本算术运算

# 加法
echo "10 + 20" | bc
# 输出: 30

# 减法
echo "100 - 50" | bc
# 输出: 50

# 乘法
echo "5 * 6" | bc
# 输出: 30

# 除法
echo "100 / 4" | bc
# 输出: 25

# 幂运算
echo "2 ^ 8" | bc
# 输出: 256

7.2 精度控制

# 设置小数位数(scale)
echo "scale=10; 22/7" | bc
# 输出: 3.1428571428

# 高精度计算
echo "scale=50; 4*a(1)" | bc -l
# 输出: 3.14159265358979323846264338327950288419716939937510
# (计算 π,使用数学库)

7.3 变量和表达式

# 使用变量
echo "a=10; b=20; a+b" | bc
# 输出: 30

# 复杂表达式
echo "x=5; y=3; x^y + x*y" | bc
# 输出: 140

7.4 脚本模式

创建 calc.bc 文件:

#!/usr/bin/bc -q

# 计算圆的面积
define circle_area(r) {
    return 3.14159 * r * r
}

# 计算圆的周长
define circle_circumference(r) {
    return 2 * 3.14159 * r
}

# 使用示例
r = 5
print "半径: ", r, "\n"
print "面积: ", circle_area(r), "\n"
print "周长: ", circle_circumference(r), "\n"

执行脚本:

bc calc.bc
# 输出:
# 半径: 5
# 面积: 78.53975
# 周长: 31.41590

7.5 交互式模式

# 启动交互式 bc
bc

# 在交互式环境中执行:
# bc> 10 + 20
# 30
# bc> scale=5
# bc> 22/7
# 3.14285
# bc> quit

7.6 使用数学库

# 计算平方根
echo "sqrt(16)" | bc -l
# 输出: 4

# 计算正弦值
echo "s(3.14159/2)" | bc -l
# 输出: .99999999999999999998

# 计算自然对数
echo "l(2.71828)" | bc -l
# 输出: .99999932734753190476

7.7 进制转换

# 十进制转二进制
echo "obase=2; 255" | bc
# 输出: 11111111

# 二进制转十进制
echo "ibase=2; 11111111" | bc
# 输出: 255

# 十六进制转十进制
echo "ibase=16; FF" | bc
# 输出: 255

7.8 条件语句和循环

创建 factorial.bc

#!/usr/bin/bc -q

# 计算阶乘
define factorial(n) {
    if (n <= 1) return 1
    return n * factorial(n - 1)
}

# 计算 10 的阶乘
print "10! = ", factorial(10), "\n"

执行:

bc factorial.bc
# 输出: 10! = 3628800

7.9 文件处理

# 从文件读取表达式
echo "10 + 20" > expr.txt
bc expr.txt
# 输出: 30

# 处理多个表达式
cat > calc.txt << EOF
scale=2
10/3
20/7
30/11
EOF

bc calc.txt
# 输出:
# 3.33
# 2.85
# 2.72

7.10 与其他命令组合

# 计算文件大小总和(字节转 MB)
ls -l | awk '{sum+=$5} END {print sum}' | bc
echo "scale=2; $(ls -l | awk '{sum+=$5} END {print sum}') / 1024 / 1024" | bc
# 输出文件总大小(MB)

# 在脚本中使用
#!/bin/sh
result=$(echo "10 * 20" | bc)
echo "计算结果: $result"

7.11 dc(逆波兰计算器)示例

# dc 使用逆波兰表示法(RPN)
echo "10 20 + p" | dc
# 输出: 30
# 说明: 10 和 20 入栈,+ 执行加法,p 打印结果

# 复杂计算
echo "10 20 * 5 + p" | dc
# 输出: 205
# 说明: 10*20+5 = 205

# 使用变量
echo "10 sa 20 sb sa lb + p" | dc
# 输出: 30
# 说明: sa 存储到寄存器 a,lb 加载寄存器 b

8. 总结与最佳实践

8.1 技术挑战总结

8.1.1 主要挑战
  1. config.h 创建问题:configure 执行后 config.h 可能未正确创建
  2. 宏定义缺失:交叉编译时 configure 无法正确检测系统功能
  3. CPP 环境变量:需要正确设置 C 预处理器
  4. 静态链接:确保零运行时依赖
8.1.2 解决方案
  1. 强制创建 config.h:使用 config.status --file=config.h
  2. 宏定义修复:在构建脚本中自动修复缺失的宏定义
  3. CPP 设置:明确设置 CPP="${CC} -E --target=..." --sysroot=...
  4. 静态链接:使用 -static 链接选项

8.2 测试验证

8.2.1 功能测试
# 基本算术测试
echo "2+2" | bc
# 预期输出: 4

# 精度测试
echo "scale=10; 22/7" | bc
# 预期输出: 3.1428571428

# 数学库测试
echo "sqrt(16)" | bc -l
# 预期输出: 4
8.2.2 兼容性测试
  • ✅ 基本算术运算
  • ✅ 高精度计算
  • ✅ 数学库函数
  • ✅ 脚本执行
  • ✅ 交互式模式
  • ✅ 进制转换

8.3 项目总结

8.3.1 成功要点
  1. 零外部依赖:通过静态链接实现,无需安装额外的运行时库
  2. 完整功能:支持 bc 和 dc 两个工具,功能完整
  3. 易于使用:遵循 POSIX 标准,语法简单易学
  4. 高性能:任意精度计算,满足复杂数学计算需求
8.3.2 应用场景
  1. 系统脚本:在 shell 脚本中进行精确的数学计算
  2. 数据处理:处理需要高精度的数值计算任务
  3. 教学工具:作为数学教学和学习的辅助工具
  4. 科学计算:进行科学计算和工程计算
8.3.3 后续优化建议
  1. 性能优化:针对 ARM 架构进行编译优化
  2. 功能扩展:考虑添加更多数学函数
  3. 文档完善:补充中文使用文档和示例

8.4 相关资源

  • GNU bc 官方文档:https://www.gnu.org/software/bc/manual/

📎 附录

A. 📁 完整文件清单

📝 创建的文件:

  • 🔧 build_ohos.sh - OpenHarmony构建脚本
  • 📝 hnp.json - HNP包配置文件
  • 📄 CHANGELOG - 变更日志(添加鸿蒙PC适配信息)
  • 📄 README.OPENSOURCE - 开源说明文档

📝 修改的文件:

  • 🔧 build_ohos.sh - 配置交叉编译、修复config.h宏定义、静态链接

📦 生成的文件:

  • 📦 output/bc.hnp - HNP格式安装包
  • 📦 output/ohos_bc_1.08.2.tar.gz - tar.gz格式发布包

B. 💻 参考命令

# 构建命令
cd /Users/lijiajun/ohos-sdk/HarmonyOSPC/build
SPECIFIC_DIR=bc-1.08.2 ./build.sh --sdk /Users/lijiajun/ohos-sdk

# 查看构建输出
ls -lh output/ | grep bc

# 验证安装目录
tree ${HNP_PUBLIC_PATH}/bc.org/bc_1.08.2/

# 验证二进制文件格式(在macOS上)
file ${HNP_PUBLIC_PATH}/bc.org/bc_1.08.2/bin/bc
file ${HNP_PUBLIC_PATH}/bc.org/bc_1.08.2/bin/dc
# 应该显示: ELF 64-bit LSB executable, ARM aarch64, statically linked

# 测试命令(在鸿蒙PC上)
export PATH=${HNP_PUBLIC_PATH}/bc.org/bc_1.08.2/bin:$PATH
bc --version
dc --version
echo "2+2" | bc
echo "10 20 + p" | dc

# 如果出现"cannot execute binary file"错误,检查:
# 1. 二进制文件格式是否正确(应为ELF格式)
# 2. 是否使用了交叉编译(--host=aarch64-unknown-linux-musl)
# 3. 链接方式是否为静态链接(-static)

C. 📌 版本信息

  • 📁 bc版本: 1.08.2
  • 📅 适配日期: 2025-12-09
  • 🎯 目标平台: aarch64-linux-ohos
  • 🔧 构建系统: Autotools (autoconf + automake)
  • 📦 依赖数量: 零外部运行时依赖(静态链接)
  • 🔗 源仓库地址: https://www.gnu.org/software/bc/
  • 🔗 适配完成仓库地址: https://gitcode.com/szkygc/bc4oh

D. 📚 相关资源

  • 🌐 GNU bc官方文档: https://www.gnu.org/software/bc/manual/
  • 💻 GNU bc下载: https://ftp.gnu.org/gnu/bc/
  • 🌐 OpenHarmony PC开发者专区: https://gitcode.com/OpenHarmonyPCDeveloper
  • 🌐 HarmonyOS PC 开发者社区: https://harmonypc.csdn.net/content

E. 💡 技术说明

任意精度计算简介

bc提供了强大的任意精度数值计算能力:

  1. 精度控制: 通过scale变量设置小数位数,不受浮点数精度限制
  2. 数学库: 使用-l选项加载数学库,支持sin、cos、sqrt、log等函数
  3. 脚本支持: 支持函数定义、条件语句、循环等编程特性
  4. 进制转换: 支持二进制、八进制、十进制、十六进制之间的转换

bc的优势

  • ✅ 任意精度:不受浮点数精度限制
  • ✅ 零依赖:静态链接,无需外部运行时库
  • ✅ 双工具:同时提供bc和dc两个工具
  • ✅ POSIX兼容:遵循POSIX标准,易于使用

🎉 结语

本文档详细介绍了bc任意精度计算器在鸿蒙PC平台上的适配过程。通过配置交叉编译、修复config.h宏定义、实现静态链接等问题,成功实现了bc和dc在鸿蒙PC平台上的部署。

bc工具为终端应用开发提供了强大的数学计算支持,是开发脚本工具和数据处理的重要基础工具。希望本文档能够帮助开发者:

  • 📊 理解任意精度计算的使用
  • 🔧 掌握Autotools项目适配OpenHarmony的方法
  • 📦 了解HNP包的构建和打包流程
  • 💻 学习命令行工具的开发实践

💬 如有问题或建议,欢迎反馈!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐