From 7d3567cd2edb9292902d2221005c5912780944d6 Mon Sep 17 00:00:00 2001 From: Annie_wang Date: Thu, 28 Jul 2022 17:37:46 +0800 Subject: [PATCH] update docs Signed-off-by: Annie_wang --- .../subsystems/figure/build-process.jpg | Bin 59879 -> 55032 bytes ...build-gn-coding-style-and-best-practice.md | 271 ++- ...ys-build-gn-kconfig-visual-config-guide.md | 34 +- .../subsystems/subsys-build-mini-lite.md | 1528 +++++++++-------- .../subsystems/subsys-build-standard-large.md | 893 ++++++++-- 5 files changed, 1657 insertions(+), 1069 deletions(-) diff --git a/en/device-dev/subsystems/figure/build-process.jpg b/en/device-dev/subsystems/figure/build-process.jpg index a48ea734509526b3ed0fe85b7c4a98b0a2a9c4f0..68fba0c4265dc6899eb6576dd243a7887d5cf615 100644 GIT binary patch literal 55032 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 MzrUH@MPFL~59}#W3;+NC literal 59879 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

1Ni&55SyIW^h#}9bGMt+tRnDiWH8) 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[](../public_sys-resources/icon-caution.gif) **CAUTION**
->Define component attributes, such as the name, source code directory, function description, mandatory or not, build targets, RAM, ROM, build outputs, adapted kernels, configurable features, and dependencies, in the JSON file of the subsystem in the **build/lite/components** directory. When adding a component, add its definition to the JSON file of the corresponding subsystem. The component configured for a product must have been defined in a subsystem. Otherwise, the verification will fail. +> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**
+> The .json file of the subsystem in the **build/lite/components** directory contains component attributes, including the name, source code directory, function description, mandatory or not, build targets, RAM, ROM, build outputs, adapted kernels, configurable features, and dependencies of the component. When adding a component, add the component information in the .json file of the corresponding subsystem. The component configured for a product must have been defined in a subsystem. Otherwise, the verification will fail. ``` component ├── interfaces │ ├── innerkits # APIs exposed internally among components -│ └── kits # App APIs provided for app developers +│ └── kits # APIs provided for application developers ├── frameworks # Framework implementation ├── services # Service implementation -└── BUILD.gn # Build script +├── BUILD.gn # Build script ``` -The following example shows how to define attributes of the sensor component of the pan-sensor subsystem: + The following example shows how to configure attributes of the sensor service component of the pan-sensor subsystem: + + ``` + { + "name": "@ohos/sensor_lite", # OpenHarmony Package Manager (HPM) component name, in the @Organization/Component name format. + "description": "Sensor services", # Description of the component functions. + "version": "3.1", # Version, which must be the same as the version of OpenHarmony. + "license": "MIT", # Component license. + "publishAs": "code-segment", # Mode for publishing the HPM package. The default value is code-segment. + "segment": { + "destPath": "" + }, # Code restoration path (source code path) set when "publishAs is code-segment. + "dirs": {"base/sensors/sensor_lite"} # Directory structure of the HPM package. This field is mandatory and can be left empty. + "scripts": {}, # Scripts to be executed. This field is mandatory and can be left empty. + "licensePath": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "component": { # Component attributes. + "name": "sensor_lite", # Component name. + "subsystem": "", # Subsystem to which the component belongs. + "syscap": [], # System capabilities provided by the component for applications. + "features": [], # List of the component's configurable features. Generally, this parameter corresponds to sub_component in build and can be configured. + "adapted_system_type": [], # Adapted system types, which can be mini, small, and standard. Multiple values are allowed. + "rom": "92KB", # Size of the component's ROM. + "ram": "~200KB", # Size of the component's RAM. + "deps": { + "components": [ # Other components on which this component depends. + "samgr_lite" + ], + "third_party": [ # Third-party open-source software on which this component depends. + "bounds_checking_function" + ] + } + "build": { # Build-related configurations. + "sub_component": [ + ""//base/sensors/sensor_lite/services:sensor_service"", # Component build entry + ], # Component build entry. Configure the module here. + "inner_kits": [], # APIs between components. + "test": [] # Entry for building the component's test cases. + } + } + } + ``` + + Observe the following rules when writing the component's **BUILD.gn**: + +- The build target name must be the same as the component name. + +- Define the configurable features in the **BUILD.gn** file of the component. Name the configurable features in the ohos_{subsystem}*{component}*{feature} format. Define the features in component description and configure them in the **config.json** file. + +- Define macros in the OHOS_{SUBSYSTEM}*{COMPONENT}*{FEATURE} format. + + > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+ > The component build script is written in GN. For details about how to use GN, see [GN Quick Start Guide](https://gn.googlesource.com/gn/+/master/docs/quick_start.md). The component is the build target, which can be a static library, a dynamic library, an executable file, or a group. + + The following example shows the **foundation/graphic/ui/BUILD.gn** file for a graphics UI component: + + ``` + # Declare the configurable features of the component. + declare_args() { + enable_ohos_graphic_ui_animator = false # Whether to enable animation. + ohos_ohos_graphic_ui_font = "vector" # Configurable font type, which can be vector or bitmap. + } -``` -{ - "components": [ - { - "component": "sensor_lite", # Component name - "description": "Sensor services", # Brief description of the component - "optional": "true", # Whether the component is mandatory for the system - "dirs": [ # Source code directory of the component - "base/sensors/sensor_lite" - ], - "targets": [ # Build entry of the component - "//base/sensors/sensor_lite/services:sensor_service" - ], - "rom": "92KB", # Component ROM - "ram": "~200KB", # Component RAM (estimated) - "output": [ "libsensor_frameworks.so" ], # Component build outputs - "adapted_kernel": [ "liteos_a" ], # Adapted kernel for the component - "features": [], # Configurable features of the component - "deps": { - "components": [ # Other components on which the component depends - "samgr_lite" - ], - "third_party": [ # Open-source third-party software on which the component depends - "bounds_checking_function" + # Basic component functions. + shared_library("base") { + sources = [ + ... + ] + include_dirs = [ + ... + ] + } + + # Build only when the animator is enabled. + if(enable_ohos_graphic_ui_animator ) { + shared_library("animator") { + sources = [ + ... ] + include_dirs = [ + ... + ] + deps = [ :base ] } } - ] -} -``` - -Observe the following rules when configuring **BUILD.gn**: - -- The build target name must be the same as the component name. -- Define the configurable features in the **BUILD.gn** file of the component. Name the configurable features in the **ohos\_**\{_subsystem_\}**\_**\{_component_\}**\_**\{_feature_\} format. Define the features in component description and configure them in the **config.json** file. -- Define macros in the **OHOS\_**\{_SUBSYSTEM_\}**\_**\{_COMPONENT_\}**\_**\{_FEATURE_\} format. - - >![](../public_sys-resources/icon-note.gif) **NOTE**
GN is used as the build script language for components. For details about how to use GN, see [GN Quick Start Guide](https://gn.googlesource.com/gn/+/master/docs/quick_start.md). In GN, a component is a target to build, which can be a static library, a dynamic library, an executable file, or a group. + ... + # It is recommended that the target name be the same as the name of the component, which can be an executable file (.bin), shared_library (.so file), static_library (.a file), or a group. + executable("ui") { + deps = [ + ":base" + ] + # The animator feature is configured by the product. + if(enable_ohos_graphic_ui_animator ) { + deps += [ + "animator" + ] + } + } + ``` -The following example shows how to build the **foundation/graphic/ui/BUILD.gn** file for a graphics UI component: +### Chipset Solution -``` - # Declare the configurable features of the component - declare_args() { - enable_ohos_graphic_ui_animator = false # Animation switch - ohos_ohos_graphic_ui_font = "vector" # Configurable font type, which can be vector or bitmap - } - - # Basic component functions - shared_library("base") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - } - - # Build only when the animator is enabled - if(enable_ohos_graphic_ui_animator ) { - shared_library("animator") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - deps = [ :base ] - } - } - ...... - # It is recommended that the target name be the same as the component name, which can be an executable .bin file, shared_library (.so file), static_library (.a file), or a group. - executable("ui") { - deps = [ - ":base" - ] - - # The animator feature is configured by the product. - if(enable_ohos_graphic_ui_animator ) { - deps += [ - "animator" - ] - } - } -``` +The chipset solution is a special component. It is built based on a development board, including the drivers, device API adaptation, and SDK. -### Chipset +The source code path is named in the **device/{Development board}/{Chipset solution vendor}** format. -- The chipset solution is a complete solution based on a development board. The solution includes the drivers, API adaptation, and SDK. -- The chipset solution is a special component, whose source code directory is named in the _**device**/\{Chipset solution vendor\}/\{Development board\}_ format. -- The chipset component is built by default based on the development board selected by the product. +The chipset solution component is built by default based on the development board selected. -The chipset solution directory tree is as follows: +The chipset solution directory structure is as follows: ``` device -└── company # Chipset solution vendor - └── board # Name of the development board - ├── BUILD.gn # Build script - ├── hals # Southbound APIs for OS adaptation - ├── linux # Linux kernel version (optional) - │ └── config.gni # Build options for the Linux version - └── liteos_a # LiteOS kernel version (optional) - └── config.gni # Build options for the LiteOS Cortex-A version +└── board # Chipset solution vendor + └── company # Development board name + ├── BUILD.gn # Build script + ├── hals # OS device API adaptation + ├── linux # (Optional) Linux kernel version + │ └── config.gni # Linux build configuration + └── liteos_a # (Optional) LiteOS kernel version + └── config.gni # LiteOS_A build configuration ``` ->![](../public_sys-resources/icon-note.gif) **NOTE**
->The **config.gni** file contains build-related configurations of the development board. The parameters in the file are globally visible to the system and can be used to build all OS components during the build process. +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+> The **config.gni** file contains build-related configuration of the development board. The parameters in the file are used to build all OS components, and are globally visible to the system during the build process. -The **config.gni** file contains the following key parameters: +- The **config.gni** file contains the following key parameters: -``` -kernel_type: kernel used by the development board, for example, liteos_a, liteos_m, or linux. -kernel_version: kernel version used by the development board, for example, 4.19. -board_cpu: CPU of the development board, for example, cortex-a7 or riscv32. -board_arch: chipset architecture of the development board, for example, armv7-a or rv32imac. -board_toolchain: name of the customized build toolchain used by the development board, for example, gcc-arm-none-eabi. If this field is not specified, ohos-clang will be used by default. -board_toolchain_prefix: prefix of the build toolchain, for example, gcc-arm-none-eabi. -board_toolchain_type: build toolchain type, for example, gcc or clang. Currently, only GCC and clang are supported. -board_cflags: build options of the .c file configured for the development board. -board_cxx_flags: build options of the .cpp file configured for the development board. -board_ld_flags: link options configured for the development board. -``` + ``` + kernel_type: Kernel used by the development board, for example, LiteOS_A, LiteOS_M, or Linux. + kernel_version: Kernel version of the development board, for example, 4.19. + board_cpu: CPU of the development board, for example, Cortex-A7 or RISCV32. + board_arch: Chipset architecture of the development board, for example, ARMv7-A or RV32IMAC. + board_toolchain: Name of the customized build toolchain used by the development board, for example, gcc-arm-none-eabi. If this field is not specified, ohos-clang will be used by default. + board_toolchain_prefix: Prefix of the toolchain, for example, gcc-arm-none-eabi. + board_toolchain_type: Toolchain type. Currently, only GCC and clang are supported. + board_cflags: Build options of the .c file configured for the development board. + board_cxx_flags: Build options of the .cpp file configured for the development board. + board_ld_flags: Linking options configured for the development board. + ``` -### Product +### Product Solution -The product solution is a complete product based on a development board. It includes the OS adaptation, component assembly configuration, startup configuration, and file system configuration. The source code directory of a product solution is named in the **vendor**/\{_Product solution vendor_\}/\{_Product name_\} format. A product solution is also a special component. +The product solution is a special component. It is a product built based on a development board. It includes the OS adaptation, component assembly and configuration, startup configuration, and file system configuration. The source code directory is named in the **vendor**/{*Product solution vendor*}/{*Product name*} format. -The product solution directory tree is as follows: +The product solution directory structure is as follows: ``` vendor @@ -232,172 +250,162 @@ vendor │ ├── BUILD.gn # Product build script │ └── config.json # Product configuration file │ └── fs.yml # File system packaging configuration - └── ...... + └── ... ``` ->![](../public_sys-resources/icon-caution.gif) **CAUTION**
->Create directories and files based on the preceding rules for new products. The Compilation and Building subsystem scans the configured products based on the rules. +> ![icon-caution.gif](/public_sys-resources/icon-caution.gif) **CAUTION**
+> Follow the preceding rules to create directories and files for new products. The Compilation and Building subsystem scans the configured products based on the rules. The key directories and files are described as follows: -- **vendor/company/product/init\_configs/etc** - - This folder contains the **rcS**, **S**_xxx_, and **fstab** scripts. The **init** process runs the **rcS**, **fstab**, and **S**_00_-_xxx_ scripts in sequence before starting system services. The **S**_xxx_ script contains content related to the development board and product. It is used to create device nodes and directories, scan device nodes, and change file permissions. These scripts are copied from the **BUILD.gn** file to the **out** directory of the product as required and packaged into the **rootfs** image. +1. **vendor/company/product/init_configs/etc** + + This folder contains the rcS, Sxxx, and fstab scripts. The init process runs the rcS, fstab, and S00-xxx scripts in sequence before starting system services. The **S***xxx* script is used to create device nodes and directories, scan device nodes, and change file permissions for the development board and product. These scripts are copied from the **BUILD.gn** file to the **out** directory of the product as required and packaged into the **rootfs** image. -- **vendor/company/product/init\_configs/init.cfg** +2. **vendor/company/product/init_configs/init.cfg** - This file is the configuration file for the **init** process to start services. Currently, the following commands are supported: + This file is the configuration file for the **init** process to start services. Currently, the following commands are supported: - - **start**: starts a service. - - **mkdir**: creates a folder. - - **chmod**: changes the permission on a specified directory or file. - - **chown**: changes the owner group of a specified directory or file. - - **mount**: mounts a device. + - **start**: starts a service. +- **mkdir**: creates a folder. + + - **chmod**: changes the permission on a specified directory or file. +- **chown**: changes the owner group of a specified directory or file. + - **mount**: mounts a device. - The fields in the file are described as follows: + The fields in the file are described as follows: -``` -{ - "jobs" : [{ # Job array. A job corresponds to a command set. Jobs are executed in the following sequence: pre-init > init > post-init. + ``` + { + "jobs" : [{ # Job array. A job corresponds to a command set. Jobs are executed in the following sequence: pre-init > init > post-init. "name" : "pre-init", - "cmds" : [ - "mkdir /storage/data", # Create a directory. - "chmod 0755 /storage/data", # Change the permission, which is in 0xxx format, for example, 0755. - "mkdir /storage/data/log", - "chmod 0755 /storage/data/log", - "chown 4 4 /storage/data/log", # Change the owner group. The first number indicates the UID, and the second indicates the GID. - ...... - "mount vfat /dev/mmcblock0 /sdcard rw, umask=000" # The command is in the mount [File system type][source] [target] [flags] [data] format. - # Currently, flags can only be nodev, noexec, nosuid, or rdonly. - ] - }, { - "name" : "init", - "cmds" : [ # Start services based on the sequence of the cmds array. - "start shell", # Note that there is only one space between start and the service name. - ...... - "start service1" - ] - }, { - "name" : "post-init", # Job that is finally executed. Operations performed after the init process is started, for example, mounting a device after the driver initialization. - "cmds" : [] - } - ], - "services" : [{ # Service array. A service corresponds to a process. - "name" : "shell", # Service name - "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # Full path of the executable file. It must start with "path". - "uid" : 0, # Process UID, which must be the same as that in the binary file. - "gid" : 0, # Process GID, which must be the same as that in the binary file. - "once" : 0, # Whether the process is a one-off process. 1: The proces is a one-off process. The init process does not restart it after the process exits. 0: The process is not a one-off process. The init process restarts it if the process exits. - "importance" : 0, # Whether the process is a key process. 1: The process is a key process. If it exits, the init process restarts the board. 0: The process is not a key process. If it exits, the init process does not restart the board. - "caps" : [4294967295] - }, - ...... - ] -} -``` - -- **vendor/company/product/init\_configs/hals** - - This file stores the content related to OS adaptation of the product. For details about APIs for implementing OS adaptation, see the readme file of each component. - -- **vendor/company/product/config.json** - - The **config.json** file is the main entry for the build and contains configurations of the development board, OS components, and kernel. - - The following example shows the **config.json** file of the IP camera developed based on the hispark\_taurus development board: - -``` -{ - "product_name": "ipcamera", # Product name - "version": "3.0", # config.json version, which is 3.0 - "type": "small", # System type, which can be mini, small, or standard - "ohos_version": "OpenHarmony 1.0", # OS version - "device_company": "hisilicon", # Chipset vendor - "board": "hispark_taurus", # Name of the development board - "kernel_type": "liteos_a", # Kernel type - "kernel_version": "3.0.0", # Kernel version - "subsystems": [ - { - "subsystem": "aafwk", # Subsystem - "components": [ - { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # Component and its features - ] - }, - { - ...... - } - ...... - More subsystems and components - } -} -``` - -- **vendor/company/product/fs.yml** - - This file packages the build result to create a configuration file system image, for example, **rootfs.img** \(user-space root file system\) and **userfs.img** \(readable and writable file\). It consists of multiple lists, and each list corresponds to a file system. The fields are described as follows: - -``` -fs_dir_name: (Mandatory) declares the name of the file system, for example, rootfs or userfs. -fs_dirs: (Optional) configures the mapping between the file directory in the out directory and the system file directory. Each file directory corresponds to a list. -source_dir: (Optional) specifies the target file directory in the out directory. If this field is missing, an empty directory will be created in the file system based on target_dir. -target_dir: (Mandatory) specifies the corresponding file directory in the file system. -ignore_files: (Optional) declares ignored files during the copy operation. -dir_mode: (Optional) specifies the file directory permission, which is set to 755 by default. -file_mode: (Optional) declares permissions of all files in the directory, which is set to 555 by default. -fs_filemode: (Optional) configures files that require special permissions. Each file corresponds to a list. -file_dir: (Mandatory) specifies the detailed file path in the file system. -file_mode: (Mandatory) declares file permissions. -fs_symlink: (Optional) configures the soft link of the file system. -fs_make_cmd: (Mandatory) creates the file system script. The script provided by the OS is stored in the build/lite/make_rootfs directory. Linux, LiteOS, ext4, jffs2, and vfat are supported. Chipset vendors can also customize the script as required. -fs_attr: (Optional) dynamically adjusts the file system based on configuration items. -``` - -The **fs\_symlink** and **fs\_make\_cmd** fields support the following variables: - -- $\{root\_path\} - - Code root directory, which corresponds to **$\{ohos\_root\_path\}** of GN - -- $\{out\_path\} - - **out** directory of the product, which corresponds to **$\{root\_out\_dir\}** of GN - -- $\{fs\_dir\} - - File system directory, which consists of the following variables - - - $\{root\_path\} - - $\{fs\_dir\_name\} - ->![](../public_sys-resources/icon-note.gif) **NOTE**
->**fs.yml** is optional and does not need to be configured for devices without a file system. + "cmds" : [ + "mkdir /storage/data", # Create a directory. + "chmod 0755 /storage/data", #Modify the permissions. The format of the permission value is 0xxx, for example, 0755. + "mkdir /storage/data/log", + "chmod 0755 /storage/data/log", + "chown 4 4 /storage/data/log", # Change the owner group. The first number is the user ID (UID), and the second number is the group ID (GID). + ... + "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # The command format is mount [File system type] [source] [target] [flags] [data]. + # The value of flags can be nodev, noexec, nosuid, or rdonly only. + ] + }, { + "name" : "init", + "cmds" : [ # Start services based on the sequence of the cmds array. + "start shell", # There is only one space between start and the service name. + ... + "start service1" + ] + }, { + "name" : "post-init", # Job that is finally executed. Operations performed after the init process is started, for example, mounting a device after the driver initialization). + "cmds" : [] + } + ], + "services" : [{ # Service array. A service corresponds to a process. + "name" : "shell", # Service name. + "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # Full path of the executable file. It must start with "path". + "uid" : 0, # Process UID, which must be the same as that in the binary file. + "gid" : 0, # Process GID, which must be the same as that in the binary file. + "once" : 0, # Whether the process is a one-off process. The value 1 indicates that process is a one-off process, and the value 0 indicates the opposite. The init process does not restart the one-off process after the process exits. + "importance" : 0, # Whether the process is a key process. The value 1 indicates a key process, and the value 0 indicates the opposite. If a key process exits, the init process will restart the board. + "caps" : [4294967295] + }, + ... + ] + } + ``` + +3. **vendor/company/product/init_configs/hals** -- **vendor/company/product/BUILD.gn** + This file contains the OS adaptation of the product. For details about APIs for implementing OS adaptation, see the readme file of each component. - This file is the entry for building the source code of the solution vendor and copying the startup configuration file. The **BUILD.gn** file in the corresponding product directory will be built by default if a product is selected. The following example shows how to build the **BUILD.gn** file of a product: +4. **vendor/company/product/config.json** -``` -group("product") { # The target name must be the same as the product name (level-3 directory name under the product directory). - deps = [] - # Copy the init configuration. - deps += [ "init_configs" ] - # Others - ...... -} -``` + The **config.json** file is the main entry for the build and contains configurations of the development board, OS, and kernel. + The following example shows the **config.json** file of the IP camera developed based on the hispark_taurus board: -## Usage Guidelines + ``` + { + "product_name": "ipcamera", # Product name + "version": "3.0", # Version of config.json. The value is 3.0. + "type": "small", # System type. The value can be mini, small, or standard. + "ohos_version": "OpenHarmony 1.0", # OS version + "device_company": "hisilicon", # Chipset vendor + "board": "hispark_taurus", # Name of the development board + "kernel_type": "liteos_a", # Kernel type + "kernel_version": "3.0.0", # Kernel version + "subsystems": [ + { + "subsystem": "aafwk", # Subsystem + "components": [ + { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # Selected component and feature configuration + ] + }, + { + ... + } + ... + More subsystems and components + } + } + ``` + +5. **vendor/company/product/fs.yml** + + This file defines the process for creating a file system image, for example, **rootfs.img** (user-space root file system) and **userfs.img** (readable and writable file). It consists of multiple lists, and each list corresponds to a file system. The fields are described as follows: + + ``` + fs_dir_name: (Mandatory) specifies name of the file system, for example, rootfs or userfs. + fs_dirs: (Optional) specifies the mapping between the file directory in the out directory and the system file directory. Each file directory corresponds to a list. + source_dir: (Optional) specifies target file directory in the out directory. If this field is not specified, an empty directory will be created in the file system based on target_dir. + target_dir: (Mandatory) specifies the file directory in the file system. + ignore_files: (Optional) declares ignored files during the copy operation. + dir_mode: (Optional) specifies the file directory permissions. The default value is 755. + file_mode: (Optional) specifies the permissions of all files in the directory. The default value is 555. + fs_filemode: (Optional) specifies the files that require special permissions. Each file corresponds to a list. + file_dir: (Mandatory) specifies the detailed file path in the file system. + file_mode: (Mandatory) declares file permissions. + fs_symlink: (Optional) specifies the soft link of the file system. + fs_make_cmd: (Mandatory) creates the file system script. The script provided by the OS is located in the build/lite/make_rootfs directory. Linux, LiteOS, ext4, jffs2, and vfat are supported. Chipset vendors can also customize the script as required. + fs_attr: (Optional) dynamically adjusts the file system based on configuration items. + ``` + + The **fs_symlink** and **fs_make_cmd** fields support the following variables: + + - ${root_path}: code root directory, which corresponds to **${ohos_root_path}** of GN. + - ${out_path}: **out** directory of the product, which corresponds to **${root_out_dir}** of GN. + - ${fs_dir}: file system directory, which consists of variables ${root_path} and ${fs_dir_name}. +> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
+> **fs.yml** is optional and not required for devices without a file system. + +6. **vendor/company/product/BUILD.gn** + + This file provides the product built entry. It is used to build the source code of the solution vendor and copy the startup configuration file. The **BUILD.gn** file in the corresponding product directory will be built by default if a product is selected. + + The following is an example of the **BUILD.gn** file of a product: + + ``` + group("product") { # The name must be the same as the product name (level-3 directory name under the product directory). + deps = [] + # Copy the init configuration. + deps += [ "init_configs" ] + # Others + ... + } + ``` + +## Guidelines ### Prerequisites -The development environment has GN, Ninja, Python 3.7.4 or later, and hb available. For details about installation methods, see [Environment Setup](../quick-start/quickstart-lite-env-setup.md). +The development environment has GN, Ninja, Python 3.9.2 or later, and hb available. For details about the installation method, see [Setting Up Environments for the Mini and Small Systems](../quick-start/quickstart-lite-env-setup.md). ### Using hb -**hb** is a command line tool for OpenHarmony to execute build commands. Common hb commands are described as follows: +**hb** is an OpenHarmony command line tool for executing build commands. Common hb commands are described as follows: -**hb set** + **hb set** ``` hb set -h @@ -410,13 +418,15 @@ optional arguments: -p, --product Set OHOS board and kernel ``` -- **hb set** \(without argument\): starts the default setting process. -- **hb set -root** _dir_: sets the root directory of the code. -- **hb set -p**: sets the product to build. +- If you run **hb set** with no argument, the default setting process starts. + +- You can run **hb set -root** *dir* to set the root directory of the source code. + +- You can run **hb set -p** to set the product to build. **hb env** -Displays the current configuration. +Displays the current settings. ``` hb env @@ -428,57 +438,66 @@ hb env [OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 ``` -**hb build** + **hb build** ``` 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@huawei + 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** \(without argument\): builds the code based on the configured code directory, product, and options. The **-f** option deletes all products to be built, which is equivalent to running **hb clean** and **hb build**. -- **hb build** _\{component\_name\}_: builds a product component separately based on the development board and kernel set for the product, for example, **hb build kv\_store**. -- **hb build -p ipcamera@hisilicon**: skips the **set** step and builds the product directly. -- You can run **hb build** in **device/device\_company/board** to select the kernel and start the build based on the current development board and the selected kernel to generate an image that contains the kernel and driver only. +- If you run **hb build** with no argument, the previously configured code directory, product, and options are used for the build. The **-f** option deletes all products to be built. It is equivalent to running **hb clean** and **hb build**. + +- You can run **hb build** *{component_name}* to build product components separately based on the development board and kernel set for the product, for example, **hb build kv_store**. + +- You can run **hb build -p ipcamera@hisilicon** to skip the setting step and build the product directly. + +- You can run **hb build** in **device/board/device_company** to select the kernel and build an image that contains the kernel and drivers only based on the current development board and the selected kernel. **hb clean** -You can run **hb clean** to clear the build result of the product in the **out** directory and retain the **args.gn** and **build.log** files only. To clear files in a specified directory, add the directory parameter to the command, for example, **hb clean out/xxx/xxx**. +You can run **hb clean** to delete all the files except **args.gn** and **build.log** in the **out** directory. To clear files in a specified directory, add the directory parameter to the command, for example, **hb clean out/board/product**. By default, the files in the **out** directory are cleared. ``` hb clean @@ -495,477 +514,468 @@ optional arguments: To add a component, determine the subsystem to which the component belongs and the component name, and then perform the following steps: -1. Add the component build script after the source code development is complete. - - The following example adds the **BUILD.gn** script \(stored in the **applications/sample/hello\_world** directory\) to build the **hello\_world** component \(as an executable file\). +1. Add the component build script after the source code development is complete. + + The following example shows the **BUILD.gn** script (in the **applications/sample/hello_world** directory) for the **hello_world** executable file. - ``` - executable("hello_world") { - include_dirs = [ - "include", - ] - sources = [ - "src/hello_world.c" + ``` + executable("hello_world") { + include_dirs = [ + "include", ] - } - ``` - - The above script is used to build **hello\_world** that can run on OpenHarmony. - - To build the preceding component separately, select a product via the **hb set** command and run the **-T** command. - - ``` - hb build -f -T //applications/sample/hello_world - ``` - - After the component functions are verified on the development board, perform steps 2 to 4 to configure the component to the product. - -2. Add component description. - - The component description is stored in the **build/lite/components** directory. New components must be added to the JSON file of the corresponding subsystem. The component description must contain the following fields: - - - **component**: name of the component - - **description**: brief description of the component - - **optional**: whether the component is optional - - **dirs**: source code directory of the component - - **targets**: component build entry - - For example, to add the **hello\_world** component to the application subsystem, add the **hello\_world** object to the **applications.json** file. - - ``` - { - "components": [ - { - "component": "hello_world", - "description": "Hello world.", - "optional": "true", - "dirs": [ - "applications/sample/hello_world" - ], - "targets": [ - "//applications/sample/hello_world" - ] - }, - ... + sources = [ + "src/hello_world.c" + ] + } + ``` + + This script can be used to build a file named **hello_world** that can run on OpenHarmony. + + To build the preceding component separately, run **hb set** to select a product and run the following command to build **hello_world** separately. + + ``` + hb build -f -T //applications/sample/hello_world + ``` + + After the component functions are verified on the development board, perform steps 2 to 4 to add the component to the product. + +2. Add the component description. + + The component description is stored in the **build/lite/components** directory. Add the new component to the .json file of the corresponding subsystem. The component description must contain the following fields: + + - **component**: component name. + - **description**: description of the component functions. + - **optional**: whether the component is optional. + - **dirs**: source code directory of the component. + - **targets**: component build entry. + + The following is an example of adding the **hello_world** component to the **applications.json** file. + + ``` + { + "components": [ + { + "component": "hello_world", + "description": "Hello world.", + "optional": "true", + "dirs": [ + "applications/sample/hello_world" + ], + "targets": [ + "//applications/sample/hello_world" + ] + }, + ... + ] + } + ``` + +3. Add the component to the product. + + The product configuration file **config.json** is located in the **vendor/company/product/** directory. This file contains the product name, OpenHarmony version, device vendor, development board, kernel type, kernel version, subsystems, and components. The following example adds **hello_world** to the **my_product.json** file: + + ``` + { + "product_name": "hello_world_test", + "ohos_version": "OpenHarmony 1.0", + "device_company": "hisilicon", + "board": "hispark_taurus", + "kernel_type": "liteos_a", + "kernel_version": "1.0.0", + "subsystems": [ + { + "subsystem": "applications", + "components": [ + { "component": "hello_world", "features":[] } + ] + }, + ... ] - } - ``` - -3. Configure the component for the product. - - The **config.json** file is stored in the **vendor/company/product/** directory. The file must contain the product name, OpenHarmony version, device vendor, development board, kernel type, kernel version, and the subsystem and component to configure. The following example adds the **hello\_world** component to the **my\_product.json** configuration file: - - ``` - { - "product_name": "hello_world_test", - "ohos_version": "OpenHarmony 1.0", - "device_company": "hisilicon", - "board": "hispark_taurus", - "kernel_type": "liteos_a", - "kernel_version": "1.0.0", - "subsystems": [ - { - "subsystem": "applications", - "components": [ - { "component": "hello_world", "features":[] } - ] - }, - ... - ] - } - ``` - -4. Build the product. - - 1. Run the **hb set** command in the root code directory and select the product. - - 2. Run the **hb build** command. + } + ``` +4. Build the product. + + 1. Run the **hb set** command in the root code directory and select the product. + + 2. Run the **hb build** command. ### Adding a Chipset Solution The following uses the RTL8720 development board provided by Realtek as an example. To a chipset solution, perform the following steps: -1. Create a directory for the chipset solution. - - To create a directory based on [Configuration Rules](#configuration-rules), run the following command in the root code directory: - - ``` - mkdir -p device/realtek/rtl8720 - ``` - -2. Create a directory for kernel adaptation and build the **config.gni** file of the development board. - - For example, to adapt the LiteOS-A kernel to the RTL8720 development board, configure the **device/realtek/rtl8720/liteos\_a/config.gni** file as follows: - - ``` - # Kernel type, e.g. "linux", "liteos_a", "liteos_m". - kernel_type = "liteos_a" - - # Kernel version. - kernel_version = "3.0.0" - - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "real-m300" - - # Board arch, e.g. "armv7-a", "rv32imac". - board_arch = "" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "gcc-arm-none-eabi" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "gcc-arm-none-eabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [] - board_cxx_flags = [] - board_ld_flags = [] - ``` - -3. Build the script. - - Create the **BUILD.gn** file in the development board directory. The target name must be the same as that of the development board. The content in the **device/realtek/rtl8720/BUILD.gn** file is configured as follows: - - ``` - group("rtl8720") { # The target can be shared_library, static_library, or an executable file. - # Content - ...... - } - ``` - -4. Build the chipset solution. - - Run the **hb build** command in the development board directory to start the build. - +1. Create a directory for the chipset solution based on the [configuration rules](#chipset-solution). + Run the following command in the root directory of the code: + + ``` + mkdir -p device/board/realtek/rtl8720 + ``` + +2. Create a directory for kernel adaptation and write the **config.gni** file of the development board. + For example, to adapt the LiteOS-A kernel to the RTL8720 development board, write the **device/realtek/rtl8720/liteo_a/config.gni** file as follows: + + ``` + # Kernel type, e.g. "linux", "liteos_a", "liteos_m". + kernel_type = "liteos_a" + + # Kernel version. + kernel_version = "3.0.0" + + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "real-m300" + + # Board arch, e.g. "armv7-a", "rv32imac". + board_arch = "" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "gcc-arm-none-eabi" + + # The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "gcc-arm-none-eabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [] + board_cxx_flags = [] + board_ld_flags = [] + ``` + +3. Write the build script. + Create the **BUILD.gn** file in the development board directory. The target name must be the same as that of the development board. The following is an example of the **device/realtek/rtl8720/BUILD.gn** file for the RTL8720 development board: + + ``` + group("rtl8720") { # The build target can be shared_library, static_library, or an executable file. + # Content + ... + } + ``` + +4. Build the chipset solution. + + Run the **hb build** command in the development board directory to start the build. ### Adding a Product Solution -You can use the Compilation and Building subsystem to customize product solutions by assembling chipset solutions and components. The procedure is as follows: - -1. Create a product directory. - - The following uses the Wi-Fi IoT component on the RTL8720 development board as an example. Run the following command in the root code directory to create a product directory based on [Configuration Rules](#configuration-rules): - - ``` - mkdir -p vendor/my_company/wifiiot - ``` - -2. Assemble the product. - - Create the **config.json** file in the product directory. The **vendor/my\_company/wifiiot/config.json** file is as follows: - - ``` - { - "product_name": "wifiiot", # Product name - "version": "3.0", # config.json version, which is 3.0 - "type": "small", # System type, which can be mini, small, or standard - "ohos_version": "OpenHarmony 1.0", # OS version - "device_company": "realtek", # Name of the chipset solution vendor - "board": "rtl8720", # Name of the development board - "kernel_type": "liteos_m", # Kernel type - "kernel_version": "3.0.0", # Kernel version - "subsystems": [ - { - "subsystem": "kernel", # Subsystem - "components": [ - { "component": "liteos_m", "features":[] } # Component and its features - ] - }, - ... - { - More subsystems and components - } - ] - } - ``` - - Before the build, the Compilation and Building subsystem checks the validity of fields, including **device\_company**, **board**, **kernel\_type**, **kernel\_version**, **subsystem**, and **component**. The **device\_company**, **board**, **kernel\_type**, and **kernel\_version** fields must match the current chipset solution, and **subsystem** and **component** must match the component description in the **build/lite/components** file. - -3. Implement adaptation to OS APIs. - - Create the **hals** directory in the product directory and store the source code as well as the build script for OS adaptation in this directory. - -4. Configure the system service. - - Create the **init\_configs** directory in the product directory and then the **init.cfg** file in the newly created directory. Configure the system service to be started. - -5. \(Optional\) Configure the init process only for the Linux kernel. - - Create the **etc** directory in the **init\_configs** directory, and then the **init.d** folder and the **fstab** file in the newly created directory. Then, create the **rcS** and **S**_xxx_ files in the **init.d** file and edit them based on product requirements. - -6. \(Optional\) Configure the file system image only for the development board that supports the file system. - - Create the **fs.yml** file in the product directory and configure it as required. A typical **fs.yml** file is as follows: - - ``` - - - fs_dir_name: rootfs # Image name - fs_dirs: - - - # Copy the files in the out/my_board/my_product/bin directory to the rootfs/bin directory and ignore the .bin files related to testing. - source_dir: bin - target_dir: bin - ignore_files: - - Test.bin - - TestSuite.bin - - - # Copy the files in the out/my_board/my_product/libs directory to the rootfs/lib directory, ignore all .a files, and set the file permissions to 644 and folder permissions 755. - source_dir: libs - target_dir: lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: usr/lib - target_dir: usr/lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: config - target_dir: etc - - - source_dir: system - target_dir: system - - - source_dir: sbin - target_dir: sbin - - - source_dir: usr/bin - target_dir: usr/bin - - - source_dir: usr/sbin - target_dir: usr/sbin - - - # Create an empty proc directory. - target_dir: proc - - - target_dir: mnt - - - target_dir: opt - - - target_dir: tmp - - - target_dir: var - - - target_dir: sys - - - source_dir: etc - target_dir: etc - - - source_dir: vendor - target_dir: vendor - - - target_dir: storage - - fs_filemode: - - - file_dir: lib/ld-uClibc-0.9.33.2.so - file_mode: 555 - - - file_dir: lib/ld-2.24.so - file_mode: 555 - - - file_dir: etc/init.cfg - file_mode: 400 - fs_symlink: - - - # Create the soft link ld-musl-arm.so.1 -> libc.so in the rootfs/lib directory. - source: libc.so - link_name: ${fs_dir}/lib/ld-musl-arm.so.1 - - - source: mksh - link_name: ${fs_dir}/bin/sh - - - source: mksh - link_name: ${fs_dir}/bin/shell - fs_make_cmd: - # Create an ext4 image for the rootfs directory using the script. - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - - fs_dir_name: userfs - fs_dirs: - - - source_dir: storage/etc - target_dir: etc - - - source_dir: data - target_dir: data - fs_make_cmd: - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - ``` - -7. \(Optional\) Configure patches if the product and components need to be patched. - - Create the **patch.yml** file in the product directory and configure it as required. A typical **patch.yml** file is as follows: - - ``` - # Directory in which the patch is to be installed - foundation/communication/dsoftbus: - # Directory in which the patch is stored - - foundation/communication/dsoftbus/1.patch - - foundation/communication/dsoftbus/2.patch - third_party/wpa_supplicant: - - third_party/wpa_supplicant/1.patch - - third_party/wpa_supplicant/2.patch - - third_party/wpa_supplicant/3.patch - ... - ``` - - If you add **--patch** when running the **hb build** command, the patch file can be added to the specified directory before the build. - - ``` - hb build -f --patch - ``` - -8. Build the script. - - Create the **BUILD.gn** file in the product directory and write the script. The following **BUILD.gn** file uses the Wi-Fi IoT component in [1](#li1970321162111) as an example: - - ``` - group("wifiiot") { # The target name must be the same as the product name. - deps = [] - # Copy the init configuration. - deps += [ "init_configs" ] - # Build the hals directory. - deps += [ "hals" ] - # Others - ...... - } - ``` - -9. Build the product. - - Run the **hb set** command in the code root directory, select the new product as prompted, and run the **hb build** command. - +You can customize a product solution by flexibly assembling a chipset solution and components. The procedure is as follows: + +1. Create a product directory based on the [configuration rules](#product-solution). + + The following uses the Wi-Fi IoT module on the RTL8720 development board as an example. Run the following command in the root directory to create a product directory: + + ``` + mkdir -p vendor/my_company/wifiiot + ``` + +2. Assemble the product. + + Create a **config.json** file, for example for wifiiot, in the product directory. The **vendor/my_company/wifiiot/config.json** file is as follows: + + ``` + { + "product_name": "wifiiot", # Product name + "version": "3.0", # Version of config.json. The value is 3.0. + "type": "small", # System type. The value can be mini, small, or standard. + "ohos_version": "OpenHarmony 1.0", # OS version + "device_company": "realtek", # Name of the chipset solution vendor + "board": "rtl8720", # Name of the development board + "kernel_type": "liteos_m", # Kernel type + "kernel_version": "3.0.0", # Kernel version + "subsystems": [ + { + "subsystem": "kernel", # Subsystem + "components": [ + { "component": "liteos_m", "features":[] } # Component and its features + ] + }, + ... + { + More subsystems and components + } + ] + } + ``` + +> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**
+> Before the build, the Compilation and Building subsystem checks the validity of fields in **config.json**. The **device_company**, **board**, **kernel_type**, and **kernel_version** fields must match the fields of the chipset solution, and **subsystem** and **component** must match the component description in the **build/lite/components** file. + +3. Implement adaptation to OS APIs. + + Create the **hals** directory in the product directory and save the source code as well as the build script for OS adaptation in this directory. + +4. Configure system services. + + Create the **init_configs** directory in the product directory and then the **init.cfg** file in the **init_configs** directory, and configure the system services to be started. + +5. (Optional) Configure the init process for the Linux kernel. + + Create the **etc** directory in the **init_configs** directory, and then the **init.d** folder and the **fstab** file in the **etc** directory. Then, create the **rcS** and **S***xxx* files in the **init.d** file and edit them based on product requirements. + +6. (Optional) Configure the file system image for the development board that supports the file system. + + Create a **fs.yml** file in the product directory and configure it as required. A typical **fs.yml** file is as follows: + + ``` + - + fs_dir_name: rootfs # Image name + fs_dirs: + - + # Copy the files in the out/my_board/my_product/bin directory to the rootfs/bin directory and ignore the .bin files related to testing. + source_dir: bin + target_dir: bin + ignore_files: + - Test.bin + - TestSuite.bin + - + # Copy the files in the out/my_board/my_product/libs directory to the rootfs/lib directory, ignore all .a files, and set the file permissions to 644 and folder permissions 755. + source_dir: libs + target_dir: lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: usr/lib + target_dir: usr/lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: config + target_dir: etc + - + source_dir: system + target_dir: system + - + source_dir: sbin + target_dir: sbin + - + source_dir: usr/bin + target_dir: usr/bin + - + source_dir: usr/sbin + target_dir: usr/sbin + - + # Create an empty proc directory. + target_dir: proc + - + target_dir: mnt + - + target_dir: opt + - + target_dir: tmp + - + target_dir: var + - + target_dir: sys + - + source_dir: etc + target_dir: etc + - + source_dir: vendor + target_dir: vendor + - + target_dir: storage + + fs_filemode: + - + file_dir: lib/ld-uClibc-0.9.33.2.so + file_mode: 555 + - + file_dir: lib/ld-2.24.so + file_mode: 555 + - + file_dir: etc/init.cfg + file_mode: 400 + fs_symlink: + - + # Create the soft link ld-musl-arm.so.1 -> libc.so in the rootfs/lib directory. + source: libc.so + link_name: ${fs_dir}/lib/ld-musl-arm.so.1 + - + source: mksh + link_name: ${fs_dir}/bin/sh + - + source: mksh + link_name: ${fs_dir}/bin/shell + fs_make_cmd: + # Run the script to create an ext4 image from rootfs. + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + - + fs_dir_name: userfs + fs_dirs: + - + source_dir: storage/etc + target_dir: etc + - + source_dir: data + target_dir: data + fs_make_cmd: + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + + ``` + +7. (Optional) Configure patches if the product and components need to be patched. + + Create a **patch.yml** file in the product directory and configure it as required. A typical **patch.yml** file is as follows: + + ``` + # Directory in which the patch is to be installed + foundation/communication/dsoftbus: + # Directory in which the patch is stored. + - foundation/communication/dsoftbus/1.patch + - foundation/communication/dsoftbus/2.patch + third_party/wpa_supplicant: + - third_party/wpa_supplicant/1.patch + - third_party/wpa_supplicant/2.patch + - third_party/wpa_supplicant/3.patch + ... + ``` + + Add **--patch** when running the **hb build** command. Then, the patch files can be added to the specified directory before the build. + + ``` + hb build -f --patch + ``` + +8. Write the build script. + + Create a **BUILD.gn** file in the product directory and write the script. The following **BUILD.gn** file uses the Wi-Fi IoT module in step 1 as an example: + + ``` + group("wifiiot") { # The target name must be the same as the product name. + deps = [] + # Copy the init configuration. + deps += [ "init_configs" ] + # Add **hals**. + deps += [ "hals" ] + # Others + ... + } + ``` + +9. Build the product. + + Run the **hb set** command in the code root directory, select the new product as prompted, and run the **hb build** command. ## Troubleshooting -### Invalid -- w Option - -- **Symptom** - - The build fails, and "usr/sbin/ninja: invalid option -- w" is displayed. - -- **Cause** - - The Ninja version in the build environment is outdated and does not support the **--w** option. - -- **Solution** - - Uninstall Ninja and GN and follow the instructions provided in [IDE](../get-code/gettools-ide.md) to install Ninja and GN of the required version. - - -### Library ncurses Not Found - -- **Symptom** - - The build fails, and "/usr/bin/ld: cannot find -lncurses" is displayed. - -- **Cause** - - The ncurses library is not installed. - -- **Solution** - - ``` - sudo apt-get install lib32ncurses5-dev - ``` - - -### mcopy not Found - -- **Symptom** - - The build fails, and "line 77: mcopy: command not found" is displayed. - -- **Cause** - - mcopy is not installed. - -- **Solution** - - ``` - sudo apt-get install dosfstools mtools - ``` - - -### No riscv File or Directory - -- **Symptom** - - The build fails, and the following information is displayed: +### "usr/sbin/ninja: invalid option -- w" Displayed During the Build Process - riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory. +- **Symptom** + + The build fails, and **usr/sbin/ninja: invalid option -- w** is displayed. -- **Cause** +- **Possible Causes** + + The Ninja version in use does not support the **--w** option. - Permission is required to access files in the **riscv** compiler directory. +- **Solution** + + Uninstall Ninja and GN, and [install Ninja and GN of the required version](../get-code/gettools-ide.md). -- **Solution** +### "/usr/bin/ld: cannot find -lncurses" Displayed During the Build Process - Run the following command to query the directory where **gcc\_riscv32** is located: +- **Symptom** + + The build fails, and **/usr/bin/ld: cannot find -lncurses** is displayed. - ``` - which riscv32-unknown-elf-gcc - ``` +- **Possible Causes** + + The ncurses library is not installed. + +- **Solution** + + ``` + sudo apt-get install lib32ncurses5-dev + ``` - Run the **chmod** command to change the directory permission to **755**. +### "line 77: mcopy: command not found" Displayed During the Build Process +- **Symptom** + + The build fails, and **line 77: mcopy: command not found** is displayed. -### No Crypto +- **Possible Causes** + + mcopy is not installed. -- **Symptom** +- **Solution** + + ``` + sudo apt-get install dosfstools mtools + ``` - The build fails, and "No component named 'Crypto'" is displayed. +### "riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory" Displayed During the Build Process -- **Cause** +- **Symptom** + + The build fails, and the following information is displayed:
**riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory** - Crypto is not installed in Python 3. +- **Possible Causes** + + Permission is required to access files in the RISC-V compiler directory. -- **Solution** - 1. Run the following command to query the Python version: +- **Solution** - ``` - python3 --version - ``` + 1. Run the following command to locate **gcc_riscv32**: - 2. Ensure that Python 3.7 or later is installed, and then run the following command to install pycryptodome: + ``` + which riscv32-unknown-elf-gcc + ``` - ``` - sudo pip3 install pycryptodome - ``` + 2. Run the **chmod** command to change the directory permission to **755**. + + -### Unexpected Operator +### "No module named 'Crypto'" Displayed During the Build Process -- **Symptom** +- **Symptom** + + The build fails, and **No module named 'Crypto'** is displayed. - The build fails, and "xx.sh \[: xx unexpected operator" is displayed. +- **Possible Causes** + + Crypto is not installed in Python 3. -- **Cause** +- **Solution** + + 1. Run the following command to query the Python version: + + ``` + python3 --version + ``` + + 2. Ensure that Python 3.9.2 or later is installed, and then run the following command to install PyCryptodome: + + ``` + sudo pip3 install pycryptodome + ``` - The build environment is shell, not bash. +### "xx.sh : xx unexpected operator" Displayed During the Build Process -- **Solution** +- **Symptom** + + The build fails, and **xx.sh [: xx unexpected operator** is displayed. - ``` - sudo rm -rf /bin/sh - sudo ln -s /bin/bash /bin/sh - ``` +- **Possible Causes** + + The build environment shell is not bash. +- **Solution** + + ``` + sudo rm -rf /bin/sh + sudo ln -s /bin/bash /bin/sh + ``` diff --git a/en/device-dev/subsystems/subsys-build-standard-large.md b/en/device-dev/subsystems/subsys-build-standard-large.md index 588d41c974..d1f3eb9fd8 100644 --- a/en/device-dev/subsystems/subsys-build-standard-large.md +++ b/en/device-dev/subsystems/subsys-build-standard-large.md @@ -1,226 +1,813 @@ -# Building the Standard System
+# Building the Standard System -## Overview +## Overview -The compilation and building subsystem provides a framework based on Generate Ninja \(GN\) and Ninja. This subsystem allows you to: +The Compilation and Building subsystem provides a build framework based on Generate Ninja (GN) and Ninja. This subsystem allows you to: -- Build products based on different chipset platforms, for example, Hi3516D V300. +- Build products based on different chipset platforms, for example, hispark_taurus_standard. -- Package capabilities required by a product by assembling modules based on the product configuration. +- Package capabilities required by a product by assembling components based on the product configuration. -### Basic Concepts +### Basic Concepts -It is considered best practice to learn the following basic concepts before you start building: +Learn the following basic concepts before you start: -- **Platform** +- Platform + + A platform consists of the development board and kernel. The supported subsystems and components vary with the platform. - A platform is a combination of development boards and kernels. +- Subsystem + + OpenHarmony is designed with a layered architecture, which consists of the kernel layer, system service layer, framework layer, and application layer from the bottom up. System functions are developed by levels, from system to subsystem and then to component. In a multi-device deployment scenario, you can customize subsystems and components as required. A subsystem, as a logical concept, consists of the least required components. - Supported subsystems and modules vary according to the platform. +- Component + + A component is a reusable software unit that contains source code, configuration files, resource files, and build scripts. Integrated in binary mode, a component can be built and tested independently. -- **Subsystems** +- GN + + GN is short for Generate Ninja. It is used to build Ninja files. - OpenHarmony is designed with a layered architecture, which from bottom to top consists of the kernel layer, system service layer, framework layer, and application layer. System functions are expanded by levels, from system to subsystem, and further to module. In a multi-device deployment scenario, unnecessary subsystems and modules can be excluded from the system as required. A subsystem is a logical concept and is a flexible combination of functions. +- Ninja + + Ninja is a small high-speed building system. -- **Module** +### Working Principles - A module is a reusable software binary unit that contains source code, configuration files, resource files, and build scripts. A module can be built independently, integrated in binary mode, and then tested independently. +The process for building an OpenHarmony system is as follows: -- **GN** +- Parsing commands: Parse the name of the product to build and load related configurations. - GN is short for Generate Ninja, which is used to generate Ninja files. +- Running GN: Configure the toolchain and global options based on the product name and compilation type. -- **Ninja** +- Running Ninja: Start building and generate a product distribution. - Ninja is a small high-speed build system. +### Constraints +- You need to obtain the source code using method 3 described in [Obtaining Source Code](../get-code/sourcecode-acquire.md). -### Working Principles +- Ubuntu 18.04 or later must be used. -The process to build OpenHarmony is as follows: +- You must install the software packages required for build. + The command is as follows: + + ``` + # Run the script in the home directory. + # ./build/build_scripts/env_setup.sh + # Do not run the command as the **root** user. Otherwise, the environment variables will be added to the **root** user. If your **shell** is not **bash** or **Zsh**, you need to manually configure the following content to your environment variables after the execution. To view your environment variables, run the **cd** command to go to your home directory and view the hidden files. + # 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 + + # If you do not need to run the script, you need to install the following: + 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 + # Install the following modules for 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 + #You also need to install LLVM, hc-gen, gcc_riscv32, Ninja, node-v14.15.4-linux-x64, and GN, and import the non-bash or non-Zsh configuration in the shell to your environment variables. + ``` -- Parsing commands: Parse the name of the product to build and load related configurations. -- Running GN: Configure toolchains and global options based on the parsed product name and compilation type. -- Running Ninja: Start building and generate a product distribution. -### Limitations and Constraints -- You must download the source code using method 3 described in [Source Code Acquisition](../get-code/sourcecode-acquire.md). -- The build environment must be Ubuntu 18.04 or later. -- You must install the software package required for build. +## Building Guidelines - The installation command is as follows: +### Directory Structure - ``` - 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 # Directory for build -## Compilation and Building Guidelines +├── __pycache__ +├── build_scripts/ # Python scripts for build +├── common/ +├── config/ # Build-related configurations +├── core +│ └── gn/ # BUILD.gn configuration + └── build_scripts/ +├── docs +gn_helpers.py* +lite/ # hb and preloader entry +misc/ +├── ohos # Process for building and packaging OpenHarmony +│ ├── kits # Kits build and packaging templates and processing +│ ├── ndk # NDK templates and processing +│ ├── notice # Notice templates and processing +│ ├── packages # Distribution packaging templates and processing +│ ├── sa_profile # SA profiles and processing +│ ├── sdk # SDK templates and processing, which contains the module configuration in the SDK +│ └── testfwk # Testing-related processing +├── ohos.gni* # Common .gni files for importing a module at a time. +├── ohos_system.prop +├── ohos_var.gni* +├── prebuilts_download.sh* +├── print_python_deps.py* +├── scripts/ +├── subsystem_config.json +├── subsystem_config_example.json +├── templates/ # C/C++ build templates +├── test.gni* +├── toolchain # Build toolchain configuration +├── tools # Common tools +├── version.gni +├── zip.py* -### Directory Structure -``` -/build # Primary directory -├── config # Build configuration items -├── core -│ └── gn # Build entry BUILD.gn configuration -├── loader # Loader of module configuration, which also generates a template for the module -├── ohos # Configuration of the process for building and packaging OpenHarmony -│ ├── kits # Build and packaging templates and processing flow for kits -│ ├── ndk # NDK template and processing flow -│ ├── notice # Notice template and processing flow -│ ├── packages # Distribution packaging template and processing flow -│ ├── sa_profile # SA template and processing flow -│ ├── sdk # SDK template and processing flow, which contains the module configuration in the SDK -│ └── testfwk # Processing flow related to the test -├── scripts # Build-related Python script -├── templates # C/C++ build templates -└── toolchain # Toolchain configuration ``` -### Build Command +### Build Command -- Run the following command in the root directory of the source code to build the full distribution: +- Run the following command in the root directory of the source code to build a full distribution: - ``` - ./build.sh --product-name {product_name} - ``` + ``` - **product\_name** indicates the product supported by the current distribution, for example, hispark_taurus_standard. + ./build.sh --product-name {product_name} + + ``` - The image generated after build is stored in the **out/{device_name}/packages/phone/images/** directory. + **{product_name}** specifies the product platform supported by the current distribution, for example, **hispark_taurus_standard**. -- The build command supports the following options: + The image generated is stored in the **out/{device_name}/packages/phone/images/** directory. - ``` - --product-name # (Mandatory) Name of the product to build, for example, Hi3516D V300 - --build-target # (Optional) One or more build targets - --gn-args # (Optional) One or more gn parameters - --ccache # (Optional) Use of Ccache for build. This option takes effect only when Ccache is installed on the local PC. - ``` +- The **./build.sh** command supports the following options: + ``` + -h, --help # Display help information and exit. + --source-root-dir=SOURCE_ROOT_DIR # Specify the path. + --product-name=PRODUCT_NAME # Specify the product name. + --device-name=DEVICE_NAME # Specify the device name. + --target-cpu=TARGET_CPU # Specify the CPU. + --target-os=TARGET_OS # Specify the operating system. + -T BUILD_TARGET, --build-target=BUILD_TARGET # specifies one or more targets to build. + --gn-args=GN_ARGS # Specify GN parameters. + --ninja-args=NINJA_ARGS # Specify Ninja parameters. + -v, --verbose # Display all commands used. + --keep-ninja-going # Keep Ninja going until 1,000,000 jobs fail. + --sparse-image + --jobs=JOBS + --export-para=EXPORT_PARA + --build-only-gn # Perform GN parsing and does not run Ninja. + --ccache # (Optional) Use ccache for build. You need to install ccache locally. + --fast-rebuild # Whether to use fast rebuild. The default value is False. + --log-level=LOG_LEVEL # Specify the log level during the build. The options are debug, info, and error. The default value is info. + --device-type=DEVICE_TYPE # Specify the device type. The default value is default. + --build-variant=BUILD_VARIANT # Specify the device operation mode. The default value is user. -### How to Develop + ``` -1. Add a module. +### How to Develop - The following steps use a custom module as an example to describe how to build the module, including build a library, an executable file, and a configuration file. +1. Add a component. + + The following use a custom component as an example to describe how to write .gn scripts for a library, an executable file, and a configuration file. + + In this example, **partA** consists of **feature1**, **feature2**, and **feature3**, which represent a dynamic library, an executable file, and an etc configuration file, respectively. + + Add **partA** to a subsystem, for example, **subsystem_examples** (defined in the **test/examples/** directory). + - The example module **partA** consists of **feature1**, **feature2**, and **feature3**. The target is a dynamic library for **feature1**, an executable file for **feature2**, and an etc configuration file for **feature3**. +The directory structure of **partA** is as follows: - Add **partA** to a subsystem, for example, **subsystem\_examples** \(defined in the **test/examples/** directory\). +``` + + test/examples/partA + ├── feature1 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld1.h + │ └── src + │ └── helloworld1.cpp + ├── feature2 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld2.h + │ └── src + │ └── helloworld2.cpp + └── feature3 + ├── BUILD.gn + └── src + └── config.conf + +``` - The complete directory structure of **partA** is as follows: +(a) Write **test/examples/partA/feature1/BUILD.gn** for the dynamic library. - ``` - test/examples/partA - ├── feature1 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld1.h - │ └── src - │ └── helloworld1.cpp - ├── feature2 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld2.h - │ └── src - │ └── helloworld2.cpp - └── feature3 - ├── BUILD.gn - └── src - └── config.conf - ``` +``` + + config("helloworld_lib_config") { + include_dirs = [ "include" ] +} + + ohos_shared_library("helloworld_lib") { + sources = [ + "include/helloworld1.h", + "src/helloworld1.cpp", + ] + public_configs = [ ":helloworld_lib_config" ] + part_name = "partA" +} + +``` - Example 1: GN script \(**test/examples/partA/feature1/BUILD.gn**\) for building a dynamic library +(b) Write **test/examples/partA/feature2/BUILD.gn** for the executable file. - ``` - config("helloworld_lib_config") { +``` + + ohos_executable("helloworld_bin") { + sources = [ + "src/helloworld2.cpp" + ] include_dirs = [ "include" ] - } - - ohos_shared_library("helloworld_lib") { - sources = [ - "include/helloworld1.h", - "src/helloworld1.cpp", + deps = [ # Dependent modules in the component + "../feature1:helloworld_lib" + ] + external_deps = [ "partB:module1" ] # (Optional) Dependent modules of another component are named in Component name:Module name format. + install_enable = true # By default, the executable file is not installed. You need to set this parameter to true for installation. + part_name = "partA" +} + +``` + +(c) Write **test/examples/partA/feature3/BUILD.gn** for the etc module. + +``` + + ohos_prebuilt_etc("feature3_etc") { + source = "src/config.conf" + relative_install_dir = "init" # (Optional) Relative directory for installing the module. The default installation directory is **/system/etc**. + part_name = "partA" +} + +``` + + (d) Add the module configuration **test/examples/bundle.json** to the **bundle.json** file of the component. Each component has a **bundle.json** file in the root directory of the component. The sample code is as follows: + + ``` + { + "name": "@ohos/, # OpenHarmony Package Manager (HPM) component name, in the "@Organization/Component name" format. + "description": "xxxxxxxxxxxxxxxxxxx", # Description of the component functions. + "version": "3.1", # Version, which must be the same as the version of OpenHarmony. + "license": "MIT", # Component license. + "publishAs": "code-segment", # Mode for publishing the HPM package. The default value is code-segment. + "segment": { + "destPath": "" + }, # Set the code restoration path (source code path) when publishAs is code-segment. + "dirs": {}, # Directory structure of the HPM package. This field is mandatory and can be left empty. + "scripts": {}, # Scripts to be executed. This field is mandatory and can be left empty. + "licensePath": "COPYING", # Path of the module's license. + "readmePath": { + "en": "README.rst" + }, # Path of module's reademe.opensource. + "component": { # Component attributes. + "name": "", # Component name. + "subsystem": "", # Subsystem to which the component belongs. + "syscap": [], # System capabilities provided by the component for applications. + "features": [], # List of the component's configurable features. Generally, this parameter corresponds to sub_component in build and can be configured. + "adapted_system_type": [], # Adapted system types, which can be mini, small, and standard. Multiple values are allowed. + "rom": "xxxKB" # ROM baseline. If there is no baseline, enter the current value. + "ram": "xxxKB", # RAM baseline. If there is no baseline, enter the current value. + "deps": { + "components": [], # Other components on which this component depends. + "third_party": [] # Third-party open-source software on which this component depends. + }, + "build": { # Build-related configurations. + "sub_component": [], # Component build entry. Configure the module here. + "inner_kits": [], # APIs between components. + "test": [] # Entry for building the component's test cases. + } + } + } + ``` + +2. Add the component to the product configuration file. + Add the component to **//vendor/{*product_company*}/{*product-name*}/config.json**. + + For example, add "subsystem_examples:partA" to the product **config.json** file. **partA** will be built and packaged into the distribution. + +3. Start the build. + For example, run the following command to build **hispark_taurus_standard**: + + ``` + + ./build.sh --product-name hispark_taurus_standard --ccache + + ``` + +4. Obtain the build result. + You can obtain the generated files from the **out/hispark_taurus/** directory and the image in the **out/hispark_taurus/packages/phone/images/** directory. + +## FAQs + +### How Do I Build a Module and Package It into a Distribution? + +- Set **part_name** for the module. A module can belong to only one part. + +- Add the module to **component.build.sub_component** of the component, or define the dependency between the module and the modules in **component.build.sub_component**. + +- Add the component to the component list of the product. + +### How Do I Set deps and external_deps? + +When adding a module, you need to declare its dependencies in **BUILD.gn**. **deps** specifies dependent modules in the same component, and **external_deps** specifies dependent modules between components. + +The dependency between modules can be classified into: + +**deps**: The dependent module to be added belongs to the same component with the current module. For example, module 2 depends on module 1, and modules 1 and 2 belong to the same component. + +**external_deps**: The dependent module to be added belongs to another component. For example, module 2 depends on module 1, and modules 1 and 2 belong to different components. + +- Example of **deps**: + + ``` + import("//build/ohos.gni") + ohos_shared_library("module1") { + ... + part_name = "part1" # (Mandatory) Name of the component to which the module belongs. + ... + } + ``` + + ``` + import("//build/ohos.gni") + ohos_shared_library("module2") { + ... + deps = [ + "GN target of module 1", + ... + ] # Intra-component dependency + part_name = "part1" # (Mandatory) Name of the part to which the module belongs. + } + ``` + +- Example of **external_deps**: + + ``` + import("//build/ohos.gni") + ohos_shared_library("module1") { + ... + part_name = "part1" # (Mandatory) Name of the component to which the module belongs. + ... + } + ``` + +- **bundle.json** file of the component to which module 1 belongs + + ``` + { + "name": "@ohos/", # HPM component name, in the "@Organization/Component name" format. + "description": "xxxxxxxxxxxxxxxx", # Description of the component functions. + "version": "3.1", # Version, which must be the same as the version of OpenHarmony. + "license": "MIT", # Component license. + "publishAs": "code-segment", # Mode for publishing the HPM package. The default value is code-segment. + "segment": { + "destPath": "" + }, # Code restoration path (source code path) when publishAs is code-segment. + "dirs": {}, # Directory structure of the HPM package. This field is mandatory and can be left empty. + "scripts": {}, # Scripts to be executed. This field is mandatory and can be left empty. + "licensePath "licensePath": "COPYING", + ": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "component": { # Component attributes. + "name": "", # Component name. + "subsystem": "", # Subsystem to which the component belongs. + "syscap": [], # System capabilities provided by the component for applications. + "features": [], # List of the component's configurable features. Generally, this parameter corresponds to sub_component in build and can be configured. + "adapted_system_type": [], # Adapted system types, which can be mini, small, and standard. Multiple values are allowed. + "rom": "xxxKB" # ROM baseline. If there is no baseline, enter the current value. + "ram": "xxxKB", # RAM baseline. If there is no baseline, enter the current value. + "deps": { + "components": [], # Other components on which this component depends. + "third_party": [] # Third-party open-source software on which this component depends. + }, + "build": { # Build-related configurations. + "sub_component": ["part1"], # Component build entry. All modules of the component are listed here. + "inner_kits": [], # APIs between components. + { + "header": { + "header_base": "Header file directory", # Directory of the header files. + "header_files": [ + "Header file name" + ] # List of header file names. + }, + "name": "GN target of module 1" + }, + ], + "test": [] # Entry for building the component's test cases. + } + } + } + ``` + + ``` + import("//build/ohos.gni") + ohos_shared_library("module2") { + ... + external_deps = [ + "part1:module1", + ... + ] # Inter-component dependency. The dependent module must be declared in **inner_kits** by the dependent component. + part_name = "part2" # (Mandatory) Name of the component to which the module belongs. + } + + ``` + +> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**
+> The values of **external_deps** are in the *Component name*:*Module name* format. The module name must exist in **inner_kits** of the dependent component. + + + + + +### How Do I Add a Module to a Standard System? + +You may need to: + +- Add a module to an existing component. + +- Add a module to a new component. + +- Add a module to a new subsystem. + +#### Adding a Module to an Existing Component + +1. Configure the **BUILD.gn** file in the module directory and select the corresponding template. + + Follow the procedure for adding a module to an existing component. Note that **part_name** in the **BUILD.gn** file is the name of the existing component. +2. Modify the **bundle.json** file. "GN target of the module in the component" + + ``` + { + "name": "@ohos/, # HPM component name, in the "@Organization/Component name" format. + "description": "xxxxxxxxxxxxxxxxxxx", # Description of the component functions. + "version": "3.1", # Version, which must be the same as the version of OpenHarmony. + "license": "MIT", # Component license. + "publishAs": "code-segment", # Mode for publishing the HPM package. The default value is code-segment. + "segment": { + "destPath": "third_party/nghttp2" + }, # Code restoration path (source code path) when publishAs is code-segment. + "dirs": {}, # Directory structure of the HPM package. This field is mandatory and can be left empty. + "scripts": {}, # Scripts to be executed. This field is mandatory and can be left empty. + "licensePath": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "component": { # Component attributes. + "name": "", # Component name. + "subsystem": "", # Subsystem to which the component belongs. + "syscap": [], # System capabilities provided by the component for applications. + "features": [], # List of the component's configurable features. Generally, this parameter corresponds to sub_component in build and can be configured. + "adapted_system_type": [], # Adapted system types, which can be mini, small, and standard. Multiple values are allowed. + "rom": "xxxKB" # ROM baseline. If there is no baseline, enter the current value. + "ram": "xxxKB", # RAM baseline. If there is no baseline, enter the current value. + "deps": { + "components": [], # Other components on which this component depends. + "third_party": [] # Third-party open-source software on which this component depends. + }, + + "build": { # Build-related configurations + "sub_component": [ + "//foundation/arkui/napi:napi_packages", # Existing module 1 + "//foundation/arkui/napi:napi_packages_ndk" # Existing module 2 + "//foundation/arkui/napi:new" # Module to add + ], # Component build entry. Configure the module here. + "inner_kits": [], # APIs between components + "test": [] # Entry for building the component's test cases. + } + } + } + ``` + + Note that the **bundle.json** file must be in the folder of the corresponding subsystem. + +#### Creating a Component and Adding a Module + +1. Configure the **BUILD.gn** file in the module directory and select the corresponding template. Note that **part_name** in the **BUILD.gn** file is the name of the newly added component. + +2. Create a **bundle.json** file in the folder of the corresponding subsystem. + + The **bundle.json** file consists of two parts: **subsystem** and **parts**. Add the component information to **parts**. When adding a component, you need to specify the **sub_component** of the component. If there are APIs provided for other components, add them in **inner_kits**. If there are test cases, add them in **test**. + +3. Add the new component to the end of existing components in **//vendor/{product_company}/{product-name}/config.json**. + + ``` + "subsystems": [ + { + "subsystem": "Name of the subsystem to which the component belongs", + "components": [ + {"component": "Component 1 name", "features":[]}, # Existing component 1 in the subsystem + { "component": "Component 2 name", "features":[] }, # Existing component 2 in the subsystem + {"component": "New component name", "features":[]} # New component in the subsystem + ] + }, + ... + ] + ``` + +#### Creating a Subsystem and Adding a Module + +1. Configure the **BUILD.gn** file in the module directory and select the corresponding template. + + Note that **part_name** in the **BUILD.gn** file is the name of the newly added component. + +2. Create a **bundle.json** file in the folder of the component of the subsystem. + + This step is the same as the step in "Creating a Component and Adding a Module." + +3. Modify the **subsystem_config.json** file in the **build** directory. + + ``` + { + "Subsystem 1 name": { # Existing subsystem 1 + "path": "Subsystem 1 directory", + "name": "Subsystem 1 name" + }, + "Subsystem 2 name": { # Existing subsystem 2 + "path": "Subsystem 2 directory", + "name": "Subsystem 2 name" + }, + "Subsystem name new": { # Subsystem to add + "path": "New subsystem directory", + "name": "New subsystem name" + }, + ... + } + ``` + + This file defines the subsystems and their paths. To add a subsystem, specify **path** and **name** for the subsystem. + +4. If **product-name** in the **//vendor/{product_company}/{product-name}** directory is **hispark_taurus_standard**, add the new component information to the end of existing components in the **config.json** file. + + ``` + "subsystems": [ + { + "subsystem": "arkui", # Name of the existing subsystem + "components": [ # All components of the subsystem + { + "component": "ace_engine_standard", # Name of the existing component + "features": [] + }, + { + "component": "napi", # Name of the existing component + "features": [] + } + { + "component": "component_new1", # Name of the new component added to the existing subsystem + "features": [] + } + ] + }, + { + "subsystem": "subsystem_new", # Name of the new subsystem to add + "components": [ + { + "component": "component_new2", # Name of the component added to the new subsystem + "features": [] + } + ] + }, + ... + ] + ``` + Verification: + - Check that **module_list** in the **BUILD.gn** file in the component directory under the corresponding subsystem directory contains the target defined in the **BUILD.gn** file of the new module. + - Check the .so file or binary file generated in the image created. + +#### Configuration Files + +There are four OpenHarmony configuration files. + +1. **vendor\Product vendor\Product name\config.json** + + ``` + { + "product_name": "MyProduct", + "version": "3.0", + "type": "standard", + "target_cpu": "arm", + "ohos_version": "OpenHarmony 1.0", + "device_company": "MyProductVendor", + "board": "MySOC", + "enable_ramdisk": true, + "subsystems": [ + { + "subsystem": "ace", + "components": [ + { "component": "ace_engine_lite", "features":[""] } + ] + }, + ... ] - public_configs = [ ":helloworld_lib_config" ] - part_name = "partA" + } + + ``` + This file specifies the name, manufacturer, device, version, type of system to be built, and subsystems of the product. + +2. **subsystem_config.json** in the **build** directory + + ``` + { + "arkui": { + "path": "foundation/arkui", + "name": "arkui" + }, + "ai": { + "path": "foundation/ai", + "name": "ai" + }, + ...... } - ``` + ``` + This file contains subsystem information. You need to configure **name** and **path** for each subsystem. + +3. **bundle.json** of a subsystem + + ``` + { + "name": "@ohos/, # HPM component name, in the "@Organization/Component name" format. + "description": "xxxxxxxxxxxxxxxxxxx", # Description of the component functions. + "version": "3.1", # Version, which must be the same as the version of OpenHarmony. + "license": "MIT", # Component license. + "publishAs": "code-segment", # Mode for publishing the HPM package. The default value is code-segment. + "segment": { + "destPath": "" + }, # Code restoration path (source code path) when publishAs is code-segment. + "dirs": {}, # Directory structure of the HPM package. This field is mandatory and can be left empty. + "scripts": {}, # Scripts to be executed. This field is mandatory and can be left empty. + "licensePath": "COPYING", + "readmePath": { + "en": "README.rst" + }, + "component": { # Component attributes. + "name": "", # Component name. + "subsystem": "", # Subsystem to which the component belongs. + "syscap": [], # System capabilities provided by the component for applications. + "features": [], # List of the component's configurable features. Generally, this parameter corresponds to sub_component in build and can be configured. + "adapted_system_type": [], # Adapted system types, which can be mini, small, and standard. Multiple values are allowed. + "rom": "xxxKB" # ROM baseline. If there is no baseline, enter the current value. + "ram": "xxxKB", # RAM baseline. If there is no baseline, enter the current value. + "deps": { + "components": [], # Other components on which this component depends. + "third_party": [] # Third-party open-source software on which this component depends. + }, + "build": { # Build-related configurations. + "sub_component": ["gn target of the module"], # Component build entry + "inner_kits": [], # APIs between components. + "test": [] # Entry for building the component's test cases. + } + } + } + ``` + The **bundle.json** file defines the components of a subsystem. + + Each component contains the module's target **component.build.sub_component**, **component.build.inner_kits** for interaction between components, and test cases **component.build.test_list**. The **component.build.sub_component** is mandatory. + +4. **BUILD.gn** of each module + + You can create **BUILD.gn** from a template or using the GN syntax. + +### How Do I Build a HAP? + +#### **HAP Description** + +An OpenHarmony Ability Package (HAP) includes resources, raw assets, JS assets, native libraries, and **config.json**. + +#### **Templates** - Example 2: GN script \(**test/examples/partA/feature2/BUILD.gn**\) for building an executable file +The compilation and build subsystem provides four templates for building HAPs. The templates are integrated in **ohos.gni**. Before using the templates, import **build/ohos.gni**. + +1. **ohos_resources** + + This template declares resource targets. After a target is built by restool, an index file is generated. The resource source file and index file are both packaged into the HAP. + + A **ResourceTable.h** file is also generated after resource building. This header file can be referenced if the resource target is relied on. + + The resource target name must end with **resources**, **resource**, or **res**. Otherwise, a build error may occur. + + The following variables are supported: + + - **sources**: a list of resource paths. + - **hap_profile**: **config.json** of the HAP required for resource building. + - **deps**: (optional) dependency of the current target. + +2. **ohos_assets** + + This template declares asset targets. + + Beware that the spelling is "assets" as opposed to "assert". + + The asset target name must end with **assets** or **asset**. + + The following variables are supported: + + - **sources**: a list for raw asset paths. + - **deps**: (optional) dependency of the current target. + +3. **ohos_js_assets** + + This template declares a JS resource target. The JS resource is the executable part of an L2 HAP. + + The JS asset target name must end with **assets** or **asset**. + + The following variables are supported: + + - **source_dir**: JS resource path, which is of the string type. + - **deps**: (optional) dependency of the current target. + +4. **ohos_hap** + + This template declares a HAP target. A HAP that will be generated and packaged into the system image. + + The following variables are supported: + + - **hap_profile**: **config.json** of the HAP. + - **deps**: dependency of the current target. + - **shared_libraries**: native libraries on which the current target depends. + - **hap_name**: (optional) name of the HAP. The default value is the target name. + - **final_hap_path**: (optional) destination path of the HAP. It takes precedence over **hap_name**. + - **subsystem_name**: name of the subsystem to which the HAP belongs. The value must be the same as that in **bundle.json**. Otherwise, the HAP will fail to be installed in the system image. + - **part_name**: name of the component to which the HAP belongs. The value must be the same as that in **bundle.json**. + - **js2abc**: whether to convert the HAP into ARK bytecode. + - **certificate_profile**: certificate profile of the HAP, which is used for signature. For details about signatures, see [Configuring Signature Information](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768). + - **certificate_file**: Certificate file. You must apply for the certificate and its profile from the official OpenHarmony website. + - **keystore_path**: keystore file, which is used for signature. + - **keystore_password**: keystore password, which is used for signature. + - **key_alias**: key alias. + - **module_install_name**: name of the HAP used during installation. + - **module_install_dir**: installation path. The default path is **system/app**. + +**HAP Example** ``` - ohos_executable("helloworld_bin") { - sources = [ - "src/helloworld2.cpp" + import("//build/ohos.gni") # Import **ohos.gni**. + ohos_hap("clock") { + hap_profile = "./src/main/config.json" # config.json + deps = [ + ":clock_js_assets", # JS assets + ":clock_resources", # Resources ] - include_dirs = [ "include" ] - deps = [ # Dependent submodule - "../feature1:helloworld_lib" + shared_libraries = [ + "//third_party/libpng:libpng", # Native library ] - external_deps = [ "partB:module1" ] # (Optional) If there is a cross-module dependency, the format is "module name: submodule name" - install_enable = true # By default, the executable file is not installed. You need to set this parameter to true for installation. - part_name = "partA" + certificate_profile = "../signature/systemui.p7b" # Certificate profile + hap_name = "SystemUI-NavigationBar" # HAP name + 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" } ``` - Example 3: GN script \(**test/examples/partA/feature3/BUILD.gn**\) for building the etc configuration file \(submodule\). +### What Does an Open-Source Software Notice Collect? - ``` - ohos_prebuilt_etc("feature3_etc") { - source = "src/config.conf" - relative_install_dir = "init" # (Optional) Directory for installing the submodule, which is relative to the default installation directory (/system/etc) - part_name = "partA" - } - ``` +#### Information to Collect - Example 4: Adding the module configuration file **test/examples/ohos.build** to the **ohos.build** file of this subsystem. Each subsystem has an **ohos.build** file in its root directory. Example: +The notice collects only the licenses of the modules packaged in the image. For example, the licenses of the tools (such as Clang, Python, and Ninja) used during the build process are not collected. - ``` - "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": [ - - ] - } - ``` +A static library itself is not packaged. However, if it is packaged into the system as part of a dynamic library or executable file, the license of the static library will be collected for completeness. - The declaration of a module contains the following parts: +The final **Notice.txt** file must include all licenses used by the files in the image and the mapping between modules and licenses. - - **module\_list**: submodule list of the module - - **inner\_kits**: APIs for other modules that depend on this module through **external\_deps** - - **system\_kits**: APIs for developers - - **test\_list**: test cases for the submodules of the module +The **Notice.txt** file is located in the **/system/etc/** directory. -2. Add the module to the product configuration file. +#### Rules for Collecting Information - Add the module to the product configuration file **//vendor/{product_company}/{product-name}/config.json**. +Licenses are collected by priority. - Add "subsystem\_examples:partA" to the product configuration file. **partA** will be built and packaged into the distribution. +1. Licenses that are directly declared in a module's **BUILD.gn** are given the top priority. The following is an example: -3. Build the module. + ``` + ohos_shared_library("example") { + ... + license_file = "path-to-license-file" + ... + } + ``` - For example, run the following command to build hispark_taurus_standard: +2. If there is no explicitly declared license, the build script searches for the **Readme.OpenSource** file in the directory of **BUILD.gn**, parses the file, and collects the obtained licenses. + If the **Readme.OpenSource** file does not contain license information, an error will be reported. - ``` - ./build.sh --product-name hispark_taurus_standard --ccache - ``` +3. If the **Readme.OpenSource** file does not exist, the build script searches for the **License**, **Copyright**, and **Notice** files from the current directory to the root directory of the source code by default. If obtained license information will be used as the licenses of the module. + +4. If no license is found, the default license (Apache License 2.0) will be used. -4. Obtain the build result. +Check items: - Files generated during the build process are stored in the **out/hispark_taurus/** directory, and the generated image is stored in the **out/hispark_taurus/packages/phone/images/** directory. +1. For third-party open-source software, such as OpenSSL and ICU, **Readme.OpenSource** must be configured in the source code directory. Check whether **Readme.OpenSource** is in the same directory as **BUILD.gn** and whether the license configured in **Readme.OpenSource** is valid. +2. If the source code is not licensed under the Apache License 2.0, the corresponding license file must be provided in the source code directory or declared by **license_file** for the module. +3. If the source code file added to **BUILD.gn** is not from the current directory, check whether the license in the repository where the source code file is located is the same as that in the repository of **BUILD.gn**. License inconsistency entails follow-up operations. -- GitLab