依据OpenHarmony构建体系的一次实践

60 阅读4分钟

构建的实践

当我们需要使用安卓上面的某一功能时发现 OpenHarmony 没有其实现,这时我们该怎么办呢?

一般有两种解决方案,一是移植安卓架构下的功能到 OpenHarmony,二是自己重新实现,这两种方法都离不开基于 OpenHarmony 的构建体系,但是按照 OpenHarmony 官方上面的文档有一部分是不能编译成功的(我试的是这样,也需你可以成功构建),所以我按照源码中的构建方法总结出以下构建实践心得,如有错误,望指出!

目标:(基于 code-v3.1-Release,最新版源码 rk3568.json 放到了 vendor 下)

移植can总线相关shell命令到openharmony中,能够成功使用;

目录结构:

    .OpenHarmony/test/canshell
    ├── canutils
    │   ├── BUILD.gn
    │   ├── include
    │   │   ├── can_config.h
    │   │   ├── can_netlink.h
    │   │   └── libsocketcan.h
    │   └── src
    │       ├── canconfig.c
    │       ├── candump.c
    │       ├── canecho.c
    │       ├── cansend.c
    │       └── cansequence.c
    ├── libsocketcan
    │   ├── BUILD.gn
    │   ├── include
    │   │   ├── can_netlink.h
    │   │   ├── libsocketcan_config.h
    │   │   └── libsocketcan.h
    │   └── src
    │       └── libsocketcan.c
    └── ohos.build

从目录结构中可以看到生成的文件有可执行文件和库文件,ohos.build是子系统描述文件,用于描述子系统包含的部件(组件)

BUILD.gn用于构建目标文件(可执行文件,库文件,配置文件等)

构建源码解读:

 ohos.build:
 {
  "subsystem": "canshell", (           //子系统的名字
  "parts": {
    "canshell": {
      "module_list": [
        "//test/canshell/libsocketcan:libsocketcan_lib",    //部件名字
        "//test/canshell/canutils:canconfig",               //在BUILD.gn中可找到
        "//test/canshell/canutils:candump",
        "//test/canshell/canutils:canecho",
        "//test/canshell/canutils:cansend",
        "//test/canshell/canutils:cansequence"
      ]
    }
  }
}

BUILD.gnimport("//build/ohos.gni")         //所有的BUILD.gn文件都要包含该头文件
 ohos_executable("canconfig") {     //构建的目标,在系统起来后,默认在bin目录下
  sources = [
    "src/canconfig.c"
  ]
  include_dirs = [ "include" ]
  deps = [
    "../libsocketcan:libsocketcan_lib"
  ]
  ……
install_enable = true           //默认安装
++subsystem_name = "canshell"++    //子系统名字,必须有这个选项,用于匹配子系统

}

   "subsystem_config.json"   (/work/code3.1/code-v3.1-Release/OpenHarmony/build
)  该文件包含源码所有子系统(也就是说,你要添加一个子系统需要再这里报个到,系统在    编译的时候会去按照你的板子配置文件在这个表里找是否有你需要用的子系统,然后按照表中    的配置找到源码进行编译)
     "canshell": {              //我们在文件最后加上 canshell子系统
     "path": "test/canshell",
        "name": "canshell"
 },
   
rk3568.json:(/work/code3.1/code-v3.1-Release/OpenHarmony/productdefine/common/products
)
    "canshell:canshell":{},   //加入子系统部件

DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到以下知识点。

`欢迎大家关注公众号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

总结:

配置构建四步走: 1.编写BUILD.gn; 2.编写ohos.build; 3.在subsystem_config.json中添加子系统; 4.在rk3568.json(自己配置的板子配置文件)中添加子系统。

我们在源码中或者官方文档中会看到bundle.json文件,那么这个文件在编译构建中起到什么作用呢?它和ohos.build又有什么不同呢?

目前我的理解是bundle.json和ohos.build都是用于描述子系统(或部件)中所包含的部件配置文件,在编译构建的过程中起到的作用应该是一样的,只是两种不同的表达方式,使用哪一种都是可以的,在上下级角度上看,bundle.json可能比ohos.build低一级,但是它们都是用于描述该软件包含的东西,提供的接口,测试的示例等,在源码中有的是用bundle.json描述,有的用ohos.build描述,所以我们在构建的时候使用谁都是OK的,还有的两个都用了,比如: archermind@archermind:/work/code3.1/code-v3.1-Release/OpenHarmony/foundation/multimedia/camera_standard$ ls bundle.json figures frameworks interfaces LICENSE OAT.xml ohos.build README.md README_zh.md sa_profile services 在这里就是两个都用到了。

bundle.json:
{
   "name": "@ohos/<component_name>",               # HPM部件英文名称,格式"@组织/部件名称"
   "description": "xxxxxxxxxxxxxxxxxxx",           # 部件功能一句话描述
   "version": "3.1",                               # 版本号,版本号与OpenHarmony版本号一致
   "license": "MIT",                               # 部件License
   "publishAs": "code-segment",                    # HPM包的发布方式,当前默认都为code_segment
   "segment": {
       "destPath": ""
   },                                              # 发布类型为code_segment时为必填项,定义发布类型code_segment的代码还原路径(源码路径)
   "dirs": {},                                     # HPM包的目录结构,字段必填内容可以留空
   "scripts": {},                                  # HPM包定义需要执行的脚本,字段必填,值非必填
   "licensePath": "COPYING",                       # 指定该模块的版权申明路径
   "readmePath": {
       "en": "README.rst"
   },                                              # 该模块的reademe.opensource的路径
   "component": {                                  # 部件属性
       "name": "<component_name>",                 # 部件名称
       "subsystem": "",                            # 部件所属子系统
       "syscap": [],                               # 部件为应用提供的系统能力
       "features": [],                             # 部件对外的可配置特性列表,一般与build中的sub_component对应,可供产品配置
       "adapted_system_type": [],                  # 轻量(mini)小型(small)和标准(standard),可以是多个
       "rom": "xxxKB",                             # ROM基线,没有基线写当前值
       "ram": "xxxKB",                             # RAM基线,没有基线写当前值
       "deps": {
           "components": [],                       # 部件依赖的其他部件
           "third_party": []                       # 部件依赖的三方开源软件
       },
       "build": {                                  # 编译相关配置
           "sub_component": [],                    # 部件编译入口,模块在此处配置
           "inner_kits": [],                       # 部件间接口
           "test": []                              # 部件测试用例编译入口
       }
   }
}