首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >bcal 适配 HarmonyOS 构建指南

bcal 适配 HarmonyOS 构建指南

作者头像
红目香薰
发布2025-12-16 16:56:33
发布2025-12-16 16:56:33
110
举报
文章被收录于专栏:CSDNToQQCodeCSDNToQQCode

目录

  • 项目简介
  • bcal 工具介绍
  • 适配 HarmonyOS 的准备工作
  • 构建脚本实现
  • 遇到的问题与解决方案
  • 构建结果验证
  • 使用示例
  • 总结

项目简介

bcal (Byte CALculator) 是一个 REPL(Read-Eval-Print Loop)命令行工具,用于存储表达式计算、SI/IEC 单位转换、字节地址计算、进制转换和 LBA/CHS 计算。对于经常处理位、字节、地址和二进制前缀的开发者来说非常有用。

主要特性
  • REPL 和单次执行模式:支持交互式和命令行参数两种使用方式
  • 存储单位表达式计算:支持 KiB、MiB、GiB、TiB、kB、MB、GB、TB 等单位
  • 通用计算器模式:可以使用 bccalc 进行通用数值计算
  • 管道输入支持:支持从管道或文件重定向输入
  • IEC/SI 标准转换:支持二进制和十进制前缀转换
  • 交互模式:存储最后一次有效结果供重复使用
  • 地址显示:以字节、LBA:OFFSET 格式显示地址
  • CHS/LBA 转换:支持 CHS 到 LBA 的相互转换
  • 进制转换:支持二进制、十进制和十六进制转换
  • 自定义参数:可自定义扇区大小、最大磁头数/柱面和最大扇区/磁道

bcal 工具介绍

安装方式
从源码安装
代码语言:javascript
复制
git clone https://github.com/jarun/bcal.git
cd bcal
make strip install

下载到本地

在这里插入图片描述
在这里插入图片描述
依赖项
  • 标准 C 库:libc
  • GNU ReadlineBSD Editline:用于交互式输入(可选)
  • GNU bccalc:用于通用数值计算(可选)
基本使用
命令行选项
代码语言:javascript
复制
usage: bcal [-c N] [-f loc] [-s bytes] [expr]
            [N [unit]] [-b [expr]] [-m] [-d] [-h]

Storage expression calculator.

positional arguments:
 expr       expression in decimal/hex operands
 N [unit]   capacity in B/KiB/MiB/GiB/TiB/kB/MB/GB/TB
            default unit is B (byte), case is ignored
            N can be decimal or '0x' prefixed hex value

optional arguments:
 -c N       show +ve integer N in binary, decimal, hex
 -f loc     convert CHS to LBA or LBA to CHS
 -s bytes   sector size [default 512]
 -b [expr]  enter bc mode or evaluate expression in bc
 -m         show minimal output (e.g. decimal bytes)
 -d         enable debug information and logs
 -h         show this help
使用示例
  1. 计算存储表达式
代码语言:javascript
复制
$ bcal "(5kb+2mb)/3"
$ bcal "5 tb / 12"
$ bcal "(2giB * 2) / (2kib >> 2)"
  1. 单位转换
代码语言:javascript
复制
$ bcal 20140115 b
$ bcal 0x1335053 B
$ bcal 0xaabbcc kb
$ bcal 0xdef Gib
  1. LBA/CHS 转换
代码语言:javascript
复制
$ bcal -f l500
$ bcal -f c10-10-10
  1. 进制转换
代码语言:javascript
复制
$ bcal -c 20140115
$ bcal -c 0b1001100110101000001010011
$ bcal -c 0x1335053
  1. 交互模式
代码语言:javascript
复制
$ bcal
bcal> 15 gib + 15 kib
bcal> r / 5
bcal> ?

适配 HarmonyOS 的准备工作

