# 部件编译构建规范 ## å‰è¨€ ### 目的 编译构建是部件化设计è½åœ°çš„切入点,一个优秀的部件在编译æ€åº”该具备å¯ç»´æŠ¤ã€å¯ç§»æ¤ã€ä½Žè€¦åˆçš„特å¾ã€‚本规范用于引导部件开å‘人员编写符åˆéƒ¨ä»¶åŒ–设计的编译脚本,使得部件在编译æ€ä¾èµ–åˆç†ã€å¯é…ç½®ã€å¯å¤ç”¨ã€å¯è£å‰ªã€‚ ### 基本概念 **部件** 部件是OpenHarmony系统能力的基本å•å…ƒï¼Œä»¥æºç 为划分ä¾æ®ï¼Œå…·æœ‰ç‹¬ç«‹çš„仓和目录,在ä¸åŒçš„设备上å¯å®žä¾‹åŒ–为ä¸åŒçš„库或二进制文件。 **特性** 部件特性为编译æ€å¯é…置的编译选项,å¯ä¾›äº§å“在编译时按需é…置。ä¸åŒçš„特性é…置,编译出部件的ä¸åŒå½¢æ€ï¼Œä½¿å¾—部件å¯ä»¥é€‚应ä¸åŒå½¢æ€äº§å“的差异化需求。部件特性的é…ç½®åªå½±å“部件内部功能的实现差异,ä¸èƒ½å½±å“部件的Public API(部件对应用æ供的接å£ï¼‰ä»¥åŠinner api(部件间的接å£ï¼‰ã€‚ **ä¾èµ–** 在编译æ€ï¼Œéƒ¨ä»¶çš„ä¾èµ–分为: - 有æ¡ä»¶ä¾èµ–:在特定场景下å¯è£å‰ªçš„ä¾èµ–,有æ¡ä»¶çš„ä¾èµ–è£å‰ªåŽä¸å½±å“部件的Public API å’Œinner api。比如音频对è“牙的ä¾èµ–。 - 强ä¾èµ–:部件间åˆç†çš„å¿…è¦çš„ä¾èµ–,ä¸å¯è£å‰ªã€‚比如syscap部件对安全库函数的ä¾èµ–。 ### 总体原则 部件编译构建应éµå¾ªä»¥ä¸‹å‡ 个原则: **独立自治** 部件编译æ€åº”内èšï¼Œæ–°å¢žå¤–部ä¾èµ–时应慎é‡ï¼Œå°½é‡å‡å°‘编译时的é™æ€ä¾èµ–。 **åˆç†ä¾èµ–** 部件间的ä¾èµ–都应基于部件间的接å£ï¼Œç¦æ¢ä¾èµ–其他部件内部的模å—和头文件。 **产å“æ— å…³** 部件在编译æ€åº”是多产å“通用的,ç¦æ¢åœ¨ç¼–译脚本ä¸ä½¿ç”¨äº§å“å称。 ### 约定 **规则:** å¿…é¡»éµå®ˆçš„约定。 **建议:** å¿…é¡»åŠ ä»¥è€ƒè™‘çš„çº¦å®šã€‚ ### 看护手段 为了维护部件编译构建规范,门ç¦ä¼šå¯¹æž„建é…置文件åšä¸€äº›æ£€æŸ¥ã€‚ 预编译检查:指在预编译阶段进行检查,检测到错误将报错并åœæ¢ç¼–译。 é™æ€æ£€æŸ¥ï¼šæŒ‡æ£€æŸ¥å·¥å…·å¯¹é…置文件进行扫æ检查,éžç¼–译手段。 ### 例外 在ä¸è¿èƒŒæ€»ä½“原则,ç»è¿‡å……分考虑,有充足的ç†ç”±çš„å‰æ下,å¯ä»¥é€‚当è¿èƒŒè§„范ä¸çº¦å®šã€‚ ä¾‹å¤–ç ´å了代ç 的一致性,请尽é‡é¿å…。“规则â€çš„例外应该是æžå°‘的。 ## 命å 编译脚本ä¸çš„å˜é‡ã€ç¼–è¯‘ç›®æ ‡ï¼ˆtarget)ã€æ¨¡æ¿ï¼Œgni文件,以åŠéƒ¨ä»¶æ述文件ä¸çš„对象和数æ®çš„命åéƒ½åº”é‡‡ç”¨å†…æ ¸é£Žæ ¼ï¼ˆunix_like),å•è¯å…¨å°å†™ï¼Œç”¨ä¸‹åˆ’线分割。如:"startup_init"。 ### 规则1.1 部件åæ ¼å¼é¡»ç»Ÿä¸€ - åè¯å½¢å¼ï¼Œéœ€ä½“现部件的功能。 - 在系统内全局唯一。 - ä¸è¶…过63个有效英文å—符。 - 使用å°å†™åŠ ä¸‹åˆ’çº¿çš„å†…æ ¸é£Žæ ¼å‘½å,例如:unix_like。 > **例外:** 三方开æºè½¯ä»¶çš„使用对应社区的原生命åæ–¹å¼ï¼Œæ¯”如:cJson。 ### 规则1.2 特性å为部件åå‰ç¼€+特性å称 特性是部件声明的å¯é…ç½®çš„ç¼–è¯‘é€‰é¡¹ï¼ŒåŠ ä¸Šéƒ¨ä»¶åå‰ç¼€å¯é¿å…系统内特性é‡å。示例: ```py declare_args() { dsoftbus_conn_p2p = true # dsoftbus 为部件å, conn_p2p 为特性å称 dsoftbus_conn_ble = false # dsoftbus 为部件å, conn_ble 为特性å称 } ``` 看护手段:预编译检查 ### 建议1.1 ç¼–è¯‘ç›®æ ‡å以部件å为å‰ç¼€+模å—å称 一个部件å¯èƒ½æœ‰å¤šä¸ªç¼–è¯‘ç›®æ ‡ï¼ˆå³æ¨¡å—),以“{部件å}_{模å—å}â€çš„æ–¹å¼å‘½åå¯ä»¥æ ¹æ®ç¼–译产物(库ã€å¯æ‰§è¡Œæ–‡ä»¶ï¼‰å¿«é€Ÿå®šä½å½’属部件和é¿å…é‡å。 å例: ```py ohos_shared_library("data") # Bad: ä¸ç²¾ç¡®ï¼Œè¿‡äºŽé€šç”¨ï¼Œç³»ç»Ÿå†…易é‡å ``` æ£ä¾‹ï¼š ```py ohos_shared_library("cellular_data_napi") # Good ``` ## æ述文件 bundle.json是定义部件的æ述文件,包å«äº†éƒ¨ä»¶çš„æ ¹ç›®å½•ã€å称ã€åŠŸèƒ½æè¿°ã€ç‰ˆæœ¬å·ã€æŽ¥å£å®šä¹‰å’Œç¼–译入å£ç‰ä¿¡æ¯ï¼Œé¡»ä¿è¯å…¶å‡†ç¡®æ€§ã€‚ ### 规则2.1 部件æ述文件ä¸å—段须准确 | å—段 | 类型 | 看护手段 | |---|---|---| |name|string。部件的HPM(OpenHarmony包管ç†å™¨ï¼‰åŒ…å称,必填。命å规则:@{organization}/{component_name}。"component_name"为部件的å称,须满足规则1.1。|é™æ€æ£€æŸ¥| |version|string。部件版本å·ï¼Œå¿…填,命åå’Œå‡çº§è·ŸéšOpenHarmony版本å·ã€‚|é™æ€æ£€æŸ¥| |destPath|string。部件æºç çš„æ ¹ç›®å½•ï¼Œå¿…å¡«ã€‚éƒ¨ä»¶çš„æ ¹ç›®å½•é¡»ç‹¬ç«‹å”¯ä¸€ï¼Œä¸å…许å˜åœ¨å¤šä¸ªæ ¹ç›®å½•ã€‚|é™æ€æ£€æŸ¥| |component:name|string。部件å,必填。须满足规则1.1。|é™æ€æ£€æŸ¥| |component:subsystem|string。部件归属的å系统å称,必填,å系统å为å°å†™è‹±æ–‡å—æ¯ç»„åˆã€ä¸ä½¿ç”¨ä¸‹åˆ’线。|é™æ€æ£€æŸ¥| |component:syscap|string list。系统能力的æ述,å¯é€‰ã€‚命å规则:大驼峰,"SystemCapability.Subsystem.部件能力.å能力(å¯é€‰ï¼‰",如`SystemCapability.Media.Camera`,`SystemCapability.Media.Camera.Front`。|é™æ€æ£€æŸ¥| |component:features|string list,部件å¯é…置的特性,å¯é€‰ï¼Œå‘½å须满足规则1.2。|é™æ€æ£€æŸ¥| |component:adapted_system_type|string list。部件适用的系统类型,必填,值为`mini`ã€`small`å’Œ`standard`,å¯åŒæ—¶æ”¯æŒå¤šç§ã€‚|é™æ€æ£€æŸ¥| |component:rom|string。ROM基线值,必填,å•ä½é»˜è®¤ä¸ºKByte。|é™æ€æ£€æŸ¥| |component:ram|string。RAM基线值,必填,å•ä½é»˜è®¤ä¸ºKByte。|é™æ€æ£€æŸ¥| |component:deps|string list。deps对象æ述了部件的外部ä¾èµ–,必填,包括其他部件和三方开æºè½¯ä»¶ï¼Œåº”该与部件编译脚本ä¸ä¾èµ–一致。|预编译检查| ### 建议2.1 部件的æ述文件应å˜æ”¾åœ¨éƒ¨ä»¶æ ¹ç›®å½•ä¸‹ 部件目录是独立的,应将bundle.json文件å˜æ”¾åˆ°éƒ¨ä»¶æ ¹ç›®å½•ä¸‹ã€‚ ## å˜é‡ ç¼–è¯‘ç›®æ ‡ï¼ˆtarget)的内置å˜é‡èµ‹å€¼å†³å®šäº†ç¼–译内容ã€ä¾èµ–和打包ç‰ä¿¡æ¯ï¼Œä¸Žå®žçŽ°éƒ¨ä»¶åŒ–设计强相关。 ### 规则3.1 部件编译脚本ä¸åªå…许引用本部件的路径,ç¦æ¢å¼•ç”¨å…¶ä»–部件的ç»å¯¹æˆ–相对路径 部件间的ä¾èµ–都必须使用"externel_deps"ï¼Œéƒ¨ä»¶ç¼–è¯‘ç›®æ ‡çš„å˜é‡sourcesã€include_dirsã€configsã€public_configsã€depsã€public_deps引用其他部件的相对和ç»å¯¹è·¯å¾„属于éžæ³•å¼•å…¥ä¾èµ–: - sources sourcesåªå…许包å«æœ¬éƒ¨ä»¶çš„æºç ,包å«å…¶ä»–部件的æºç ç ´å了部件æºç 目录独立的原则。 - include_dirs include_dirsåªå…许引用本部件的头文件æœç´¢è·¯å¾„,编译å•å…ƒå¯¹å…¶ä»–部件的接å£çš„ä¾èµ–都通过externel_deps自动导入。 - configs configsåªå…许引用本部件的é…置路径,引用其他部件的configså¯èƒ½ä¼šå¼•å…¥æŽ¥å£ä¾èµ–。 - pulic_configs pulic_configsåªå…许引用本部件的é…置路径,引用其他部件的configså¯èƒ½ä¼šå¼•å…¥æŽ¥å£ä¾èµ–。 - deps depsåªå…许用于部件内模å—çš„ä¾èµ–,直接引用其他部件的模å—å¯èƒ½ä¼šå¯¼è‡´ä¾èµ–其他部件的内部模å—和接å£ã€‚ 例: base/foos/foo_a/BUILD.gn ```py deps = [ "//base/foo/foo_b:b" ] # Bad, ç»å¯¹è·¯å¾„ä¾èµ–其他部件 deps = [ "../../foo_b:b" ] # Bad, 相对路径ä¾èµ–其他部件 deps = [ "a" ] # Good, ä¾èµ–当å‰éƒ¨ä»¶å†…çš„å…¶ä»–æ¨¡å— ``` > **例外:** 对三方开æºè½¯ä»¶çš„引用除外。 - public_deps public_depsåªå…许用于部件内模å—çš„ä¾èµ–,直接引用其他部件的模å—å¯èƒ½ä¼šå¯¼è‡´ä¾èµ–其他部件的内部模å—和接å£ã€‚ > **例外:** 对三方开æºè½¯ä»¶çš„引用除外。 看护手段:é™æ€æ£€æŸ¥ ### 规则3.2 éƒ¨ä»¶ç¼–è¯‘ç›®æ ‡å¿…é¡»æŒ‡å®šéƒ¨ä»¶å’Œå系统å 部件的编译å•å…ƒohos_shared_libraryã€ohos_static_libraryã€ohos_executable_libraryã€ohos_source_set都必须指定"part_name"å’Œ"subsystem_name"。 以developtools/syscap_codec/BUILD.gnçš„ohos_shared_library编译å•å…ƒä¸ºä¾‹ï¼š ```py ohos_shared_library("syscap_interface_shared") { include_dirs = [ "include", "src", ] public_configs = [ ":syscap_interface_public_config" ] sources = [ "./interfaces/inner_api/syscap_interface.c", "./src/endian_internal.c", "./src/syscap_tool.c", ] deps = [ "//third_party/bounds_checking_function:libsec_static", "//third_party/cJSON:cjson_static", ] subsystem_name = "developtools" # 必须指定subsystem_name part_name = "syscap_codec" # 必须指定part_name } ``` 看护手段:é™æ€æ£€æŸ¥ ### 建议3.1 部件内部的引用使用相对路径 部件内的引用使用相对路径的优点: - è„šæœ¬æ›´ç®€æ´ - éƒ¨ä»¶çš„ç¼–è¯‘è„šæœ¬ä¸Žéƒ¨ä»¶çš„æ ¹ç›®å½•è§£è€¦ã€‚ 例: base/foos/foo_a/BUILD.gn ```py include_dirs = [ "./include", # Good, 相对路径引用 "//base/foo/foo_a/include" # Bad, ç»å¯¹è·¯å¾„引用 ] deps = [ "sub_module:foo", # Good, 相对路径引用 "base/foo/foo_a/sub_moudule:foo" # Bad, ç»å¯¹è·¯å¾„引用 ] ``` 看护手段:é™æ€æ£€æŸ¥ ### 建议3.2 部件内部模å—çš„å¯è§åº¦è®¾ç½®ä¸ºéƒ¨ä»¶å†…å¯è§ 部件内部的模å—应使用`"visibility"`å—æ®µæ ‡è¯†ï¼Œé˜²æ¢è¢«å…¶ä»–部件ä¾èµ–。示例: base/foos/foo_a/BUILD.gn ```py ohos_shared_library("foo_a") { visibility = [ "./*" ] # foo_aåªåœ¨base/foo/foo_aåŠå…¶å目录下å¯è§ } ohos_shared_library("foo_a") { visibility = [ ":*" ] # foo_aåªåœ¨æœ¬BUILD.gnå¯è§ } ``` ## 其他 ### 规则4.1 部件编译脚本ä¸ç¦æ¢ä½¿ç”¨äº§å“å称å˜é‡ 部件是通用的系统能力,与特定产å“æ— å…³ã€‚ç¼–è¯‘è„šæœ¬ä¸ä½¿ç”¨äº§å“å称,将导致部件功能与产å“绑定,ä¸å…·å¤‡é€šç”¨æ€§ã€‚部件ä¸åŒäº§å“å½¢æ€ä¸Šçš„差异应抽象为特性或者è¿è¡Œæ—¶çš„æ’件。 > **例外:** vendorå’Œdevice目录下三方厂商部件的编译脚本例外。 看护手段:é™æ€æ£€æŸ¥ ### 建议4.1 é¿å…import其他部件目录下的gni文件 部件内的gni文件用于声明部件内部编译å˜é‡å’Œæ¨¡æ¿ï¼Œimport其他部件的gni文件ç‰åŒäºŽä½¿ç”¨å…¶ä»–部件内部的å˜é‡å’Œæ¨¡æ¿ï¼Œå³å¼•å…¥å¯¹å…¶ä»–部件的ä¾èµ–。影å“多个部件的å˜é‡ã€args和模æ¿åº”定义在编译框架的gni文件ä¸ã€‚ > **例外:** build目录下编译框架定义全局的编译选项的gniå¯ä»¥è¢«æ‰€æœ‰éƒ¨ä»¶import。 看护手段:é™æ€æ£€æŸ¥ ### 建议4.2 部件使用统一的编译å•å…ƒæ¨¡æ¿ è½»é‡ã€å°åž‹å’Œæ ‡å‡†çš„系统的编译å•å…ƒéƒ½åº”使用ohos定义的模æ¿ï¼Œæ¯”如`ohos_shared_library`ã€`ohos_static_library`ã€`ohos_executable`ã€`ohos_source_set`ç‰ä»¥"ohos_"为å‰ç¼€çš„模æ¿ã€‚ 例如: ```py executable("foundation") { # Bad, ä¸æŽ¨èä½¿ç”¨å†…ç½®çš„æ¨¡æ¿ ... } ohos_executable("foundation") { # Good, 推è使用ohoså®šåˆ¶æ¨¡æ¿ ... } ```