[GN] 谷歌元構建系統GN,toolchain配置

注:主要信息來自於GN的幫助文件

典型格式: 

tool(<tool type>) {
    <tool variables...>
  }


tool type可選的範圍:

編譯器:
"cc": C編譯器
"cxx": C++ 編譯器
"objc": Objective C 編譯器
"objcxx": Objective C++ 編譯器
"rc": Resource compiler (Windows .rc files)
"asm": 彙編器

鏈接器:
"alink": 靜態庫鏈接器,一般進行打包操作,即ar
"solink": 動態庫鏈接器
"link": 完整鏈接器,主要用於鏈接出可執行文件

其他工具:
"stamp": 創建時間戳文件
"copy": 複製操作
"action": 默認執行

平臺專用工具:
"copy_bundle_data": [iOS, macOS] 複製捆綁文件的工具
"compile_xcassets": [iOS, macOS] 編制資產目錄的工具


每個工具可以使用的屬性變量

command  [string with substitutions]
適用於:所有工具,"action"則爲必選項
指定一個可以執行的語句

default_output_dir  [string with substitutions]
適用於:鏈接器
相對於輸出文件的默認目錄(root_build_dir)的路徑。 它可以包含其他替換模式。 這將是{{output_dir}}擴展的默認值(下面討論)但會被目標中的“ output_dir”變量覆蓋(如果有的話)。
GN除了傳遞此字符串外,不對其進行任何處理,可能具有特定於目標的覆蓋。

default_output_extension [string ]
適用於:鏈接器工具
擴展可鏈接工具的主要輸出。它包括前導點。這將是{{output_extension}}擴展的默認值(如下所述),但如果指定了目標,則將被目標中的“ output extension”變量覆蓋。空字符串表示無擴展名。
GN除了對該擴展進行傳遞外,實際上並沒有做任何其他事情,可能會傳遞特定於目標的覆蓋。 人們通常會在“輸出”中使用{{output_extension}}值來讀取該值。
示例:default_output_extension =“ .exe”

depfile [string with substitutions]
適用於:編譯器工具(可選)
如果該工具可以寫入“ .d”文件,則可以指定結果文件的名稱。 這些文件用於列出在構建時發現的頭文件依賴項(或其他隱式輸入依賴項)。 另請參見“ depsformat”。
示例:depfile =“ {{output}}。d”

depsformat [string]
適用於:編譯器工具(當指定了depfile時)
deps輸出的格式。 可選值爲“ gcc”或“ msvc”。 有關更多信息,請參見Ninja文檔中的“ deps”。
示例:depsformat =“ gcc”

description  [string with substitutions, optional]
適用於:所有工具
運行命令時要打印什麼。
示例:description =“Compiling {{source}}”

lib_switch  [string, optional, link tools only]
lib_dir_switch  [string, optional, link tools only]

適用於:鏈接器工具(“alink”除外)
這些字符串將分別放在庫和庫搜索目錄的前面,因爲鏈接器在指定它們的方式上有所不同。
如果指定:
lib_switch =“ -l”
lib_dir_switch =“ -L”
那麼[“ freetype”,“ expat”]的“ {{libs}}”擴展爲“ -lfreetype -lexpat”。

outputs  [list of strings with substitutions]
適用於:鏈接器和編譯器工具(必需)
該工具生成的輸出文件的名稱數組。這些是相對於構建輸出目錄的。必須始終至少有一個輸出文件。可以有多個輸出(例如,鏈接器可能會產生一個庫和一個導入庫)。
該數組僅向GN聲明該工具將生成什麼文件。您有責任指定實際產生這些文件的工具命令。
如果爲共享庫鏈接指定了多個輸出,則應考慮設置link_output,depend_output和runtime_outputs。
生成.obj文件的編譯器工具示例:
outputs = [
"{{source_out_dir}}/{{source_name_part}}.obj"
]
生成.dll和.lib的鏈接器工具的示例。使用{{target_output_name}},{{output_extension}}和{{output_dir}}可使目標覆蓋這些值。
outputs = [
"{{output_dir}}/{{target_output_name}}"
    "{{output_extension}}",
"{{output_dir}}/{{target_output_name}}.lib",
]

pool [label, optional]
適用於:所有工具(可選)
工具使用的池的標籤。 池用於限制在構建過程中可以同時執行的任務數。

link_output  [string with substitutions]
depend_output  [string with substitutions]

適用於:僅“ solink”(可選)
這兩個文件指定應使用solink工具的哪個輸出進行鏈接和依賴項跟蹤。 這些應與“outputs”中的條目匹配。 如果未指定,則“outputs”數組中的第一項將全部使用。 有關更多信息,請參見下面的“共享庫的單獨鏈接和依賴性”。
在Windows上,這些工具會生成.dll共享庫和.lib導入庫,您將希望前兩個成爲導入庫,第三個成爲.dll文件。 在Linux上,如果不執行單獨的鏈接/依賴關係優化,則所有這些都應該是.so輸出。

