3. gn入門


Chromium是用gn和ninja進行編譯的,即gn把.gn文件轉換成.ninja文件,然后ninja根據.ninja文件將源碼生成目標程序。gn和ninja的關系就與cmake和make的關系差不多。

1. 環境配置

在我們自己的項目中,也可以使用gn來進行編譯。
在windows上總是會遇到各種各樣的問題,還是直接下載二進制程序省心:

https://github.com/ninja-build/ninja/releases
https://chrome-infra-packages.appspot.com/p/gn/gn

然后設置環境變量,以便在命令行中直接使用。

2. 示例

這里寫個hello_word來演示下gn的基本使用。
首先,寫一個hello_word.cc源碼文件:

#include <iostream>

int main()
{
    std::cout << "Hello world: gn build example" << std::endl;

    return 0;
}

然后在同一目錄下創建BUILD.gn文件:

executable("hello_world") {
  sources = [
    "hello_world.cc",
  ]
}

同時,gn還需要在項目根目錄有一個.gn文件用於指定編譯工具鏈。這里我們直接拷貝gn官方的例子的配置,完整工程:hello_world.zip
之后就可以直接執行編譯:

gn gen out/Default
ninja -C out/Default

這樣就會在out/Default目錄生成可執行文件hello_world.exe。
image.png
這樣一個簡單的示例就完成了。

在自己的項目中使用gn,必須遵循以下要求:

  1. 在根目錄創建.gn文件,該文件用於指定BUILDCONFIG.gn文件的位置;
  2. 在BUILDCONFIG.gn中指定編譯時使用的編譯工具鏈;
  3. 在獨立的gn文件中定義編譯使用的工具鏈;
  4. 在項目根目錄下創建BUILD.gn文件,指定編譯的目標。

3. 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
。。。
注意//代表從項目根目錄開始。

4. BUILD.gn文件語法

gn語法很接近python,主要的官方文檔是以下兩篇:
https://chromium.googlesource.com/chromium/src/tools/gn/+/48062805e19b4697c5fbd926dc649c78b6aaa138/docs/language.md
https://gn.googlesource.com/gn/+/master/docs/reference.md

這里簡單介紹下一些關鍵用法:

4.1 新增編譯參數

declare_args() {
  enable_test = true
}

這樣就新增了一個enable_test的gn編譯參數,默認值是true。在BUILD.gn文件中,你就可以根據這個編譯參數的值進行一些特殊化配置:

if(enable_test)
{
...
}

4.2 新增宏

  defines = [ "AWESOME_FEATURE", "LOG_LEVEL=3" ]

這些宏可以直接在C++或C代碼中使用。

4.3 新增編譯單元

target就是一個最小的編譯單元,可以將它單獨傳遞給ninja進行編譯。
從google文檔上看有以下幾種target:

因此,我們的hello示例其實也只是增加了一個executable target。

4.4 新增配置

使用config可以提供一個公共的配置對象,包括編譯flag、include、defines等,可被其他target包含。

  config("myconfig") {
    include_dirs = [ "include/common" ]
    defines = [ "ENABLE_DOOM_MELON" ]
  }

  executable("mything") {
    configs = [ ":myconfig" ]
  }

4.5 新增模板

模板,顧名思義,可以用來定義可重用的代碼,比如添加新的target類型等。
通常可以將模板單獨定義成一個.gni文件,然后其他文件就可以通過import來引入實現共享。這部分就比較復雜,具體例子可參閱官方文檔。

4.6 新增依賴關系

平時我們在編譯的時候都會很小心地處理各種動態庫和靜態庫的鏈接引入,在gn中,我們需要使用deps來實現庫的依賴關系:

if (enable_nacl) {
      deps += [ "//components/nacl/loader:nacl_loader_unittests" ]

      if (is_linux) {
        # TODO(dpranke): Figure out what platforms should actually have this.
        deps += [ "//components/nacl/loader:nacl_helper" ]

        if (enable_nacl_nonsfi) {
          deps += [
            "//components/nacl/loader:helper_nonsfi",
            "//components/nacl/loader:nacl_helper_nonsfi_unittests",
          ]
        }
      }
    }

5.通用toolchain配置

gn編譯的toolchain配置非常關鍵,決定了你編譯的方式和產物的用途,chromium自帶的toolchains也能實現跨平台,但是太過龐大,我們日常使用的話,可以使用:https://github.com/timniederhausen/gn-build

6.使用gn編譯mini_chromium庫

mini_chromium提供了一個mini版本的chromium base庫,里面提供很多有用的工具:日志庫、字符串處理、文件處理等,github地址:https://github.com/chromium/mini_chromium.git
默認它使用的是gyp編譯,但是其實它已經寫好了BUILD.gn文件,我們只需添加.gn文件指定編譯工具鏈即可,修改后的倉庫:https://github.com/243286065/mini_chromium.git。
最后是再windows上和ubuntu上測試通過。不過發現mini_chromium上的確實內容太少了,連timer和json庫都沒有。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM