diff --git a/zh-cn/device-dev/quick-start/quickstart-build.md b/zh-cn/device-dev/quick-start/quickstart-build.md new file mode 100644 index 0000000000000000000000000000000000000000..0cc4275aabdaf7e000ffd04c181ab7cbf43aa3db --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-build.md @@ -0,0 +1,41 @@ +# 编译形态整体说明 + +**编译构建支持的产品列表** + +| 编译形态 | 开发板 | 主芯片 | 内核 | 系统类型 | +| ----------------------------- | --------------- | ----------- | ----------- | ----------- | +| neptune100 | neptune100 | winnermicro | liteos_m | mini | +| rk3568 | rk3568 | rockchip | linux | standard | +| rk3568_mini_system | rk3568 | rockchip | linux | standard | +| bearpi_hm_micro | bearpi_hm_micro | stm32mp1xx | liteos_a | small | +| bearpi_hm_nano | bearpi_hm_nano | hi3861v100 | liteos_m | mini | +| wifiiot_hispark_pegasus | hispark_pegasus | hi3861v100 | liteos_m | mini | +| ipcamera_hispark_aries | hispark_aries | hi3518ev300 | liteos_a | small | +| ipcamera_hispark_taurus | hispark_taurus | hi3516dv300 | liteos_a | small | +| ipcamera_hispark_taurus_linux | hispark_taurus | hi3516dv300 | linux | small | +| hispark_taurus_standard | hispark_taurus | hi3516dv300 | linux | standard | +| watchos | hispark_taurus | hi3516dv300 | linux | standard | +| hispark_phoenix | hispark_phoenix | hi3751v350 | linux | standard | +| hispark_taurus_mini_system | hispark_taurus | hi3516dv300 | liteos_a | mini | +| hispark_pegasus_mini_system | hispark_pegasus | hi3861v100 | liteos_m | mini | +| gr5515_sk_iotlink_demo | gr5515_sk | gr551x | liteos_m | mini | +| gr5515_sk_xts_demo | gr5515_sk | gr551x | liteos_m | mini | +| wifi_demo | dev_wifi_a | asr582x | liteos_m | mini | +| xts_demo | dev_wifi_a | asr582x | liteos_m | mini | +| display_demo | v200zr | bes2600 | liteos_m | mini | +| xts_demo | v200zr | bes2600 | liteos_m | mini | +| iotlink_demo | v200zr | bes2600 | liteos_m | mini | +| mini_distributed_music_player | v200zr | bes2600 | liteos_m | mini | +| niobe407 | niobe407 | stm32f4xx | liteos_m | mini | +| qemu_mini_system_demo | arm_mps2_an386 | qemu | liteos_m | mini | +| qemu_cksy_mini_system_demo | SmartL_E802 | qemu | liteos_m | mini | +| qemu_cm55_mini_system_demo | arm_mps3_an547 | qemu | liteos_m | mini | +| qemu_xtensa_mini_system_demo | esp32 | qemu | liteos_m | mini | +| qemu_riscv_mini_system_demo | ricsv32_virt | qemu | liteos_m | mini | +| qemu_ca7_mini_system_demo | arm_virt | qemu | liteos_a | small | +| qemu_small_system_demo | arm_virt | qemu | liteos_a | small | +| qemu-arm-linux-min | qemu-arm-linux | qemu | linux | standard | +| qemu-arm-linux-headless | qemu-arm-linux | qemu | linux | standard | +| iotlink_demo | cst85_wblink | chipsea | liteos_m | mini | +| dsoftbus_demo | cst85_wblink | chipsea | liteos_m | mini | +| xts_demo | cst85_wblink | chipsea | liteos_m | mini | diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-ide-directory.md b/zh-cn/device-dev/quick-start/quickstart-standard-ide-directory.md index 448912788ad796bb2c58f90cf19cfd9829c84691..23c92d7e820d16ba8ec5c3ca55dc2ad598006c4e 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-ide-directory.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-ide-directory.md @@ -18,4 +18,5 @@ - [运行](quickstart-ide-standard-running-rk3568-running.md) - 附录 - [Hi3516开发板介绍](quickstart-ide-standard-board-introduction-hi3516.md) - - [RK3568开发板介绍](quickstart-ide-standard-board-introduction-rk3568.md) \ No newline at end of file + - [RK3568开发板介绍](quickstart-ide-standard-board-introduction-rk3568.md) + - [编译形态整体说明](quickstart-build.md) \ No newline at end of file diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md b/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md index 87ccb1063cccd231134cdcb4476502f48cc5a474..9173ab71c468560ac1fbbe3374771a16c0a9414a 100644 --- a/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md +++ b/zh-cn/device-dev/quick-start/quickstart-standard-package-directory.md @@ -21,5 +21,6 @@ - 开发板介绍 - [Hi3516开发板介绍](quickstart-standard-board-introduction-hi3516.md) - [RK3568开发板介绍](quickstart-standard-board-introduction-rk3568.md) + - [编译形态整体说明](quickstart-build.md) - [参考信息](quickstart-standard-reference.md) - [使用HiTool烧录代码](quickstart-standard-hitool.md) \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md b/zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md index 550c4f64bbcdffc4d62396fafc51899d74e28f2c..d93ffb34a803de4b7dc5e743dd9cac9e2c04f56d 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md +++ b/zh-cn/device-dev/subsystems/subsys-build-gn-coding-style-and-best-practice.md @@ -39,9 +39,9 @@ action("some_action") { outputs = [ _output ] args = [ ... - "--output", - rebase_path(_output, root_build_dir), - ... + "--output", + rebase_path(_output, root_build_dir), + ... ] ... } @@ -70,7 +70,7 @@ declare_args() { - 加入"${target_name}"可以防止子目标重名。 - 加入双下划线可以很方便地区分出子目标属于哪一个模块,方便在出现问题时快速定位。 - + ``` # 例3 template("ohos_shared_library") { @@ -137,17 +137,17 @@ import("//a.gni") 编译脚本实质上完成了两件工作: 1. **描述模块之间依赖关系(deps)** - + 实践过程中,最常出现的问题是**依赖关系缺失**。 2. **描述模块编译的规则(rule)** - + 实践过程中,容易出现的问题是**输入和输出不明确**。 依赖缺失会导致两个问题: - **概率性编译错误** - + ``` # 例6 # 依赖关系缺失,导致概率性编译出错 @@ -164,13 +164,13 @@ import("//a.gni") deps = [ ":b" ] } ``` - + 上面的例子中,libb.so在链接的时候会链接liba.so,实质上构成b依赖a,但是b的依赖列表(deps)却没有声明对a的依赖。由于编译是并发执行的,如果libb.so在链接的时候liba.so还没有编译出来,就会出现编译错误。 - + 由于liba.so也有可能在libb.so之前编译出来,所以依赖缺失导致的编译错误是概率性的。 - **依赖关系缺失导致模块没有参与编译** - + 还是上面的例子,如果我们指定ninja编译目标为images,由于images仅仅依赖b,所以a不会参与编译。由于b实质上依赖a, 这时b在链接时会出现必现错误。 有一种不太常见的问题是**过多的依赖**。**过多的依赖会降低并发,导致编译变慢**。见下面的例子: @@ -186,13 +186,13 @@ template("too_much_deps") { action(_gen_resource_target) { ... } - + _compile_resource_target = "${target_name}__compile_res" action(_compile_resource_target) { deps = [":$_gen_resource_target"] ... } - + _compile_js_target = "${target_name}__js" action(_compile_js_target) { # 这个deps不需要 @@ -261,20 +261,17 @@ write_file("a.out") - **原生模板是最小功能模板**,无法提供external_deps的解析,notice收集,安装信息生成等的额外功能,这些额外功能最好是随着模块编译时同时生成,所以必须对原生模板做额外的扩展才能满足实际的需求。 - 当输入文件依赖的文件发生变化时,gn原生的action模板不能自动感知不到这种编译,无法重新编译。见例8 - - - + 原生模板和编译系统提供的模板之间的对应关系: - - | 编译系统提供的模板 | 原生模板 | - | :------------------ | -------------- | - | ohos_shared_library | shared_library | - | ohos_source_set | source_set | - | ohos_executable | executable | - | ohos_static_library | static_library | - | action_with_pydeps | action | - | ohos_group | group | - + +| 编译系统提供的模板 | 原生模板 | +|:------------------- | -------------- | +| ohos_shared_library | shared_library | +| ohos_source_set | source_set | +| ohos_executable | executable | +| ohos_static_library | static_library | +| action_with_pydeps | action | +| ohos_group | group | ### 使用python脚本 @@ -288,7 +285,7 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 ### rebase_path - 仅在向action的参数列表中(args)调用rebase_path。 - + ``` # 例10 template("foo") { @@ -310,7 +307,7 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 ``` - 同一变量做两次rebase_path会出现意想不到的结果。 - + ``` # 例11 template("foo") { @@ -337,11 +334,11 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 模块间数据分享是很常见的事情,比如A模块想要知道B模块的输出和deps。 - 同一BUILD.gn之间数据分享 - + 同一BUILD.gn之间数据可以通过定义全局变量的方式来共享。 - + 下面的例子中,模块a的输出是模块b的输入,可以通过定义全局变量的方式来共享给b - + ``` # 例12 _output_a = get_label_info(":a", "out_dir") + "/a.out" @@ -356,13 +353,13 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 ``` - 不同BUILD.gn之间数据分享 - + 不同BUILD.gn之间传递数据,最好的办法是将需要共享的数据保存成文件,然后不同模块之间通过文件来传递和共享数据。这种场景比较复杂,读者可以参照OpenHarmony的hap编译过程的write_meta_data。 ### forward_variable_from - 自定义模板需要首先将testonly传递(forward)进来。因为该模板的target有可能被testonly的目标依赖。 - + ``` # 例13 # 自定义模板首先要传递testonly @@ -373,7 +370,7 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 ``` - 不推荐使用*来forward变量,需要的变量应该**显式地,一个一个地**被forward进来。 - + ``` # 例14 # Bad,使用*forward变量 @@ -386,10 +383,10 @@ action中的script推荐使用python脚本,不推荐使用shell脚本。相比 template("bar") { # forward_variable_from(invoker, [ - "testonly", - "deps", - ... - ]) + "testonly", + "deps", + ... + ]) ... } ``` @@ -495,15 +492,17 @@ set_source_assignment_filter([]) ### 部件内依赖采用deps,跨部件依赖采用external_deps - 部件在OpenHarmony上指能提供某个能力的一组模块。 + - 在模块定义的时候可以声明part_name,用来表明当前模块属于哪个部件。 -- 每个部件会声明其inner-kit,供其他部件调用。部件innerkit的声明见源码中的ohos.build。 +- 每个部件会声明其inner-kit,供其他部件调用。部件innerkit的声明见源码中的bundle.json。 + - 部件间依赖只能依赖innerkit,不能依赖非innerkit的模块。 - 如果a模块和b模块的part_name相同,那么a、b模块属于同一个部件,a,b模块之间的依赖关系可以用deps来声明。 - 如果a、b模块的part_name不同,那么a、b模块不属于同一个部件,a、b模块之间的依赖关系需要通过external_deps来声明,依赖方式为"部件名:模块名"的方式。见例19。 - + ``` # 例19 shared_library("a") { @@ -512,14 +511,3 @@ set_source_assignment_filter([]) ... } ``` - - - - - - - - - - - diff --git a/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guide.md b/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guide.md index 78d686a60a99296691ce6653b3156a0c399c9829..21fe0efae13e0700b95c8b595a05bf4516b08597 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guide.md +++ b/zh-cn/device-dev/subsystems/subsys-build-gn-kconfig-visual-config-guide.md @@ -7,7 +7,7 @@ 基于Kconfig实现的可视化配置功能具有以下优点: -- 能直观且全面地展示软件的组件选项。 +- 能直观且全面地展示软件的部件选项。 - 可靠性强,如Linux-kernel、buildroot等知名软件都采用Kconfig进行可视化配置。 ### 基本概念 diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md index 1d9f26eaa987cf8553777a15a3fd7c422e1c18f8..8f1d027709e80ed28137aa2ea9b6fa9bc63412c6 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md +++ b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md @@ -1,25 +1,24 @@ # 轻量和小型系统编译构建指导 - ## 概述 - 一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: -- 支持按组件拼装产品并编译。 + 一个基于gn和ninja的构建系统,以支持OpenHarmony部件化开发为目标,提供以下基本功能: -- 独立构建芯片解决方案厂商源码。 +- 支持按部件拼装产品并编译。 -- 独立构建单个组件。 +- 独立构建芯片解决方案厂商源码。 +- 独立构建单个部件。 ### 基本概念 在使用编译构建子系统前,应了解如下基本概念: - 子系统 - 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 + 子系统是一个逻辑概念,它由一个或多个具体的部件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 部件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或部件。 -- 组件 - 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 +- 部件 + 系统最小的可复用、可配置、可裁剪的功能单元。部件具备目录独立可并行开发、可独立编译、可独立测试的特征。 - gn Generate ninja的缩写,用于产生ninja文件。 @@ -30,18 +29,16 @@ - hb OpenHarmony的命令行工具,用来执行编译命令。 - ### 目录结构 - ``` build/lite -├── components # 组件描述文件 +├── components # 部件描述文件 ├── figures # readme中的图片 ├── hb # hb pip安装包源码 ├── make_rootfs # 文件系统镜像制作脚本 ├── config # 编译配置项 -│ ├── component # 组件相关的模板定义 +│ ├── component # 部件相关的模板定义 │ ├── kernel # 内核相关的编译配置 │ └── subsystem # 子系统编译配置 ├── platform # ld脚本 @@ -49,152 +46,162 @@ build/lite └── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 ``` - ### 构建流程 编译构建流程如下图所示,主要分设置和编译两步: **图1** 编译构建流程 + ![zh-cn_image_0000001171796557](figures/zh-cn_image_0000001171796557.jpg) 1. hb set: 设置OpenHarmony源码目录和要编译的产品。 -2. hb build: 编译产品、开发板或者组件。编译主要过程如下: +2. hb build: 编译产品、开发板或者部件。编译主要过程如下: + 1. 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 2. 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 3. 调用ninja:调用ninja -C out/board/product启动编译。 - 4. 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 - + 4. 系统镜像打包:将部件编译产物打包,设置文件属性和权限,制作文件系统镜像。 ## 配置规则 -为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: +为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,部件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: +### 部件 -### 组件 + 部件源码路径命名规则为:**{领域}/{子系统}/{部件}**,部件目录树规则如下: - 组件源码路径命名规则为:**{领域}/{子系统}/{组件}**,组件目录树规则如下: > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** -> 组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 - +> 部件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增部件时需要在对应子系统json文件中添加相应的部件定义。产品所配置的部件必须在某个子系统中被定义过,否则会校验失败。 ``` component ├── interfaces -│ ├── innerkits # 系统内接口,组件间使用 +│ ├── innerkits # 系统内接口,部件间使用 │ └── kits # 应用接口,应用开发者使用 ├── frameworks # framework实现 ├── services # service实现 -└── BUILD.gn # 组件编译脚本 +└── BUILD.gn # 部件编译脚本 ``` - 以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: + 以泛sensor子系统的sensor服务部件为例,部件属性定义描述文件字段说明如下: + + ``` + { + "name": "@ohos/sensor_lite", # HPM部件英文名称,格式"@组织/部件名称" + "description": "Sensor services", # 部件功能一句话描述 + "version": "3.1", # 版本号,版本号与OpenHarmony版本号一致 + "license": "MIT", # 部件License + "publishAs": "code-segment", # HPM包的发布方式,当前默认都为code_segment + "segment": { + "destPath": "" + }, # 发布类型为code_segment时为必填项,定义发布类型code_segment的代码还原路径(源码路径) + "dirs": {"base/sensors/sensor_lite"}, # HPM包的目录结构,字段必填内容可以留空 + "scripts": {}, # HPM包定义需要执行的脚本,字段必填,值非必填 + "licensePath": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "component": { # 部件属性 + "name": "sensor_lite", # 部件名称 + "subsystem": "", # 部件所属子系统 + "syscap": [], # 部件为应用提供的系统能力 + "features": [], # 部件对外的可配置特性列表,一般与build中的sub_component对应,可供产品配置 + "adapted_system_type": [], # 轻量(mini)小型(small)和标准(standard),可以是多个 + "rom": "92KB", # 部件ROM值 + "ram": "~200KB", # 部件RAM估值 + "deps": { + "components": [ # 部件依赖的其他部件 + "samgr_lite", + "ipc_lite" + ], + "third_party": [ # 部件依赖的三方开源软件 + "bounds_checking_function" + ] + } + "build": { # 编译相关配置 + "sub_component": [ + ""//base/sensors/sensor_lite/services:sensor_service"", # 部件编译入口 + ], # 部件编译入口,模块在此处配置 + "inner_kits": [], # 部件间接口 + "test": [] # 部件测试用例编译入口 + } + } + } + ``` -``` -{ - "components": [ - { - "component": "sensor_lite", # 组件名称 - "description": "Sensor services", # 组件一句话功能描述 - "optional": "true", # 组件是否为最小系统必选 - "dirs": [ # 组件源码路径 - "base/sensors/sensor_lite" - ], - "targets": [ # 组件编译入口 - "//base/sensors/sensor_lite/services:sensor_service" - ], - "rom": "92KB", # 组件ROM值 - "ram": "~200KB", # 组件RAM估值 - "output": [ "libsensor_frameworks.so" ], # 组件编译输出 - "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核 - "features": [], # 组件可配置的特性 - "deps": { - "components": [ # 组件依赖的其他组件 - "samgr_lite", - "ipc_lite" - - ], - "third_party": [ # 组件依赖的三方开源软件 - "bounds_checking_function" - ] - } - } - ] -} -``` + 部件BUILD.gn的编写建议如下: - 组件BUILD.gn的编写建议如下: -- 编译目标名称与组件一致。 +- 编译目标名称与部件一致。 -- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos_{subsystem}_{component}_{feature}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 +- 部件对外可配置的特性变量需声明在该部件BUILD.gn中,特性变量命名规则:ohos_{subsystem}_{component}_{feature}。特性在部件描述中也需要同步定义,在产品配置文件config.json中按需配置。 - 宏定义规则:OHOS_{SUBSYSTEM}_{COMPONENT}_{FEATURE} + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > 组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 - - 以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: + > 部件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。部件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 -``` - # 声明组件可配置的特性 - declare_args() { - enable_ohos_graphic_ui_animator = false # 动效特性开关 - ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap - } - - # 组件基础功能 - shared_library("base") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - } - - # 仅在animator开启时编译 - if(enable_ohos_graphic_ui_animator ) { - shared_library("animator") { - sources = [ - ...... - ] - include_dirs = [ + 以图形的UI部件为例,foundation/graphic/ui/BUILD.gn文件如下: + + ``` + # 声明部件可配置的特性 + declare_args() { + enable_ohos_graphic_ui_animator = false # 动效特性开关 + ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap + } + + # 部件基础功能 + shared_library("base") { + sources = [ + ...... + ] + include_dirs = [ + ...... + ] + } + + # 仅在animator开启时编译 + if(enable_ohos_graphic_ui_animator ) { + shared_library("animator") { + sources = [ + ...... + ] + include_dirs = [ ...... - ] - deps = [ :base ] - } - } - ...... - # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 - executable("ui") { - deps = [ - ":base" - ] - - # animator特性由产品配置 - if(enable_ohos_graphic_ui_animator ) { - deps += [ - "animator" - ] - } - } -``` + ] + deps = [ :base ] + } + } + ...... + # target名称建议与部件名称一致, 部件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 + executable("ui") { + deps = [ + ":base" + ] + # animator特性由产品配置 + if(enable_ohos_graphic_ui_animator ) { + deps += [ + "animator" + ] + } + } + ``` ### 芯片解决方案 - 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。 -- 芯片解决方案是一个特殊的组件,源码路径规则为:**device/{芯片解决方案厂商}/{开发板}**。 - -- 芯片解决方案组件会随产品选择的开发板默认编译。 - +- 芯片解决方案是一个特殊的部件,源码路径规则为:**device/{开发板}/{芯片解决方案厂商}**。 +- 芯片解决方案部件会随产品选择的开发板默认编译。 + 芯片解决方案目录树规则如下: ``` device -└── company # 芯片解决方案厂商 - └── board # 开发板名称 +└── board # 芯片解决方案厂商 + └── company # 开发板名称 ├── BUILD.gn # 编译脚本 ├── hals # OS南向接口适配 ├── linux # 可选,linux内核版本 @@ -203,10 +210,8 @@ device └── config.gni # liteos_a版本编译配置 ``` - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** -> config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。 - +> config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS部件,编译阶段系统全局可见。 config.gni的关键字段介绍如下: @@ -223,14 +228,12 @@ board_cxx_flags: 开发板配置的cpp文件编译选项。 board_ld_flags: 开发板配置的链接选项。 ``` - ### 产品解决方案 -产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/{产品解决方案厂商}/{产品名称}**_。_产品解决方案也是一个特殊的组件。 +产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、部件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/{产品解决方案厂商}/{产品名称}**_。_产品解决方案也是一个特殊的部件。 产品解决方案的目录树规则如下: - ``` vendor └── company # 产品解决方案厂商 @@ -245,28 +248,29 @@ vendor └── ...... ``` - > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** > **新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。** - 关键的目录和文件详细介绍如下: - 1. **vendor/company/product/init_configs/etc** 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS->fstab->S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 2. **vendor/company/product/init_configs/init.cfg** init进程启动服务的配置文件,当前支持解析的命令有: - + - start: 启动某个服务 + - mkdir: 创建文件夹 + - chmod: 修改指定路径/文件的权限 + - chown: 修改指定路径/文件的属组 + - mount: 挂载命令 - - 该文件中的各个字段的解释如下: + 该文件中的各个字段的解释如下: + ``` { "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 @@ -308,44 +312,42 @@ vendor ``` 3. **vendor/company/product/init_configs/hals** - 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 + 解决方案厂商对OS的适配,需要实现的接口请见各个部件的readme说明文档。 4. **vendor/company/product/config.json** - config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。 - + config.json为编译构建的主入口,包含了开发板、OS部件和内核等配置信息。 + 以基于hispark_taurus开发板的ipcamera产品为例,配置文件如下: - ``` { - "product_name": "ipcamera", # 产品名称 - "version": "3.0", # config.json的版本号, 固定"3.0" - "type": "small", # 系统类型, 可选[mini, small, standard] - "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 - "device_company": "hisilicon", # 芯片厂商 - "board": "hispark_taurus", # 开发板名称 - "kernel_type": "liteos_a", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "aafwk", # 选择的子系统 - "components": [ - { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 - ] - }, - { - ...... - } - ...... - 更多子系统和组件 - } - } - ``` + "product_name": "ipcamera", # 产品名称 + "version": "3.0", # config.json的版本号, 固定"3.0" + "type": "small", # 系统类型, 可选[mini, small, standard] + "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 + "device_company": "hisilicon", # 芯片厂商 + "board": "hispark_taurus", # 开发板名称 + "kernel_type": "liteos_a", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "aafwk", # 选择的子系统 + "components": [ + { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的部件和部件特性配置 + ] + }, + { + ...... + } + ...... + 更多子系统和部件 + } + } + ``` 5. **vendor/company/product/fs.yml** 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: - ``` fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 @@ -358,30 +360,29 @@ vendor file_dir: 必填,文件系统下具体文件路径 file_mode: 必填,文件权限声明 fs_symlink: 选填,配置文件系统软连接 - fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 + fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 fs_attr: 选填,根据配置项动态调整文件系统 ``` - 其中fs_symlink、fs_make_cmd字段支持以下变量: + 其中fs_symlink、fs_make_cmd字段支持以下变量: + - ${root_path} - 代码根目录,对应gn的${ohos_root_path} - + 代码根目录,对应gn的${ohos_root_path} + - ${out_path} - 产品out目录,对应gn的${root_out_dir} - - - ${fs_dir} - 文件系统目录,由以下变量拼接而成 - - - ${root_path} - - ${fs_dir_name} - - > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** - > fs.yml是可选的,对于没有文件系统的设备可不配置。 + 产品out目录,对应gn的${root_out_dir} + - ${fs_dir} + 文件系统目录,由以下变量拼接而成 + + - ${root_path} + - ${fs_dir_name} + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:** + > fs.yml是可选的,对于没有文件系统的设备可不配置。 6. **vendor/company/product/BUILD.gn** 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: - ``` group("product") { # target名称需与product名称即三级目录名称一致 deps = [] @@ -392,13 +393,11 @@ vendor } ``` - ## 使用指导 - ### 前提条件 -开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建基础环境](../quick-start/quickstart-lite-env-setup.md)。 +开发环境需安装gn、ninja构建工具、python 3.9.2及以上和hb。安装方法请见[搭建基础环境](../quick-start/quickstart-lite-env-setup.md)。 ### hb工具使用说明 @@ -427,7 +426,6 @@ optional arguments: 查看当前设置信息 - ``` hb env [OHOS INFO] root path: xxx @@ -442,58 +440,63 @@ hb env ``` hb build -h -usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] - [--dmverity] [--tee] [-p PRODUCT] [-f] [-n] - [-T [TARGET [TARGET ...]]] [-v] [-shs] [--patch] +usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] [-cpu TARGET_CPU] [--dmverity] [--tee] + [-p PRODUCT] [-f] [-n] [-T [TARGET [TARGET ...]]] [-v] [-shs] [--patch] [--compact-mode] + [--gn-args GN_ARGS] [--keep-ninja-going] [--build-only-gn] [--log-level LOG_LEVEL] [--fast-rebuild] + [--device-type DEVICE_TYPE] [--build-variant BUILD_VARIANT] [component [component ...]] positional arguments: - component name of the component + component name of the component, mini/small only optional arguments: -h, --help show this help message and exit -b BUILD_TYPE, --build_type BUILD_TYPE - release or debug version + release or debug version, mini/small only -c COMPILER, --compiler COMPILER - specify compiler + specify compiler, mini/small only -t [TEST [TEST ...]], --test [TEST [TEST ...]] compile test suit - --dmverity Enable dmverity + -cpu TARGET_CPU, --target-cpu TARGET_CPU + select cpu + --dmverity enable dmverity --tee Enable tee -p PRODUCT, --product PRODUCT - build a specified product with - {product_name}@{company}, eg: camera@example + build a specified product with {product_name}@{company} -f, --full full code compilation -n, --ndk compile ndk -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] - Compile single target + compile single target -v, --verbose show all command lines while building -shs, --sign_haps_by_server sign haps by server --patch apply product patch before compiling - - --dmverity Enable dmverity - -p PRODUCT, --product PRODUCT - build a specified product with - {product_name}@{company}, eg: ipcamera@hisilcon - -f, --full full code compilation - -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] - Compile single target + --compact-mode compatible with standard build system set to false if we use build.sh as build entrance + --gn-args GN_ARGS specifies gn build arguments, eg: --gn-args="foo="bar" enable=true blah=7" + --keep-ninja-going keeps ninja going until 1000000 jobs fail + --build-only-gn only do gn parse, donot run ninja + --log-level LOG_LEVEL + specifies the log level during compilationyou can select three levels: debug, info and error + --fast-rebuild it will skip prepare, preloader, gn_gen steps so we can enable it only when there is no change + for gn related script + --device-type DEVICE_TYPE + specifies device type + --build-variant BUILD_VARIANT + specifies device operating mode ``` - hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. -- hb build {component_name}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv_store)。 +- hb build {component_name}:基于设置好的产品对应的单板、内核,单独编译部件(e.g.:hb build kv_store)。 - hb build -p ipcamera\@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 -- 在device/device_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 +- 在device/board/device_company下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 **hb clean** 清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 - ``` hb clean usage: hb clean [-h] [out_path] @@ -505,16 +508,14 @@ optional arguments: -h, --help show this help message and exit ``` +### 新增部件 -### 新增组件 - -本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: - -1. 源码开发完成后,添加组件编译脚本。 - - 以编译组件hello_world可执行文件为例,applications/sample/hello_world/BUILD.gn可以写为: +本小节介绍如何新增一个部件,首先确定部件归属的子系统和部件名称,然后按如下步骤新增: +1. 源码开发完成后,添加部件编译脚本。 + 以编译部件hello_world可执行文件为例,applications/sample/hello_world/BUILD.gn可以写为: + ``` executable("hello_world") { include_dirs = [ @@ -528,28 +529,26 @@ optional arguments: 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello_world的可执行文件。 - 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: + 单独编译该部件,hb set任意选择一款产品,然后使用-T选项单独编译部件: - ``` hb build -f -T //applications/sample/hello_world ``` - 组件在开发板上功能验证完成后,可按步骤2-4将组件配置到产品中。 - -2. 添加组件描述。 - - 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: - - - component:组件名称。 - - description:组件的一句话功能描述。 - - optional:组件是否为系统可选。 - - dirs:组件源码路径。 - - targets:组件编译入口。 - - 以将hello_world组件加入应用子系统为例,在applications.json中添加hello_world对象: + 部件在开发板上功能验证完成后,可按步骤2-4将部件配置到产品中。 +2. 添加部件描述。 + + 部件描述位于build/lite/components下,新增的部件需加入对应子系统的json文件中。一个部件描述必选的字段有: + + - component:部件名称。 + - description:部件的一句话功能描述。 + - optional:部件是否为系统可选。 + - dirs:部件源码路径。 + - targets:部件编译入口。 + 以将hello_world部件加入应用子系统为例,在applications.json中添加hello_world对象: + ``` { "components": [ @@ -569,11 +568,10 @@ optional arguments: } ``` -3. 将组件配置到产品。 - - 产品的配置文件config.json位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello_world组件加入产品配置文件my_product.json中为例,加入hello_world对象: - +3. 将部件配置到产品。 + 产品的配置文件config.json位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和部件。以将hello_world部件加入产品配置文件my_product.json中为例,加入hello_world对象: + ``` { "product_name": "hello_world_test", @@ -595,11 +593,11 @@ optional arguments: ``` 4. 编译产品。 + 1. 代码根目录输入hb set选择对应产品。 - + 2. 执行hb build。 - ### 新增芯片解决方案 编译构建支持添加新的芯片解决方案厂商,具体步骤如下: @@ -607,14 +605,13 @@ optional arguments: 1. 创建芯片解决方案目录。 按照[芯片解决方案配置规则](#配置规则)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: - ``` - mkdir -p device/realtek/rtl8720 + mkdir -p device/board/realtek/rtl8720 ``` 2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 - 以realtek的“rtl8720“开发板的liteos_a适配为例,device/realtek/rtl8720/liteo_a/config.gni的内容如下: - + 以realtek的“rtl8720“开发板的liteos_a适配为例,device/board/realtek/rtl8720/liteo_a/config.gni的内容如下: + ``` # Kernel type, e.g. "linux", "liteos_a", "liteos_m". kernel_type = "liteos_a" @@ -651,8 +648,8 @@ optional arguments: ``` 3. 编写编译脚本。 - 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: - + 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/board/realtek/rtl8720/BUILD.gn内容可以是: + ``` group("rtl8720") { # target类型也可以shared_library, static_library, executable # 具体内容 @@ -663,22 +660,20 @@ optional arguments: 4. 编译芯片解决方案。 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 - ### 新增产品解决方案 -编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: +编译构建支持芯片解决方案和部件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: 1. 创建产品目录 按照[产品解决方案配置规则](#配置规则)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: - ``` mkdir -p vendor/my_company/wifiiot ``` 2. 拼装产品 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my_company/wifiiot/config.json可以是: - + ``` { "product_name": "wifiiot", # 产品名称 @@ -693,18 +688,18 @@ optional arguments: { "subsystem": "kernel", # 选择的子系统 "components": [ - { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 + { "component": "liteos_m", "features":[] } # 选择的部件和部件特性 ] }, ... { - 更多子系统和组件 + 更多子系统和部件 } ] } ``` - - 注意:编译构建系统编译前会对device_company,board,kernel_type,kernel_version、subsystem、component字段进行有效性检查,其中device_company,board,kernel_type,kernel_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 + + 注意:编译构建系统编译前会对device_company,board,kernel_type,kernel_version、subsystem、component字段进行有效性检查,其中device_company,board,kernel_type,kernel_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的部件描述匹配。 3. 适配OS接口 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 @@ -717,7 +712,7 @@ optional arguments: 6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: - + ``` - fs_dir_name: rootfs # 镜像的名称 @@ -819,9 +814,9 @@ optional arguments: ``` -7. 配置产品Patch(可选,视产品涉及组件是否需要打补丁而定) +7. 配置产品Patch(可选,视产品涉及部件是否需要打补丁而定) 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: - + ``` # 需要打patch的路径 foundation/communication/dsoftbus: @@ -834,16 +829,16 @@ optional arguments: - third_party/wpa_supplicant/3.patch ... ``` - + 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: - + ``` hb build -f --patch ``` 8. 编写编译脚本 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: - + ``` group("wifiiot") { # target名称与产品名一致 deps = [] @@ -859,10 +854,8 @@ optional arguments: 9. 编译产品。 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 - ## 常见问题 - ### 编译构建过程中,提示“usr/sbin/ninja: invalid option -- w” - **现象描述:** @@ -874,7 +867,6 @@ optional arguments: - **解决办法:** 卸载环境中ninja和gn,按照[获取工具](../get-code/gettools-ide.md)。 - ### 编译构建过程中,提示“/usr/bin/ld: cannot find -lncurses” - **现象描述:** @@ -889,7 +881,6 @@ optional arguments: sudo apt-get install lib32ncurses5-dev ``` - ### 编译构建过程中,提示“line 77: mcopy: command not found” - **现象描述:** @@ -904,7 +895,6 @@ optional arguments: ​sudo apt-get install dosfstools mtools ``` - ### 编译构建过程中,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory” - **现象描述:** @@ -915,14 +905,13 @@ optional arguments: - ​**解决办法:** 查询gcc_riscv32所在目录。 - + ``` which riscv32-unknown-elf-gcc ``` - + 使用chmod命令修改目录权限为755。 - ### 编译构建过程中,提示“No module named 'Crypto'” - **现象描述:** @@ -932,17 +921,18 @@ optional arguments: python3未安装Crypto。 - **解决办法:** + 1. 查询Python版本号。 - - ``` - python3 --version - ``` - 2. 需使用python3.7以上版本,然后安装pycryptodome。 - - ``` - sudo pip3 install pycryptodome - ``` - + + ``` + python3 --version + ``` + + 2. 需使用python3.9.2以上版本,然后安装pycryptodome。 + + ``` + sudo pip3 install pycryptodome + ``` ### 编译构建过程中,提示“xx.sh : xx unexpected operator” @@ -957,4 +947,4 @@ optional arguments: ``` sudo rm -rf /bin/sh sudo ln -s /bin/bash /bin/sh - ``` + ``` \ No newline at end of file diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md index 1f0f2d7ae491612cb60fc048483fc4c6f801d2f5..6cbd7db62b7dc1081ef2f54342ca39a29b4f89b0 100644 --- a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md +++ b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md @@ -1,26 +1,24 @@ # 标准系统编译构建指导 - ## 概述 编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: - 构建不同芯片平台的产品。如:hispark_taurus_standard平台。 -- 根据产品配置,按照组件组装并打包产品特性的能力。 - +- 根据产品配置,按照部件组装并打包产品特性的能力。 ### 基本概念 在了解编译构建子系统的能力前,应了解如下基本概念: - 平台 - 开发板和内核的组合,不同平台支持的子系统和组件不同。 + 开发板和内核的组合,不同平台支持的子系统和部件不同。 - 子系统 - OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 + OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 部件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或部件。子系统是一个逻辑概念,它具体由对应的部件构成。 -- 组件 +- 部件 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 - gn @@ -29,10 +27,9 @@ - ninja ninja是一个专注于速度的小型构建系统。 - ### 运作机制 -OpenHarmony的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: +OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: - 命令行解析:解析待编译的产品名称,加载相关配置。 @@ -40,7 +37,6 @@ OpenHarmony的编译构建流程主要包括编译命令行解析,调用gn, - 执行ninja:启动编译并生成对应的产品版本。 - ### 约束与限制 - 需按照[源码获取](../get-code/sourcecode-acquire.md)指导下载全量源码(采用方式三获取)。 @@ -49,72 +45,131 @@ OpenHarmony的编译构建流程主要包括编译命令行解析,调用gn, - 安装编译所需的程序包。 安装命令: - + ``` - sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 + # 推荐使用脚本,在家目录执行 + # ./build/build_scripts/env_setup.sh + # 不要用root执行,会将环境变量加到root。如果你的sheel不是bash或者zsh,执行完还需要你手动配置以下内容到你的环境变量中,cd ~到你用户家目录查看隐藏文件能显示你的用户环境变量文件。 + # export PATH=/home/tools/llvm/bin:$PATH + # export PATH=/home/tools/hc-gen:$PATH + # export PATH=/home/tools/gcc_riscv32/bin:$PATH + # export PATH=/home/tools/ninja:$PATH + # export PATH=/home/tools/node-v12.20.0-linux-x64/bin:$PATH + # export PATH=/home/tools/gn:$PATH + # export PATH=/root/.local/bin:$PATH + + # 如果不用脚本执行,则需要安装以下内容 + apt-get update -y + apt-get install -y apt-utils binutils bison flex bc build-essential make mtd-utils gcc-arm-linux-gnueabi u-boot-tools python3.9.2 python3-pip git zip unzip curl wget gcc g++ ruby dosfstools mtools default-jre default-jdk scons python3-distutils perl openssl libssl-dev cpio git-lfs m4 ccache zlib1g-dev tar rsync liblz4-tool genext2fs binutils-dev device-tree-compiler e2fsprogs git-core gnupg gnutls-bin gperf lib32ncurses5-dev libffi-dev zlib* libelf-dev libx11-dev libgl1-mesa-dev lib32z1-dev xsltproc x11proto-core-dev libc6-dev-i386 libxml2-dev lib32z-dev libdwarf-dev + apt-get install -y grsync xxd libglib2.0-dev libpixman-1-dev kmod jfsutils reiserfsprogs xfsprogs squashfs-tools pcmciautils quota ppp libtinfo-dev libtinfo5 libncurses5 libncurses5-dev libncursesw5 libstdc++6 python2.7 gcc-arm-none-eabi vim ssh locales doxygen + # python需要安装以下模块 + chmod +x /usr/bin/repo + pip3 install --trusted-host https://repo.huaweicloud.com -i https://repo.huaweicloud.com/repository/pypi/simple requests setuptools pymongo kconfiglib pycryptodome ecdsa ohos-build pyyaml prompt_toolkit==1.0.14 redis json2html yagmail python-jenkins + pip3 install esdk-obs-python --trusted-host pypi.org + pip3 install six --upgrade --ignore-installed six + #还需要安装llvm,hc-gen,gcc_riscv32,ninja,node-v14.15.4-linux-x64,gn并将上述shell环境非bash或者zsh的配置内容导入到你用户的环境变量中 ``` -## 编译构建使用指导 +## 编译构建使用指导 ### 目录结构 - ``` + /build # 编译构建主目录 -├── config # 编译相关的配置项 + +├── __pycache__ # ---------------------- +├── build_scripts/ # 编译相关的python脚本 +├── common/ # ---------------------- +├── config/ # 编译相关的配置项 ├── core -│ └── gn # 编译入口BUILD.gn配置 -├── loader # 各个组件配置加载、模板生成 -├── ohos # OpenHarmony编译打包流程配置 -│ ├── kits # kits编译打包模板和处理流程 -│ ├── ndk # ndk模板和处理流程 -│ ├── notice # notice模板和处理流程 -│ ├── packages # 版本打包模板和处理流程 -│ ├── sa_profile # sa模板和处理流程 -│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 -│ └── testfwk # 测试相关的处理 -├── scripts # 编译相关的python脚本 -├── templates # c/c++编译模板定义 -└── toolchain # 编译工具链配置 -``` +│ ├── gn/ # 编译入口BUILD.gn配置 + └── build_scripts/ # ---------------------- +├── docs # ---------------------- +gn_helpers.py* # ---------------------- +lite/ # hb和preloader入口 +misc/ +├── ohos # OpenHarmony编译打包流程配置 +│ ├── kits # kits编译打包模板和处理流程 +│ ├── ndk # ndk模板和处理流程 +│ ├── notice # notice模板和处理流程 +│ ├── packages # 版本打包模板和处理流程 +│ ├── sa_profile # sa模板和处理流程 +│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 +│ └── testfwk # 测试相关的处理 +├── ohos.gni* # 汇总了常用的gni文件,方便各个模块一次性import +├── ohos_system.prop # ---------------------- +├── ohos_var.gni* # ---------------------- +├── prebuilts_download.sh* # ---------------------- +├── print_python_deps.py* # ---------------------- +├── scripts/ # ---------------------- +├── subsystem_config.json # ---------------------- +├── subsystem_config_example.json # ---------------------- +├── templates/ # c/c++编译模板定义 +├── test.gni* # ---------------------- +├── toolchain # 编译工具链配置 +├── tools # 常用工具 +├── version.gni # ---------------------- +├── zip.py* # ---------------------- +``` + ### 编译命令 - 代码根目录下执行全量版本的编译命令: - + ``` + ./build.sh --product-name {product_name} + ``` {product_name}为当前版本支持的平台。比如:hispark_taurus_standard等。 编译完成后,结果镜像保存在 out/{device_name}/packages/phone/images/ 目录下。 -- 编译命令支持选项: - - ``` - --product-name # 必须 编译的产品名称,如:hispark_taurus_standard - --build-target # 可选 指定编译目标,可以指定多个 - --gn-args # 可选 gn参数,支持指定多个 - --ccache # 可选 编译使用ccache,需要本地安装ccache +- 编译命令支持选项:./build.sh -h + ``` + -h, --help # 显示帮助信息并退出 + --source-root-dir=SOURCE_ROOT_DIR # 指定路径 + --product-name=PRODUCT_NAME # 指定产品名 + --device-name=DEVICE_NAME # 指定装置名称 + --target-cpu=TARGET_CPU # 指定cpu + --target-os=TARGET_OS # 指定操作系统 + -T BUILD_TARGET, --build-target=BUILD_TARGET # 指定编译目标,可以指定多个 + --gn-args=GN_ARGS # gn参数,支持指定多个 + --ninja-args=NINJA_ARGS # ninja参数,支持指定多个 + -v, --verbose # 生成时显示所有命令行 + --keep-ninja-going # 让ninja持续到1000000个工作失败 + --sparse-image + --jobs=JOBS + --export-para=EXPORT_PARA + --build-only-gn # 只做gn解析,不运行ninja + --ccache # 可选 编译使用ccache,需要本地安装ccache + --fast-rebuild # 快速重建,default=False + --log-level=LOG_LEVEL # 指定编译期间的日志级别','三个级别可选:debug, info and error,default='info' + --device-type=DEVICE_TYPE # 指定设备类型,default='default' + --build-variant=BUILD_VARIANT # 指定设备操作模式,default='user' + ``` ### 开发步骤 -1. 添加组件。 - 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 - - 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 - - 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem_examples子系统中(subsystem_examples子系统定义在test/examples/目录)。 +1. 添加部件。 + 本节以添加一个自定义的部件为例,描述如何编译部件,编译库、编译可执行文件等。 + + 示例部件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 + + 示例部件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem_examples子系统中(subsystem_examples子系统定义在test/examples/目录)。 + + 示例部件partA的完整目录结构如下: - 示例组件partA的完整目录结构如下: - ``` + test/examples/partA ├── feature1 │ ├── BUILD.gn @@ -132,15 +187,17 @@ OpenHarmony的编译构建流程主要包括编译命令行解析,调用gn, ├── BUILD.gn └── src └── config.conf + ``` - 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: - + 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: + ``` + config("helloworld_lib_config") { include_dirs = [ "include" ] } - + ohos_shared_library("helloworld_lib") { sources = [ "include/helloworld1.h", @@ -149,188 +206,220 @@ OpenHarmony的编译构建流程主要包括编译命令行解析,调用gn, public_configs = [ ":helloworld_lib_config" ] part_name = "partA" } + ``` 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: - ``` + ohos_executable("helloworld_bin") { sources = [ "src/helloworld2.cpp" ] include_dirs = [ "include" ] - deps = [ # 依赖组件内模块 + deps = [ # 依赖部件内模块 "../feature1:helloworld_lib" ] - external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” + external_deps = [ "partB:module1" ] # (可选)如果有跨部件的依赖,格式为“部件名:模块名” install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 part_name = "partA" } + ``` - 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: - + 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: + ``` + ohos_prebuilt_etc("feature3_etc") { source = "src/config.conf" relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 part_name = "partA" } - ``` - - 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: - ``` - "partA": { - "module_list": [ - "//test/examples/partA/feature1:helloworld_lib", - "//test/examples/partA/feature2:helloworld_bin", - "//test/examples/partA/feature3:feature3_etc", - ], - "inner_kits": [ - - ], - "system_kits": [ - - ], - "test_list": [ + + 示例4:在部件的bundle.json中添加模块配置:test/examples/bundle.json。每个部件都有一个bundle.json配置文件,在部件的根目录下。示例如下: - ] - } + ``` + { + "name": "@ohos/", # 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": "", # 部件名称 + "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": [] # 部件测试用例编译入口 + } + } + } ``` - 一个组件包含module_list、inner_kits、system_kits、test_list四个部分的声明,其中: - - module_list:组件所包含的模块列表; - - - inner_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external_deps中添加依赖的模块; +2. 将部件添加到产品配置中。 + 在产品的配置中添加部件,产品对应的配置文件://vendor/{product_company}/{product-name}/config.json。 - - system_kits:组件提供给开发者开发应用的接口; - - - test_list:组件中对应模块的测试用例; - -2. 将组件添加到产品配置中。 - 在产品的配置中添加组件,产品对应的配置文件://vendor/{product_company}/{product-name}/config.json。 - 在产品配置文件中添加 "subsystem_examples:partA",表示该产品中会编译并打包partA到版本中。 3. 编译。 - 以编译hispark_taurus_standard为例,编译命令如下: - + 以编译hispark_taurus_standard为例,编译命令如下: + ``` + ./build.sh --product-name hispark_taurus_standard --ccache + ``` 4. 编译输出。 编译所生成的文件都归档在out/hispark_taurus/目录下,结果镜像输出在 out/hispark_taurus/packages/phone/images/ 目录下。 - ## 常见问题 - ### 如何将一个模块编译并打包到版本中? - 模块要指定part_name,指定它归属的部件,一个模块只能属于一个部件; -- 部件的模块,要在部件配置的module_list中,或者可以被module_list中的模块依赖到; +- 部件的模块,要在部件配置的component.build.sub_component中,或者可以被component.build.sub_component中的模块依赖到; - 部件要加到对应产品的部件列表中。 - ### 关于deps、external_deps的使用 在添加一个模块的时候,需要在BUILD.gn中声明它的依赖,为了便于后续处理部件间依赖关系,我们将依赖分为两种——部件内依赖deps和部件间依赖external_deps。 -**依赖分类:** - -部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。 - -部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。 +### 依赖分类: -部件内依赖使用deps,部件间依赖使用external_deps。 +- 1.部件内依赖: 现有模块module1属于部件part1,要添加一个属于部件part1的模块module2,module2依赖于module1,这种情况就属于部件内依赖。 -**示例:** +- 2.部件间依赖: 现有模块module1属于部件part1,要添加一个模块module2,module2依赖于module1,module2属于部件part2。模块module2与模块module1分属于两个不同的部件,这种情况就属于部件间依赖。 -部件内依赖示例: +- ##### 部件内依赖示例: - -``` -import("//build/ohos.gni") -ohos_shared_library("module1") { - …… - part_name = "part1" # 必选,所属部件名称 -} -``` + ``` + import("//build/ohos.gni") + ohos_shared_library("module1") { + …… + part_name = "part1" # 必选,所属部件名称 + …… + } + ``` - -``` -import("//build/ohos.gni") -ohos_shared_library("module2") { - …… - deps = [ - "module1的gn target", - …… - ] # 部件内模块依赖 - part_name = "part1" # 必选,所属部件名称 -} -``` + ``` + import("//build/ohos.gni") + ohos_shared_library("module2") { + …… + deps = [ + "module1的gn target", + …… + ] # 部件内模块依赖 + part_name = "part1" # 必选,所属部件名称 + } + ``` -部件内依赖和一般的依赖一样 +- ##### 部件间依赖示例: -部件间依赖示例: + ``` + import("//build/ohos.gni") + ohos_shared_library("module1") { + …… + part_name = "part1" # 必选,所属部件名称 + …… + } + ``` - -``` -import("//build/ohos.gni") -ohos_shared_library("module1") { - …… - part_name = "part1" # 必选,所属部件名称 -} -``` +- 模块1所属部件的bundle.json文件 -模块1所属部件的ohos.build文件 + ``` + { + "name": "@ohos/", # HPM部件英文名称,格式"@组织/部件名称" + "description": "xxxxxxxxxxxxxxxx", # 部件功能一句话描述 + "version": "3.1", # 版本号,版本号与OpenHarmony版本号一致 + "license": "MIT", # 部件License + "publishAs": "code-segment", # HPM包的发布方式,当前默认都为code_segment + "segment": { + "destPath": "" + }, # 发布类型为code_segment时为必填项,定义发布类型code_segment的代码还原路径(源码路径) + "dirs": {}, # HPM包的目录结构,字段必填内容可以留空 + "scripts": {}, # HPM包定义需要执行的脚本,字段必填,值非必填 + "licensePath "licensePath": "COPYING", + ": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "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": ["part1"], # 部件编译入口,部件所有模块在此列表 + "inner_kits": [ # 部件间接口 + { + "header": { + "header_base": "头文件所属目录", # 头文件所属目录 + "header_files": [ + "头文件名" + ] # 头文件名列表 + }, + "name": "module1的gn target" + }, + ], + "test": [] # 部件测试用例编译入口 + } + } + } + ``` - -``` -{ - "subsystem":"子系统名称", - "parts": { - "part1": { - "inner_kits": [ - { - "header": { - "header_base": "头文件所属目录", # 头文件所属目录 - "header_files": [ - "头文件名" - ] # 头文件名列表 - }, - "name": "module1的gn target" - }, - ], - …… - } - } -} -``` + ``` + import("//build/ohos.gni") + ohos_shared_library("module2") { + …… + external_deps = [ + "part1:module1", + …… + ] # 部件间模块依赖,这里依赖的模块必须是依赖的部件声明在inner_kits中的模块 + part_name = "part2" # 必选,所属部件名称 + } - -``` -import("//build/ohos.gni") -ohos_shared_library("module2") { - …… - external_deps = [ - "part1:module1", - …… - ] # 部件间模块依赖,这里依赖的模块必须是依赖的部件声明在inner_kits中的模块 - part_name = "part2" # 必选,所属部件名称 -} -``` + ``` > ![icon-caution.gif](public_sys-resources/icon-caution.gif) **注意:** > 部件间依赖要写在external_deps里面,格式为”部件名:模块名"的形式,并且依赖的模块必须是依赖的部件声明在inner_kits中的模块。 + + + ### 标准系统如何添加一个模块 要添加的模块可以分为以下三种情况,对原有的配置文件进行不同程度的修改。 @@ -346,82 +435,145 @@ ohos_shared_library("module2") { 1. 在模块目录下配置BUILD.gn,根据类型选择对应的模板。 这一步与在原有部件中添加一个模块的方法基本一致,只需注意该模块对应BUILD.gn文件中的part_name为新建部件的名称即可。 -2. 修改或者新建ohos.build配置文件。 - - ``` +2. 修改bundle.json配置文件。"部件包含模块的gn目标" + + ``` { - "subsystem": "子系统名", - "parts": { - "新建部件名": { - "module_list": [ - "部件包含模块的gn目标" - ], - "inner_kits": [ - ], - "test_list": [ - "测试用例", - ] + "name": "@ohos/", # HPM部件英文名称,格式"@组织/部件名称" + "description": "xxxxxxxxxxxxxxxxxxx", # 部件功能一句话描述 + "version": "3.1", # 版本号,版本号与OpenHarmony版本号一致 + "license": "MIT", # 部件License + "publishAs": "code-segment", # HPM包的发布方式,当前默认都为code_segment + "segment": { + "destPath": "third_party/nghttp2" + }, # 发布类型为code_segment时为必填项,定义发布类型code_segment的代码还原路径(源码路径) + "dirs": {}, # HPM包的目录结构,字段必填内容可以留空 + "scripts": {}, # HPM包定义需要执行的脚本,字段必填,值非必填 + "licensePath": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "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": [ + "//foundation/arkui/napi:napi_packages", # 原有模块1 + "//foundation/arkui/napi:napi_packages_ndk" # 原有模块2 + "//foundation/arkui/napi:new" # 新增模块new + ], # 部件编译入口,模块在此处配置 + "inner_kits": [], # 部件间接口 + "test": [] # 部件测试用例编译入口 + } } - } } ``` - 在原有子系统中添加一个新的部件,有两种方法,一种是在该子系统原有的ohos.build文件中添加该部件,另一种是新建一个ohos.build文件,注意无论哪种方式该ohos.build文件均在对应子系统所在文件夹下。 + 注意无论哪种方式该bundle.json文件均在对应子系统所在文件夹下。 + +**新建部件并在其中添加一个模块** - ohos.build文件包含两个部分,第一部分subsystem说明了子系统的名称,parts定义了该子系统包含的部件,要添加一个部件,需要把该部件对应的内容添加进parts中去。添加的时候需要指明该部件包含的模块module_list,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test_list中说明,inner_kits与test_list没有也可以不添加。 +1. 在模块目录下配置BUILD.gn,根据类型选择对应的模板。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 + +2. 新建一个bundle.json文件,bundle.json文件均在对应子系统所在文件夹下。bundle.json文件包含两个部分,第一部分subsystem说明了子系统的名称,parts定义了该子系统包含的部件,要添加一个部件,需要把该部件对应的内容添加进parts中去。添加的时候需要指明该部件包含的模块sub_component,假如有提供给其它部件的接口,需要在inner_kits中说明,假如有测试用例,需要在test中说明,inner_kits与test没有也可以不添加。 + +2. 在//vendor/{product_company}/{product-name}/config.json中添加对应的部件,直接添加到原有部件后即可。 -3. 在//vendor/{product_company}/{product-name}/config.json中添加对应的部件,直接添加到原有部件后即可。 - ``` - { - "parts":{ - "部件所属子系统名:部件名":{} - } - } + "subsystems": [ + { + "subsystem": "部件所属子系统名", + "components": [ + { "component": "部件名1", "features":[] }, # 子系统下的原有部件1 + { "component": "部件名2", "features":[] }, # 子系统下的原有部件2 + { "component": "部件名new", "features":[] } # 子系统下的新增部件new + ] + }, + ....... + ] ``` **新建子系统并在该子系统的部件下添加模块** 1. 在模块目录下配置BUILD.gn,根据类型选择对应的模板。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 -2. 在新建的子系统目录下每个部件对应的文件夹下创建ohos.build文件,定义部件信息。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 +2. 在新建的子系统目录下每个部件对应的文件夹下创建bundle.json文件,定义部件信息。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 3. 修改build目录下的subsystem_config.json文件。 - + ``` { - "子系统名": { - "path": "子系统目录", - "name": "子系统名", - ... - } + "子系统名1": { # 原有子系统1 + "path": "子系统目录1", + "name": "子系统名1" + }, + "子系统名2": { # 原有子系统2 + "path": "子系统目录2", + "name": "子系统名2" + }, + "子系统名new": { # 新增子系统new + "path": "子系统目录new", + "name": "子系统名new" + }, + ... } ``` 该文件定义了有哪些子系统以及这些子系统所在文件夹路径,添加子系统时需要说明子系统path与name,分别表示子系统路径和子系统名。 4. 在//vendor/{product_company}/{product-name}目录下的产品配置如product-name是hispark_taurus_standard时,在config.json中添加对应的部件,直接添加到原有部件后即可。 - + ``` - { - ... - "parts":{ - "部件所属子系统名:部件名":{} - } - } + "subsystems": [ + { + "subsystem": "arkui", # 原有的子系统名 + "components": [ # 单个子系统下的所有部件集合 + { + "component": "ace_engine_standard", # 原有的部件名 + "features": [] + }, + { + "component": "napi", # 原有的部件名 + "features": [] + } + { + "component": "component_new1", # 原有子系统新增的的部件名component_new1 + "features": [] + } + ] + }, + { + "subsystem": "subsystem_new", # 新增的子系统名 + "components": [ + { + "component": "component_new2", # 新增子系统新增的的部件名component_new2 + "features": [] + } + ] + }, + ... + ] ``` - - 成功添加验证: - - - 在输出文件夹的对应子系统文件夹下的部件文件夹下的BUILD.gn文件中module_list包含了新建模块的BUILD.gn中定义的目标。 - - 编译完成后打包到image中去,生成对应的so文件或者二进制文件。 + 成功添加验证: + - 在输出文件夹的对应子系统文件夹下的部件文件夹下的BUILD.gn文件中module_list包含了新建模块的BUILD.gn中定义的目标。 + - 编译完成后打包到image中去,生成对应的so文件或者二进制文件。 **配置文件说明** OpenHarmony的配置文件主要有四个。 1. vendor\产品厂商\产品名\config.json - + ``` { "product_name": "MyProduct", @@ -444,55 +596,71 @@ OpenHarmony的配置文件主要有四个。 } ``` - 指明了产品名,产品厂商,产品设备,版本,要编译的系统类型,以及产品包含的子系统。 2. build目录下的subsystem_config.json文件。 - + ``` { - "ace": { - "project": "hmf/ace", - "path": "foundation/ace", - "name": "ace", - "dir": "foundation" - } - } - + "arkui": { + "path": "foundation/arkui", + "name": "arkui" + }, + "ai": { + "path": "foundation/ai", + "name": "ai" + }, + ...... + } ``` - 该文件对子系统进行了说明,我们需要该子系统定义中的name与path,分别表示子系统的名称和所在文件夹路径。 -3. 子系统中ohos.build文件。 - +3. 子系统中bundle.json文件。 + ``` { - "subsystem": "ace", - "parts": { - "napi": { - "module_list": [ - "//foundation/arkui/napi:napi_packages" - ], - "inner_kits": [ - ], - "test_list": [ - "//foundation/arkui/napi:napi_packages_test", - "//foundation/arkui/napi/test/unittest:unittest" - ] + "name": "@ohos/", # 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" + }, + "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": ["部件包含模块的gn目标"], # 部件编译入口 + "inner_kits": [], # 部件间接口 + "test": [] # 部件测试用例编译入口 + } } - } } - ``` - - ohos.build文件定义了子系统包含的部件。 - - 每个部件定义它所包含的模块目标module_list,以及部件间交互的接口inner_kits,测试用例test_list。部件包含的模块目标module_list是必须要说明的。 + bundle.json文件定义了子系统包含的部件。 + + 每个部件定义它所包含的模块目标component.build.sub_component,以及部件间交互的接口component.build.inner_kits,测试用例component.build.test_list。部件包含的 + 模块目标component.build.sub_component是必须要说明的。 4. 每个模块对应的BUILD.gn文件。 可以使用提供的模板,也可以使用gn语法规则自定义编写。 - ### hap的编译 **hap包的构成** @@ -514,6 +682,7 @@ ohos_resources - 资源目标的目标名必须以"resources"或"resource"或"res"结尾,否则编译检查时会报错 - 支持的变量: + 1. sources: 资源的路径,变量类型是list,可以写多个路径 2. hap_profile: 编译资源时需要提供对应hap包的config.json 3. deps: 当前目标的依赖,可选 @@ -527,6 +696,7 @@ ohos_assets - assets目标的目标名必须以"assets"或"asset"结尾 - 支持的变量: + 1. sources:raw assets所在路径,变量类型是list,可以写多个路径 2. deps: 当前目标的依赖,可选 @@ -537,6 +707,7 @@ ohos_js_assets - JS assets目标的目标名必须以"assets"或"asset"结尾 - 支持的变量: + 1. source_dir: JS 资源的路径,变量类型是string,只能写一个 2. deps: 当前目标的依赖,可选 @@ -545,15 +716,16 @@ ohos_hap - 声明一个hap目标,该目标会生成一个hap包,最终将会打包到system镜像中 - 支持的变量: + 1. hap_profile: hap包的config.json 2. deps: 当前目标的依赖 3. shared_libraries: 当前目标依赖的native库 4. hap_name: hap包的名字,可选,默认为目标名 5. final_hap_path: 用户可以制定生成的hap的位置,可选,final_hap_path中会覆盖hap_name - 6. subsystem_name: hap包从属的子系统名,需要和ohos.build中的名字对应,否则将导致无法安装到system镜像中 + 6. subsystem_name: hap包从属的子系统名,需要和bundle.json中的名字对应,否则将导致无法安装到system镜像中 7. part_name: hap包从属的部件名,同subsystem_name 8. js2abc: 是否需要将该hap包转换为ARK的字节码 - 签名篇见:[配置应用签名]( https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768) + 签名篇见:[配置应用签名]( https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768) 9. certificate_profile: hap对应的授权文件,用于签名 10. certificate_file: 证书文件,证书文件和授权文件,应用开发者需要去openharmony官网申请 11. keystore_path: keystore文件,用于签名 @@ -561,35 +733,33 @@ ohos_hap 13. key_alias: key的别名 14. module_install_name:安装时的hap包名称 15. module_install_dir: 安装到system中的位置,默认安装在system/app目录下 - - **开发示例** - - - ``` - import("//build/ohos.gni") # 引用ohos.gni - ohos_hap("clock") { - hap_profile = "./src/main/config.json" # config.json - deps = [ - ":clock_js_assets", # JS assets - ":clock_resources", # 资源 - ] - shared_libraries = [ - "//third_party/libpng:libpng", # native库 - ] - certificate_profile = "../signature/systemui.p7b" # Cer文件 - hap_name = "SystemUI-NavigationBar" # 名字 - part_name = "prebuilt_hap" - subsystem_name = "applications" - } - ohos_js_assets("clock_js_assets") { - source_dir = "./src/main/js/default" - } - ohos_resources("clock_resources") { - sources = [ "./src/main/resources" ] - hap_profile = "./src/main/config.json" - } - ``` - + + **hap开发示例** + + ``` + import("//build/ohos.gni") # 引用ohos.gni + ohos_hap("clock") { + hap_profile = "./src/main/config.json" # config.json + deps = [ + ":clock_js_assets", # JS assets + ":clock_resources", # 资源 + ] + shared_libraries = [ + "//third_party/libpng:libpng", # native库 + ] + certificate_profile = "../signature/systemui.p7b" # Cer文件 + hap_name = "SystemUI-NavigationBar" # 名字 + part_name = "prebuilt_hap" + subsystem_name = "applications" + } + ohos_js_assets("clock_js_assets") { + source_dir = "./src/main/js/default" + } + ohos_resources("clock_resources") { + sources = [ "./src/main/resources" ] + hap_profile = "./src/main/config.json" + } + ``` ### 开源软件Notice收集策略说明 @@ -599,22 +769,22 @@ ohos_hap 静态库本身是不会被打包的,一般是作为动态库或者可执行程序的一部分被打包到系统中的,为了确保完备,静态库的都会收集。 -最终合并的Notice.txt要体现出镜像中每个文件都是用了哪些License,模块和License要有对应关系。 +最终合并的NOTICE.txt要体现出镜像中每个文件都是用了哪些License,模块和License要有对应关系。 -最终合并的Notice.txt文件在/system/etc/ 目录下。 +最终合并的NOTICE.txt文件在/system/etc/ 目录下。 **收集规则** 按照优先级收集License 1. 模块在BUILD.gn中直接声明自己使用的License文件,优先级最高。如下图示例: - + ``` - ohos_shared_library("example") { - ... - license_file = "path-to-license-file" - ... - } + ohos_shared_library("example") { + ... + license_file = "path-to-license-file" + ... + } ``` 2. 如果模块没有显式声明,那么编译脚本会在BUILD.gn所在的当前目录中查找Readme.OpenSource文件,解析该文件,找出该文件中声明的license,将其作为模块的License。 @@ -630,4 +800,4 @@ ohos_hap 2. 代码目录下,如果代码使用的不是Apache2.0 License,需要在目录下提供对应的License文件,或者直接在模块中指定license_file。 -3. 如果BUILD.gn中添加的源码文件不是当前目录的,需要检查下源码文件所在仓下的license是否和BUILD.gn文件所在仓的一致,不一致的需要处理。 +3. 如果BUILD.gn中添加的源码文件不是当前目录的,需要检查下源码文件所在仓下的license是否和BUILD.gn文件所在仓的一致,不一致的需要处理。 \ No newline at end of file