output_prefix  [string]
適用於:鏈接器工具(可選)
用於輸出名稱的前綴。 默認爲空。 如果該前綴尚不存在,則將在該前綴之前加上目標的名稱(如果是手動爲其指定,則爲output_name)。 結果將顯示在{{output_name}}替換模式中。 單個目標可以通過設置以下內容來選擇退出輸出前綴:
output_prefix_override = true
這通常用於在庫上添加“ lib”:
output_prefix = "lib"

precompiled_header_type  [string]
適用於:“ cc”,“ cxx”,“ objc”,“ objcxx”
預編譯頭文件的類型。 如果未定義或爲空字符串,則預編譯的頭文件將不會用於此工具。 否則,請使用“ gcc”或“ msvc”。
對於要用於給定目標的預編譯頭,目標(或應用於它的配置)還必須指定“ precompiled_header”,並且
“ msvc”樣式的標頭,一個“ precompiled_source”值。 如果類型是“ gcc”,然後“ precompiled_header”和“ precompiled_source”都必須解析爲同一文件,儘管每種格式都需要不同。

restat  [boolean]
適用於:所有工具(可選,默認爲false)
請求Ninja在此工具運行後檢查文件時間戳,以確定是否有任何更改。 如果您的工具能夠在輸出文件未更改的情況下跳過寫入輸出,請設置此選項。
通常,Ninja會假定運行工具時輸出是新的,並且下游依賴項必須重建。 當將此設置爲trye時,Ninja可以跳過對實際不影響輸出的輸入更改重建下游依賴項。

rspfile  [string with substitutions]
適用於:除“action”外的所有工具(可選)
響應文件的名稱。 如果爲空,將不使用響應文件

rspfile_content  [string with substitutions]
適用於:除“action”以外的所有工具(使用“ rspfile”時需要)
要寫入響應文件的內容。 這可能包括要發送給該工具的全部或部分命令,使您可以繞過OS命令行長度限制。 此示例將輸入和庫添加到響應文件,但直接在命令行上傳遞鏈接器標誌:
tool("link") {
command = "link -o {{output}} {{ldflags}} @{{output}}.rsp"
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
}

runtime_outputs  [string list with substitutions]
適用於:鏈接器工具
如果指定,則此列表是應添加到運行時deps的輸出的子集(請參見“ gn help runtime_deps”)。 默認情況下(如果runtime_outputs爲空或未指定),它將是link_output。


擴展工具變量

所有路徑都相對於根構建目錄,該目錄是運行所有工具的當前目錄。 這些擴展適用於所有工具:

 {{label}}
當前目標的標籤。 通常在鏈接工具的“description”字段中使用。 對於默認工具鏈中的目標,該工具鏈將從標籤中省略,對於其他工具鏈中的目標,該工具鏈也將包括在內。

{{label_name}}
目標標籤的簡稱。 這是冒號後面的部分。 對於“ // foo / bar:baz”,它會變成“ baz”。 與{{target_output_name}}不同,它不受工具中的“ output_prefix”或目標上設置的“ output_name”的影響。

{{output}}
當前構建步驟的相對路徑和輸出名稱。 如果有多個輸出,則將擴展爲所有輸出的列表。 示例:“ out / base / my_file.o”

{{target_gen_dir}}
{{target_out_dir}}

當前目標分別生成文件的目錄和輸出目錄。 沒有結尾的斜槓。 另請參閱{{output_dir}}瞭解鏈接器工具。 示例:“ out / base / test”

{{target_output_name}}
當前目標的簡稱,不包含路徑信息;如果目標中指定了“ output_name”變量的值,則簡稱該值。 如果有的話,這將包括“ output_prefix”。 另請參見{{label_name}}。
示例:目標名爲“ foo”的目標爲“ libfoo”,鏈接器工具“ lib”的輸出前綴。

編譯器工具具有單個輸入和單個輸出的概念,以及一組特定於編譯器的標誌。 提供以下擴展:
{{asmflags}}
{{cflags}}
{{cflags_c}}
{{cflags_cc}}
{{cflags_objc}}
{{cflags_objcc}}
{{defines}}
{{include_dirs}}

字符串對應於爲目標指定的已處理標誌/定義/包含目錄。
示例:“-enable-foo --enable-bar”
Defines將以“ -D”作爲前綴,include目錄將以“ -I”作爲前綴(這些與Posix工具以及Microsoft的工具一起使用)。

{{source}}
當前輸入文件的相對路徑和名稱。
 示例:“ ../../ base / my_file.cc”

{{source_file_part}}
源文件的文件部分,包括擴展名(無目錄信息)。
示例:“ foo.cc”

{{source_name_part}}
源文件的文件名部分,沒有目錄或擴展名。
示例:“ foo”

{{source_gen_dir}}
{{source_out_dir}}

當前輸入文件的生成文件和輸出目錄中的目錄分別。 如果源文件與聲明目標所在的目錄位於同一目錄中,則它們將與上面的“目標”版本相同。 示例:“ gen / base / test”

