写点什么

鸿蒙组件化构建

作者:SkyFire
  • 2023-11-11
    中国香港
  • 本文字数:14376 字

    阅读完需:约 47 分钟

鸿蒙系统架构简介



鸿蒙系统软件部分从下往上分为内核层、系统服务层、应用框架层和应用层。

内核层

内核层包括 KAL(内核抽象层)和驱动子系统等,主要是负责操作系统相关的流程,提供底层通用能力,与提供的服务应用等没有关系。

KAL

鸿蒙系统被设计用于各种不同的设备上,包括收集、智能电视、手表等不同规模,不同性能的硬件上,面对不同的需求场景,对内核的要求也不同,因此鸿蒙设计之初就将内核抽象出来,形成内核抽象层 KAL,KAL 为上层提供统一的进程调度、内存管理、文件系统等模型,而下层则适配了不同的内核:标准 Linux、LiteOS 等。

驱动子系统

驱动子系统主要包括 HDF(HarmonyOS 驱动框架),此框架独立于内核(受益于 KAL),对上层提供统一的外设访问能力。


除了 KAL 和驱动子系统,还有硬件抽象层 HAL、硬件驱动接口 HDI、操作系统抽象层 OSAL 等逻辑层次,其设计均是为了统一各种不同应用场景下系统的对外接口,方便上层应用的开发。

系统服务层与应用框架层

系统服务层主要实现应用服务通用的能力,应用框架层将系统服务层实现的能力封装对上层用户提供。包括基本能力子系统集、基础软件服务子系统集、增强软件服务子系统集和硬件服务子系统集。

基本能力子系统集

基本能力子系统集是所有应用程序的基础,是所有应用服务都需要的功能。


在系统服务层包含以下组件:


  • 分布式软总线:各终端通信能力组件,是鸿蒙万物互联的基础

  • 分布式任务调度:鸿蒙有一项能力,可以把一个正在运行的应用迁移到其他的设备,正是这个分布式任务调度提供的功能

  • 分布式数据管理:补充分布式数据管理用于同步各终端应用数据,是分布式任务调度的补充,没有分布式数据管理,分布式任务调度也无法正常运行

  • 方舟多语言运行时组件:方舟编译器的运行时

  • 公共基础库子系统:提供其他的关键系统服务依赖的基础能力

  • 多模输入子系统:提供诸如、语音、触摸屏、各类传感器的输入处理

  • 图形子系统:图形图像处理

  • 安全子系统:系统安全审计、防护

  • AI 子系统:提供 AI 通用能力


其中,多模输入、图形、安全、AI 同时由应用框架层开放给上层开发者供应用服务调用。


此外,应用框架层也有一部分不依赖系统服务层的组件:


  • UI 框架

  • Ability 框架

  • 用户程序框架


这部分组件为上层应用服务开发提供标准开发框架。

基础软件服务子系统集

此子系统集提供基础的软件服务,可用于大多数通用设备,如手机、手表等。

增强软件服务子系统集

此子系统集提供了特定场景定制扩展的软件服务,如智慧屏、智能穿戴设备、嵌入式设备等。

硬件服务子系统集

此子系统集提供特定场景定制扩展的硬件服务,与特定硬件相关,如位置服务、生物识别、穿戴、嵌入式设备等。


总体来说,各子系统集在系统服务层和应用框架层都有子系统,系统服务层利用下层的操作系统,实现核心功能,应用框架层将这些功能打包开放给上层开发者,供应用于服务调用。

GN 和 Ninja 介绍

GN(Generate Ninja)是一个构建工具,它是由 Google 开发的,用于构建大型项目的工具。GN 的主要目标是提供一种高度可扩展和可配置的构建系统,以满足各种项目的需求。它通常与 Ninja 构建系统一起使用,Ninja 是另一个由 Google 开发的构建工具,专注于构建速度和效率。


以下是一些 GN 构建工具的主要特点和用途:


  1. 高度可配置:GN 允许开发人员定义项目的构建规则,包括编译选项、目标文件、依赖关系等。这使得 GN 非常适合于需要定制化构建过程的项目。

  2. 通用性:GN 可以用于各种编程语言和平台,包括 C、C++、Rust、Go 等,以及 Windows、Linux、macOS 等操作系统

  3. 易于学习和使用:GN 使用 Python-like 的配置文件语言,相对容易理解和编写。它的语法清晰,易于上手。

  4. 并行构建:GN 可以生成 Ninja 构建文件,这些文件可以用于并行构建项目,以提高构建速度。

  5. 构建性能:GN 专注于构建性能,可以快速地生成构建文件,同时支持增量构建,只重新构建发生更改的文件,以减少构建时间。

  6. 交叉编译支持:GN 支持交叉编译,可以用于为不同的目标平台生成代码。

  7. 可扩展性:开发人员可以编写自定义构建规则和工具链,以满足项目的特殊需求。

  8. 良好的社区支持:GN 有一个活跃的社区,提供了丰富的文档和示例,以帮助开发人员使用和定制 GN 来满足他们的需求。


GN 是一个强大的构建工具,适用于大型项目和需要高度可配置构建系统的项目。它可以帮助开发人员管理复杂的构建过程,提高构建效率,同时保持灵活性和可扩展性。


Ninja 是一个快速且轻量级的构建工具,它的主要目标是提供高效的编译和构建过程,特别适用于大型项目。Ninja 是由 Google 开发,用于替代 Make 等传统构建工具,以提供更好的性能和可维护性。