1. 项目结构
代码语言:javascript
复制
code/bcal/
├── build_ohos.sh      # HarmonyOS 构建脚本
├── hnp.json           # HNP 包配置文件
├── Makefile           # 构建文件
├── src/
│   ├── bcal.c         # 主程序源码
│   └── readline_stub.h # readline 替代实现
├── inc/               # 头文件目录
└── README.md          # 项目说明
2. HNP 配置文件

创建 hnp.json 文件:

代码语言:javascript
复制
{
    "type":"hnp-config",
    "name":"bcal",
    "version":"2.4.0",
    "install":{}
}
3. 构建脚本框架

创建 build_ohos.sh 脚本,参考其他项目的构建脚本结构:

代码语言:javascript
复制
#!/bin/bash
# bcal HarmonyOS 构建脚本

export BCAL_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/bcal.org/bcal_2.4.0

sys_prefix=${PREFIX}
export PREFIX=${BCAL_INSTALL_HNP_PATH}
echo "${PREFIX}"

# 创建安装目录
mkdir -p ${BCAL_INSTALL_HNP_PATH}

# 构建和安装
make clean
make VERBOSE=1
make install

# 复制 HNP 配置文件
cp hnp.json ${BCAL_INSTALL_HNP_PATH}/

# 打包
pushd ${BCAL_INSTALL_HNP_PATH}/../
    ${HNP_TOOL} pack -i ${BCAL_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
    tar -zvcf ${ARCHIVE_PATH}/ohos_bcal_2.4.0.tar.gz bcal_2.4.0/
popd

export PREFIX=${sys_prefix}

构建脚本实现

完整的 build_ohos.sh
代码语言:javascript
复制
#!/bin/bash
# ============================================================================
# build_ohos.sh - bcal 工具 HarmonyOS 构建脚本
# ============================================================================

# 设置 HNP 安装路径
export BCAL_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/bcal.org/bcal_2.4.0

# 保存并临时修改 PREFIX
sys_prefix=${PREFIX}
export PREFIX=${BCAL_INSTALL_HNP_PATH}
echo "${PREFIX}"

# 创建安装目录(确保目录存在)
mkdir -p ${BCAL_INSTALL_HNP_PATH}

# 清理之前的构建产物
make clean

# 编译时禁用 readline(使用 stub 实现)
# HarmonyOS SDK 中没有 readline 库,需要使用自定义的 stub 实现
make VERBOSE=1 CPPFLAGS="-UHAVE_READLINE" LDLIBS_READLINE="" || {
    echo "Error: make failed"
    exit 1
}

# 安装
make install || {
    echo "Error: make install failed"
    exit 1
}

# 复制 HNP 配置文件
cp hnp.json ${BCAL_INSTALL_HNP_PATH}/ || {
    echo "Error: failed to copy hnp.json"
    exit 1
}

# 打包
if [ -d "${BCAL_INSTALL_HNP_PATH}" ]; then
    pushd ${BCAL_INSTALL_HNP_PATH}/../ > /dev/null
        ${HNP_TOOL} pack -i ${BCAL_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_bcal_2.4.0.tar.gz bcal_2.4.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: ${BCAL_INSTALL_HNP_PATH}"
    export PREFIX=${sys_prefix}
    exit 1
fi

# 恢复 PREFIX
export PREFIX=${sys_prefix}

遇到的问题与解决方案

问题一:clang-15 链接器参数语法变更
错误现象
代码语言:javascript
复制
clang-15: error: '-fuse-ld=' taking a path is deprecated; use '--ld-path=' instead [-Werror,-Wfuse-ld-path]
问题分析

clang-15 编译器不再支持 -fuse-ld=/path/to/ld 的语法,需要使用新的 --ld-path=/path/to/ld 语法。

解决方案

build.sh 中修改 CFLAGSLDFLAGS

修改前:

代码语言:javascript
复制
export CFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM} -fuse-ld=${LD} --sysroot=${SYSROOT}"
export LDFLAGS="${LDFLAGS} -fuse-ld=${LD} --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"

修改后:

代码语言:javascript
复制
export CFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM} --ld-path=${LD} --sysroot=${SYSROOT}"
export LDFLAGS="${LDFLAGS} --ld-path=${LD} --target=${TARGET_PLATFORM} --sysroot=${SYSROOT}"
问题二:readline 库缺失
错误现象
代码语言:javascript
复制
src/bcal.c:31:10: fatal error: 'readline/history.h' file not found
#include <readline/history.h>
         ^~~~~~~~~~~~~~~~~~~~
