一约巷、Ninja編譯工具簡介
在Unix/Linux下通常使用Make/Makefile來控制代碼的編譯挠阁,但是Makefile對于比較大的項(xiàng)目有時(shí)候會(huì)比較慢榛瓮,Ninja是Google的一名程序員推出的注重速度的構(gòu)建工具日杈,通過將編譯任務(wù)并行組織律秃,大大提高了構(gòu)建速度。
Ninja的目標(biāo)是成為匯編程序冻河。
二箍邮、編譯生成bin文件過程
2.1 JSON文件
首先執(zhí)行 hpm dist
。
編譯的時(shí)候使用到了 json 文件 BearPi-HM_Nano.json
叨叙,位于 bulid/lite/product 中锭弊,該文件描述了一些編譯模塊的路徑。
-
模塊:applications
作用:這個(gè)路徑下存放了hi3681編寫的應(yīng)用程序代碼擂错,例如 hello world 代碼就放在這個(gè)路徑下味滞。 -
模塊:iot_hardware
作用:存放了 hi3681 芯片相關(guān)的驅(qū)動(dòng)、例如spi、gpio剑鞍、uart等昨凡。 -
模塊:vendor
作用:存放了 hi3681 相關(guān)的廠商SDK之類的文件。其中蚁署,app_io_init.c 是hi3681內(nèi)核啟動(dòng)后的io口相關(guān)設(shè)置便脊,用戶需根據(jù)應(yīng)用場景,合理選擇各外設(shè)的IO復(fù)用配置形用。app_main.c 是內(nèi)核啟動(dòng)進(jìn)入的應(yīng)用程序入口就轧。
例如 applications 模塊中的 sample:app 指向位于 applications/BearPi/BearPi-HM_Nano/sample 下的 模塊BUILD.gn
中的 app。
2.2 模塊BUILD.gn
模塊BUILD.gn
的 app 下有許多模塊田度,其中 my_app:myapp 指向位于 applications/BearPi/BearPi-HM_Nano/sample/my_app 下的 業(yè)務(wù)BUILD.gn
。
2.3 業(yè)務(wù)BUILD.gn
業(yè)務(wù)BUILD.gn
的 myapp 會(huì)將 hello_world.c 編譯成 libmyapp.a
文件解愤。
隨后
libmyapp.a
跟著眾多 .a 文件被鏈接編譯進(jìn) Hi3861_wifiiot.bin
文件镇饺。三、代碼運(yùn)行過程
3.1 app_main()
打開位于 vendor/hisi/hi3861/app/wifiiot_app/src 的 app_main.c
送讲,內(nèi)核啟動(dòng)進(jìn)入的應(yīng)用程序入口函數(shù)為 app_main()
在
app_main()
中奸笤,首先打印了 SDK 版本:
const hi_char* sdk_ver = hi_get_sdk_version();
printf("sdk ver:%s\r\n", sdk_ver);
然后進(jìn)行外設(shè)初始化、內(nèi)存初始化哼鬓、文件系統(tǒng)初始化监右、WIFI初始化,
最后執(zhí)行 HOS_SystemInit()
進(jìn)行鴻蒙系統(tǒng)的初始化异希。
3.2 HOS_SystemInit()
打開位于 base/startup/services/bootstrap_lite/source 的 system_init.c
在 HOS_SystemInit()
中健盒,主要是初始化了一些相關(guān)模塊、系統(tǒng)称簿,包括有 bsp扣癣、device(設(shè)備)。其中最終的是 MODULE_INIT(run)
憨降,它負(fù)責(zé)調(diào)用了所有 run 段的代碼父虑,那么 run 段的代碼是哪些呢?事實(shí)上就是我們前面 application 中 hello_world.c 使用 SYS_RUN()
宏設(shè)置的函數(shù)名授药。
include "ohos_init.h"
#include "ohos_types.h"
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
SYS_RUN(HelloWorld);
也就是說所有用SYS_RUN() 宏設(shè)置的函數(shù)都會(huì)在使用MODULE_INIT(run);的時(shí)候被調(diào)用士嚎,為了驗(yàn)證這一點(diǎn),我們可以加一些打印信息悔叽,如下:
我們重新編譯后燒錄莱衩。打開串口查看打印信息,如下:
3.3 MODULE_INIT(run)
SYS_RUN(app_entry) 定義的函數(shù)指針 __zinitcall_run_app_entry 通過強(qiáng)制編譯的方式進(jìn)入 .zinitcall.run2.init 段中骄蝇。在鏈接腳本中定義的兩個(gè)符號 __zinitcall_run_start (理解為數(shù)組名)和 __zinitcall_run_end 分別指向 __zinitcall_run_app_entry 所在數(shù)據(jù)段的起始位置和結(jié)束位置膳殷。 又因?yàn)?MODULE_INIT(run) 的功能就是遍歷 __zinitcall_run_start 和 __zinitcall_run_end 所指定的區(qū)域(理解為函數(shù)指針數(shù)組),并調(diào)用每個(gè)單元(指針)所指向的函數(shù),因此赚窃,__zinitcall_run_app_entry 所指向的函數(shù)必然被調(diào)用册招,即:app_entry() 必然被調(diào)用。
總結(jié):
通過強(qiáng)制編譯鏈接構(gòu)成一個(gè)全局指針數(shù)組(每個(gè)SYS_RUN()
定義一個(gè)數(shù)組元素)在鏈接腳本中定義符號自動(dòng)確認(rèn)這個(gè)數(shù)組的起始地址和結(jié)束地址
MODULE_INIT()
通過遍歷的方式調(diào)用數(shù)組元素所指向的函數(shù)勒极。
? 由 Leung 寫于 2021 年 5 月 16 日
? 參考:【鴻蒙2.0設(shè)備開發(fā)教程】小熊派HarmonyOS 鴻蒙·季 開發(fā)教程
第3章 Hi3681開發(fā)入門是掰、啟動(dòng)流程_連志安-CSDN博客
分析 helloworld程序是如何被調(diào)用,SYS_RUN做什么事情
#2020征文-開發(fā)板#SYS_RUN()和MODULE_INIT()之間的那些事
HarmonyOS編譯框架介紹_懿傕的博客-CSDN博客
鴻蒙OS開源代碼精要解讀之—— 系統(tǒng)服務(wù)框架子系統(tǒng)(服務(wù)啟動(dòng))