1# 模块 2## 模块配置规则 3 4编译子系统通过模块、部件和产品三层配置来实现编译和打包。模块就是编译子系统的一个目标,包括(动态库、静态库、配置文件、预编译模块等)。模块要定义属于哪个部件,一个模块只能归属于一个部件。OpenHarmony使用定制化的Gn模板来配置模块规则,Gn语法相关的基础知识请参考[官网手册](https://gn.googlesource.com/gn/+/main/docs/reference.md)。 5 6以下是常用的模块配置规则: 7 8``` 9# C/C++模板 10ohos_shared_library 11ohos_static_library 12ohos_executable 13ohos_source_set 14 15# 预编译模板: 16ohos_prebuilt_executable 17ohos_prebuilt_shared_library 18ohos_prebuilt_static_library 19 20#hap模板 21ohos_hap 22ohos_app_scope 23ohos_js_assets 24ohos_resources 25 26#rust模板 27ohos_rust_executable 28ohos_rust_shared_library 29ohos_rust_static_library 30ohos_rust_proc_macro 31ohos_rust_shared_ffi 32ohos_rust_static_ffi 33ohos_rust_cargo_crate 34ohos_rust_systemtest 35ohos_rust_unittest 36ohos_rust_fuzztest 37 38#其他常用模板 39#配置文件 40ohos_prebuilt_etc 41 42#sa配置 43ohos_sa_profile 44``` 45 46ohos开头的模板与内建模板的差异主要在于:推荐使用ohos定制模板。 47 48### C/C++模板示例 49 50ohos开头的模板对应的.gni文件路径在:openharmony/build/templates/cxx/cxx.gni。 51 52ohos_shared_library示例 53 54```shell 55import("//build/ohos.gni") 56ohos_shared_library("helloworld") { 57 sources = ["file"] 58 include_dirs = [] # 如有重复头文件定义,优先使用前面路径头文件。 59 cflags = [] # 如重复冲突定义,后面的参数优先生效,也就是该配置项中优先生效。 60 cflags_c = [] 61 cflags_cc = [] 62 ldflags = [] # 如重复冲突定义,前面参数优先生效,也就是ohos_template中预制参数优先生效。 63 configs = [] 64 deps = [] # 部件内模块依赖 65 66 external_deps = [ # 跨部件模块依赖定义 67 "part_name:module_name", # 定义格式为 "部件名:模块名称"。 68 ] # 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块。 69 70 output_name = [string] # 模块输出名 71 output_extension = [] # 模块名后缀 72 module_install_dir = "" # 模块安装路径,缺省在/system/lib64或/system/lib下; 模块安装路径从system/,vendor/后开始指定。 73 relative_install_dir = "" # 模块安装相对路径,相对于/system/lib64或/system/lib;如果有module_install_dir配置时,该配置不生效。 74 75 part_name = "" # 必选,所属部件名称 76 output_dir 77 78 # Sanitizer配置,每项都是可选的,默认为false/空。 79 sanitize = { 80 # 各个Sanitizer开关 81 cfi = [boolean] # 控制流完整性检测 82 cfi_cross_dso = [boolean] # 开启跨so调用的控制流完整性检测 83 integer_overflow = [boolean] # 整数溢出检测 84 boundary_sanitize = [boolean] # 边界检测 85 ubsan = [boolean] # 部分ubsan选项 86 all_ubsan = [boolean] # 全量ubsan选项 87 ... 88 89 debug = [boolean] # 调测模式 90 blocklist = [string] # 屏蔽名单路径 91 } 92 93 testonly = [boolean] 94 license_as_sources = [] 95 license_file = [] # 后缀名是.txt的文件 96 remove_configs = [] 97 no_default_deps = [] 98 install_images = [] 99 install_enable = [boolean] 100 symlink_target_name = [] 101 version_script = [] 102 use_exceptions = [] 103} 104``` 105 106ohos_static_library示例 107 108```shell 109import("//build/ohos.gni") 110ohos_static_library("helloworld") { 111 sources = ["file"] # 后缀名是.c的相关文件 112 include_dirs = ["dir"] # 包含目录 113 configs = [] # 配置 114 deps = [] # 部件内模块依赖 115 part_name = "" # 部件名称 116 subsystem_name = "" # 子系统名称 117 cflags = [] 118 119 external_deps = [ # 跨部件模块依赖定义, 120 "part_name:module_name", # 定义格式为 "部件名:模块名称" 121 ] # 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块。 122 123 lib_dirs = [] 124 public_configs = [] 125 126 # Sanitizer配置,每项都是可选的,默认为false/空 127 sanitize = { 128 # 各个Sanitizer开关 129 cfi = [boolean] # 控制流完整性检测 130 cfi_cross_dso = [boolean] # 开启跨so调用的控制流完整性检测 131 integer_overflow = [boolean] # 整数溢出检测 132 boundary_sanitize = [boolean] # 边界检测 133 ubsan = [boolean] # 部分ubsan选项 134 all_ubsan = [boolean] # 全量ubsan选项 135 ... 136 137 debug = [boolean] # 调测模式 138 blocklist = [string] # 屏蔽名单路径 139 } 140 141 remove_configs = [] 142 no_default_deps = [] 143 license_file = [] # 后缀名是.txt的文件 144 license_as_sources = [] 145 use_exceptions = [] 146} 147``` 148 149ohos_executable示例 150 151```shell 152import("//build/ohos.gni") 153ohos_executable("helloworld") { 154 configs = [] # 配置 155 part_name = "" # 部件名称 156 subsystem_name = "" # 子系统名称 157 deps = [] # 部件内模块依赖 158 159 external_deps = [ # 跨部件模块依赖定义, 160 "part_name:module_name", # 定义格式为 "部件名:模块名称" 161 ] # 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块。 162 ohos_test = [] 163 test_output_dir = [] 164 165 # Sanitizer配置,每项都是可选的,默认为false/空 166 sanitize = { 167 # 各个Sanitizer开关 168 cfi = [boolean] # 控制流完整性检测 169 cfi_cross_dso = [boolean] # 开启跨so调用的控制流完整性检测 170 integer_overflow = [boolean] # 整数溢出检测 171 boundary_sanitize = [boolean] # 边界检测 172 ubsan = [boolean] # 部分ubsan选项 173 all_ubsan = [boolean] # 全量ubsan选项 174 ... 175 176 debug = [boolean] # 调测模式 177 blocklist = [string] # 屏蔽名单路径 178 } 179 180 testonly = [boolean] 181 license_as_sources = [] 182 license_file = [] # 后缀名是.txt的文件 183 remove_configs = [] 184 static_link = [] 185 install_images = [] 186 module_install_dir = "" # 模块安装路径,从system/,vendor/后开始指定 187 relative_install_dir = "" 188 symlink_target_name = [] 189 output_dir = [directory] # 存放输出文件的目录 190 install_enable = [boolean] 191 version_script = [] 192 use_exceptions = [] 193} 194``` 195 196ohos_source_set示例 197 198```shell 199import("//build/ohos.gni") 200ohos_source_set("helloworld") { 201 sources = ["file"] # 后缀名是.c的相关文件 202 include_dirs = [] # 包含目录 203 configs = [] # 配置 204 public = [] # .h类型头文件 205 defines = [] 206 public_configs = [] 207 part_name = "" # 部件名称 208 subsystem_name = "" # 子系统名称 209 deps = [] # 部件内模块依赖 210 211 external_deps = [ # 跨部件模块依赖定义, 212 "part_name:module_name", # 定义格式为 "部件名:模块名称" 213 ] # 这里依赖的模块必须是依赖的部件声明在inner_kits中的模块 214 215 # Sanitizer配置,每项都是可选的,默认为false/空 216 sanitize = { 217 # 各个Sanitizer开关 218 cfi = [boolean] # 控制流完整性检测 219 cfi_cross_dso = [boolean] # 开启跨so调用的控制流完整性检测 220 integer_overflow = [boolean] # 整数溢出检测 221 boundary_sanitize = [boolean] # 边界检测 222 ubsan = [boolean] # 部分ubsan选项 223 all_ubsan = [boolean] # 全量ubsan选项 224 ... 225 226 debug = [boolean] # 调测模式 227 blocklist = [string] # 屏蔽名单路径 228 } 229 230 testonly = [boolean] 231 license_as_sources = [] 232 license_file = [] 233 remove_configs = [] 234 no_default_deps = [] 235 license_file = [] # 后缀名是.txt的文件 236 license_as_sources = [] 237 use_exceptions = [] 238} 239``` 240 241**注意**: 242 - 只有sources和part_name是必选,其他都是可选的; 243 - Sanitizer配置详见:[Sanitizer使用说明](subsys-build-reference.md#Sanitizer使用说明) 244 245### 预编译模板示例 246 247预编译模板的.gni相关文件路径在:openharmony/build/templates/cxx/prebuilt.gni。 248 249ohos_prebuilt_executable示例 250 251```shell 252import("//build/ohos.gni") 253ohos_prebuilt_executable("helloworld") { 254 source = "file" # 源 255 output = [] 256 install_enable = [boolean] 257 258 deps = [] # 部件内模块依赖 259 public_configs = [] 260 subsystem_name = "" # 子系统名 261 part_name = "" # 部件名 262 263 testonly = [boolean] 264 visibility = [] 265 266 install_images = [] 267 module_install_dir = "" # 模块安装路径,从system/,vendor/后开始指定 268 relative_install_dir = "" # 模块安装相对路径,相对于system/etc;如果有module_install_dir配置时,该配置不生效。 269 symlink_target_name = [] 270 271 272 license_file = [] # 后缀名是.txt的文件 273 license_as_sources = [] 274} 275``` 276 277ohos_prebuilt_shared_library示例 278 279```shell 280import("//build/ohos.gni") 281ohos_prebuilt_shared_library("helloworld") { 282 source = "file" # 一般是后缀为.so的文件 283 output = [] 284 install_enable = [boolean] 285 286 deps = [] # 部件内模块依赖 287 public_configs = [] 288 subsystem_name = "" # 子系统名 289 part_name = "" # 部件名 290 291 testonly = [boolean] 292 visibility = [] 293 294 install_images = [] 295 module_install_dir = "" # 模块安装路径,从system/,vendor/后开始指定 296 relative_install_dir = "" # 模块安装相对路径,相对于system/etc;如果有module_install_dir配置时,该配置不生效。 297 symlink_target_name = [string] 298 299 300 license_file = [string] # 后缀名是.txt的文件 301 license_as_sources = [] 302} 303``` 304 305ohos_prebuilt_static_library示例 306 307```shell 308import("//build/ohos.gni") 309ohos_prebuilt_static_library("helloworld") { 310 source = "file" # 一般是后缀为.so的文件 311 output = [] 312 313 deps = [] # 部件内模块依赖 314 public_configs = [] 315 subsystem_name = "" # 子系统名 316 part_name = "" # 部件名 317 318 testonly = [boolean] 319 visibility = [] 320 321 license_file = [string] # 后缀名是.txt的文件 322 license_as_sources = [] 323} 324``` 325 326**注意**:只有sources和part_name是必选,其他都是可选的。 327 328### Hap模板 329 330hap模板详见:[ HAP编译构建指导](subsys-build-gn-hap-compilation-guide.md) 331 332### Rust模板 333 334rust模板详见:[ Rust模块配置规则和指导](subsys-build-rust-compilation.md) 335 336### 其他常用模板 337 338ohos_prebuilt_etc示例: 339 340```shell 341import("//build/ohos.gni") 342ohos_prebuilt_etc("helloworld") { 343 # ohos_prebuilt_etc模板最常用属性: 344 source = "file" # 指定单个原文件 345 module_install_dir = "" # 模块安装路径,从system/,vendor/后开始指定 346 subsystem_name = "" # 子系统名 347 part_name = "" # 必选,所属部件名称 348 install_images = [] 349 relative_install_dir = "" # 模块安装相对路径,相对于system/etc;如果有module_install_dir配置时,该配置不生效。 350 351 # ohos_prebuilt_etc模板不常用属性: 352 deps = [] # 部件内模块依赖 353 testonly = [boolean] 354 visibility = [] 355 public_configs = [] 356 symlink_target_name = [string] 357 license_file = [string] 358 license_as_sources = [] 359} 360``` 361 362ohos_sa_profile示例: 363 364```shell 365import("//build/ohos.gni") 366ohos_sa_profile("helloworld") { 367 sources = [".xml"] # xml文件 368 part_name = "" # 部件名 369 subsystem_name = "" # 子系统名 370} 371``` 372 373**注意**:只有sources和part_name是必选,其他都是可选的。 374 375## 新增并编译模块 376 377新建模块可以分为以下三种情况。主要的添加逻辑如下面的流程图所示,若没有子系统则需新建子系统并在该子系统的部件下添加模块,若没有部件则需新建部件并在其中添加模块,否则直接在原有部件中添加模块即可,需要注意的是芯片解决方案作为特殊部件是没有对应子系统的。 378 379- 在原有部件中添加一个模块 380 381- 新建部件并在其中添加模块 382 383- 新建子系统并在该子系统的部件下添加模块 384 385  386 387**在原有部件中添加一个模块** 388 3891. 在模块目录下配置BUILD.gn,根据模板类型选择对应的gn模板。 390 3912. 修改bundle.json配置文件。 392 393 ```shell 394 { 395 "name": "@ohos/<component_name>", # HPM部件英文名称,格式"@组织/部件名称" 396 "description": "xxxxxxxxxxxxxxxxxxx", # 部件功能一句话描述 397 "version": "3.1", # 版本号,版本号与OpenHarmony版本号一致 398 "license": "MIT", # 部件License 399 "publishAs": "code-segment", # HPM包的发布方式,当前默认都为code-segment 400 "segment": { 401 "destPath": "third_party/nghttp2" 402 }, # 发布类型为code-segment时为必填项,定义发布类型code-segment的代码还原路径(源码路径)。 403 "dirs": {}, # HPM包的目录结构,字段必填内容可以留空 404 "scripts": {}, # HPM包定义需要执行的脚本,字段必填,值非必填 405 "licensePath": "COPYING", 406 "readmePath": { 407 "en": "README.rst" 408 }, 409 "component": { # 部件属性 410 "name": "<component_name>", # 部件名称 411 "subsystem": , # 部件所属子系统 412 "syscap": [], # 部件为应用提供的系统能力 413 "features": [], # 部件对外的可配置特性列表,一般与build中的sub_component对应,可供产品配置。 414 "adapted_system_type": [], # 轻量(mini)小型(small)和标准(standard),可以是多个 415 "rom": "xxxKB" # ROM基线,没有基线写当前值 416 "ram": "xxxKB", # RAM基线,没有基线写当前值 417 "deps": { 418 "components": [], # 部件依赖的其他部件 419 "third_party": [] # 部件依赖的三方开源软件 420 }, 421 422 "build": { # 编译相关配置 423 "sub_component": [ 424 "//foundation/arkui/napi:napi_packages", # 原有模块1 425 "//foundation/arkui/napi:napi_packages_ndk" # 原有模块2 426 "//foundation/arkui/napi:new" # 新增模块new 427 ], # 部件编译入口,模块在此处配置 428 "inner_kits": [], # 部件间接口 429 "test": [] # 部件测试用例编译入口 430 } 431 } 432 } 433 ``` 434 435 **注意**:无论哪种方式该bundle.json文件均在对应子系统所在文件夹下。 436 4373. 成功添加验证:编译完成后打包到image中去,生成对应的so文件或者二进制文件。 438 439**新建部件并在其中添加一个模块** 440 4411. 在模块目录下配置BUILD.gn,根据模板类型选择对应的gn模板。这一步与在原有部件中添加一个模块的方法基本一致,只需注意该模块对应BUILD.gn文件中的part_name为新建部件的名称即可。 442 4432. 新建一个bundle.json文件,bundle.json文件均在对应子系统所在文件夹下。 444 4453. 在vendor/{product_company}/{product-name}/config.json中添加对应的部件,直接添加到原有部件后即可。 446 447 ```shell 448 "subsystems": [ 449 { 450 "subsystem": "部件所属子系统名", 451 "components": [ 452 { "component": "部件名1", "features":[] }, # 子系统下的原有部件1 453 { "component": "部件名2", "features":[] }, # 子系统下的原有部件2 454 { "component": "部件名new", "features":[] } # 子系统下的新增部件new 455 ] 456 }, 457 . 458 ] 459 ``` 460 4614. 成功添加验证:编译完成后打包到image中去,生成对应的so文件或者二进制文件。 462 463 464**新建子系统并在该子系统的部件下添加模块** 465 4661. 在模块目录下配置BUILD.gn,根据模板类型选择对应的gn模板。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 467 4682. 在新建的子系统目录下每个部件对应的文件夹下创建bundle.json文件,定义部件信息。这一步与新建部件并在其中添加模块中对应的步骤并无区别。 469 4703. 修改build目录下的subsystem_config.json文件。 471 472 ```shell 473 { 474 "子系统名1": { # 原有子系统1 475 "path": "子系统目录1", 476 "name": "子系统名1" 477 }, 478 "子系统名2": { # 原有子系统2 479 "path": "子系统目录2", 480 "name": "子系统名2" 481 }, 482 "子系统名new": { # 新增子系统new 483 "path": "子系统目录new", 484 "name": "子系统名new" 485 }, 486 487 } 488 ``` 489 490 该文件定义了有哪些子系统以及这些子系统所在文件夹路径,添加子系统时需要说明子系统path与name,分别表示子系统路径和子系统名。 491 4924. 在vendor/{product_company}/{product-name}目录下的产品配置如product-name是hispark_taurus_standard时,在config.json中添加对应的部件,直接添加到原有部件后即可。 493 494 ```shell 495 "subsystems": [ 496 { 497 "subsystem": "arkui", # 原有的子系统名 498 "components": [ # 单个子系统下的所有部件集合 499 { 500 "component": "ace_engine_standard", # 原有的部件名 501 "features": [] 502 }, 503 { 504 "component": "napi", # 原有的部件名 505 "features": [] 506 } 507 { 508 "component": "component_new1", # 原有子系统新增的的部件名component_new1 509 "features": [] 510 } 511 ] 512 }, 513 { 514 "subsystem": "subsystem_new", # 新增的子系统名 515 "components": [ 516 { 517 "component": "component_new2", # 新增子系统新增的的部件名component_new2 518 "features": [] 519 } 520 ] 521 }, 522 523 ] 524 ``` 525 5264. 成功添加验证:编译完成后打包到image中去,生成对应的so文件或者二进制文件。 527 528 529**编译模块** 530 531主要有两种编译方式,[命令行方式和hb方式](subsys-build-all.md#编译命令),这里以命令行方式为例。 532 533 模块可以使用“--build-target 模块名"单独编译,编译命令如下: 534 535 ```shell 536 ./build.sh --build-target 模块名 537 ``` 538 539 也可以编译相应产品,以编译hispark_taurus_standard为例,编译命令如下: 540 541 ```shell 542 ./build.sh --product-name hispark_taurus_standard --build-target 模块名 --ccache 543 ``` 544 545 还可以编译模块所在的部件: 546 547 ```shell 548 ./build.sh --product-name hispark_taurus_standard --build-target musl --build-target 模块名 --ccache 549 ``` 550