问题分析

HarmonyOS SDK 的 sysroot 中没有 readline 库。bcal 默认依赖 readline 用于交互式输入,但该功能在 HarmonyOS 环境中不可用。

解决方案

创建 readline 的 stub 实现,使代码可以在没有 readline 的情况下编译:

1. 创建 src/readline_stub.h

代码语言:javascript
复制
#ifndef READLINE_STUB_H
#define READLINE_STUB_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Simple readline stub implementation for systems without readline
static inline char *readline(const char *prompt) {
    if (prompt) {
        fputs(prompt, stdout);
        fflush(stdout);
    }
    
    char *line = NULL;
    size_t len = 0;
    ssize_t read = getline(&line, &len, stdin);
    
    if (read == -1) {
        free(line);
        return NULL;
    }
    
    // Remove trailing newline
    if (read > 0 && line[read - 1] == '\n') {
        line[read - 1] = '\0';
    }
    
    return line;
}

static inline void add_history(const char *line) {
    // Stub: do nothing
    (void)line;
}

static inline int read_history(const char *filename) {
    // Stub: do nothing
    (void)filename;
    return 0;
}

static inline int write_history(const char *filename) {
    // Stub: do nothing
    (void)filename;
    return 0;
}

#endif // READLINE_STUB_H

2. 修改 src/bcal.c 使用条件编译:

代码语言:javascript
复制
#include <getopt.h>
#if defined(HAVE_READLINE) && HAVE_READLINE == 1
#include <readline/history.h>
#include <readline/readline.h>
#else
#include "readline_stub.h"
#endif
#include "dslib.h"
#include "log.h"

3. 处理 readline 特定函数调用:

代码语言:javascript
复制
#if defined(HAVE_READLINE) && HAVE_READLINE == 1
    rl_bind_key('\t', rl_insert);
#else
    // Tab completion not available without readline
#endif

4. 在构建脚本中禁用 readline:

代码语言:javascript
复制
make VERBOSE=1 CPPFLAGS="-UHAVE_READLINE" LDLIBS_READLINE=""
问题三:构建脚本错误处理不完善
错误现象
代码语言:javascript
复制
cp: directory /Users/jianguo/HarmonyOSPC/build/data/service/hnp/bcal.org/bcal_2.4.0 does not exist
pushd: /Users/jianguo/HarmonyOSPC/build/data/service/hnp/bcal.org/bcal_2.4.0/../: No such file or directory
popd: directory stack empty
问题分析

构建脚本缺少错误处理和目录检查,导致在编译失败时后续步骤无法正确执行。

解决方案

添加完善的错误处理和目录检查:

代码语言:javascript
复制
# 创建安装目录(确保目录存在)
mkdir -p ${BCAL_INSTALL_HNP_PATH}

# 添加错误处理
make VERBOSE=1 CPPFLAGS="-UHAVE_READLINE" LDLIBS_READLINE="" || {
    echo "Error: make failed"
    exit 1
}

make install || {
    echo "Error: make install failed"
    exit 1
}

# 打包前检查目录是否存在
if [ -d "${BCAL_INSTALL_HNP_PATH}" ]; then
    pushd ${BCAL_INSTALL_HNP_PATH}/../ > /dev/null
        # ... 打包操作 ...
    popd > /dev/null
else
    echo "Error: Installation directory does not exist"
    exit 1
fi

构建结果验证

构建输出

成功构建后,会在 output/ 目录下生成以下文件:

  • bcal.hnp - HarmonyOS Native Package 格式包(约 45KB)
  • ohos_bcal_2.4.0.tar.gz - tar.gz 压缩包(约 45KB)
