当前位置: 首页 > news >正文

bcal 适配 HarmonyOS 构建指南

欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/

项目说明
三方库名称bcal
开源协议GPLv3
源码版本2.4.0
目标平台鸿蒙PC
依赖项libc;可选 GNU Readline/Editline、GNUbccalc(鸿蒙构建中禁用 readline,使用 stub)
操作系统平台macos
原仓库地址https://github.com/jarun/bcal
鸿蒙化适配仓库地址https://gitcode.com/nutpi/bcal
交叉编译环境https://atomgit.com/OpenHarmonyPCDeveloper/build
hnp包验证环境https://bxming.blog.csdn.net/article/details/155073889

项目简介

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 工具介绍

安装方式

从源码安装
gitclone https://github.com/jarun/bcal.gitcdbcalmakestripinstall
依赖项
  • 标准 C 库:libc
  • GNU ReadlineBSD Editline:用于交互式输入(可选)
  • GNU bccalc:用于通用数值计算(可选)

基本使用

命令行选项
usage: bcal[-c N][-f loc][-s bytes][expr][N[unit]][-b[expr]][-m][-d][-h]Storage expression calculator. positional arguments:exprexpressionindecimal/hex operands N[unit]capacityinB/KiB/MiB/GiB/TiB/kB/MB/GB/TB default unit is B(byte),caseis ignored N can be decimal or'0x'prefixed hex value optional arguments:-cN show +ve integer Ninbinary, decimal, hex-floc convert CHS to LBA or LBA to CHS-sbytes sector size[default512]-b[expr]enterbcmode or evaluate expressioninbc-mshow minimal output(e.g. decimal bytes)-denabledebug information and logs-hshow thishelp
使用示例
  1. 计算存储表达式
$ bcal"(5kb+2mb)/3"$ bcal"5 tb / 12"$ bcal"(2giB * 2) / (2kib >> 2)"
  1. 单位转换
$ bcal20140115b $ bcal 0x1335053 B $ bcal 0xaabbcc kb $ bcal 0xdef Gib
  1. LBA/CHS 转换
$ bcal-fl500 $ bcal-fc10-10-10
  1. 进制转换
$ bcal-c20140115$ bcal-c0b1001100110101000001010011 $ bcal-c0x1335053
  1. 交互模式
$ bcal bcal>15gib +15kib bcal>r /5bcal>?

适配 HarmonyOS 的准备工作

1. 项目结构

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

2. HNP 配置文件

创建hnp.json文件:

{"type":"hnp-config","name":"bcal","version":"2.4.0","install":{}}

3. 构建脚本框架

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

#!/bin/bash# bcal HarmonyOS 构建脚本exportBCAL_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/bcal.org/bcal_2.4.0sys_prefix=${PREFIX}exportPREFIX=${BCAL_INSTALL_HNP_PATH}echo"${PREFIX}"# 创建安装目录mkdir-p${BCAL_INSTALL_HNP_PATH}# 构建和安装makecleanmakeVERBOSE=1makeinstall# 复制 HNP 配置文件cphnp.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/popdexportPREFIX=${sys_prefix}

构建脚本实现

完整的 build_ohos.sh

#!/bin/bash# ============================================================================# build_ohos.sh - bcal 工具 HarmonyOS 构建脚本# ============================================================================# 设置 HNP 安装路径exportBCAL_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/bcal.org/bcal_2.4.0# 保存并临时修改 PREFIXsys_prefix=${PREFIX}exportPREFIX=${BCAL_INSTALL_HNP_PATH}echo"${PREFIX}"# 创建安装目录(确保目录存在)mkdir-p${BCAL_INSTALL_HNP_PATH}# 清理之前的构建产物makeclean# 编译时禁用 readline(使用 stub 实现)# HarmonyOS SDK 中没有 readline 库,需要使用自定义的 stub 实现makeVERBOSE=1CPPFLAGS="-UHAVE_READLINE"LDLIBS_READLINE=""||{echo"Error: make failed"exit1}# 安装makeinstall||{echo"Error: make install failed"exit1}# 复制 HNP 配置文件cphnp.json${BCAL_INSTALL_HNP_PATH}/||{echo"Error: failed to copy hnp.json"exit1}# 打包if[-d"${BCAL_INSTALL_HNP_PATH}"];thenpushd${BCAL_INSTALL_HNP_PATH}/../>/dev/null${HNP_TOOL}pack-i${BCAL_INSTALL_HNP_PATH}-o${ARCHIVE_PATH}/||{echo"Error: HNP pack failed"popd>/dev/nullexportPREFIX=${sys_prefix}exit1}tar-zvcf${ARCHIVE_PATH}/ohos_bcal_2.4.0.tar.gz bcal_2.4.0/||{echo"Error: tar failed"popd>/dev/nullexportPREFIX=${sys_prefix}exit1}popd>/dev/nullelseecho"Error: Installation directory does not exist:${BCAL_INSTALL_HNP_PATH}"exportPREFIX=${sys_prefix}exit1fi# 恢复 PREFIXexportPREFIX=${sys_prefix}

