OpenHarmony源碼解析之編譯構(gòu)建

前言

OpenHarmony是由開放原子開源基金會(OpenAtom Foundation)孵化及運營的開源項目,目標是面向全場景被啼、全連接帜消、全智能時代、基于開源的方式浓体,搭建一個智能終端設(shè)備操作系統(tǒng)的框架和平臺泡挺,促進萬物互聯(lián)產(chǎn)業(yè)的繁榮發(fā)展。最近在學習OpenHarmony源代碼命浴,個人認為學習有三個階段粘衬,分別是看、實操咳促、寫(歸納總結(jié))稚新,本著追求學習的終極目標,因此有了這篇文章跪腹。

一褂删、OpenHarmony編譯框架特點

OpenHarmony編譯框架是基于模塊化的,從大到小依次劃分為產(chǎn)品冲茸、子系統(tǒng)集(或領(lǐng)域)屯阀、子系統(tǒng)缅帘、部件、模塊难衰、特性钦无。這種模塊化的樹狀編譯框架,非常方便根據(jù)目標產(chǎn)品硬件資源的大小進行靈活的裁剪盖袭,從而實現(xiàn)“統(tǒng)一OS失暂,彈性部署”的目標。

1.產(chǎn)品(product)
產(chǎn)品是基于解決方案為基于開發(fā)板的完整產(chǎn)品鳄虱,主要包含產(chǎn)品對OS的適配弟塞、部件拼裝配置、啟動配置和文件系統(tǒng)配置等拙已。build.sh編譯的時候通過--product-name編譯選項指定决记;hb編譯的時候通過hb set進行設(shè)置。

#適用于標準(即L2或standard)系統(tǒng)編譯
./build.sh --product-name rk3568 --ccache

cd build #進入源碼下build目錄
hb set   #執(zhí)行hb set命令倍踪,選擇對應(yīng)的產(chǎn)品名稱
hb build #執(zhí)行hb build命令系宫,進行編譯

2.子系統(tǒng)集(domain)
OpenHarmony技術(shù)架構(gòu)中有四大子系統(tǒng)集:“系統(tǒng)基本能力子系統(tǒng)集”、“基礎(chǔ)軟件服務(wù)子系統(tǒng)集”建车、“增強軟件服務(wù)子系統(tǒng)集”笙瑟、“硬件服務(wù)子系統(tǒng)集”。四大子系統(tǒng)不會直接出現(xiàn)在編譯選項或者參數(shù)中癞志,而是有對應(yīng)的一級源代碼文件夾:“系統(tǒng)基本能力子系統(tǒng)集”對應(yīng)源碼foundation文件夾往枷;“基礎(chǔ)軟件服務(wù)子系統(tǒng)集”和“硬件服務(wù)子系統(tǒng)集”對應(yīng)源碼base文件夾;“增強軟件服務(wù)子系統(tǒng)集”對應(yīng)源碼domains文件夾凄杯。

.
├── applications //應(yīng)用程序
├── arkcompiler  //ark編譯器
├── base         //“基礎(chǔ)軟件服務(wù)子系統(tǒng)集”和“硬件服務(wù)子系統(tǒng)集”
├── build        //編譯目錄
├── build.py -> build/lite/build.py //軟鏈接
├── build.sh -> build/build_scripts/build.sh //軟鏈接错洁,標準系統(tǒng)編譯入口
├── commonlibrary  //通用庫
├── developtools   //開發(fā)工具
├── device         //芯片相關(guān)
├── docs           //文檔md文件目錄
├── drivers        //驅(qū)動文件
├── foundation     //“系統(tǒng)基本能力子系統(tǒng)集”
├── ide            //ide
├── interface      //接口
├── kernel         //內(nèi)核,liteos-m戒突,liteos-a屯碴,linux,uniproton
├── napi_generator //native api相關(guān)
├── prebuilts      //編譯工具路徑
├── productdefine  //產(chǎn)品定義
├── qemu-run -> vendor/ohemu/common/qemu-run //qemu模擬器運行腳本
├── test           //測試用例
├── third_party    //三方庫
└── vendor         //產(chǎn)品

