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