遇到的问题与解决方案

问题一:clang-15 链接器参数语法变更

错误现象
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

修改前:

exportCFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM}-fuse-ld=${LD}--sysroot=${SYSROOT}"exportLDFLAGS="${LDFLAGS}-fuse-ld=${LD}--target=${TARGET_PLATFORM}--sysroot=${SYSROOT}"

修改后:

exportCFLAGS="-fPIC -D__MUSL__=1 -D__OHOS__ -fstack-protector-strong --target=${TARGET_PLATFORM}--ld-path=${LD}--sysroot=${SYSROOT}"exportLDFLAGS="${LDFLAGS}--ld-path=${LD}--target=${TARGET_PLATFORM}--sysroot=${SYSROOT}"

问题二:readline 库缺失

错误现象
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

#ifndefREADLINE_STUB_H#defineREADLINE_STUB_H#include<stdio.h>#include<stdlib.h>#include<string.h>// Simple readline stub implementation for systems without readlinestaticinlinechar*readline(constchar*prompt){if(prompt){fputs(prompt,stdout);fflush(stdout);}char*line=NULL;size_tlen=0;ssize_tread=getline(&line,&len,stdin);if(read==-1){free(line);returnNULL;}// Remove trailing newlineif(read>0&&line[read-1]=='\n'){line[read-1]='\0';}returnline;}staticinlinevoidadd_history(constchar*line){// Stub: do nothing(void)line;}staticinlineintread_history(constchar*filename){// Stub: do nothing(void)filename;return0;}staticinlineintwrite_history(constchar*filename){// Stub: do nothing(void)filename;return0;}#endif// READLINE_STUB_H

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

#include<getopt.h>#ifdefined(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 特定函数调用:

#ifdefined(HAVE_READLINE)&&HAVE_READLINE==1rl_bind_key('\t',rl_insert);#else// Tab completion not available without readline#endif

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

makeVERBOSE=1CPPFLAGS="-UHAVE_READLINE"LDLIBS_READLINE=""

问题三:构建脚本错误处理不完善

错误现象
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
问题分析

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

解决方案

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

# 创建安装目录(确保目录存在)mkdir-p${BCAL_INSTALL_HNP_PATH}# 添加错误处理makeVERBOSE=1CPPFLAGS="-UHAVE_READLINE"LDLIBS_READLINE=""||{echo"Error: make failed"exit1}makeinstall||{echo"Error: make install failed"exit1}# 打包前检查目录是否存在if[-d"${BCAL_INSTALL_HNP_PATH}"];thenpushd${BCAL_INSTALL_HNP_PATH}/../>/dev/null# ... 打包操作 ...popd>/dev/nullelseecho"Error: Installation directory does not exist"exit1fi

构建结果验证

构建输出

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

  • bcal.hnp- HarmonyOS Native Package 格式包(约 45KB)
  • ohos_bcal_2.4.0.tar.gz- tar.gz 压缩包(约 45KB)

验证命令

# 检查文件是否存在ls-lhoutput/bcal.hnp output/ohos_bcal_2.4.0.tar.gz# 检查 HNP 文件格式fileoutput/bcal.hnp# 查看 tar.gz 内容tar-tzfoutput/ohos_bcal_2.4.0.tar.gz

安装目录结构

bcal_2.4.0/ ├── bin/ │ └── bcal # 可执行文件 ├── hnp.json # HNP 配置文件 └── share/ ├── doc/ │ └── bcal/ │ └── README.md └── man/ └── man1/ └── bcal.1.gz # 手册页

终于编译成功了

使用示例

基本计算

# 计算存储表达式$ bcal"(5kb+2mb)/3"$ bcal"5 tb / 12"$ bcal"(2giB * 2) / (2kib >> 2)"# 单位转换$ bcal20140115b $ bcal 0x1335053 B $ bcal 0xaabbcc kb