3.子系統(tǒng)(subsystem)
子系統(tǒng)是一個邏輯概念膊存,它具體由對應(yīng)的部件構(gòu)成导而。在多設(shè)備部署場景下,支持根據(jù)實際需求裁剪某些非必要的子系統(tǒng)或部件隔崎。在build/subsystem_config.json中定義今艺。

{
  "arkui": {
    "path": "foundation/arkui", //子系統(tǒng)源碼路徑
    "name": "arkui"             //子系統(tǒng)名稱
  },
  "ai": {
    "path": "foundation/ai",
    "name": "ai"
  },
  "distributeddatamgr": {
    "path": "foundation/distributeddatamgr",
    "name": "distributeddatamgr"
  },
  "security": {
    "path": "base/security",
    "name": "security"
  },
  "startup": {
    "path": "base/startup",
    "name": "startup"
  },
  "hiviewdfx": {
    "path": "base/hiviewdfx",
    "name": "hiviewdfx"
  },
  "kernel": {
    "path": "kernel",
    "name": "kernel"
  },
  "thirdparty": {
    "path": "third_party",
    "name": "thirdparty"
  }
  ...
}

** 4.部件(component)**
部件對子系統(tǒng)的進一步拆分,可復用的軟件單元爵卒,它包含源碼虚缎、配置文件、資源文件和編譯腳本钓株;能獨立構(gòu)建实牡,以二進制方式集成陌僵,具備獨立驗證能力的二進制單元。部件由對應(yīng)源碼文件夾下的bundle.json文件進行定義创坞。以napi部件為例foundation/arkui/napi/bundle.json

{
    "name": "@ohos/napi",
    "description": "Node-API (formerly N-API) is an API for build native Addons",
    "version": "3.1",
    "license": "Apache 2.0",
    "publishAs": "code-segment",
    "segment": {
        "destPath": "foundation/arkui/napi"
    },
    "dirs": {},
    "scripts": {},
    "component": {
        "name": "napi",       //部件名稱
        "subsystem": "arkui", //所屬子系統(tǒng)
        "syscap": [
            "SystemCapability.ArkUI.ArkUI.Napi",
            "SystemCapability.ArkUI.ArkUI.Libuv"
        ],
        "features": ["napi_enable_container_scope"], //部件特性
        "adapted_system_type": [
            "standard"
        ],
        "rom": "5120KB", //部件rom大小
        "ram": "10240KB",//部件ram大小
        "deps": {        //部件依賴
            "components": [ //部件依賴的部件
                "hiviewdfx_hilog_native",
                "hilog"
            ],
            "third_party": [//部件依賴的三方庫
                "jerryscript",
                "libuv",
                "node",
                "bounds_checking_function",
                "v8"
            ]
        },
        "build": {
            "group_type": {
                "base_group": [
                    "http://foundation/arkui/napi:napi_packages",
                    "http://foundation/arkui/napi:napi_packages_ndk"
                ],
                "fwk_group": [],
                "service_group": []
            },
            "inner_kits": [//部件對外暴露的接口碗短,用于其它部件或者模塊進行引用
                {
                    "header": {
                      "header_base": "http://foundation/arkui/napi/interfaces/kits",
                      "header_files": [
                          "napi/native_api.h"
                      ]
                    },
                    "name": "http://foundation/arkui/napi:ace_napi"
                  },
                  {
                    "header": {
                      "header_base": "http://foundation/arkui/napi/interfaces/inner_api",
                      "header_files": [
                          "napi/native_common.h",
                          "napi/native_node_api.h"
                      ]
                    },
                    "name": "http://foundation/arkui/napi:ace_napi"
                  },
                  {
                    "header": {
                      "header_base": "http://foundation/arkui/ace_engine/frameworks/core/common/",
                      "header_files": [
                          "container_scope.h"
                      ]
                    },
                    "name": "http://foundation/arkui/napi:ace_container_scope"
                  }
            ],
            "test": [
                "http://foundation/arkui/napi:napi_packages_test",
                "http://foundation/arkui/napi/sample/native_module_systemtest:systemtest",
                "http://foundation/arkui/napi/test/unittest:unittest"
            ]
        }
    }
}

