鸿蒙系统架构简介
鸿蒙系统软件部分从下往上分为内核层、系统服务层、应用框架层和应用层。
内核层
内核层包括 KAL(内核抽象层)和驱动子系统等,主要是负责操作系统相关的流程,提供底层通用能力,与提供的服务应用等没有关系。
KAL
鸿蒙系统被设计用于各种不同的设备上,包括收集、智能电视、手表等不同规模,不同性能的硬件上,面对不同的需求场景,对内核的要求也不同,因此鸿蒙设计之初就将内核抽象出来,形成内核抽象层 KAL,KAL 为上层提供统一的进程调度、内存管理、文件系统等模型,而下层则适配了不同的内核:标准 Linux、LiteOS 等。
驱动子系统
驱动子系统主要包括 HDF(HarmonyOS 驱动框架),此框架独立于内核(受益于 KAL),对上层提供统一的外设访问能力。
除了 KAL 和驱动子系统,还有硬件抽象层 HAL、硬件驱动接口 HDI、操作系统抽象层 OSAL 等逻辑层次,其设计均是为了统一各种不同应用场景下系统的对外接口,方便上层应用的开发。
系统服务层与应用框架层
系统服务层主要实现应用服务通用的能力,应用框架层将系统服务层实现的能力封装对上层用户提供。包括基本能力子系统集、基础软件服务子系统集、增强软件服务子系统集和硬件服务子系统集。
基本能力子系统集
基本能力子系统集是所有应用程序的基础,是所有应用服务都需要的功能。
在系统服务层包含以下组件:
分布式软总线:各终端通信能力组件,是鸿蒙万物互联的基础
分布式任务调度:鸿蒙有一项能力,可以把一个正在运行的应用迁移到其他的设备,正是这个分布式任务调度提供的功能
分布式数据管理:补充分布式数据管理用于同步各终端应用数据,是分布式任务调度的补充,没有分布式数据管理,分布式任务调度也无法正常运行
方舟多语言运行时组件:方舟编译器的运行时
公共基础库子系统:提供其他的关键系统服务依赖的基础能力
多模输入子系统:提供诸如、语音、触摸屏、各类传感器的输入处理
图形子系统:图形图像处理
安全子系统:系统安全审计、防护
AI 子系统:提供 AI 通用能力
其中,多模输入、图形、安全、AI 同时由应用框架层开放给上层开发者供应用服务调用。
此外,应用框架层也有一部分不依赖系统服务层的组件:
这部分组件为上层应用服务开发提供标准开发框架。
基础软件服务子系统集
此子系统集提供基础的软件服务,可用于大多数通用设备,如手机、手表等。
增强软件服务子系统集
此子系统集提供了特定场景定制扩展的软件服务,如智慧屏、智能穿戴设备、嵌入式设备等。
硬件服务子系统集
此子系统集提供特定场景定制扩展的硬件服务,与特定硬件相关,如位置服务、生物识别、穿戴、嵌入式设备等。
总体来说,各子系统集在系统服务层和应用框架层都有子系统,系统服务层利用下层的操作系统,实现核心功能,应用框架层将这些功能打包开放给上层开发者,供应用于服务调用。
GN 和 Ninja 介绍
GN(Generate Ninja)是一个构建工具,它是由 Google 开发的,用于构建大型项目的工具。GN 的主要目标是提供一种高度可扩展和可配置的构建系统,以满足各种项目的需求。它通常与 Ninja 构建系统一起使用,Ninja 是另一个由 Google 开发的构建工具,专注于构建速度和效率。
以下是一些 GN 构建工具的主要特点和用途:
高度可配置:GN 允许开发人员定义项目的构建规则,包括编译选项、目标文件、依赖关系等。这使得 GN 非常适合于需要定制化构建过程的项目。
通用性:GN 可以用于各种编程语言和平台,包括 C、C++、Rust、Go 等,以及 Windows、Linux、macOS 等操作系统
易于学习和使用:GN 使用 Python-like 的配置文件语言,相对容易理解和编写。它的语法清晰,易于上手。
并行构建:GN 可以生成 Ninja 构建文件,这些文件可以用于并行构建项目,以提高构建速度。
构建性能:GN 专注于构建性能,可以快速地生成构建文件,同时支持增量构建,只重新构建发生更改的文件,以减少构建时间。
交叉编译支持:GN 支持交叉编译,可以用于为不同的目标平台生成代码。
可扩展性:开发人员可以编写自定义构建规则和工具链,以满足项目的特殊需求。
良好的社区支持:GN 有一个活跃的社区,提供了丰富的文档和示例,以帮助开发人员使用和定制 GN 来满足他们的需求。
GN 是一个强大的构建工具,适用于大型项目和需要高度可配置构建系统的项目。它可以帮助开发人员管理复杂的构建过程,提高构建效率,同时保持灵活性和可扩展性。
Ninja 是一个快速且轻量级的构建工具,它的主要目标是提供高效的编译和构建过程,特别适用于大型项目。Ninja 是由 Google 开发,用于替代 Make 等传统构建工具,以提供更好的性能和可维护性。
以下是一些关于 Ninja 的主要特点和用途:
极速构建:Ninja 的设计注重构建速度。它使用了一种轻量级的构建规则语言,能够以最小的开销进行构建。这使得 Ninja 非常适合大型项目,可以显著减少构建时间。
简化配置:Ninja 的配置文件非常简单,易于理解和维护。它的语法非常基础,通常只需定义目标、依赖关系和构建规则,不需要繁琐的 Makefile 语法。
跨平台支持:Ninja 可以在多种操作系统上运行,包括 Linux、Windows、macOS 等。这使得它成为一个跨平台的构建工具,可以在不同的开发环境中使用。
并行构建:Ninja 支持并行构建,可以同时构建多个目标,以充分利用多核处理器和加速构建过程。
增量构建:Ninja 能够检测源文件和依赖文件的更改,只重新构建发生更改的部分,从而减少不必要的构建步骤,提高构建效率。
扩展性:Ninja 允许开发人员编写自定义构建规则,以满足项目特殊的需求。这使得它非常灵活,适用于各种不同类型的项目。
易于集成:Ninja 可以与其他构建工具和开发环境集成,例如 CMake、GN(Generate Ninja)、IDE 等,使得构建过程更加流畅。
Ninja 是一个优秀的构建工具,特别适用于需要高效构建的大型项目。它的速度和简单性使得开发人员可以更专注于开发工作,而不必担心构建过程的瓶颈。因此,Ninja 已经在许多开源项目和商业项目中被广泛采用。
GN 的构建流程
GN 项目的构建大致分为以下几个步骤。
查找.gn 文件
GN 工具会在当前目录下查找.gn 文件,这是整个编译工程的入口配置。
.gn 文件中记录了编译工具链相关配置和项目根目录。
运行 BUILDCONFIG.gn 文件
此文件是在.gn 文件中指定的,用于配置环境和工具链、通用编译参数等信息。
运行源码根目录下的 BUILD.gn 文件
项目根目录也是在.gn 文件中指定,对于 GN 来说,每个组件/子组件都有一个 BUILD.gn 文件。
评估依赖关系
根目录下的 BUILD.gn 中会决定整个项目依赖哪些组件
递归生成.ninja 文件
对于上面评估过的组件/子组件,对每个组件生成.ninja 配置文件。
生成 build.ninja
这个文件是总的编译入口,最终 ninja 就是调用这个文件完成整个项目的构建。
鸿蒙构建
鸿蒙项目整个的构建流程是上述描述的 GN 构建流程基本一致,只是为了完成组件化构建,将组件列表和组件间依赖关系作为独立的配置文件存储,并在 gn 配置文件中编写逻辑应用这些配置。
鸿蒙构建关键文件
鸿蒙编译框架中,有一些关键的文件,如下(基于 OpenHarmony_release_v1.1.0 版本):
build/lite/config/BUILDCONFIG.gn
此文件主要配置构建工具链和一些通用默认的配置。
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/ohos_var.gni")
import("${device_path}/config.gni")
if (target_os == "") {
target_os = "ohos"
}
if (target_cpu == "") {
target_cpu = board_cpu
}
# Only gcc avaiable for liteos_m.
if (ohos_kernel_type == "liteos_m" || ohos_kernel_type == "linux") {
use_board_toolchain = true
}
# Set current toolchain with to board configuration.
if (board_toolchain != "" && use_board_toolchain) {
ohos_current_toolchain = board_toolchain
ohos_current_toolchain_type = board_toolchain_type
ohos_build_compiler = ohos_current_toolchain_type
hos_build_compiler = ohos_current_toolchain_type
if (board_toolchain_path != "") {
compile_prefix = "${board_toolchain_path}/${board_toolchain_prefix}"
} else {
compile_prefix = "${board_toolchain_prefix}"
}
ohos_current_toolchain_prefix = compile_prefix
ohos_current_sysroot = board_configed_sysroot
set_default_toolchain("//build/lite/toolchain:${board_toolchain}")
if (board_toolchain_type == "gcc") {
ohos_current_cc_command = "${compile_prefix}gcc"
ohos_current_cxx_command = "${compile_prefix}g++"
ohos_current_ar_command = "${compile_prefix}ar"
ohos_current_ld_command = ohos_current_cc_command
ohos_current_strip_command = "${compile_prefix}strip --strip-unneeded"
default_target_configs = [ "//build/lite/config:gcc_opt" ]
} else if (board_toolchain_type == "clang") {
ohos_current_cc_command = "${compile_prefix}clang"
ohos_current_cxx_command = "${compile_prefix}clang++"
ohos_current_ar_command = "${compile_prefix}llvm-ar"
ohos_current_as_command = ohos_current_cc_command
ohos_current_ld_command = ohos_current_cc_command
ohos_current_strip_command = "$compile_prefix/llvm-objcopy --strip-all"
default_target_configs = [ "//build/lite/config:clang" ]
default_target_configs += [ "//build/lite/config:clang_opt" ]
}
} else {
# OHOS default toolchain: ohos_clang
ohos_current_toolchain = "ohos_clang"
ohos_build_compiler = "clang"
hos_build_compiler = "clang"
ohos_clang_toolchain_dir = rebase_path("${ohos_build_compiler_dir}/bin")
compile_prefix = rebase_path("${ohos_build_compiler_dir}/bin")
ohos_current_cc_command = "${compile_prefix}/clang"
ohos_current_cxx_command = "${compile_prefix}/clang++"
ohos_current_ar_command = "${compile_prefix}/llvm-ar"
ohos_current_as_command = ohos_current_cc_command
ohos_current_ld_command = ohos_current_cc_command
ohos_current_strip_command =
"$ohos_clang_toolchain_dir/llvm-objcopy --strip-all"
set_default_toolchain("//build/lite/toolchain:linux_x86_64_ohos_clang")
default_target_configs = [ "//build/lite/config:clang" ]
default_target_configs += [ "//build/lite/config:clang_opt" ]
}
default_target_configs += [
"//build/lite/config:board_config",
"//build/lite/config:cpu_arch",
"//build/lite/config:common",
"//build/lite/config:default_link_path",
]
if (ohos_build_type == "debug") {
default_target_configs += [ "//build/lite/config:debug" ]
} else if (ohos_build_type == "release") {
default_target_configs += [ "//build/lite/config:release" ]
}
if (ohos_kernel_type == "liteos_a" || ohos_kernel_type == "linux") {
default_target_configs += [
"//build/lite/config/kernel/liteos/cortex_a:default",
"//build/lite/config:security",
"//build/lite/config:exceptions",
]
} else if (ohos_kernel_type == "liteos_m") {
default_target_configs += [ "//build/lite/config:stack_protector" ]
}
default_target_configs += [
"//build/lite/config:language_c",
"//build/lite/config:language_cpp",
"//build/lite/config:kernel_macros",
]
default_shared_library_configs =
default_target_configs + [ "//build/lite/config:shared_library_config" ]
default_static_library_configs = default_target_configs
if (ohos_kernel_type != "liteos_m") {
default_static_library_configs += [ "//build/lite/config:static_pie_config" ]
}
default_executable_configs = default_static_library_configs +
[ "//build/lite/config:pie_executable_config" ]
set_defaults("executable") {
configs = default_executable_configs
}
set_defaults("static_library") {
configs = default_static_library_configs
}
set_defaults("shared_library") {
configs = default_shared_library_configs
}
set_defaults("source_set") {
configs = default_target_configs
}
复制代码
build/lite/components/*.json
这些文件描述了每个子系统包含组件的信息,命名为 “子系统.json”,下面以 kernel.json 为例,介绍下内核子系统的描述。
{
"components": [
{
"component": "liteos_a",
"description": "liteos-a kernel",
"optional": "false",
"dirs": [
"kernel/liteos_a"
],
"targets": [
"//kernel/liteos_a:kernel"
],
"rom": "1.98MB",
"ram": "",
"output": [
"liteos.bin"
],
"adapted_board": [
"hi3516dv300",
"hi3516dv300_openharmony",
"hi3518ev300",
"hi3518ev300_openharmony"
],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": [
"FreeBSD",
"musl",
"zlib",
"FatFs",
"Linux_Kernel",
"lwip",
"NuttX",
"mtd-utils"
]
}
},
{
"component": "liteos_m",
"description": "liteos-m kernel",
"optional": "false",
"dirs": [
"kernel/liteos_m"
],
"targets": [
"//kernel/liteos_m:kernel"
],
"rom": "40KB",
"ram": "",
"output": [],
"features": [],
"adapted_board": [],
"adapted_kernel": [ "liteos_m" ],
"deps": {
"components": [],
"third_party": [
"bounds_checking_function",
"FatFs"
]
}
},
{
"component": "linux_hi3516dv300",
"description": "linux 4.9",
"optional": "false",
"dirs": [
"vendor/hisi/camera/dvkit_product/linux/hi3516dv300"
],
"targets": [
"//vendor/hisi/camera/dvkit_product/linux/hi3516dv300/Hi3516CV500_SDK_V2.0.2.0:linux_kernel"
],
"rom": "",
"ram": "",
"output": [
"u-boot-hi3516dv300.bin",
"uImage_hi3516dv300_smp",
"rootfs.img"
],
"features": [],
"adapted_board": [
"hi3516dv300",
"hi3516dv300_openharmony"
],
"adapted_kernel": [ "linux" ],
"deps": {
"components": [],
"third_party": []
}
},
{
"component": "linux_4_1_9",
"description": "linux 4.1.9",
"optional": "false",
"dirs": [
"vendor/hisi/camera/dvkit_product/linux/hi3516dv300/Hi3516CV500_SDK_V2.0.3.0"
],
"targets": [
"//vendor/hisi/camera/dvkit_product/linux/hi3516dv300/Hi3516CV500_SDK_V2.0.3.0:linux_kernel"
],
"rom": "",
"ram": "",
"output": [
"u-boot-hi3516dv300.bin",
"uImage_hi3516dv300_smp",
"rootfs.img"
],
"features": [],
"adapted_board": [
"hi3516dv300",
"hi3516dv300_openharmony"
],
"adapted_kernel": [ "linux" ],
"deps": {
"components": [],
"third_party": []
}
},
{
"component": "linux_hi3518ev300",
"description": "linux 4.9",
"optional": "false",
"dirs": [
"vendor/hisi/camera/dvkit_product/linux/hi3518ev300"
],
"targets": [
"//vendor/hisi/camera/dvkit_product/linux/hi3518ev300/Hi3516EV200_SDK_V1.0.1.2_LINUX:linux_kernel"
],
"rom": "",
"ram": "",
"output": [
"u-boot-hi3518ev300.bin",
"uImage_hi3518ev300",
"rootfs.img"
],
"features": [],
"adapted_board": [
"hi3518ev300",
"hi3518ev300_openharmony"
],
"adapted_kernel": [ "linux" ],
"deps": {
"components": [],
"third_party": []
}
}
]
}
复制代码
顶层配置只有一项 components,描述组件信息。对于每一项 components,关键信息如下:
component: 组件名
description:组件描述
optional:该组件在此子系统中是否是可选项
dirs:组件源码路径,可以指定多处
targets:GN 的编译目标
rom:组件构建出来将会占用的 rom 空间,预估值
ram:组件运行时所需内存空间,预估值
output:组件构建出的产物列表
adapted_board:适配的单板
adapted_kernel:适配的内核
features:组件中包含的可选特性
deps:组件依赖,其中有包含了依赖的其他组件、第三方组件、内核、单板细节等。
各组件下的 BUILD.gn 文件
这些文件是真正描述一个组件的编译流程以及所包含的 feature 信息。
下面举例说明 foundation/ai/engine/services/BUILD.gn
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/config/component/lite_component.gni")
# manage all components of aisystem
lite_component("ai") {
features = [
"client:client",
"server:server",
]
if (ohos_build_type == "debug") {
deps = [ "//foundation/ai/engine/test" ]
}
}
复制代码
文件中描述了 ai 子系统相关组件中包含的 feature。
vendor/hisilicon/*/config.json
此文件是配置产品配置文件,配置了某个具体的产品包含哪些子系统,哪些组件,哪些特性以及其他的产品信息。
以 vendor/hisilicon/hispark_aries/config.json 文件为例:
{
"product_name": "ipcamera_hispark_aries",
"ohos_version": "OpenHarmony 1.0",
"device_company": "hisilicon",
"board": "hispark_aries",
"kernel_type": "liteos_a",
"kernel_version": "",
"subsystems": [
{
"subsystem": "aafwk",
"components": [
{ "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = false" ] }
]
},
{
"subsystem": "hiviewdfx",
"components": [
{ "component": "hilog", "features":[] }
]
},
{
"subsystem": "distributed_schedule",
"components": [
{ "component": "system_ability_manager", "features":[] },
{ "component": "foundation", "features":[] },
{ "component": "distributed_schedule", "features":[] }
]
},
{
"subsystem": "security",
"components": [
{ "component": "hichainsdk", "features":[] },
{ "component": "permission", "features":[] },
{ "component": "app_verify", "features":[] }
]
},
{
"subsystem": "multimedia",
"components": [
{ "component": "media_service", "features":[] }
]
},
{
"subsystem": "graphic",
"components": [
{ "component": "graphic_utils", "features":[] },
{ "component": "surface", "features":[] }
]
},
{
"subsystem": "startup",
"components": [
{ "component": "syspara", "features":[] },
{ "component": "bootstrap", "features":[] },
{ "component": "init", "features":[] },
{ "component": "appspawn", "features":[] }
]
},
{
"subsystem": "kernel",
"components": [
{ "component": "liteos_a", "features":[] }
]
},
{
"subsystem": "communication",
"components": [
{ "component": "ipc", "features":[] },
{ "component": "soft_bus", "features":[] },
{ "component": "wpa_supplicant", "features":[] }
]
},
{
"subsystem": "drivers",
"components": [
{ "component": "adapter_uhdf", "features":[] },
{ "component": "peripheral_display", "features":[] },
{ "component": "peripheral_input", "features":[] },
{ "component": "peripheral_wlan", "features":[] }
]
},
{
"subsystem": "appexecfwk",
"components": [
{ "component": "bundle_mgr", "features":[] }
]
},
{
"subsystem": "utils",
"components": [
{ "component": "kv_store", "features":[] },
{ "component": "os_dump", "features":[] }
]
},
{
"subsystem": "vendor",
"components": [
{ "component": "middleware", "features":[] },
{ "component": "hi3518ev300_init", "features":[] },
{ "component": "hardware", "features":[] }
]
},
{
"subsystem": "test",
"components": [
{ "component": "developer_test", "features":[] },
{ "component": "xts_acts", "features":[] },
{ "component": "xts_tools", "features":[] }
]
},
{
"subsystem": "ai",
"components": [
{ "component": "ai_engine", "features":[] }
]
}
],
"vendor_adapter_dir": "//device/hisilicon/hardware",
"third_party_dir": "//third_party",
"product_adapter_dir": "//vendor/hisilicon/hispark_aries/hals",
"ohos_product_type":"",
"ohos_manufacture":"",
"ohos_brand":"",
"ohos_market_name":"",
"ohos_product_series":"",
"ohos_product_model":"",
"ohos_software_model":"",
"ohos_hardware_model":"",
"ohos_hardware_profile":"",
"ohos_serial":"",
"ohos_bootloader_version":"",
"ohos_secure_patch_level":"",
"ohos_abi_list":""
}
复制代码
该文件描述了 ipcamera_hispark_aries 产品。
主要包括:
产品名称
版本信息
设备厂商
单板信号
内核类型
内核版本
子系统列表
组件列表
特性列表
...
build/lite/BUILD.gn
项目的总构建入口,后面介绍构建过程的时候会重点介绍此文件,此处不展开。
build/lite/build.py
hb 构建工具,此工具根据命令行参数进行 GN 和 ninja 工具的调用,真实发起构建动作。
鸿蒙构建过程
编译工具 hb
hb 编译工具的文档位于:build/lite/README_zh.md,可根据此文档安装、执行构建工具。
编译流程如下:
流程如下:
hb set:设置 OpenHarmony 源码目录和要编译的产品。
hb build: 编译产品、开发板或者组件。解决方案编译实现如下:
读取开发板配置:主要包括开发板使用的编译工具链、编译链接命令和选项等。
调用 gn: 调用 gn gen 命令,读取产品配置(主要包括开发板、内核、选择的组件等)生成解决方案 out 目录和 ninja 文件。
调用 ninja:调用 ninja -C out/company/product 启动编译。
系统镜像打包:将组件编译产物打包,制作文件系统镜像。
GN 编译流程
hb 工具执行过程中,逻辑最复杂的步骤是执行 gn gen 命令。
解析.gn 文件
hb 会切换到 build/lite 目录执行 gn gen 命令,根据前文对 gn 的介绍,gn 工具会在此目录查找.gn 文件。以下是.gn 文件的内容:
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# The location of the build configuration file.
buildconfig = "//build/lite/config/BUILDCONFIG.gn"
# The source root location.
root = "//build/lite"
复制代码
此文件设置了编译配置和工程根目录。
编译配置文件在上一节介绍过,此处不再赘述。
工程根目录配置为//build/lite(//是指源码树根目录),gn 接下来会在工程跟目录下查找导入 BUILD.gn(主构建配置)
导入主构建配置
导入主构件配置就可以获取本产品需要的所有子系统、组件、特性,然后递归生成 ninja 构建文件。
主构建配置 build/lite/BUILD.gn 内容如下:
# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//build/lite/ndk/ndk.gni")
group("ohos") {
deps = []
if (ohos_build_target == "") {
# Step 1: Read product configuration profile.
product_cfg = read_file("${product_path}/config.json", "json")
kernel = product_cfg.kernel_type
# Step 2: Loop subsystems configured by product.
foreach(product_configed_subsystem, product_cfg.subsystems) {
subsystem_name = product_configed_subsystem.subsystem
subsystem_info = {
}
# Step 3: Read OS subsystems profile.
subsystem_info =
read_file("//build/lite/components/${subsystem_name}.json", "json")
# Step 4: Loop components configured by product.
foreach(product_configed_component,
product_configed_subsystem.components) {
# Step 5: Check whether the component configured by product is exist.
component_found = false
foreach(system_component, subsystem_info.components) {
if (product_configed_component.component ==
system_component.component) {
component_found = true
}
}
assert(
component_found,
"Component \"${product_configed_component.component}\" not found" +
", please check your product configuration.")
# Step 6: Loop OS components and check validity of product configuration.
foreach(component, subsystem_info.components) {
kernel_valid = false
board_valid = false
# Step 6.1: Skip component which not configured by product.
if (component.component == product_configed_component.component) {
# Step 6.1.1: Loop OS components adapted kernel type.
foreach(component_adapted_kernel, component.adapted_kernel) {
if (component_adapted_kernel == kernel && kernel_valid == false) {
kernel_valid = true
}
}
assert(
kernel_valid,
"Invalid component configed, ${subsystem_name}:${product_configed_component.component} " + "not available for kernel: $kernel!")
# Step 6.1.2: Add valid component for compiling.
foreach(component_target, component.targets) {
deps += [ component_target ]
}
}
}
}
}
# Step 7: Add device and product target by default.
deps += [
"${device_path}/../",
"${product_path}" ]
} else {
deps += string_split(ohos_build_target, "&&")
}
}
group("ndk") {
# Add native API targets.
deps = []
if (ohos_build_ndk) {
deps += [ "//build/lite/ndk:ndk" ]
}
}
if (ohos_build_target == "") {
action("gen_rootfs") {
deps = [ ":ohos" ]
script = "//build/lite/gen_rootfs.py"
outputs = [ "$target_gen_dir/gen_rootfs.log" ]
out_dir = rebase_path("$root_out_dir")
args = [
"--path=$out_dir",
"--kernel=$ohos_kernel_type",
"--storage=$storage_type",
"--strip_command=$ohos_current_strip_command",
"--dmverity=$enable_ohos_security_dmverity",
]
}
}
if (ohos_build_type == "debug" && product != "") {
action("gen_testfwk_info") {
outputs = [ "$root_out_dir/gen_testfwk_info.log" ]
script = "//build/lite/testfwk/gen_testfwk_info.py"
archive_dir_name = "test_info"
args = [
"--component-info-file",
rebase_path("${product_path}/config.json"),
"--output-json-fold",
rebase_path("${root_out_dir}/${archive_dir_name}/build_configs/"),
"--output-json-file-name",
"infos_for_testfwk.json",
"--output-module-list-files-fold",
rebase_path("${root_out_dir}/${archive_dir_name}/module_list_files/"),
]
}
}
复制代码
读取产品配置文件。产品配置文件是使用 hb set 配置来的,此过程会读取//vendor/hisilicon/*/config.json,获取产品配置。
根据产品配置中的子系统列表配置,读取每个子系统的组件配置,build/lite/components/下的子系统配置中组件是全集。
在组件全集中查找产品配置的组件列表,正常情况下,产品配置的组件应该都在组件全集中。
验证依赖合法性,如特定组件依赖特定的内核、单板等。
待验证通过后,将组件的 target 加入依赖列表中。
最后,将设备路径和产品目标加入依赖列表中。
以上步骤完成了具体产品的所有组件依赖,并将此数据交给 gn 继续分析。通过前面的介绍可以知道,每个组件中配置了其他的组件依赖,因此,最终生成了一颗以 ohos 为根节点的组件依赖树。从而生成所有依赖组件的 ninja 构建配置。
新增组件
如果我们想在鸿蒙系统中增加一个组件,经过上文描述的构建框架,这个流程会变得出乎意料的简单。
编写源码,任意放在某个路径下(还是推荐沿用当前目录规划结构)
编写当前组建的 BUILD.gn,此文件仅构建当前组件,因此也会很简单。
在 build/lite/components/下的文件中注册组件信息,可以选择一个现有的子系统,或者创建一个新的子系统配置,如果有依赖其他组件或者第三方组件,一并描述。
在产品配置中增加对新子系统(如果有)和组件的引用。
经过以上流程,就可以将一个新的组件增加到现有的编译体系中,并对原有的构建工程完全不会产生影响。
总结
鸿蒙构建框架的主要优势如下:
在 GN 基础之上,进一步将构建脚本与依赖配置解耦。可以看到,上面的新增组件过程,完全没有修改构建系统的配置或者代码(指的是 gn 代码),只是增加了 json 配置文件和新组件的编译配置。
此编译架构不依赖目录结构。原则上在此构建系统基础上增加新组建,源码可以放在任意位置,因此可以很简单地将一个成熟组件引入此系统。鸿蒙中依赖的第三方组件正是以此种方式引入的,只是鸿蒙专门为其增加了一个 third_party 配置。
引入子系统、组件层级关系。这两个概念的引入,可以有效减轻组件数量增长时,组件间关系带来的复杂性。
声明式配置。GN 是一种半声明式脚本,鸿蒙编译框架的依赖和属性描述完全使用 json 文件,使配置更加简单。
华为在鸿蒙中的工程实践有很多方面值得学习,这里仅分析了其构建框架,其他方面的一些分析,网上也可以找到很多相关文章,这里介绍其中一个比较好的分析网站:
中俊为 | we harmonyos
在这个瞬息万变的时代,我们始终坚信,脚踏实地是成功的基石,而紧跟业界发展动态则是不可或缺的智慧。我们不仅仅是实干家,更是时代的见证者。在勤奋工作的同时,我们始终保持对行业发展的敏感感知,紧贴潮流,洞悉趋势。踏实干活是我们的底色,是我们前行的力量。我们深知,只有脚踏实地,才能在竞争激烈的市场中立于不败之地。每一份付出,都是对自己价值的承诺,每一个进步,都是团队共同努力的结果。然而,我们不仅仅满足于眼前的成果。业界的风云变幻,新技术的涌现,市场的脉搏,都需要我们保持高度的警觉。只有时刻关注业界发展动态,不断学习,才能真正站在潮流之巅,引领时代的脉搏。因此,我们既是脚踏实地的奋斗者,又是业界发展的领航者。在实现个人价值的同时,我们更关注行业的未来,为团队的成功而不懈努力。脚踏实地,紧握时代脉搏,让我们共同创造更加辉煌的明天。
评论