LBA/CHS 转换

# LBA 转 CHS$ bcal-fl500 $ bcal-fl0x600-18-0x7e# CHS 转 LBA$ bcal-fc10-10-10 $ bcal-fc0x10-0x10-0x10

进制转换

# 显示二进制、十进制和十六进制$ bcal-c20140115$ bcal-c0b1001100110101000001010011 $ bcal-c0x1335053

交互模式

$ bcal bcal>15gib +15kib bcal>r /5bcal>b# 切换到 bc 模式bcal>?# 显示帮助bcal>q# 退出

管道输入

# 从管道输入$printf'15 kib + 15 gib \n r / 5'|bcal-m# 从文件输入$catexpr15gib +15kib r /5$ bcal-m<expr

总结

适配要点

  1. 链接器参数更新:使用--ld-path=替代已弃用的-fuse-ld=语法
  2. readline 依赖处理:创建 stub 实现,使代码可以在没有 readline 的情况下编译
  3. 错误处理完善:添加完善的错误检查和错误处理机制
  4. 目录管理:确保安装目录在构建前已创建

技术亮点

  • 条件编译:使用条件编译实现 readline 的可选依赖
  • Stub 模式:通过 stub 实现保持代码兼容性
  • 错误恢复:完善的错误处理确保构建过程的可靠性

适用场景

bcal工具特别适用于:

  • 存储系统开发:计算存储容量、地址转换
  • 文件系统开发:LBA/CHS 转换
  • 系统管理:存储单位转换和计算
  • 嵌入式开发:处理二进制前缀和地址计算

参考资源

  • bcal 官方仓库
  • HarmonyOS 原生应用开发文档
  • GNU Readline 文档
http://www.jsqmd.com/news/648209/

相关文章:

  • RVC变声器完整指南:10分钟训练高质量AI音色的终极教程
  • Knwl.js插件依赖管理终极指南:实现插件间高效数据共享与协作
  • 终极指南:如何通过Easy Rules监控和分析Java规则引擎运行历史
  • 如何自定义CodeLlama对话模板:打造企业专属交互体验
  • PyQt5入门实战:从零实现一个表达式输入式计算器(附完整代码)
  • lingbot-depth-pretrain-vitl-14部署案例:平台镜像市场一键部署ins-lingbot-depth-vitl14-v1
  • Chart.js项目实战:AI产业应用广度监控系统
  • LFE shell脚本编程:从零开始编写可执行的Lisp脚本
  • 如何快速开始RAGEN:5分钟部署你的第一个AI智能体
  • 如何在5分钟内将SDS动态字符串库集成到您的C项目中:完整配置指南
  • 知识表示学习避坑指南:TransE算法中的5个常见错误与调试技巧
  • ROS2与gh_mirrors/si/simulator的完美集成:现代自动驾驶开发最佳实践
  • 多模态大模型版本失控?3类致命陷阱正在拖垮你的AIGC产线(附NASA级版本溯源Checklist)
  • Google Maps Scraper深度解析:架构设计与核心技术实现
  • Brave安全实践:如何在生产环境中安全部署分布式追踪系统
  • 巧用Simscape Multibody位置控制实现高精度关节速度跟踪
  • 别再死记硬背了!用‘快递系统’类比彻底搞懂AUTOSAR CAN通信栈(附信号/PDU/报文关系图)
  • Katran与Kubernetes集成:云原生负载均衡终极指南
  • HTML5解析终极指南:gumbo-parser纯C库架构演进与设计变迁史
  • Blowfish主题SEO优化:让你的网站在搜索引擎中脱颖而出的7个策略
  • 知识图谱维护的‘隐形杀手’:我们如何用Cypher脚本和人工审核搞定数据质量评估?
  • 大规模向量索引构建实战:pgvectorscale并行构建与内存优化
  • 开发者高效学习法:1年掌握3年经验的秘密
  • 手把手教你将IgH EtherCAT Master移植到ARM开发板(Linux 4.19内核适配指南)
  • Kured高级时间窗口管理:如何设置精确的重启调度策略
  • 性能基准测试完全手册:如何验证pgvectorscale的28倍性能提升
  • 从‘遍地都是’到‘最新版本’:聊聊H5st参数演变与前端风控对抗的那些事儿
  • 软件市场中的产品定位与竞争策略
  • Gitify跨平台适配终极指南:macOS、Windows和Linux的统一通知体验
  • VScode:从零开始配置C/C++开发环境的完整教程