验证命令
代码语言:javascript
复制
# 检查文件是否存在
ls -lh output/bcal.hnp output/ohos_bcal_2.4.0.tar.gz

# 检查 HNP 文件格式
file output/bcal.hnp

# 查看 tar.gz 内容
tar -tzf output/ohos_bcal_2.4.0.tar.gz
安装目录结构
代码语言:javascript
复制
bcal_2.4.0/
├── bin/
│   └── bcal              # 可执行文件
├── hnp.json              # HNP 配置文件
└── share/
    ├── doc/
    │   └── bcal/
    │       └── README.md
    └── man/
        └── man1/
            └── bcal.1.gz  # 手册页

终于编译成功了

使用示例

基本计算
代码语言:javascript
复制
# 计算存储表达式
$ bcal "(5kb+2mb)/3"
$ bcal "5 tb / 12"
$ bcal "(2giB * 2) / (2kib >> 2)"

# 单位转换
$ bcal 20140115 b
$ bcal 0x1335053 B
$ bcal 0xaabbcc kb
LBA/CHS 转换
代码语言:javascript
复制
# LBA 转 CHS
$ bcal -f l500
$ bcal -f l0x600-18-0x7e

# CHS 转 LBA
$ bcal -f c10-10-10
$ bcal -f c0x10-0x10-0x10
进制转换
代码语言:javascript
复制
# 显示二进制、十进制和十六进制
$ bcal -c 20140115
$ bcal -c 0b1001100110101000001010011
$ bcal -c 0x1335053
交互模式
代码语言:javascript
复制
$ bcal
bcal> 15 gib + 15 kib
bcal> r / 5
bcal> b          # 切换到 bc 模式
bcal> ?          # 显示帮助
bcal> q          # 退出
管道输入
代码语言:javascript
复制
# 从管道输入
$ printf '15 kib + 15 gib \n r / 5' | bcal -m

# 从文件输入
$ cat expr
15 gib + 15 kib
r / 5
$ bcal -m < expr

总结

适配要点
  1. 链接器参数更新:使用 --ld-path= 替代已弃用的 -fuse-ld= 语法
  2. readline 依赖处理:创建 stub 实现,使代码可以在没有 readline 的情况下编译
  3. 错误处理完善:添加完善的错误检查和错误处理机制
  4. 目录管理:确保安装目录在构建前已创建
技术亮点
  • 条件编译:使用条件编译实现 readline 的可选依赖
  • Stub 模式:通过 stub 实现保持代码兼容性
  • 错误恢复:完善的错误处理确保构建过程的可靠性
适用场景

bcal 工具特别适用于:

  • 存储系统开发:计算存储容量、地址转换
  • 文件系统开发:LBA/CHS 转换
  • 系统管理:存储单位转换和计算
  • 嵌入式开发:处理二进制前缀和地址计算
参考资源
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 项目简介
    • 主要特性
  • bcal 工具介绍
    • 安装方式
      • 从源码安装
      • 依赖项
    • 基本使用
      • 命令行选项
      • 使用示例
  • 适配 HarmonyOS 的准备工作
    • 1. 项目结构
    • 2. HNP 配置文件
    • 3. 构建脚本框架
  • 构建脚本实现
    • 完整的 build_ohos.sh
  • 遇到的问题与解决方案
    • 问题一:clang-15 链接器参数语法变更
      • 错误现象
      • 问题分析
      • 解决方案
    • 问题二:readline 库缺失
      • 错误现象
      • 问题分析
      • 解决方案
    • 问题三:构建脚本错误处理不完善
      • 错误现象
      • 问题分析
      • 解决方案
  • 构建结果验证
    • 构建输出
    • 验证命令
    • 安装目录结构
  • 使用示例
    • 基本计算
    • LBA/CHS 转换
    • 进制转换
    • 交互模式
    • 管道输入
  • 总结
    • 适配要点
    • 技术亮点
    • 适用场景
    • 参考资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档