[gn+ninja學習 0x02] GN入門示例
OpenHarmony使用gn+ninja來維護開源項目的構建。之前沒有接觸過gn+ninja,是時候系統性的來學習下了。邊學邊記錄下學習過程,希望對同樣需要學習gn+ninja的朋友有所幫助。
這一篇,我們通過示例來學習GN的入門知識。
1、環境配置
作為開源軟件,可以自己編譯,也可以直接使用現有的二進制文件,官方下載地址如下。通常外網速度慢,甚至打不開。還好,gn、ninja相關的源代碼可以在OpenHarmony的third party倉庫下找到,見參考資料。
搭建OpenHarmony環境后,也會自動配置gn和ninja的構建環境,這就很方便了。下載openharmony源碼,使用hb編譯時會自動下載gn+ninja工具時,在目錄prebuilts/build-tools/linux-x86/bin下可以找到gn+ninja。更多信息請參考OpenHarmony的環境搭建文檔吧。
2、GN Quick Start guide快速入門
快速入門參考了官方文檔,讀者也可以去閱讀下原文https://gitee.com/openharmony/third_party_gn/blob/master/docs/quick_start.md。
(1)Running GN
搭建好環境后,就可以命令行運行gn命令。如下:
(2)Setting up a build
GN允許你設置專有的構建目錄,不同的構建目錄使用不同的參數設置。設置構建目錄后,當配置文件更新時,Ninja文件會自動重新生成,而不需要重新運行GN。設置構建目錄使用下述命令:
不是隨便一個目錄就可以運行上述命令的,否則會報錯:
如果想練習下設置構建目錄,可以切換到gn的example目錄下進行嘗試,如下:
(3)Passing build arguments傳遞構建參數
執行命令gn args --list out/my_build ,可以查詢可用的參數列表及其他們的默認值。必須指定構建目錄,可用參數在不同的構建目錄下是不一樣的。
執行命令gn args out/my_build可以為構建目錄設置構建參數,該命令執行后,會打開一個編輯器,輸入構建參數,類似下面:
3、Step-by-step示例學習
(1)Adding a build file添加構建文件
切換到目錄~/openharmony/third_party/gn/examples/simple_build/,這是最小化的GN構建示例目錄。在目錄下有個tutorial 目錄,內有一個源文件tutorial.cc,但是有利于構建之外。在tutorial 目錄下創建一個BUILD.gn文件,用于構建可執行文件target:
然后,把構建target目標告知構建系統。simple_build目錄下的BUILD.gn文件,是GN構建的入口根文件,從這里加載啟動后,然后加載依賴。因此,我們在此根文件中添加引用到我們上述創建的構建target。
通常,把一個可執行文件作為另外一個可執行文件的依賴,沒有意義,無法鏈接。我們創建一個tools組group。在GN中,group用于收集維護不會編譯或者鏈接的依賴。如下:
(2)Testing your addition驗證編譯
命令行進入simple_build命令,執行如下命令,可以看到會有打印輸出“Hello from the tutorial.”。
(3)Declaring dependencies 聲明依賴
我們再來看下examples/simple_build/BUILD.gn中的構建target的定義,⑴處定義的可執行文件構建target依賴hello_shared和hello_static,前面的冒號表示這些依賴的target在當前文件中定義,可以在下文找到。⑵處定義了一個共享庫的構建target,它定義了一個函數GetSharedText(),也演示了如何使用預處理宏。⑶處定義了一個靜態庫的構建target,它定義了一個函數GetStaticText()。
(4)Test the binary測試運行二進制
命令行進入simple_build命令,執行如下命令,可以看到會有打印輸出“Hello, world”。命令中-C指定構建目錄,后面的hello也可以構建的target名稱。使用命令gn ls out可以輸出所有的構建target。
(5)Putting settings in a config使用config配置設置
使用library庫的時候,經常需要編譯選項、宏定義、include頭文件包含等??梢园堰@些設置放到一個config的命名設置集里,不能放置源文件或依賴。如下:
為了把一個config里面的設置應用到target里,可以加到configs列表里,如注釋所示,使用+=,這樣默認的設置不會被覆蓋。
一個config也能應用到所有依賴當前target的target上,只需要把config添加到public_configs 列表里,如下。public_configs 里面的設置也會應用到當前的target,不需要重復指定。
構建配置一般設置一些配置項,可以默認應用到所有的targe里。例如,在文件examples\simple_build\build\BUILDCONFIG.gn中,定義了如下默認configs??梢栽贐UILD.gn的target里使用語句“print(configs)”打印輸出默認配置。
(6)Add a new build argument添加構建參數
可以使用declare_args聲明可以接受的構建參數,并提供默認值??梢允褂妹畈榭礃嫿▍档氖褂脦椭鷊n help buildargs。
聲明參數后,在生成構建目錄時,可以在命令行指定構建參數:
4、gn常用命令
- gn gen out/dir [–args=“…”]:創建新的編譯目錄,會自動創建args.gn文件作為編譯參數。
- gn args --list out/dir:列出可選的編譯參數。
- gn ls out/dir:列出所有的target。
- gn ls out/dir “//:hello_word*”:列出匹配的target。
- gn desc out/dir “//:hello_word”:查看指定target的描述信息,包括src源碼文件、依賴的lib、編譯選項等。
- gn refs out/dir 文件:查看依賴該文件的target。
- gn refs out/dir //:hello_word:查看依賴該target的target。
注意//代表從項目根目錄開始。
5、小結
我們初步了解了下構建系統、元構建系統是做什么的,了解到gn是個元構建系統,類似cmake。接下來的一篇會介紹gn入門知識、具體如何使用等等。