5.模塊(module)
模塊就是編譯子系統(tǒng)的一個編譯目標,部件也可以是編譯目標题涨。模塊屬于哪個部件偎谁,在gn文件中由part_name指定。

ohos_shared_library("ace_napi") { //ace_napi為模塊名携栋,同時也是編譯目標
    deps = [ ":ace_napi_static" ] //模塊的依賴搭盾,被依賴的對象即使沒有被subsystem顯式包含咳秉,也會被編譯
    public_configs = [ ":ace_napi_config" ] //模塊配置參數(shù)婉支,比如cflag
    if (!is_cross_platform_build) {
        public_deps = [ "http://third_party/libuv:uv" ]
    }
    subsystem_name = "arkui" //模塊所屬部件所屬子系統(tǒng)名稱
    part_name = "napi"       //模塊所屬部件名稱,一個模塊只能屬于一個部件
}

6.特性(feature)
特性是部件用于體現(xiàn)不同產(chǎn)品之間的差異澜建。通常不同特性可以定義不同編譯宏或者代碼向挖,從而影響到源代碼中define的特性。
vender/hihope/rk3568_mini_system/config.json

ohos_shared_library("ace_napi") { //ace_napi為模塊名炕舵,同時也是編譯目標
    deps = [ ":ace_napi_static" ] //模塊的依賴何之,被依賴的對象即使沒有被subsystem顯式包含,也會被編譯
    public_configs = [ ":ace_napi_config" ] //模塊配置參數(shù)咽筋,比如cflag
    if (!is_cross_platform_build) {
        public_deps = [ "http://third_party/libuv:uv" ]
    }
    subsystem_name = "arkui" //模塊所屬部件所屬子系統(tǒng)名稱
    part_name = "napi"       //模塊所屬部件名稱溶推,一個模塊只能屬于一個部件
}

foundation/communication/dsoftbus/bundle.json

