1.準(zhǔn)備工作
我的本地代碼是基于最新發(fā)布的OpenHarmony 1.1.0 LTS(2021-04-01)版本抓取的,代碼根目錄OHOS1_1_0LTS:
$repo init -u https://gitee.com/openharmony/manifest.git -b refs/tags/OpenHarmony_release_v1.1.0 --no-repo-verify
$repo sync
我還有Hi3861_Wifiiot開發(fā)板和開發(fā)環(huán)境,如下:
在Linux環(huán)境下的DecEco IDE下創(chuàng)建新工程“Test_Wifiiot”,在“HPM”標(biāo)簽下找到“@ohos/wifi_iot”,點(diǎn)擊“Install to project”選擇“Test_Wifiiot”項(xiàng)目,開始下載并安裝組件到項(xiàng)目里。
2.全編譯+模塊編譯
2.1 OHOS1_1_0LTS的全代碼編譯
在代碼根目錄下執(zhí)行:
OHOS1_1_0LTS$hb set
[OHOS INFO] Input code path:.
OHOS Which product do you need?
ipcamera_hispark_pegasus@hisilicon
->ipcamera_hispark_taurus@hisilicon
ipcamera_hispark_aries@hisilicon
這一步完成后,會(huì)在代碼根目錄下生成“ohos_config.json”文件,然后就可以開始編譯了:
OHOS1_1_0LTS$hb build
OHOS1_1_0LTS$python build.py
OHOS1_1_0LTS$python build.py -p ipcamera_hispark_taurus@hisilicon
效果都是一樣的。
第一次全編譯了2491個(gè)文件,以后再操作上面的命令就不是全編譯了,只編譯需要編譯的部分。
2.2 Test_Wifiiot項(xiàng)目的全編譯
新下載的項(xiàng)目代碼根目錄下并沒有“build.py”文件。
$hb set
會(huì)生成“ohos_config.json”,但沒有完成配置,hb build 會(huì)失敗。
可以執(zhí)行
$ln -s ./build/lite/build.py build.py
創(chuàng)建build.py的軟鏈接,再執(zhí)行
$python build.py wifiiot
就可以正常編譯了。
Test_Wifiiot項(xiàng)目還可以用DevEco IDE進(jìn)行一鍵編譯,操作步驟見官方的文檔:
https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905
2.3 OHOS1_1_0LTS的組件/倉庫/Target編譯
一開始,關(guān)于模塊編譯,我在網(wǎng)上搜到了:
《HarmonyOS單模塊編譯與源碼導(dǎo)讀》(Link: https://harmonyos.51cto.com/posts/3094 )
這篇文章(下文簡(jiǎn)稱《導(dǎo)讀》),仔細(xì)閱讀,并對(duì)比本地代碼OHOS1_1_0LTS查看了build\lite目錄下,并沒有上文所提到的compile.py文件和product目錄,這個(gè)可能是鴻蒙系統(tǒng)迭代更新版本給拿掉了。
查看OHOS1_1_0LTS\build\lite目錄下的README_zh.md,雖然看到增加了-T的說明:
-T[TARGET [TARGET ...]], --target [TARGET [TARGET ...]]
Compile single target
但沒做進(jìn)一步使用說明,因?yàn)閷?duì)鴻蒙的編譯系統(tǒng)還沒多少了解,我還是不大清楚如何使用操作。
官方文檔“輕量和小型系統(tǒng)編譯構(gòu)建指導(dǎo)”:
https://device.harmonyos.com/cn/docs/develop/subsystems/oem_subsys_build_des-0000001060646620
可能沒有更新,甚至沒有對(duì)“-T”參數(shù)的描述。
不過官方文檔中“組件描述位于build/lite/components下”這句話倒提醒了我,去里面看了一下,
原來這就是鴻蒙系統(tǒng)所有組件描述文件的存放位置,每個(gè)組件文件內(nèi)又有多個(gè)【組件和target】的描述。
打開“applications.json”看一下,這里就有上面《導(dǎo)讀》提到的東西:
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
"targets": [
"http://applications/sample/camera/launcher:launcher_hap",
"http://applications/sample/camera/cameraApp:cameraApp_hap",
"http://applications/sample/camera/setting:setting_hap",
"http://applications/sample/camera/gallery:gallery_hap",
"http://applications/sample/camera/media:media_sample"
],
趕緊操作一下:
OHOS1_1_0LTS$hb build -T //applications/sample/camera/launcher:launcher_hap
編譯OK,不過時(shí)間還是有點(diǎn)長
官方文檔說“組件即為gn中的編譯單元,可以為靜態(tài)庫、動(dòng)態(tài)庫或可執(zhí)行文件。”
編譯構(gòu)建流程圖上也是寫 hb build [component]
OHOS1_1_0LTS$hb build camera_sample_app
編譯OK,但感覺與target編譯以及最上面hb build是一樣的效果~~
我還在OHOS1_1_0LTS\applications\sample\camera\README_zh.md 文檔中看到對(duì)媒體子系統(tǒng)組件的使用說明:
單倉的編譯構(gòu)建,在根目錄下進(jìn)行單倉的構(gòu)建和編譯
# 開發(fā)板選擇
hb set
# 單倉構(gòu)建和編譯
hb build camera_lite
再查看一下build\lite\components\multimedia.json,原來單倉編譯就是組件編譯,而Target編譯,實(shí)際上看起來又與組件編譯差別不大,有些組件本身就是一個(gè)target,有些組件分多個(gè)target。
"component": "camera_lite",
"description": "Camera service.",
"optional": "true",
"dirs": [
"foundation/multimedia/camera_lite",
"foundation/multimedia/utils/lite/hals"
],
"targets": [
"http://foundation/multimedia/camera_lite/frameworks:camera_lite"
],
小結(jié):
鴻蒙系統(tǒng)所有組件描述文件的存放在build/lite/components/目錄下,每個(gè)組件文件內(nèi)又有多個(gè)組件和target的描述。
組件/倉庫編譯指令:
$hb build component_name
Target編譯指令(可一次編譯多個(gè)target,用&&連接):
$hb build -T target_name
$hb build -T target1_name&&target2_name
3.編譯系統(tǒng)build目錄結(jié)構(gòu)
首先必須要仔細(xì)研讀 build\lite\README_zh.md 文檔,文檔上沒有的地方,我這里補(bǔ)充一下我的理解,做成表格更容易管理。這個(gè)表格會(huì)在以后學(xué)習(xí)過程中根據(jù)新的理解做更新。
4.編譯結(jié)果out目錄結(jié)構(gòu)
打開“os-release”文件查看:
VERSION="OpenHarmony 1.0"
RELEASE_TIME="2021-04-18 07:38:53"
分別是鴻蒙系統(tǒng)的版本號(hào),和當(dāng)次編譯(內(nèi)核?系統(tǒng)?)的時(shí)間
5.構(gòu)建系統(tǒng)Gn+Ninja
在學(xué)習(xí)鴻蒙之前,我對(duì)Gn/Ninja并不了解,只是知道有這么個(gè)東西,因?yàn)橛貌坏剿砸矝]有去學(xué)習(xí)的動(dòng)力。
這幾天因?yàn)橄肷钊肓私庖幌馒櫭傻木幾g系統(tǒng),就通過網(wǎng)絡(luò)資源簡(jiǎn)單學(xué)習(xí)了一下,也只是知道了個(gè)大概,我看到的資料里覺得比較好的,有如下鏈接:
首先最重要的“gn help
【下文中對(duì)gn定義的關(guān)鍵字不再解釋,請(qǐng)自行隨時(shí) gn help?!?/p>
《淺析鴻蒙中的Gn和Ninjia(一)》
Link: https://harmonyos.51cto.com/posts/2972
《HarmonyOS 2.0研究(1) -環(huán)境搭建及編譯過程分析》【強(qiáng)烈推薦】【本文內(nèi)簡(jiǎn)稱為《過程分析》】
Link:https://my.oschina.net/u/2502829/blog/4613535
《#2020征文-開發(fā)板#鴻蒙liteos-a如何啟動(dòng)第一個(gè)用戶進(jìn)程init_lite》【本文內(nèi)簡(jiǎn)稱為《如何啟動(dòng)init_lite》】
Link:https://harmonyos.51cto.com/posts/1998#bkwz
《GN語法和操作》
Link:https://blog.csdn.net/yujiawang/article/details/72627138
為了快速理解Gn+Ninja是如何工作的,我自己做了一個(gè) GnHelloWorld工程來做測(cè)試和驗(yàn)證,源代碼放在gitee上:
https://gitee.com/liangkzgitee/GnProjs.git
壓縮包也添加在本文附件里,請(qǐng)大家按readme.txt文檔操作,逐步進(jìn)行跟蹤和分析。
readme.txt 文檔內(nèi)容如下:
這是一個(gè)最簡(jiǎn)單的Gn+Ninja構(gòu)建系統(tǒng)的例子工程,通過這個(gè)簡(jiǎn)單的工程和下面的操作,
學(xué)習(xí)Gn+Ninja構(gòu)建系統(tǒng)是如何構(gòu)建編譯我們的源代碼的。
原始工程目錄如下:
GnHelloWorld/ #工程根目錄
├──build/ #編譯構(gòu)建主目錄
│ └──config/ #編譯相關(guān)的配置項(xiàng)
│ ├──toolchans/ #編譯工具鏈相關(guān)
│ │ └──BUILD.gn #編譯選項(xiàng)、鏈接選項(xiàng)等等
│ └──BUILDCONFIG.gn #指定默認(rèn)編譯工具鏈
├──src/ #源代碼目錄
│ ├──BUILD.gn #(*)
│ └──hello.c #(*)源代碼
├──.gn #Gn構(gòu)建系統(tǒng)入口
├──BUILD.gn #
└──Readme.txt #(*)本文
Step1:
在"GnHelloWorld"目錄下執(zhí)行:"gn gen out"命令后,會(huì)生成一個(gè)"out"目錄,
GnHelloWorld/
├──......[略]
├──out/
│ ├──obj/
│ │ └──src/
│ │ └──hello.ninja #編譯hello.c的ninja腳本
│ ├──args.gn #構(gòu)建參數(shù)
│ ├──build.ninja
│ ├──build.ninja.d
│ └──toolchain.ninja
├──......[略]
Step2: [建議操作這步之前,先備份out目錄,如: "cp -r out out_bak"]
在"GnHelloWorld"目錄下執(zhí)行: "ninja -C out",會(huì)在out目錄下生成
GnHelloWorld/
├──......[略]
├──out_bak/ #Step1 的 out 目錄的副本
│ ├──obj/
│ │ └──src/
│ │ └──hello.ninja
│ ├──args.gn
│ ├──build.ninja
│ ├──build.ninja.d
│ └──toolchain.ninja
├──out/ #out目錄有更新,見#
│ ├──obj/
│ │ ├──src
│ │ │ ├──hello.ninja
│ │ │ └──hello.o #編譯鏈工具根據(jù)規(guī)則生成的 .o
│ │ └──all.stamp #
│ ├──.ninja_deps #
│ ├──.ninja_log #
│ ├──args.gn
│ ├──build.ninja
│ ├──build.ninja.d
│ ├──hello #編譯后生成的可執(zhí)行文件
│ └──toolchain.ninja
├──......[略]
Step3:
在"GnHelloWorld"目錄下執(zhí)行: 執(zhí)行"./out/hello",輸出"Hello Gn World!"
Step1做了如下工作:
1.執(zhí)行g(shù)n gen 時(shí)帶的參數(shù)被記錄下來,生成out/args.gn【本例不帶args參數(shù)】
2.找到 “.gn”文件并將其所在的目錄設(shè)為“souce root”,解析該文件以獲取buildconfig。
3.執(zhí)行buildconfig所指向的文件BUILDCONFIG.gn,設(shè)置一個(gè)默認(rèn)的編譯工具鏈,
生成out/toolchain.ninja。
4.加載“souce root”目錄下的“BUILD.gn”文件,根據(jù)其內(nèi)容加載它依賴的其它
目錄下的BUILD.gn文件,生成out/build.ninja.d。
5.根據(jù)out/build.ninja.d中各個(gè)BUILD.gn的內(nèi)容,遞歸解決各自的依賴關(guān)系,
解決掉依賴關(guān)系之后,就在out/obj/對(duì)應(yīng)目錄下,生成“.ninja”,
如例子中的“out/obj/src/hello.ninja”。
6.解決掉所有的依賴關(guān)系后,在out/目錄下生成一個(gè)“build.ninja”。
Step2做了如下工作:
根據(jù)上面的.ninja文件所定義的規(guī)則和依賴關(guān)系,依次編譯出各自的中間文件,
最終生成可執(zhí)行文件“out/hello”。
理解了上面的東西之后,你就可以開始進(jìn)一步學(xué)習(xí)更復(fù)雜的東西了,可以參考Gn的官方文檔,
或者網(wǎng)絡(luò)上的其它資源,自己動(dòng)手做驗(yàn)證。
6.編譯流程分析
我們r(jià)epo/sync完整個(gè)鴻蒙代碼后,要編譯系統(tǒng),一般做以下三步:
1. 首次編譯,需要首先 hb set
2. 首次編譯,hb build 會(huì)啟動(dòng)全編譯
3. 修改某個(gè)文件,比如 init_lite 的main 文件main函數(shù)加行l(wèi)og,再次編譯 hb build或者h(yuǎn)b build init_lite。
這三步操作,鴻蒙的編譯系統(tǒng)都做了哪些具體工作?
帶著這個(gè)疑問,我希望能夠抽絲剝繭,一步一步來確認(rèn),可能中間會(huì)有暫不理解的,先跳過,未來再做進(jìn)一步完善。
可惜目前我對(duì)python的了解也不多,無法對(duì)相關(guān)腳本做非常詳細(xì)的分析,對(duì)Gn構(gòu)建系統(tǒng)的理解也還不夠深入,無法給出理想的分析結(jié)果,所以只能先把我現(xiàn)在知道的寫下來,以后學(xué)習(xí)過程中逐步補(bǔ)充完善。
6.1設(shè)置環(huán)境hb set
【查看/build/lite/README_zh.md】
設(shè)置OpenHarmony源碼目錄和要編譯的產(chǎn)品,在代碼根目錄生成“ohos_config.json”文件。
具體 hb set命令怎么調(diào)用/build/lite/hb/目錄下的相關(guān)腳本,再結(jié)合系統(tǒng)環(huán)境變量$PATH等相關(guān)必要信息來生成這個(gè).json文件的,懂python的可以進(jìn)去看一下。
打開“ohos_config.json”文件查看:
{
"root_path": "/home/lkz/Work/OHOS1_1_0LTS",
"board": "hispark_taurus",
"kernel": "liteos_a",
"product": "ipcamera_hispark_taurus",
"product_path": "/home/lkz/Work/OHOS1_1_0LTS/vendor/hisilicon/hispark_taurus",
"device_path": "/home/lkz/Work/OHOS1_1_0LTS/device/hisilicon/hispark_taurus/sdk_liteos"
}
這些將作為非常重要的參數(shù)交給下一步編譯使用。
6.2全編譯hb build
【查看/build/lite/README_zh.md】
編譯產(chǎn)品、開發(fā)板或者組件。解決方案編譯實(shí)現(xiàn)如下:
A. 讀取開發(fā)板配置:主要包括開發(fā)板使用的編譯工具鏈、編譯鏈接命令和選項(xiàng)等。
B. 調(diào)用gn: 調(diào)用gn gen命令,讀取產(chǎn)品配置(主要包括開發(fā)板、內(nèi)核、選擇的組件等)生成解決方案out目錄和ninja文件。
C. 調(diào)用ninja:調(diào)用ninja -C out/company/product啟動(dòng)編譯。
D. 系統(tǒng)鏡像打包:將組件編譯產(chǎn)物打包,制作文件系統(tǒng)鏡像。
說的很“框架”,下面我們一步一步來看一下。
A. 檢測(cè)/讀取/配置所有的必要參數(shù)
包括但不限于以下列出來的幾個(gè)文件:
ohos_config.json
Build\lite\ohos_var.gni 定義使用于所有組件的全局變量
device\hisilicon\hispark_pegasus\sdk_liteos\config.gni 這是編譯LiteOS_A內(nèi)核所需要用到的配置
vendor\hisilicon\hispark_taurus\config.json 這是hisilicon提供的產(chǎn)品全量配置表:子系統(tǒng)、組件列表等等
通過hb build傳進(jìn)去的參數(shù),比如 -n 表示編譯NDK,則會(huì)將ohos_build_ndk變量由默認(rèn)的FALSE改為TRUE。
B. 調(diào)用gn gen命令生成out目錄和ninja文件
很復(fù)雜,也很簡(jiǎn)單。
復(fù)雜是中間涉及到太多的Python和Gn語法,我暫時(shí)無法完整理解。
簡(jiǎn)單是因?yàn)槲易鲞^了上面的GnHelloWorld工程來做測(cè)試和分析,知道了框架。
更詳細(xì)的分析過程,請(qǐng)看《過程分析》這篇文章。
下面是我對(duì)//build/lite/BUILD.gn這個(gè)文件中的 group("ohos") 的分解,最終得到"ohos"的完整的依賴關(guān)系:
C. 調(diào)用ninja啟動(dòng)編譯
這里就開始根據(jù)上一步生成的 .ninja 文件里的規(guī)則調(diào)用編譯工具鏈來編譯各目錄下的源文件了,生成 .o/.a/.so/可執(zhí)行文件 等等,其中.so文件會(huì)先在out\hispark_taurus\ipcamera_hispark_taurus\目錄下生成,等編譯完之后會(huì)轉(zhuǎn)移到out\hispark_taurus\ipcamera_hispark_taurus\libs\usr\目錄下,還生成了.ninja_log和.ninja_deps文件。
編輯:hfy
-
Linux
+關(guān)注
關(guān)注
87文章
11123瀏覽量
207921 -
編譯系統(tǒng)
+關(guān)注
關(guān)注
0文章
10瀏覽量
8853 -
鴻蒙系統(tǒng)
+關(guān)注
關(guān)注
183文章
2627瀏覽量
65790
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論