鏈接器工具具有多個輸入和(可能)多個輸出。 靜態庫工具(“alink”)不被視爲鏈接器工具。 提供以下擴展:
{{inputs}}
{{inputs_newline}}

擴展到鏈接步驟的輸入。 這將是目標文件和靜態庫的列表。
示例:“ obj / foo.o obj / bar.o obj / somelibrary.a”
“ _newline”版本將用換行符而不是空格分隔輸入文件。 這在響應文件中很有用:某些鏈接器可以帶有“ -filelist”標誌,該標誌需要換行符分隔的文件,而某些Microsoft工具具有固定大小的緩衝區,用於解析響應文件的每一行。

{{ldflags}}
擴展到爲目標指定的已處理的ldflags和庫搜索路徑集。
示例:“-m64 -fPIC -pthread -L / usr / local / mylib”

{{libs}}
展開到要鏈接到的系統庫的列表。 每一個都將以“ lib_switch”作爲前綴。
作爲支持Mac的特殊情況,名稱以“ .framework”結尾的庫將添加到{{libs}}中,其前面帶有“ -framework”,而lib前綴將被忽略。
示例:“-lfoo -lbar”

{{output_dir}}
如果目標未覆蓋輸出目錄,則目標中的“ output_dir”變量的值或工具中的“ default_output_dir”值的值。 這將相對於root_build_dir,並且不會以斜槓結尾。 將會 ”。” 用於輸出到root_build_dir。
這與GN根據目標的路徑定義的{{target_out_dir}}略有不同,並且不可替代。 {{output_dir}}用於最終輸出,{{target_out_dir}}通常用於目標文件和其他輸出。
通常{{output_dir}}可以用{{target_out_dir}}或{{root_out_dir}}來定義

{{output_extension}}
如果目標未指定輸出擴展名,則目標中的“ output_extension”變量的值,或工具中的“ default_output_extension”值的值。
示例:“.so”

{{solibs}}
{{inputs}}中未指定的共享庫依賴項中的額外庫。 這是共享庫中link_output文件的列表(如果solink工具指定了與“ depend_output”分開的“ link_output”變量)。
通常,您的工具應將它們與libs一樣對待。
示例:“ libfoo.so libbar.so”

靜態庫(“alink”)工具允許{{arflags}}以及常見的工具替換。
複製工具允許通用的編譯器/鏈接器替換,以及{{source}}作爲複製源。 印章工具僅允許替換常用工具。
copy_bundle_data和compile_xcassets工具僅允許通用工具替換。 這兩個工具都是創建iOS / macOS捆綁包所必需的,僅需要在這些平臺上進行定義。
將使用一個源調用copy_bundle_data工具,並且需要將其複製(可選地優化數據表示)至其輸出。 可以使用目錄作爲輸入來調用它,並且需要遞歸複製它。
將使用需要編譯爲單個輸出的一個或多個源(每個資產目錄)來調用compile_xcassets工具。 可以使用以下替代方法:
{{inputs}}
擴展到.xcassets列表,以用作編譯資產目錄的輸入。

{{bundle_product_type}}
擴展到將包含已編譯資產目錄的捆綁軟件的product_type。 通常對應於相應create_bundle目標的product_type屬性。

{{bundle_partial_info_plist}}
擴展到資產目錄編譯器生成的部分Info.plist的路徑。 通常基於create_bundle目標的target_name。

共享庫的單獨鏈接和依賴性
共享庫的特殊之處在於,並非對它們所做的所有更改都需要重新鏈接從屬目標。 如果共享庫已更改,但導入或導出沒有不同,則無需重新鏈接從屬代碼,這可以加快構建速度。
如果您的鏈接步驟可以輸出共享庫中的導出列表,並且僅在新的導出庫不同的情況下才寫入文件,所以該文件的時間戳可用於觸發重新鏈接,而實際的共享庫將用於鏈接 。
您需要指定
restat = true
在鏈接器工具中執行此操作,因此Ninja將在鏈接後檢測依賴項文件的時間戳是否已更改(否則,它將始終假定運行命令會更新輸出):
tool("solink") {
    command = "..."
    outputs = [
    "{{output_dir}}/{{target_output_name}}{{output_extension}}",
    "{{output_dir}}/{{target_output_name}}"
        "{{output_extension}}.TOC",
    ]
    link_output =
    "{{output_dir}}/{{target_output_name}}{{output_extension}}"
    depend_output =
    "{{output_dir}}/{{target_output_name}}"
        "{{output_extension}}.TOC"
    restat = true
}
例如:
 

toolchain("my_toolchain") {
# Put these at the top to apply to all tools below.
lib_switch = "-l"
lib_dir_switch = "-L"

tool("cc") {
    command = "gcc {{source}} -o {{output}}"
    outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
    description = "GCC {{source}}"
}
tool("cxx") {
    command = "g++ {{source}} -o {{output}}"
    outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
    description = "G++ {{source}}"
}
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章