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