{
  "name": "@openharmony/dsoftbus",
  "version": "3.1.0",
  "description": "dsoftbus",
  ...
  "component": {
     "name": "dsoftbus",
     "subsystem": "communication",
     "adapted_system_type": [
     "mini",
    "small",
     "standard"
  ],

  "features": [
    "dsoftbus_feature_conn_p2p",
    "dsoftbus_feature_disc_ble",
    "dsoftbus_feature_conn_br",
    "dsoftbus_feature_conn_ble",
    "dsoftbus_feature_lnn_net",
    "dsoftbus_feature_trans_udp_stream",
    "dsoftbus_feature_trans_udp_file",
    "dsoftbus_get_devicename",
    "dsoftbus_feature_product_config_path",
    "dsoftbus_feature_ifname_prefix",
    "dsoftbus_feature_lnn_wifiservice_dependence",
    "dsoftbus_standard_feature_dfinder_support_multi_nif",
    "dsoftbus_feature_protocol_newip"
  ],
},

foundation/communication/dsoftbus/core/adapter/core_adapter.gni

if (dsoftbus_get_devicename == false) {//特性取值不同,影響編譯不同代碼
  bus_center_core_adapter_src += [ "$dsoftbus_root_path/core/adapter/bus_center/src/lnn_settingdata_event_monitor_virtual.cpp" ]
  bus_center_core_adapter_inc +=[ "$dsoftbus_root_path/core/adapter/bus_center/include" ]
  bus_center_core_adapter_deps += []
} else {
  bus_center_core_adapter_src += ["$dsoftbus_root_path/core/adapter/bus_center/src/lnn_settingdata_event_monitor.cpp","$dsoftbus_root_path/core/adapter/bus_center/src/lnn_ohos_account.cpp",]
  bus_center_core_adapter_inc += ["$dsoftbus_root_path/adapter/common/bus_center/include","$dsoftbus_root_path/core/adapter/bus_center/include","http://foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb/include","http://foundation/distributeddatamgr/relational_store/interfaces/inner_api/dataability/include","http://base/account/os_account/interfaces/innerkits/ohosaccount/native/include/",]
  bus_center_core_adapter_deps += ["${ability_base_path}:want","${ability_base_path}:zuri","${ability_runtime_inner_api_path}/dataobs_manager:dataobs_manager","${ability_runtime_path}/frameworks/native/ability/native:abilitykit_native","http://base/account/os_account/frameworks/ohosaccount/native:libaccountkits","http://base/account/os_account/frameworks/osaccount/native:os_account_innerkits","http://foundation/distributeddatamgr/data_share/interfaces/inner_api:datashare_consumer","http://foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common","http://foundation/distributeddatamgr/relational_store/interfaces/inner_api/dataability:native_dataability","http://foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb",]
}

7.各部分關(guān)系
一個產(chǎn)品(product) 可以包含 1~n個子系統(tǒng)(subsystem)奸攻,一個子系統(tǒng)可以包含1~n個部件(component)蒜危,一個**部件**可以包含1~n個模塊(module),不同產(chǎn)品的中的相同部件可以編譯不同的特性(feature)睹耐,子系統(tǒng)集(domain)在源代碼一級根目錄有體現(xiàn)辐赞。

二、OpenHarmony構(gòu)建工具介紹

OpenHarmony構(gòu)建工具由shell腳本硝训、python腳本响委、gn、ninjia窖梁、clang/llvm等構(gòu)成赘风。GN is “Generate Ninja” 一個用來生成.ninja 的工具,直接編寫.ninja文件難度較大纵刘,且非常乏味贝次。Ninja 原意是忍者的意思,它是一個專注于速度的小型構(gòu)建工具彰导,利用gn生成的.ninja文件作為輸入蛔翅。clang/llvm執(zhí)行真正的編譯和鏈接工作敲茄,clang負責編譯前端,llvm負責編譯優(yōu)化和后端(通常編譯工具分前端山析、優(yōu)化堰燎、后端)。 GN的語法相對比較簡單笋轨,有點面向?qū)ο缶幊陶Z言的思想秆剪;Ninja號稱比make編譯速度更快,推測原因make編譯過程有大量的延時變量和預(yù)置變量爵政,需要在編譯過程進行推導其值仅讽,因此需要消耗大量cpu資源進行計算,形如$@钾挟,$^洁灵,$<,$\*掺出,$徽千?。補充一點:每個.c 和.c++文件是獨立編譯的汤锨,編譯過程彼此之間并不進行通信双抽,因此可進行并行編譯。編譯和鏈接過程及常見的問題如何解決闲礼,后續(xù)單獨出一期牍汹,此處先挖個坑。

三柬泽、OpenHarmony構(gòu)建過程

Openharmony完整的編譯構(gòu)建流程主要可以分成以下五個大階段:Preloder慎菲、Loader、GN聂抢、Ninja钧嘶、Post build。Preloader和Loader階段主要是執(zhí)行python腳本preloader.py和loader.py琳疏,Preloader階段根據(jù)vendor倉的產(chǎn)品配置config.json文件對產(chǎn)品配置進行解析有决,并將解析結(jié)果輸出到out/preloader/{product_name}目錄下;Loader階段進行部件化配置的加載空盼,將部件的編譯gn文件书幕,并將解析結(jié)果輸出到out/{product_name}/build_configs文件夾下。GN階段以.gn和.gni文件作為輸入揽趾,通過GN工具生成.ninja文件台汇,輸出到out/{product_name}/obj目錄下。Ninja階段以.ninja文件作為輸入,通過Ninja工具生調(diào)用clang/llvm編譯工具鏈編譯生成目標苟呐,如靜態(tài)庫out/{product_name}/obj目錄下痒芝,共享庫out/{product_name}/ {part_name}目錄下,可執(zhí)行程序牵素。又可以分為10個小階段:prebuild严衬、preload、load笆呆、pre_target_generate请琳、target_generate、post_target_generate赠幕、pre_target_compilation俄精、target_compilation、post_target_compilation榕堰、post_build竖慧。

hb/modules/interface/build_module_interface.py

     def run(self):
         try:
             self._prebuild()
             self._preload()
             self._load()
             self._pre_target_generate()
             self._target_generate()
             self._post_target_generate()
             self._pre_target_compilation()
             self._target_compilation()
         except OHOSException as exception:
                      raise exception
         else:
             self._post_target_compilation()
         finally:
             self._post_build()