以下是一些关于 Ninja 的主要特点和用途:


  1. 极速构建:Ninja 的设计注重构建速度。它使用了一种轻量级的构建规则语言,能够以最小的开销进行构建。这使得 Ninja 非常适合大型项目,可以显著减少构建时间。

  2. 简化配置:Ninja 的配置文件非常简单,易于理解和维护。它的语法非常基础,通常只需定义目标、依赖关系和构建规则,不需要繁琐的 Makefile 语法。

  3. 跨平台支持:Ninja 可以在多种操作系统上运行,包括 Linux、Windows、macOS 等。这使得它成为一个跨平台的构建工具,可以在不同的开发环境中使用。

  4. 并行构建:Ninja 支持并行构建,可以同时构建多个目标,以充分利用多核处理器和加速构建过程。

  5. 增量构建:Ninja 能够检测源文件和依赖文件的更改,只重新构建发生更改的部分,从而减少不必要的构建步骤,提高构建效率。

  6. 扩展性:Ninja 允许开发人员编写自定义构建规则,以满足项目特殊的需求。这使得它非常灵活,适用于各种不同类型的项目。

  7. 易于集成: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_configsif (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,关键信息如下:


  1. component: 组件名

  2. description:组件描述

  3. optional:该组件在此子系统中是否是可选项

  4. dirs:组件源码路径,可以指定多处

  5. targets:GN 的编译目标

  6. rom:组件构建出来将会占用的 rom 空间,预估值

  7. ram:组件运行时所需内存空间,预估值

  8. output:组件构建出的产物列表

  9. adapted_board:适配的单板

  10. adapted_kernel:适配的内核

  11. features:组件中包含的可选特性

  12. 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/"), ] }}
复制代码


  1. 读取产品配置文件。产品配置文件是使用 hb set 配置来的,此过程会读取//vendor/hisilicon/*/config.json,获取产品配置。

  2. 根据产品配置中的子系统列表配置,读取每个子系统的组件配置,build/lite/components/下的子系统配置中组件是全集。

  3. 在组件全集中查找产品配置的组件列表,正常情况下,产品配置的组件应该都在组件全集中。

  4. 验证依赖合法性,如特定组件依赖特定的内核、单板等。

  5. 待验证通过后,将组件的 target 加入依赖列表中。

  6. 最后,将设备路径和产品目标加入依赖列表中。


以上步骤完成了具体产品的所有组件依赖,并将此数据交给 gn 继续分析。通过前面的介绍可以知道,每个组件中配置了其他的组件依赖,因此,最终生成了一颗以 ohos 为根节点的组件依赖树。从而生成所有依赖组件的 ninja 构建配置。

新增组件

如果我们想在鸿蒙系统中增加一个组件,经过上文描述的构建框架,这个流程会变得出乎意料的简单。


  1. 编写源码,任意放在某个路径下(还是推荐沿用当前目录规划结构)

  2. 编写当前组建的 BUILD.gn,此文件仅构建当前组件,因此也会很简单。

  3. 在 build/lite/components/下的文件中注册组件信息,可以选择一个现有的子系统,或者创建一个新的子系统配置,如果有依赖其他组件或者第三方组件,一并描述。

  4. 在产品配置中增加对新子系统(如果有)和组件的引用。


经过以上流程,就可以将一个新的组件增加到现有的编译体系中,并对原有的构建工程完全不会产生影响。

总结

鸿蒙构建框架的主要优势如下:


  • 在 GN 基础之上,进一步将构建脚本与依赖配置解耦。可以看到,上面的新增组件过程,完全没有修改构建系统的配置或者代码(指的是 gn 代码),只是增加了 json 配置文件和新组件的编译配置。

  • 此编译架构不依赖目录结构。原则上在此构建系统基础上增加新组建,源码可以放在任意位置,因此可以很简单地将一个成熟组件引入此系统。鸿蒙中依赖的第三方组件正是以此种方式引入的,只是鸿蒙专门为其增加了一个 third_party 配置。

  • 引入子系统、组件层级关系。这两个概念的引入,可以有效减轻组件数量增长时,组件间关系带来的复杂性。

  • 声明式配置。GN 是一种半声明式脚本,鸿蒙编译框架的依赖和属性描述完全使用 json 文件,使配置更加简单。


华为在鸿蒙中的工程实践有很多方面值得学习,这里仅分析了其构建框架,其他方面的一些分析,网上也可以找到很多相关文章,这里介绍其中一个比较好的分析网站:


中俊为 | we harmonyos


在这个瞬息万变的时代,我们始终坚信,脚踏实地是成功的基石,而紧跟业界发展动态则是不可或缺的智慧。我们不仅仅是实干家,更是时代的见证者。在勤奋工作的同时,我们始终保持对行业发展的敏感感知,紧贴潮流,洞悉趋势。踏实干活是我们的底色,是我们前行的力量。我们深知,只有脚踏实地,才能在竞争激烈的市场中立于不败之地。每一份付出,都是对自己价值的承诺,每一个进步,都是团队共同努力的结果。然而,我们不仅仅满足于眼前的成果。业界的风云变幻,新技术的涌现,市场的脉搏,都需要我们保持高度的警觉。只有时刻关注业界发展动态,不断学习,才能真正站在潮流之巅,引领时代的脉搏。因此,我们既是脚踏实地的奋斗者,又是业界发展的领航者。在实现个人价值的同时,我们更关注行业的未来,为团队的成功而不懈努力。脚踏实地,紧握时代脉搏,让我们共同创造更加辉煌的明天。

发布于: 刚刚阅读数: 6
用户头像

SkyFire

关注

这个cpper很懒,什么都没留下 2018-10-13 加入

会一点点cpp的苦逼码农

评论

发布
暂无评论
鸿蒙组件化构建_鸿蒙_SkyFire_InfoQ写作社区