鸿蒙开发命令

上次介绍了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作为应用的一部分理应归属这里

img

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

img

一切都对上了,接下来就完整的了解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 = true
    subsystem_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(VERSION 3.10)
project(hnpcli)

set(CMAKE_C_STANDARD 17)

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.sh hnpcli

小插曲 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作为最底层的工具,无依赖是其关键要求,这里仍有个小插曲,bash-5.3中仍在使用过期的getwd不安全接口,在muslc中未定义该方法,因此在muslc_gext项目中我们替代实现了他,因此编译过程也是非常顺利

muslc_gext

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

Logo

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

更多推荐