1e41f4b71Sopenharmony_ci# Build System Coding Specifications and Best Practices 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciGenerate Ninja (GN) is a meta-build system that generates build files for Ninja. It is the front end of Ninja. GN and Ninja together complete OpenHarmony build tasks. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci### GN 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciGN is used in large software systems such as Chromium, Fuchsia, and OpenHarmony. However, the GN syntax has limitations rooted in its design philosophy. For details, see https://gn.googlesource.com/gn/+/main/docs/language.md#Design-philosophy. For example, GN does not support wildcards and cannot get the length of a list. If you find it complex to implement something with GN, stop and consider whether it is necessary to do it. For more details about GN, see https://gn.googlesource.com/gn/+/main/docs/. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci### Intended Audience and Purpose 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ciThis document is intended for OpenHarmony developers. It describes the GN coding style and practices, but does not cover the GN syntax. For details about the GN basics, see https://gn.googlesource.com/gn/+/main/docs/reference.md. 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci### General Principles 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ciScripts must be easy to read and maintain, and have good scalability and performance while functioning well. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci## Coding Style 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci### Naming 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ciFollow the Linux kernel naming style, that is, lowercase letters + underscores (_). 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci#### Local Variables 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ciA local variable is a variable restricted to use in a certain scope and cannot be passed down. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ciDifferent from global variables, local variables start with an underscore (_). 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci```shell 32e41f4b71Sopenharmony_ci# Example 1: 33e41f4b71Sopenharmony_ciaction("some_action") { 34e41f4b71Sopenharmony_ci ... 35e41f4b71Sopenharmony_ci # _output is a local variable. 36e41f4b71Sopenharmony_ci _output = "${target_out_dir}/${target_name}.out" 37e41f4b71Sopenharmony_ci outputs = [ _output ] 38e41f4b71Sopenharmony_ci args = [ 39e41f4b71Sopenharmony_ci ... 40e41f4b71Sopenharmony_ci "--output", 41e41f4b71Sopenharmony_ci rebase_path(_output, root_build_dir), 42e41f4b71Sopenharmony_ci ... 43e41f4b71Sopenharmony_ci ] 44e41f4b71Sopenharmony_ci ... 45e41f4b71Sopenharmony_ci} 46e41f4b71Sopenharmony_ci``` 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci#### Global Variables 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ciA global variable starts with a lowercase letter. 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ciUse **declare_args** to declare the variable value only if the variable value can be modified by **gn args**. 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci```shell 55e41f4b71Sopenharmony_ci# Example 2 56e41f4b71Sopenharmony_cideclare_args() { 57e41f4b71Sopenharmony_ci # The value of some_feature can be changed by gn args. 58e41f4b71Sopenharmony_ci some_feature = false 59e41f4b71Sopenharmony_ci} 60e41f4b71Sopenharmony_ci``` 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci#### Targets 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ciName the targets in the lowercase letters + underscores (_) format. 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ciName the subtargets in templates in the ${target_name}+double underscores (__)+suffix format. This naming convention has the following advantages: 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci- ${target_name} prevents duplicate subtarget names. 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci- The double underscores (__) help locate the module to which a subtarget belongs. 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ci ```shell 73e41f4b71Sopenharmony_ci # Example 3 74e41f4b71Sopenharmony_ci template("ohos_shared_library") { 75e41f4b71Sopenharmony_ci # "{target_name}" (Target name) + "__" (double underscores) + "notice" (suffix) 76e41f4b71Sopenharmony_ci _notice_target = "${target_name}__notice" 77e41f4b71Sopenharmony_ci collect_notice(_notice_target) { 78e41f4b71Sopenharmony_ci ... 79e41f4b71Sopenharmony_ci } 80e41f4b71Sopenharmony_ci shared_library(target_name) { 81e41f4b71Sopenharmony_ci ... 82e41f4b71Sopenharmony_ci } 83e41f4b71Sopenharmony_ci } 84e41f4b71Sopenharmony_ci ``` 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci#### Custom Templates 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ciName templates in the verb+object format. 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci```shell 91e41f4b71Sopenharmony_ci# Example 4 92e41f4b71Sopenharmony_ci# Good 93e41f4b71Sopenharmony_citemplate("compile_resources") { 94e41f4b71Sopenharmony_ci ... 95e41f4b71Sopenharmony_ci} 96e41f4b71Sopenharmony_ci``` 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci### Formatting 99e41f4b71Sopenharmony_ci 100e41f4b71Sopenharmony_ciGN scripts must be formatted before being submitted. Formatting ensures consistency in style, such as code alignment and line feed. Use the format tool provided by GN to format your scripts. The command is as follows: 101e41f4b71Sopenharmony_ci 102e41f4b71Sopenharmony_ci```shell 103e41f4b71Sopenharmony_ci$ gn format path-to-BUILD.gn 104e41f4b71Sopenharmony_ci``` 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci**gn format** sorts the imported files in alphabetical order. To maintain the original sequence, add an empty comment line. 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ciFor example, the original import sequence is as follows: 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci```shell 111e41f4b71Sopenharmony_ci# Example 5 112e41f4b71Sopenharmony_ciimport("//b.gni") 113e41f4b71Sopenharmony_ciimport("//a.gni") 114e41f4b71Sopenharmony_ci``` 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_ci**gn format** sorts the files as follows: 117e41f4b71Sopenharmony_ci 118e41f4b71Sopenharmony_ci```shell 119e41f4b71Sopenharmony_ciimport("//a.gni") 120e41f4b71Sopenharmony_ciimport("//b.gni") 121e41f4b71Sopenharmony_ci``` 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ciTo maintain the original sequence, add an empty comment line. 124e41f4b71Sopenharmony_ci 125e41f4b71Sopenharmony_ci```shell 126e41f4b71Sopenharmony_ciimport("//b.gni") 127e41f4b71Sopenharmony_ci# Comment to keep the original sequence 128e41f4b71Sopenharmony_ciimport("//a.gni") 129e41f4b71Sopenharmony_ci``` 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci## Coding Practices 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci### Guidelines 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ciThe build script completes the following tasks: 136e41f4b71Sopenharmony_ci 137e41f4b71Sopenharmony_ci1. Describes the dependency (deps) between modules. 138e41f4b71Sopenharmony_ci 139e41f4b71Sopenharmony_ci In practice, the most common problem is lack of dependency. 140e41f4b71Sopenharmony_ci 141e41f4b71Sopenharmony_ci2. Defines the module build rules (rule). 142e41f4b71Sopenharmony_ci 143e41f4b71Sopenharmony_ci In practice, unclear input and output are common problems. 144e41f4b71Sopenharmony_ci 145e41f4b71Sopenharmony_ciLack of dependency leads to the following problems: 146e41f4b71Sopenharmony_ci 147e41f4b71Sopenharmony_ci- Unexpected compilation error 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci ```shell 150e41f4b71Sopenharmony_ci # Example 6 151e41f4b71Sopenharmony_ci # Lack of dependency poses a possibility of compilation errors. 152e41f4b71Sopenharmony_ci shared_library("a") { 153e41f4b71Sopenharmony_ci ... 154e41f4b71Sopenharmony_ci } 155e41f4b71Sopenharmony_ci shared_library("b") { 156e41f4b71Sopenharmony_ci ... 157e41f4b71Sopenharmony_ci ldflags = [ "-la" ] 158e41f4b71Sopenharmony_ci deps = [] 159e41f4b71Sopenharmony_ci ... 160e41f4b71Sopenharmony_ci } 161e41f4b71Sopenharmony_ci group("images") { 162e41f4b71Sopenharmony_ci deps = [ ":b" ] 163e41f4b71Sopenharmony_ci } 164e41f4b71Sopenharmony_ci ``` 165e41f4b71Sopenharmony_ci 166e41f4b71Sopenharmony_ci In this example, **libb.so** is linked to **liba.so**, which means that **b** depends on **a**. However, the dependency of **b** on **a** is not declared in the dependency list (**deps**) of **b**. Compilation is performed concurrently. An error occurs if **liba.so** is not available when **libb.so** attempts to create a link to it. 167e41f4b71Sopenharmony_ci 168e41f4b71Sopenharmony_ci If **liba.so** is available, the compilation is successful. Therefore, lack of dependency poses a possibility of compilation errors. 169e41f4b71Sopenharmony_ci 170e41f4b71Sopenharmony_ci- Missing compilation of modules 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci In example 6, images are the target to build. Since images depend only on **b**, **a** will not be compiled. However, as **b** depends on **a**, an error occurs when **b** is linked. 173e41f4b71Sopenharmony_ci 174e41f4b71Sopenharmony_ciAnother problem is unnecessary dependencies. Unnecessary dependencies reduce concurrency and slow down compilation. The following is an example: 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci**_compile_js_target** does not necessarily depend on **_compile_resource_target**. If this dependency is added, **_compile_js_target** can be compiled only after **_compile_resource_target** is compiled. 177e41f4b71Sopenharmony_ci 178e41f4b71Sopenharmony_ci```shell 179e41f4b71Sopenharmony_ci# Example 7: 180e41f4b71Sopenharmony_ci# Unnecessary dependencies slow down compilation. 181e41f4b71Sopenharmony_citemplate("too_much_deps") { 182e41f4b71Sopenharmony_ci ... 183e41f4b71Sopenharmony_ci _gen_resource_target = "${target_name}__res" 184e41f4b71Sopenharmony_ci action(_gen_resource_target) { 185e41f4b71Sopenharmony_ci ... 186e41f4b71Sopenharmony_ci } 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci _compile_resource_target = "${target_name}__compile_res" 189e41f4b71Sopenharmony_ci action(_compile_resource_target) { 190e41f4b71Sopenharmony_ci deps = [":$_gen_resource_target"] 191e41f4b71Sopenharmony_ci ... 192e41f4b71Sopenharmony_ci } 193e41f4b71Sopenharmony_ci 194e41f4b71Sopenharmony_ci _compile_js_target = "${target_name}__js" 195e41f4b71Sopenharmony_ci action(_compile_js_target) { 196e41f4b71Sopenharmony_ci # This deps is not required. 197e41f4b71Sopenharmony_ci deps = [":$_compile_resource_target"] 198e41f4b71Sopenharmony_ci } 199e41f4b71Sopenharmony_ci} 200e41f4b71Sopenharmony_ci``` 201e41f4b71Sopenharmony_ci 202e41f4b71Sopenharmony_ciUnclear input leads to the following problems: 203e41f4b71Sopenharmony_ci 204e41f4b71Sopenharmony_ci- Modified code is not compiled during incremental compilation. 205e41f4b71Sopenharmony_ci- The cache being used is still hit after the code is changed. 206e41f4b71Sopenharmony_ci 207e41f4b71Sopenharmony_ciIn the following example, **foo.py** references the functions in **bar.py**. This means **bar.py** is the input of **foo.py**. You need to add **bar.py** to **input** or **depfile** of **implict_input_action**. Otherwise, if **bar.py** is modified, **implict_input_action** will not be recompiled. 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci```shell 210e41f4b71Sopenharmony_ci# Example 8: 211e41f4b71Sopenharmony_ciaction("implict_input_action") { 212e41f4b71Sopenharmony_ci script = "//path-to-foo.py" 213e41f4b71Sopenharmony_ci ... 214e41f4b71Sopenharmony_ci} 215e41f4b71Sopenharmony_ci``` 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci```shell 218e41f4b71Sopenharmony_ci#!/usr/bin/env 219e41f4b71Sopenharmony_ci# Content of foo.py 220e41f4b71Sopenharmony_ciimport bar 221e41f4b71Sopenharmony_ci... 222e41f4b71Sopenharmony_cibar.some_function() 223e41f4b71Sopenharmony_ci... 224e41f4b71Sopenharmony_ci``` 225e41f4b71Sopenharmony_ci 226e41f4b71Sopenharmony_ciUnclear output leads to the following problems: 227e41f4b71Sopenharmony_ci 228e41f4b71Sopenharmony_ci- Implicit output 229e41f4b71Sopenharmony_ci- A failure to obtain the implicit output from the cache 230e41f4b71Sopenharmony_ci 231e41f4b71Sopenharmony_ciIn the following example, **foo.py** generates two files: **a.out** and **b.out**. However, the output of **implict_output_action** declares only **a.out**. In this case, **b.out** is an implicit output, and the cache stores only **a.out**. When the cache is hit, **b.out** cannot be compiled. 232e41f4b71Sopenharmony_ci 233e41f4b71Sopenharmony_ci```shell 234e41f4b71Sopenharmony_ci# Example 9 235e41f4b71Sopenharmony_ciaction("implict_output_action") { 236e41f4b71Sopenharmony_ci outputs = ["${target_out_dir}/a.out"] 237e41f4b71Sopenharmony_ci script = "//path-to-foo.py" 238e41f4b71Sopenharmony_ci ... 239e41f4b71Sopenharmony_ci} 240e41f4b71Sopenharmony_ci``` 241e41f4b71Sopenharmony_ci 242e41f4b71Sopenharmony_ci```shell 243e41f4b71Sopenharmony_ci#!/usr/bin/env 244e41f4b71Sopenharmony_ci# Content of foo.py 245e41f4b71Sopenharmony_ci... 246e41f4b71Sopenharmony_ciwrite_file("b.out") 247e41f4b71Sopenharmony_ciwrite_file("a.out") 248e41f4b71Sopenharmony_ci... 249e41f4b71Sopenharmony_ci``` 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci### Templates 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci**Do not use GN native templates. Use the templates provided by the build system.** 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ciThe GN native templates include **source_set**, **shared_library**, **static_library**, **action**, **executable** and **group**. 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ciThe native templates are not recommended due to the following reasons: 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci- The native templates provide only the minimal build configuration. They cannot provide functions, such as parsing **external_deps**, collecting notice, and generating installation information. 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ci- The native **action** template cannot automatically detect the changes in the dependencies of the input file, and cannot start recompilation. See Example 8. 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci The table below lists the mapping between the GN native templates and templates provided by OpenHarmony Compilation and Build subsystem. 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci| OpenHarmony Template | GN Native Template | 266e41f4b71Sopenharmony_ci| :------------------ | -------------- | 267e41f4b71Sopenharmony_ci| ohos_shared_library | shared_library | 268e41f4b71Sopenharmony_ci| ohos_source_set | source_set | 269e41f4b71Sopenharmony_ci| ohos_executable | executable | 270e41f4b71Sopenharmony_ci| ohos_static_library | static_library | 271e41f4b71Sopenharmony_ci| action_with_pydeps | action | 272e41f4b71Sopenharmony_ci| ohos_group | group | 273e41f4b71Sopenharmony_ci 274e41f4b71Sopenharmony_ci### Using Python Scripts 275e41f4b71Sopenharmony_ci 276e41f4b71Sopenharmony_ciYou are advised to use Python scripts instead of shell scripts in **action**. Compared with shell scripts, Python scripts feature: 277e41f4b71Sopenharmony_ci 278e41f4b71Sopenharmony_ci- More user-friendly syntax, which eliminates errors caused by lack of a space 279e41f4b71Sopenharmony_ci- Easier to read 280e41f4b71Sopenharmony_ci- Easier to maintain and debug 281e41f4b71Sopenharmony_ci- Faster compilation due to caching of Python tasks 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci### rebase_path 284e41f4b71Sopenharmony_ci 285e41f4b71Sopenharmony_ci- Call **rebase_path** only in **args** of **action**. 286e41f4b71Sopenharmony_ci 287e41f4b71Sopenharmony_ci ```shell 288e41f4b71Sopenharmony_ci # Example 10 289e41f4b71Sopenharmony_ci template("foo") { 290e41f4b71Sopenharmony_ci action(target_name) { 291e41f4b71Sopenharmony_ci ... 292e41f4b71Sopenharmony_ci args = [ 293e41f4b71Sopenharmony_ci # Call rebase_path only in args. 294e41f4b71Sopenharmony_ci "--bar=" + rebase_path(invoker.bar, root_build_dir), 295e41f4b71Sopenharmony_ci ... 296e41f4b71Sopenharmony_ci ] 297e41f4b71Sopenharmony_ci ... 298e41f4b71Sopenharmony_ci } 299e41f4b71Sopenharmony_ci } 300e41f4b71Sopenharmony_ci 301e41f4b71Sopenharmony_ci foo("good") { 302e41f4b71Sopenharmony_ci bar = something 303e41f4b71Sopenharmony_ci ... 304e41f4b71Sopenharmony_ci } 305e41f4b71Sopenharmony_ci ``` 306e41f4b71Sopenharmony_ci 307e41f4b71Sopenharmony_ci- If rebase_path is called twice for the same variable, unexpected results occur. 308e41f4b71Sopenharmony_ci 309e41f4b71Sopenharmony_ci ```shell 310e41f4b71Sopenharmony_ci # Example 11 311e41f4b71Sopenharmony_ci template("foo") { 312e41f4b71Sopenharmony_ci action(target_name) { 313e41f4b71Sopenharmony_ci ... 314e41f4b71Sopenharmony_ci args = [ 315e41f4b71Sopenharmony_ci # After rebase_path is called twice for bar, the bar value passed is incorrect. 316e41f4b71Sopenharmony_ci "--bar=" + rebase_path(invoker.bar, root_build_dir), 317e41f4b71Sopenharmony_ci ... 318e41f4b71Sopenharmony_ci ] 319e41f4b71Sopenharmony_ci ... 320e41f4b71Sopenharmony_ci } 321e41f4b71Sopenharmony_ci } 322e41f4b71Sopenharmony_ci 323e41f4b71Sopenharmony_ci foo("bad") { 324e41f4b71Sopenharmony_ci # Do not call rebase_path here. 325e41f4b71Sopenharmony_ci bar = rebase_path(some_value, root_build_dir) 326e41f4b71Sopenharmony_ci ... 327e41f4b71Sopenharmony_ci } 328e41f4b71Sopenharmony_ci ``` 329e41f4b71Sopenharmony_ci 330e41f4b71Sopenharmony_ci### Sharing Data Between Modules 331e41f4b71Sopenharmony_ci 332e41f4b71Sopenharmony_ciIt is common to share data between modules. For example, module A wants to know the output and **deps** of module B. 333e41f4b71Sopenharmony_ci 334e41f4b71Sopenharmony_ci- Data sharing within the same **BUILD.gn** 335e41f4b71Sopenharmony_ci 336e41f4b71Sopenharmony_ci Data in the same **BUILD.gn** can be shared by defining global variables. 337e41f4b71Sopenharmony_ci 338e41f4b71Sopenharmony_ci In the following example, the output of module **a** is the input of module **b**, and can be shared with module **b** via global variables. 339e41f4b71Sopenharmony_ci 340e41f4b71Sopenharmony_ci ```shell 341e41f4b71Sopenharmony_ci # Example 12 342e41f4b71Sopenharmony_ci _output_a = get_label_info(":a", "out_dir") + "/a.out" 343e41f4b71Sopenharmony_ci action("a") { 344e41f4b71Sopenharmony_ci outputs = _output_a 345e41f4b71Sopenharmony_ci ... 346e41f4b71Sopenharmony_ci } 347e41f4b71Sopenharmony_ci action("b") { 348e41f4b71Sopenharmony_ci inputs = [_output_a] 349e41f4b71Sopenharmony_ci ... 350e41f4b71Sopenharmony_ci } 351e41f4b71Sopenharmony_ci ``` 352e41f4b71Sopenharmony_ci 353e41f4b71Sopenharmony_ci- Data sharing between different **BUILD.gn**s 354e41f4b71Sopenharmony_ci 355e41f4b71Sopenharmony_ci The best way to share data between different **BUILD.gn** is to save the data as files and transfer the files between modules. You can refer to **write_meta_data** in the OpenHarmony HAP build process. 356e41f4b71Sopenharmony_ci 357e41f4b71Sopenharmony_ci### forward_variable_from 358e41f4b71Sopenharmony_ci 359e41f4b71Sopenharmony_ci- To customize a template, pass (**forward**) **testonly** first because the **testonly** target may depend on the template target. 360e41f4b71Sopenharmony_ci 361e41f4b71Sopenharmony_ci ```shell 362e41f4b71Sopenharmony_ci # Example 13 363e41f4b71Sopenharmony_ci # For a customized template, pass testonly first. 364e41f4b71Sopenharmony_ci template("foo") { 365e41f4b71Sopenharmony_ci forward_variable_from(invoker, ["testonly"]) 366e41f4b71Sopenharmony_ci ... 367e41f4b71Sopenharmony_ci } 368e41f4b71Sopenharmony_ci ``` 369e41f4b71Sopenharmony_ci 370e41f4b71Sopenharmony_ci- Do not use asterisks (*) to **forward** variables. Required variables must be explicitly forwarded one by one. 371e41f4b71Sopenharmony_ci 372e41f4b71Sopenharmony_ci ```shell 373e41f4b71Sopenharmony_ci # Example 14 374e41f4b71Sopenharmony_ci # Bad. The asterisk (*) is used to forward the variable. 375e41f4b71Sopenharmony_ci template("foo") { 376e41f4b71Sopenharmony_ci forward_variable_from(invoker, "*") 377e41f4b71Sopenharmony_ci ... 378e41f4b71Sopenharmony_ci } 379e41f4b71Sopenharmony_ci 380e41f4b71Sopenharmony_ci # Good. Variables are explicitly forwarded one by one. 381e41f4b71Sopenharmony_ci template("bar") { 382e41f4b71Sopenharmony_ci # 383e41f4b71Sopenharmony_ci forward_variable_from(invoker, [ 384e41f4b71Sopenharmony_ci "testonly", 385e41f4b71Sopenharmony_ci "deps", 386e41f4b71Sopenharmony_ci ... 387e41f4b71Sopenharmony_ci ]) 388e41f4b71Sopenharmony_ci ... 389e41f4b71Sopenharmony_ci } 390e41f4b71Sopenharmony_ci ``` 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci### target_name 393e41f4b71Sopenharmony_ci 394e41f4b71Sopenharmony_ciThe value of **target_name** varies with the scope. 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci```shell 397e41f4b71Sopenharmony_ci# Example 15 398e41f4b71Sopenharmony_ci# The value of target_name varies with the scope. 399e41f4b71Sopenharmony_citemplate("foo") { 400e41f4b71Sopenharmony_ci # The displayed target_name is "${target_name}". 401e41f4b71Sopenharmony_ci print(target_name) 402e41f4b71Sopenharmony_ci _code_gen_target = "${target_name}__gen" 403e41f4b71Sopenharmony_ci code_gen(_code_gen_target) { 404e41f4b71Sopenharmony_ci # The displayed target_name is "${target_name}__gen". 405e41f4b71Sopenharmony_ci print(target_name) 406e41f4b71Sopenharmony_ci ... 407e41f4b71Sopenharmony_ci } 408e41f4b71Sopenharmony_ci _compile_gen_target = "${target_name}__compile" 409e41f4b71Sopenharmony_ci compile(_compile_gen_target) { 410e41f4b71Sopenharmony_ci # The displayed target_name is "${target_name}__compile". 411e41f4b71Sopenharmony_ci print(target_name) 412e41f4b71Sopenharmony_ci ... 413e41f4b71Sopenharmony_ci } 414e41f4b71Sopenharmony_ci ... 415e41f4b71Sopenharmony_ci} 416e41f4b71Sopenharmony_ci``` 417e41f4b71Sopenharmony_ci 418e41f4b71Sopenharmony_ci### public_configs 419e41f4b71Sopenharmony_ci 420e41f4b71Sopenharmony_ciTo export header files from a module, use **public_configs**. 421e41f4b71Sopenharmony_ci 422e41f4b71Sopenharmony_ci```shell 423e41f4b71Sopenharmony_ci# Example 16 424e41f4b71Sopenharmony_ci# b depends on a and inherits from the headers of a. 425e41f4b71Sopenharmony_ciconfig("headers") { 426e41f4b71Sopenharmony_ci include_dirs = ["//path-to-headers"] 427e41f4b71Sopenharmony_ci ... 428e41f4b71Sopenharmony_ci} 429e41f4b71Sopenharmony_cishared_library("a") { 430e41f4b71Sopenharmony_ci public_configs = [":headers"] 431e41f4b71Sopenharmony_ci ... 432e41f4b71Sopenharmony_ci} 433e41f4b71Sopenharmony_ciexecutable("b") { 434e41f4b71Sopenharmony_ci deps = [":a"] 435e41f4b71Sopenharmony_ci ... 436e41f4b71Sopenharmony_ci} 437e41f4b71Sopenharmony_ci``` 438e41f4b71Sopenharmony_ci 439e41f4b71Sopenharmony_ci### template 440e41f4b71Sopenharmony_ci 441e41f4b71Sopenharmony_ciA custom template must contain a subtarget named **target_name**. This subtarget is used as the target of the template and depends on other subtargets. Otherwise, the subtargets will not be compiled. 442e41f4b71Sopenharmony_ci 443e41f4b71Sopenharmony_ci```shell 444e41f4b71Sopenharmony_ci# Example 17 445e41f4b71Sopenharmony_ci# A custom template must have a subtarget named target_name. 446e41f4b71Sopenharmony_citemplate("foo") { 447e41f4b71Sopenharmony_ci _code_gen_target = "${target_name}__gen" 448e41f4b71Sopenharmony_ci code_gen(_code_gen_target) { 449e41f4b71Sopenharmony_ci ... 450e41f4b71Sopenharmony_ci } 451e41f4b71Sopenharmony_ci _compile_gen_target = "${target_name}__compile" 452e41f4b71Sopenharmony_ci compile(_compile_gen_target) { 453e41f4b71Sopenharmony_ci # The displayed target_name is "${target_name}__compile". 454e41f4b71Sopenharmony_ci print(target_name) 455e41f4b71Sopenharmony_ci ... 456e41f4b71Sopenharmony_ci } 457e41f4b71Sopenharmony_ci ... 458e41f4b71Sopenharmony_ci group(target_name) { 459e41f4b71Sopenharmony_ci deps = [ 460e41f4b71Sopenharmony_ci # _compile_gen_target depends on _code_gen_target. Therefore, target_name only needs to depend on _compile_gen_target. 461e41f4b71Sopenharmony_ci ":$_compile_gen_target" 462e41f4b71Sopenharmony_ci ] 463e41f4b71Sopenharmony_ci } 464e41f4b71Sopenharmony_ci} 465e41f4b71Sopenharmony_ci``` 466e41f4b71Sopenharmony_ci 467e41f4b71Sopenharmony_ci### set_source_assignment_filter 468e41f4b71Sopenharmony_ci 469e41f4b71Sopenharmony_ciIn addition to **sources**, **set_source_assignment_filter** can be used to filter other variables. After the filtering is complete, clear the filter and **sources**. 470e41f4b71Sopenharmony_ci 471e41f4b71Sopenharmony_ci```shell 472e41f4b71Sopenharmony_ci# Example 18 473e41f4b71Sopenharmony_ci# Use set_source_assignment_filter to filter dependencies and add the dependencies with labels matching *:*_res to the dependency list. 474e41f4b71Sopenharmony_ci_deps = [] 475e41f4b71Sopenharmony_ciforeach(_possible_dep, invoker.deps) { 476e41f4b71Sopenharmony_ci set_source_assignment_filter(["*:*_res"]) 477e41f4b71Sopenharmony_ci _label = get_label_info(_possible_dep, "label_no_toolchain") 478e41f4b71Sopenharmony_ci sources = [] 479e41f4b71Sopenharmony_ci sources = [ _label ] 480e41f4b71Sopenharmony_ci if (sources = []) { 481e41f4b71Sopenharmony_ci _deps += _sources 482e41f4b71Sopenharmony_ci } 483e41f4b71Sopenharmony_ci} 484e41f4b71Sopenharmony_cisources = [] 485e41f4b71Sopenharmony_ciset_source_assignment_filter([]) 486e41f4b71Sopenharmony_ci``` 487e41f4b71Sopenharmony_ci 488e41f4b71Sopenharmony_ciIn the latest version, **set_source_assignment_filter** is replaced by **filter_include** and **filter_exclude**. 489e41f4b71Sopenharmony_ci 490e41f4b71Sopenharmony_ci### Setting deps and external_deps 491e41f4b71Sopenharmony_ci 492e41f4b71Sopenharmony_ciAn OpenHarmony component is a group of modules that can provide a capability. When defining a module, set **part_name** to specify the component to which the module belongs. 493e41f4b71Sopenharmony_ci 494e41f4b71Sopenharmony_ciYou must also declare **inner_kits** of a component for other components to call. For details, see **bundle.json** in the source code. **inner_kits** applies only to dependent modules in different components. 495e41f4b71Sopenharmony_ci 496e41f4b71Sopenharmony_ciIf modules **a** and **b** has the same **part_name**, modules **a** and **b** belong to the same component. In this case, declare the dependency between them using **deps**. 497e41f4b71Sopenharmony_ci 498e41f4b71Sopenharmony_ciIf modules **a** and **b** have different **part_name**, modules **a** and **b** belong to different components. In this case, declare the dependency between them using **external_deps** in the *Component name:Module name* format. See Example 19. 499e41f4b71Sopenharmony_ci 500e41f4b71Sopenharmony_ci```shell 501e41f4b71Sopenharmony_ci# Example 19 502e41f4b71Sopenharmony_cishared_library("a") { 503e41f4b71Sopenharmony_ci ... 504e41f4b71Sopenharmony_ci external_deps = ["part_name_of_b:b"] 505e41f4b71Sopenharmony_ci ... 506e41f4b71Sopenharmony_ci} 507e41f4b71Sopenharmony_ci```