news 2026/2/8 14:49:27

蓝香蕉代码 |【鸿蒙命令行 hdc/bash/hnpcli】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
蓝香蕉代码 |【鸿蒙命令行 hdc/bash/hnpcli】

鸿蒙开发命令

上次介绍了lycium_plusplus项目,用于C/C++库的开发,同时也简单展示了tree命令在迁移到该项目后的适配方式,在框架中,我们频繁用到了cmakemake等编译框架相关的工具链,这些工具链前期也在鸿蒙电脑上完成了适配,考虑了下,lycium++可能已经基本具备在鸿蒙电脑上进行C/C++代码编译的基本条件,重新梳理后,我们的项目中前期已经预埋了在鸿蒙电脑上编译的分支,这次想想,一次性把几个重大阻碍进行了适配;

  • bash鸿蒙电脑最新的版本打开终端后,提供了一个zsh的解释器,zsh大名鼎鼎,但对于广泛的bash脚本的兼容性,并不是想想的那么完美,于是引入一个bash显得还是很有必要性的
  • hnpcli我们在鸿蒙电脑上发布命令行的方式仍然以DevBox + hnp为主,因此hnpcli打包工具也是必要的
  • hdchdc作为OpenHarmony官方的开源设备调试器,没有当然不行

基于这三个场景,最近几天将这些命令进行了适配:

框架的改造

由于我们是基于tpc_c_cplusplus升级的框架,其中有部分库已经疏于维护或其他原因,不足以满足使用,在适配这三个命令的过程中,我们对框架进行了又一次的改造,这次调整了依赖顺序,优先依赖outerrepo中引入的库(这部分库至少我会在长期进行编译验证,确保编译时成功的)

此时,在HPKBUILD框架中,依赖的顺序变成了 outer > thirdparty > community,方便我们在处理一些疏于维护的库时,可以自行引入

hnpcli

hnpcli是一个制作OpenHarmony Native package(hnp)的命令行工具,主要在我们框架中承担打包xxx.hnp的动作,这个命令如何编译这里就不再赘述,直接按照代码仓的介绍就可以hnpcli,这里重点讲讲这个命令适配时,都做了什么

源码获取

在构建hnpcli命令前,首先是找到源码,这是个头疼的问题,我尽管使用了很多次,却并不知道他的源码在哪里,迫不得已重新下载了OpenHarmony的全量源码后,通过检索hnpcli的方式找到了代码仓,其位于startup_appspawn中,appspawn官方名称为应用孵化器部件,这时候也就理解了,hnp作为应用的一部分理应归属这里

找到hnp的目录service/hnp,readme也详细介绍了native软件包开发的指南,这也是我们前期在DevBox中新增和发布命令的主要来源

一切都对上了,接下来就完整的了解hnpcli如何构建

理解和编译

service/hnp/BUILD.gn构建文件中,存放着我们找到的hnpcli的可执行文件构建信息:

ohos_executable("hnpcli") {include_dirs= ["pack/include","base", ]sources= ["${appspawn_path}/service/hnp/base/hnp_file.c","${appspawn_path}/service/hnp/base/hnp_json.c","${appspawn_path}/service/hnp/base/hnp_log.c","${appspawn_path}/service/hnp/base/hnp_zip.c","${appspawn_path}/service/hnp/hnpcli_main.c","${appspawn_path}/service/hnp/pack/src/hnp_pack.c", ]configs= []cflags= []defines= ["HNP_CLI"]external_deps= ["bounds_checking_function:libsec_static","cJSON:cjson_static","zlib:libz", ]install_enable=truesubsystem_name="${subsystem_name}"part_name="${part_name}"}

这里可以看到,hnpcli的源码非常少,依赖也相对简单,bounds_checking_function+cJSON+zlib就是其全部依赖,至此,快速完成hnpcli的可能性极大的提高了,同时也看出,hnpcli主要是用过json进行配置解析,然后进行归档打包的一个工具,并不会非常神秘