四、OpenHarmony構(gòu)建過程逆向分析

存儲中的鏡像(如flash或emmc)一般由芯片廠家提供的燒錄工具或者產(chǎn)線生產(chǎn)過程通過專用編程器寫入相應(yīng)分區(qū)局冰。OpenHarmony編譯完成后鏡像img文件所在的目錄out/{product_name}/package/phone/image测蘑。鏡像img文件一般由打包工具按照一定的規(guī)則將輸入文件夾(含文件夾目錄層級)和文件夾下所有文件(如庫文件灌危、可執(zhí)行文件康二、配置文件、啟動腳本文件)整體打包而成勇蝙,打包過程需要考慮文件系統(tǒng)格式沫勿,在產(chǎn)品啟動過程中會使用mount進行掛載,因此需要考慮文件夾和文件的層級關(guān)系及文件夾味混、庫文件产雹、可執(zhí)行文件、配置文件翁锡、啟動腳本文件的權(quán)限蔓挖。這些文件夾、文件從何而來馆衔?文件夾直接在宿主機采用mkdir創(chuàng)建瘟判,庫文件、可執(zhí)行文件編譯完成以后直接copy到對應(yīng)文件夾中角溃,其它配置或者腳本也是提前準備或者編譯過程生成拷获,然后copy到對應(yīng)文件夾中。

out/rk3568/packages/phone# tree . -L 1

.
├── chip_prod
├── data
├── hisysevent
├── images
├── NOTICE_FILES
├── NOTICE_module_info.json
├── NOTICE.txt
├── NOTICE.txt.md5.stamp
├── notice_verify_result.out
├── NOTICE.xml
├── NOTICE.xml.gz
├── ramdisk
├── root
├── sa_profile
├── sys_prod
├── system
├── system_install_modules.json
├── system_install_parts.json
├── system_module_info.json
├── system_modules_list.txt
├── system_notice_files.zip
├── system.zip
├── updater
└── vendor

build/ohos/images/mkimage# tree . -L 1

.
├── chip_prod_image_conf.txt
├── dac.txt
├── debug
├── imkcovert.py
├── mkcpioimage.py
├── mkextimage.py
├── mkf2fsimage.py
├── mkimages.py
├── __pycache__
├── ramdisk_image_conf.txt
├── README.txt
├── sys_prod_image_conf.txt
├── system_image_conf.txt
├── updater_image_conf.txt
├── updater_ramdisk_image_conf.txt
├── userdata_image_conf.txt
└── vendor_image_conf.txt
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末减细,一起剝皮案震驚了整個濱河市匆瓜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖驮吱,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茧妒,死亡現(xiàn)場離奇詭異,居然都是意外死亡左冬,警方通過查閱死者的電腦和手機嘶伟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來又碌,“玉大人九昧,你說我怎么就攤上這事”显龋” “怎么了铸鹰?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皂岔。 經(jīng)常有香客問我蹋笼,道長,這世上最難降的妖魔是什么躁垛? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任剖毯,我火速辦了婚禮,結(jié)果婚禮上教馆,老公的妹妹穿的比我還像新娘逊谋。我一直安慰自己,他們只是感情好土铺,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布胶滋。 她就那樣靜靜地躺著,像睡著了一般悲敷。 火紅的嫁衣襯著肌膚如雪究恤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天后德,我揣著相機與錄音部宿,去河邊找鬼。 笑死瓢湃,一個胖子當著我的面吹牛理张,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箱季,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼涯穷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了藏雏?” 一聲冷哼從身側(cè)響起拷况,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤作煌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赚瘦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粟誓,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年起意,在試婚紗的時候發(fā)現(xiàn)自己被綠了鹰服。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡揽咕,死狀恐怖悲酷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亲善,我是刑警寧澤设易,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蛹头,受9級特大地震影響顿肺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渣蜗,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一屠尊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耕拷,春花似錦讼昆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嫌吠。三九已至止潘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辫诅,已是汗流浹背凭戴。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炕矮,地道東北人么夫。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像肤视,于是被迫代替她去往敵國和親档痪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容