淺析鴻蒙中的 Gn 與 Ninja(一)

目錄:工具

Ninja簡介post

make 的 3 個特性學習

舉例說明Ninja 的用法ui

如何向構建工具 Ninja 描述構建圖url

後記spa

下載Ninja學習手冊及源代碼.net

 

鴻蒙系統的編譯構建是基於 Gn 和 Ninja 完成的,那麼 Gn 和 Ninjia 有什麼關係呢?具體又是如何工做的呢?想必大多數熱衷於應用開發的同窗都尚未深究過,那麼今天就藉此機會帶着你們扒一扒 Gn 和 Ninja。命令行

 

咱們先來講說 Ninja 吧!3d

 

Ninja 是藉由 Google Chrome 項目而誕生的一個構建工具,它的誕生目標是爲了速度。換句話說,在 Google Chrome 項目的開發過程當中,開發者們認爲同類型的其它構建工具不給力,因此纔會考慮從新開發更高效的工具。要說同類型,那麼不得不提構建界的老大哥 make !make 即 GNU Make,一個用於決定如何使用命令完成最終目標構建的程序。blog

 

在這裏強調 make 的 3 個特性:

  1. make 只是一個通用程序,它不知道如何具體的完成目標的構建工做
  2. make 須要 makefile 中的描述來決定目標構建的具體方案
  3. make 須要藉助其它工具(如:gcc)才能執行方案,最終完成工做

淺析鴻蒙中的 Gn 與 Ninja(一)

這是否是跑題了!不是說好的討論 Ninja 嗎?怎麼扯到 make 上去了?!

 

由於 Ninja 能夠看做是一個更好的 make !而大多數同窗都熟悉 make ,因此經過對比 make 學習 Ninja 是一個很是好的選擇!上述關於 make 的 3 個特性對於 Ninjia 一樣適用(理論上,make 有的 Ninjia 都有,而且更好!)。那麼,是否是得先學習 make 再學習 Ninja 呢?我以爲倒也不是!畢竟咱們最終仍是在鴻蒙上作應用開發,編譯構建系統只須要大致瞭解便可。

 

接下來經過一個簡單的例子向你們展現 Ninja 的用法!

 

test.c 是一個簡單的 Hello World 程序,用於打印一個字符串和頭文件 test.h 中常量 CONST 的值。

淺析鴻蒙中的 Gn 與 Ninja(一)

根據 C 程序的編譯方式可知:

  1. 在預處理階段 test.h 中的代碼直接嵌入test.c 中(頭文件 .h 最終成爲源文件 .c 的一部分)
  2. test.c 編譯後獲得目標文件 test.o
  3. test.o 連接後獲得最終的可執行程序  test.out

 

各個文件在編譯過程當中有明顯的上下游關係,即:上游文件影響或者產生下游文件。

淺析鴻蒙中的 Gn 與 Ninja(一)

上圖即描述了編譯過程,同時也反映了這樣一個事實:任何一個文件被改動時只可能影響下游文件,而不會影響上游文件。如:test.c 被修改了,那麼可能致使編譯獲得 test.o 發生改變,進而致使最終的可執行程序 test.out 改變。所以,當 test.c 被修改時,那麼應該從新觸發編譯和連接這兩個動做。

 

看到這裏,有同窗可能存在這樣的疑問:怎麼知道文件已經被修改了並觸發相應動做呢?

 

其實很簡單,能夠根據文件修改時間判斷呀!目前幾乎主流的文件系統都會記錄文件被修改的時間,因此結合文件的上下游關係可知:上游文件被修改的時間應該老是 小於等於 下游文件被修改的時間。這樣,只須要遍歷一次上面的構建圖就能夠知道執行哪些動做產生最終可執行程序了。

淺析鴻蒙中的 Gn 與 Ninja(一)

 

接下來思考這樣一個問題:如何向構建工具 Ninja 描述構建圖

 

Ninja 的本質是一種通用程序。既然是程序,那麼擅長的必然是處理結構化文本!所以,能夠用結構化文本(Ninja腳本)來描述構建圖。

 

下面直接上代碼!

淺析鴻蒙中的 Gn 與 Ninja(一)

解讀:

1. Ninja 腳本中的 build 語句描述構建圖中的一個文件上下游關係。如:build test.o cc test.c 指明 test.o 由 test.c 經過規則 cc 而構建,test.c 在構建圖中位於 test.o 的上游,從 test.c 到 test.o 須要執行的動做經過規則 cc 定義。Ninja 經過判斷上下游文件的修改時間決定是否執行規則中定義的動做。多個 build 語句共同描述一個編譯構建圖。

 

2. Ninja 腳本中經過 rule 定義規則描述構建圖中須要執行的動做。如:規則 cc 所定義的具體動做是  gcc -c $in -o $out ,其中 $in 指代上游文件, $out 指代下游文件。對於 build test.o cc test.c 而言,最終執行的動做爲:gcc -c test.c -o test.o 。

 

3. 由 C 語言及其編譯方式可知:當源文件包含的頭文件改動時,源文件須要從新編譯。所以,在構建圖中頭文件瓜熟蒂落的成爲了源文件的上游文件,須要考慮的僅僅是如何定義 rule 最終觸發編譯動做。這裏使用的技巧是經過命令 touh 更新源文件的修改時間,因而可定義 rule dp 的執行動做爲 touch $out。這樣 build test.c : dp test.h 的意思就很清楚了:當 test.h 被修改時,執行 touch test.c 更新修改時間,進而觸發從新編譯。

 

4. default test.out  指明默認構建的目標是 test.out,即: ninja 執行當前腳本時默認編譯構建的是 test.out。

 

理解了 Ninja 腳本的基本構成後就能夠經過實驗進一步體會了!

 

1. 將上面的腳本另存爲文件,並重命名爲 build.ninja,且與 test.c 和 test.h 位於同一目錄下

淺析鴻蒙中的 Gn 與 Ninja(一)

2. 打開命令行定位到源碼目錄,執行 ninja > log.txt

淺析鴻蒙中的 Gn 與 Ninja(一)

經過編譯輸出(log.txt)以及 test.out 的運行結果可知目標構建成功。

 

後記:

這只是一個 Ninja 的入門級介紹,更多的細節你們能夠參考附件中的手冊。同時,文中的示例代碼也能夠在附件中下載。你們能夠本身動手修改源碼(好比:修改 test.h 中 CONST 的值)而後自行編譯體會 Ninja 的用法。

 

Enjoy it!

下載Ninja學習手冊及源代碼

做者:唐佐林

想了解更多內容,請訪問: 51CTO和華爲官方戰略合做共建的鴻蒙技術社區https://harmonyos.51cto.com

相關文章
相關標籤/搜索