1e41f4b71Sopenharmony_ci# Component Building Specifications
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## About This Document
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Purpose
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciCompilation and building is an important part for implementing the component-based design. A component in the compiled state should be maintainable, portable, and loosely coupled. This document provides guidelines for writing build scripts so that the components to build are configurable, reusable, and tailorable, with reasonable dependencies.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci### Basic Concepts
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci**Component**
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ciA component is a basic unit that constitutes OpenHarmony system capabilities. It contains the minimum required source code and has independent repositories and directories. It can be instantiated into different libraries or binary files on different devices.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci**Feature**
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ciComponent features are configurable options in the build of a product. A component can be configured with different features to adapt to different product form factors. The configuration of component features affects only the implementations of component internal functions. It does not affect the public APIs (APIs provided by the component for applications) or inner APIs (APIs between components).
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci**Dependency**
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ciA component in the compiled state has the following dependencies:
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci- Conditional dependency: The dependency can be tailored in specific scenarios, and the removal of the dependency does not affect the public or inner APIs of the component. For example, audio has conditional dependency on Bluetooth.
24e41f4b71Sopenharmony_ci- Strong dependency: The dependency between components cannot be tailored. For example, the syscap component has strong dependency on the security library functions.
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci### General Principles
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ciThe compilation and building of components must comply with the following:
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci**Independent and Autonomous**
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ciThe component in the compiled state must be highly cohesive. Exercise caution when adding external dependencies, and minimize static dependencies in build.
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci**Reasonable Dependency**
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ciSet up inter-component dependency based on the interfaces between components. Avoid the dependency on the modules or header files of other components.
37e41f4b71Sopenharmony_ci
38e41f4b71Sopenharmony_ci**Product Independent**
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ciThe component in the compiled state should be applicable to multiple products. Do not use product names in build scripts.
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci### Conventions
43e41f4b71Sopenharmony_ci
44e41f4b71Sopenharmony_ci**Rule**: a convention that must be complied with
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ci**Suggestion**: a convention that must be taken into consideration
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci### Guarding Method
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ciThe gated check-in conducts the following checks on the build configuration files:
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ciPrebuild check: The files are checked in the prebuild phase. If an error is detected, the build stops.
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ciStatic check: The check tool scans and checks configuration files for errors.
55e41f4b71Sopenharmony_ci
56e41f4b71Sopenharmony_ci### Exception
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ciAn exception is allowed only with sufficient reasons as long as the general principles are not violated.
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ciHowever, exceptions compromise code consistency and should be avoided as far as possible. Exceptions to the "rules" should be rare.
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci## Naming
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ciThe names of variables and build targets in build scripts, templates, gni files, and objects and data in component description files must be in the kernel style (unix_like). That is, the words are in lowercase and separated by underscores (_). For example, **startup_init**.
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci### Rule 1.1 Use consistent format for component names.
67e41f4b71Sopenharmony_ci- The component name must reflect the functions of the component.
68e41f4b71Sopenharmony_ci- The component name must be globally unique in the system.
69e41f4b71Sopenharmony_ci- The component name cannot exceed 63 valid characters.
70e41f4b71Sopenharmony_ci- The component name consists of lowercase letters and underscores (_), for example, **unix_like**.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci> **Exception**: Third-party open-source software can use the native naming format, for example, **cJson**.
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci### Rule 1.2 Name features in the *component name*_*feature name* format.
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ciA feature is a configurable option declared by a component. Adding a component name prefix can prevent duplicate feature names. 
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ciExample:
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci```py
81e41f4b71Sopenharmony_cideclare_args() {
82e41f4b71Sopenharmony_ci  dsoftbus_conn_p2p = true # dsoftbus is the component name, and conn_p2p is the feature name.
83e41f4b71Sopenharmony_ci  dsoftbus_conn_ble = false # dsoftbus is the component name, and conn_ble is the feature name.
84e41f4b71Sopenharmony_ci}
85e41f4b71Sopenharmony_ci```
86e41f4b71Sopenharmony_ci
87e41f4b71Sopenharmony_ciGuarding method: prebuild check
88e41f4b71Sopenharmony_ci
89e41f4b71Sopenharmony_ci### Suggestion 1.1: Name build targets in the *component name*_*module name* format.
90e41f4b71Sopenharmony_ci
91e41f4b71Sopenharmony_ciA component may have multiple build targets (modules). The component and module names help you quickly locate the component based on the output (library or executable file) and prevents duplicate names.
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ciExample:
94e41f4b71Sopenharmony_ci```py
95e41f4b71Sopenharmony_ciohos_shared_library("data") # Inaccurate, too general, and easy to duplicate
96e41f4b71Sopenharmony_ci```
97e41f4b71Sopenharmony_ciExample: 
98e41f4b71Sopenharmony_ci```py
99e41f4b71Sopenharmony_ciohos_shared_library("cellular_data_napi") # Good example
100e41f4b71Sopenharmony_ci```
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ci## Description File
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ciThe **bundle.json** file defines a component. It contains information, such as the root directory, name, function description, version number, interface definition, and build entry of a component. The information in **bundle.json** file must be correct.
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci### Rule 2.1 Ensure correct component information in the file.
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci| Field| Type| Mandatory| Description| Guarding Method|
109e41f4b71Sopenharmony_ci|---|---|---|---|---|
110e41f4b71Sopenharmony_ci|name|String|Yes|OpenHarmony package manager (HPM) package name of the component.<br>Naming rule: @{organization}/{component_name}<br>{component_name} must comply with **Rule 1.1**.|Static check|
111e41f4b71Sopenharmony_ci|version|String|Yes|Component version number, which must be consistent with that of OpenHarmony.|Static check|
112e41f4b71Sopenharmony_ci|destPath|String|Yes|Root directory of the component source code.<br>The root directory of each component must be unique.|Static check|
113e41f4b71Sopenharmony_ci|component:name|String|Yes|Component name, which must comply with **Rule 1.1**.|Static check|
114e41f4b71Sopenharmony_ci|component:subsystem|String|Yes|Subsystem to which the component belongs. The subsystem name consists of lowercase letters and cannot contain underscores (_).|Static check|
115e41f4b71Sopenharmony_ci|component:syscap|String list|No|System capabilities.<br>Naming rule: **SystemCapability**.*Subsystem*.*Component capability*.*Sub-capability* (optional) in upper camel case<br/>Example: **SystemCapability.Media.Camera,SystemCapability.Media.Camera.Front**|Static check|
116e41f4b71Sopenharmony_ci|component:features|String list|No|Features that can be configured for the component. The feature names must comply with **Rule 1.2**.|Static check|
117e41f4b71Sopenharmony_ci|component:adapted_system_type|String list|Yes|Type of the system to which the component applies. The value can be **mini**, **small**, **standard**,or their combination.|Static check|
118e41f4b71Sopenharmony_ci|component:rom|String|Yes|ROM size, in KB.|Static check|
119e41f4b71Sopenharmony_ci|component:ram|String|Yes|RAM size, in KB.|Static check|
120e41f4b71Sopenharmony_ci|component:deps|String list|Yes|Dependencies of the component, including other components and third-party open-source software. The dependencies must be the same as that in the component build script.|Prebuild check|
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci
123e41f4b71Sopenharmony_ci### Suggestion 2.1 Place the component description file in the root directory of the component.
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ciThe component directory is independent. Place the **bundle.json** file in the root directory of the component.
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci## Variables
128e41f4b71Sopenharmony_ci
129e41f4b71Sopenharmony_ciThe built-in variable values of the build target determine the content to compile, dependencies, and data to package.
130e41f4b71Sopenharmony_ci
131e41f4b71Sopenharmony_ci### Rule 3.1 Do not include the absolute or relative paths of other components in the build script of a component.
132e41f4b71Sopenharmony_ci
133e41f4b71Sopenharmony_ciUse **external_deps** to include the dependency between components. The variables **sources**, **include_dirs**, **configs**, **public_configs**, **deps**, and **public_deps** of the component build target cannot reference the relative or absolute paths of other components.
134e41f4b71Sopenharmony_ci
135e41f4b71Sopenharmony_ci- sources
136e41f4b71Sopenharmony_ci
137e41f4b71Sopenharmony_ci  **Sources** can contain only the source code of a component. If **sources** contain the source code of other components, the independence of the component's source code directories will be violated.
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci- include_dirs
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci  **include_dirs** can contain only the header file paths of a component. The dependencies on other components are automatically imported through **external_deps**.
142e41f4b71Sopenharmony_ci
143e41f4b71Sopenharmony_ci- configs
144e41f4b71Sopenharmony_ci
145e41f4b71Sopenharmony_ci  **configs** can reference only the configuration paths of a component. Referencing the **configs** of other components may cause interface dependency.
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci- pulic_configs
148e41f4b71Sopenharmony_ci
149e41f4b71Sopenharmony_ci  **public_configs** can reference only the configuration paths of a component. Referencing the **configs** of other components may cause interface dependency.
150e41f4b71Sopenharmony_ci
151e41f4b71Sopenharmony_ci- deps
152e41f4b71Sopenharmony_ci
153e41f4b71Sopenharmony_ci  **deps** can contain only dependencies between the modules in a component. Referencing a module in another component may cause dependency on the module and interfaces of the referenced component.
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ci  Example:
156e41f4b71Sopenharmony_ci
157e41f4b71Sopenharmony_ci  base/foos/foo_a/BUILD.gn
158e41f4b71Sopenharmony_ci
159e41f4b71Sopenharmony_ci  ```py
160e41f4b71Sopenharmony_ci  deps = [ "//base/foo/foo_b:b" ] # Not recommended. deps contains the absolute path of another component.
161e41f4b71Sopenharmony_ci  deps = [ "../../foo_b:b" ] # Not recommended. deps contains the relative path of another component.
162e41f4b71Sopenharmony_ci  deps = [ "a" ] # Recommended.
163e41f4b71Sopenharmony_ci  ```
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci  > **Exception**: References to third-party open-source software are allowed.
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci- public_deps
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci  **Public_deps** can contain only dependencies between the modules in a component. Referencing a module in another component may cause dependency on the module and interfaces of the referenced component.
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci  > **Exception**: References to third-party open-source software are allowed.
172e41f4b71Sopenharmony_ci  
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ciGuarding method: static check
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci### Rule 3.2 The component name and subsystem name must be specified for the component build target.
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ci**part_name** and **subsystem_name** are mandatory for **ohos_shared_library**, **ohos_static_library**, **ohos_executable_library**, and **ohos_source_set** of a component. 
179e41f4b71Sopenharmony_ci
180e41f4b71Sopenharmony_ciThe following uses **ohos_shared_library** in **developtools/syscap_codec/BUILD.gn** as an example.
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ci```py
183e41f4b71Sopenharmony_ciohos_shared_library("syscap_interface_shared") {
184e41f4b71Sopenharmony_ci  include_dirs = [
185e41f4b71Sopenharmony_ci    "include",
186e41f4b71Sopenharmony_ci    "src",
187e41f4b71Sopenharmony_ci  ]
188e41f4b71Sopenharmony_ci  public_configs = [ ":syscap_interface_public_config" ]
189e41f4b71Sopenharmony_ci  sources = [
190e41f4b71Sopenharmony_ci    "./interfaces/inner_api/syscap_interface.c",
191e41f4b71Sopenharmony_ci    "./src/endian_internal.c",
192e41f4b71Sopenharmony_ci    "./src/syscap_tool.c",
193e41f4b71Sopenharmony_ci  ]
194e41f4b71Sopenharmony_ci  deps = [
195e41f4b71Sopenharmony_ci    "//third_party/bounds_checking_function:libsec_static",
196e41f4b71Sopenharmony_ci    "//third_party/cJSON:cjson_static",
197e41f4b71Sopenharmony_ci  ]
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ci  subsystem_name = "developtools" # subsystem_name is mandatory.
200e41f4b71Sopenharmony_ci  part_name = "syscap_codec" # part_name is mandatory.
201e41f4b71Sopenharmony_ci}
202e41f4b71Sopenharmony_ci```
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ciGuarding method: static check
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci### Suggestion 3.1 Use relative paths for internal references of a component.
207e41f4b71Sopenharmony_ci
208e41f4b71Sopenharmony_ciUsing relative paths for references within a component can:
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci- Make the script simpler.
211e41f4b71Sopenharmony_ci
212e41f4b71Sopenharmony_ci- Decouple the build script of a component from the root directory of the component.
213e41f4b71Sopenharmony_ci
214e41f4b71Sopenharmony_ciExample:
215e41f4b71Sopenharmony_ci
216e41f4b71Sopenharmony_cibase/foos/foo_a/BUILD.gn
217e41f4b71Sopenharmony_ci
218e41f4b71Sopenharmony_ci```py
219e41f4b71Sopenharmony_ciinclude_dirs = [
220e41f4b71Sopenharmony_ci    "./include", # Recommended.
221e41f4b71Sopenharmony_ci    "//base/foo/foo_a/include" # Not recommended.
222e41f4b71Sopenharmony_ci]
223e41f4b71Sopenharmony_ci
224e41f4b71Sopenharmony_cideps = [
225e41f4b71Sopenharmony_ci    "sub_module:foo", # Recommended.
226e41f4b71Sopenharmony_ci    "base/foo/foo_a/sub_module:foo" # Not recommended.
227e41f4b71Sopenharmony_ci]
228e41f4b71Sopenharmony_ci```
229e41f4b71Sopenharmony_ci
230e41f4b71Sopenharmony_ciGuarding method: static check
231e41f4b71Sopenharmony_ci
232e41f4b71Sopenharmony_ci### Suggestion 3.2 Make the internal modules of a component only visible to the component.
233e41f4b71Sopenharmony_ci
234e41f4b71Sopenharmony_ciSet **visibility** for the internal modules of a component to prevent them from being dependencies of other components. 
235e41f4b71Sopenharmony_ci
236e41f4b71Sopenharmony_ciExample:
237e41f4b71Sopenharmony_ci
238e41f4b71Sopenharmony_cibase/foos/foo_a/BUILD.gn
239e41f4b71Sopenharmony_ci
240e41f4b71Sopenharmony_ci```py
241e41f4b71Sopenharmony_ciohos_shared_library("foo_a") {
242e41f4b71Sopenharmony_ci    visibility = [ "./*" ] # foo_a is visible only to base/foo/foo_a and its subdirectories.
243e41f4b71Sopenharmony_ci}
244e41f4b71Sopenharmony_ci
245e41f4b71Sopenharmony_ciohos_shared_library("foo_a") {
246e41f4b71Sopenharmony_ci    visibility = [ ":*" ] # foo_a is visible only to this BUILD.gn.
247e41f4b71Sopenharmony_ci}
248e41f4b71Sopenharmony_ci```
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci## Others
251e41f4b71Sopenharmony_ci
252e41f4b71Sopenharmony_ci### Rule 4.1 Do not use the product name variable in the component build script.
253e41f4b71Sopenharmony_ci
254e41f4b71Sopenharmony_ciA component is a common system capability and is irrelevant to a specific product. If the product name is used in the build script, the component functions are bound to the product, which violates the commonality of the component. Abstract the differences between components in different product forms as features or runtime plug-ins.
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ci> **Exception**: The build scripts of third-party components in the **vendor** and **device** directories are excluded.
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ciGuarding method: static check
259e41f4b71Sopenharmony_ci
260e41f4b71Sopenharmony_ci### Suggestion 4.1 Do not import .gni files in directories of other components.
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ciThe **.gni** file declares the internal build variables and templates of the component. Importing the **.gni** file of another component means to use the internal variables and templates of another component, which introduces the dependency on that component. The variables, args, and templates that affect multiple components should be defined in the **.gni** file of the build framework.
263e41f4b71Sopenharmony_ci
264e41f4b71Sopenharmony_ci> **Exception**: The **.gni** file (containing global build options) of the build framework in the **build** directory can be imported by all components.
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ciGuarding method: static check
267e41f4b71Sopenharmony_ci
268e41f4b71Sopenharmony_ci### Suggestion 4.2 Use a unified template for component build units.
269e41f4b71Sopenharmony_ci
270e41f4b71Sopenharmony_ciUse **ohos_** templates, such as **ohos_shared_library**, **ohos_static_library**, **ohos_executable**, and **ohos_source_set**, for the build units of mini, small, and standard systems.
271e41f4b71Sopenharmony_ci
272e41f4b71Sopenharmony_ciExample:
273e41f4b71Sopenharmony_ci
274e41f4b71Sopenharmony_ci```py
275e41f4b71Sopenharmony_ci  executable ("foundation") {# The built-in template is not recommended.
276e41f4b71Sopenharmony_ci    ...
277e41f4b71Sopenharmony_ci  }
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci  ohos_executable("foundation") {# The ohos template is recommended.
280e41f4b71Sopenharmony_ci    ...
281e41f4b71Sopenharmony_ci  }
282e41f4b71Sopenharmony_ci```
283