首先进行工程改造,我们的编译框架主要使用CMake、Make等编译框架,不太适合完成复刻一次OpenHarmony的GN编译框架(这是一样令人头大的事情,我不愿意为此付出时间)

  1. 一比一将GN框架修改为CMake框架:由于两个框架间有极大的逻辑相似性,因此改造起来相对轻松
  • ohos_executable == add_executable
  • target_link_libraries == external_deps
  • include_directories == include_dirs
  • defines == add_definitions

因此改造后如下:

cmake_minimum_required(VERSION3.10) project(hnpcli) set(CMAKE_C_STANDARD17) add_definitions(-DHNP_CLI) find_library(MYBOUNDS_CHECK libboundscheck.a) find_library(MYJSON libcjson.a) find_library(MYZLIB libz_static.a) find_path(BOUNDS_CHECK_INCLUDE_DIR securec.h) find_path(CJSON_INCLUDE_DIR cjson/cJSON.h) find_path(ZLIB_INCLUDE_DIR zlib.h) message(STATUS"BOUNDS_CHECK library found at: ${MYBOUNDS_CHECK}") message(STATUS"CJSON library found at: ${MYJSON}") message(STATUS"ZLIB library found at: ${MYZLIB}") message(STATUS"BOUNDS_CHECK_INCLUDE_DIR library found at: ${BOUNDS_CHECK_INCLUDE_DIR}") message(STATUS"CJSON_INCLUDE_DIR library found at: ${CJSON_INCLUDE_DIR}") message(STATUS"ZLIB_INCLUDE_DIR library found at: ${ZLIB_INCLUDE_DIR}") set(STARTUP_APPSPAWN_PATH$ENV{HNPCLI_BUILD_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/pack/src${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/pack/include${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base${BOUNDS_CHECK_INCLUDE_DIR}${ZLIB_INCLUDE_DIR}${CJSON_INCLUDE_DIR}/cjson ) add_executable(hnpcli${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base/hnp_file.c${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base/hnp_json.c${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base/hnp_log.c${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/base/hnp_zip.c${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/hnpcli_main.c${CMAKE_CURRENT_SOURCE_DIR}/${STARTUP_APPSPAWN_PATH}/service/hnp/pack/src/hnp_pack.c ) target_link_libraries(hnpcli${MYBOUNDS_CHECK}${MYJSON}${MYZLIB}) install(TARGETS hnpcli DESTINATION bin )
  1. 有了CMakeLists.txt,紧接着就是写编译命令了,CMake+make+make install的编译手法太过简单,直接参考代码,就不在这里啰嗦,核心是在编译框架下需要-DCMAKE_PREFIX_PATH="$LYCIUM_ROOT/usr/cJson/$ARCH:$LYCIUM_ROOT/usr/libboundscheck/$ARCH:$LYCIUM_ROOT/usr/zlib_static/$ARCH" \指定目录和库的搜索路径,方便在CMakeLists.txt中指定链接库

  2. 增加hnp.json

  3. 执行编译

    build.shhnpcli

    小插曲 depends=("cJson" "libboundscheck" "zlib_static")

    为了编译hnpcli,我依赖的几个库居然不是无法编译,就是不存在,strcpy_s这类安全库函数在win上可以很方便使用,但在鸿蒙中并没有纳入标准库,不得不在框架中引入了libboundscheck,zlib又存在编译问题,cJson居然没有在官方适配清单中看到,只好造一次车轮了

  • libboundscheck适配起来超级简单,原有的库已经包含了动态库的Makefile,我又想使用静态库的方式让命令更加稳定,因此仅仅是增加了静态库的Makefile参数,很方便的编译成功
  • zlib同样使用静态库的方式,同样参考OpenHarmony/third_party_zlibBUILD.gn重写了CMakeLists.txt(这里比较傻的是,由于前面适配的惯性,导致我忽略了源代码仓中天然包含了configure和Makefile的情况,不过也无伤大雅)
  • cJson没什么好说的,代码仓天然有CMakeLists.txt文件(智商已恢复),直接交叉编译

这几个库也都上传到了社区,合入lycium_plusplus,大家需要可以自行选用

至此,hnpcli的适配工作也完成了,在鸿蒙电脑上尝试,也没有什么问题

hdcbash

这两个命令其实没有什么特殊的,与hnpcli处理逻辑大同小异

  • hdc需要额外适配libusbopenssl,这里我选了openssl 3.6的版本,如果需要openssl 1_1_1f的,要注意接口不兼容哦
  • bash适配起来更加容易,bash作为最底层的工具,无依赖是其关键要求,这里仍有个小插曲,bash3.6中仍在使用过期的getwd不安全接口,在muslc中未定义该方法,因此在muslc_gext项目中我们替代实现了他,因此编译过程也是非常顺利

muslc_gext

这个项目本意是把一些大家遇到的在鸿蒙适配过程中不兼容的glibc库接口进行再实现,降低适配难度,避免大家都因同一个接口反复折腾,大家有遇到相关的接口也可以一起共享交流muslc_gext

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/7 13:32:56

28、系统与数据模型全解析:从基础到实践

系统与数据模型全解析:从基础到实践 1. 系统模型概述 在系统设计与分析领域,有多种重要的模型,它们各自有着独特的功能和用途。 - 系统流(System Flows) :可用于表示错误处理过程,帮助我们在系统出现问题时进行有效的应对和处理。 - 生态系统地图(Ecosystem Map…

作者头像 李华
网站建设 2026/2/8 3:05:10

29、数据建模:BDD与DFD的深度解析

数据建模:BDD与DFD的深度解析 1. 业务数据图(BDD)基础 在数据建模领域,业务数据图(BDD)是一个重要的工具。它能帮助我们从业务视角来理解和展示数据对象之间的关系。例如,学生和课程之间存在多对多的关系,一个学生可以选择任意数量的课程,而一门课程也可以有零到无限…

作者头像 李华
网站建设 2026/2/6 9:12:03

大模型自动化新纪元:Open-AutoGLM与manus协同架构详解,性能提升5倍的秘密

第一章:大模型自动化新纪元的开启 人工智能正以前所未有的速度演进,大语言模型的崛起标志着自动化技术进入全新阶段。这些模型不仅能够理解自然语言,还能生成代码、撰写文档、执行复杂推理,甚至自主完成任务编排。这一变革正在重塑…

作者头像 李华
网站建设 2026/2/4 23:53:44

4、Subversion 使用指南:从基础到实践

Subversion 使用指南:从基础到实践 1. Subversion 工作副本与仓库的跟踪机制 在 Subversion 中,工作副本与仓库的交互是核心操作。假设 Sally 对 integer.c 进行了更改并提交,创建了版本 6。当你使用 svn update 更新工作副本时,会看到如下结果: calc/Makefile:6 …

作者头像 李华
网站建设 2026/2/4 13:33:56

6、Subversion 使用指南:基础操作与历史查看

Subversion 使用指南:基础操作与历史查看 1. 冲突处理 在使用 Subversion 时,可能会遇到文件冲突的情况。当出现冲突时,Subversion 会创建一些临时文件,如 sandwich.txt.mine 、 sandwich.txt.r1 和 sandwich.txt.r2 ,并且在这些临时文件被移除之前,不允许提交 …

作者头像 李华
网站建设 2026/2/5 12:22:31

10、Subversion 高级功能:文件锁定、外部定义及相关操作解析

Subversion 高级功能:文件锁定、外部定义及相关操作解析 1. 文件锁定与提交 在使用 Subversion 进行版本控制时,文件锁定是一个重要的功能,它可以确保同一时间只有一个用户对文件进行修改,避免冲突。 当尝试删除 banana.jpg 并提交时,可能会遇到锁定问题,如下所示:…

作者头像 李华