Fuchsia 建構系統會使用多個「資訊清單」檔案,指出如何將檔案安裝到容器中,例如將檔案複製到 Fuchsia 套件,或是複製到開機檔案系統映像檔。
本頁面記錄建構作業中使用的這些檔案格式,但不應在建構作業外公開。
請注意,產生及處理這些檔案的指令碼和 .gni 檔案位於 Fuchsia 來源樹狀結構的 //build/dist/ 下方。
FINI (Fuchsia INI) 資訊清單檔案格式
建構期間叫用的多項工具都會使用 FINI 資訊清單格式,包括產生 Fuchsia 套件封存檔的 ffx package build 指令,以及產生 ZBI 映像檔的 zbi 工具。
語法非常簡單:每行文字看起來都像 <destination>=<source>,其中 <destination> 是目的地檔案路徑 (相對於最終容器的頂端),而 <source> 是來源內容的檔案路徑 (相對於目前目錄,也就是大多數情況下的建構目錄)。
請注意,目的地路徑絕不應以目錄分隔符號開頭,且 FINI 檔案不支援註解、區段和Windows INI 檔案格式的其他功能。
例如:
bin/foo=foo
lib/ld.so.1=user.libc_x64/libc.so
meta/foo.cm=obj/src/foo/cml/foo_component/foo.cm
meta/package=gen/src/foo/foo_meta_package.txt
發布資訊清單檔案格式
這是 JSON 檔案,必須包含清單,其中每個項目都是 JSON 物件,做為單一「發布」項目,說明如何將一個來源檔案安裝到容器中,並提供產生該檔案的目標 GN 標籤。這裡使用的結構定義為:
source:來源路徑字串 (必要)。destination:目的地路徑字串 (必要)。label:指向產生來源檔案的目標的 GN 標籤。僅用於偵錯 (選用)。
範例:
{
"destination": "bin/foo",
"source": "x64-asan/foo",
"label": "//some/dir:foo"
}
雖然概念上與 FINI 資訊清單類似,但發布資訊清單提供的資訊稍微多一點 (GN 標籤),這在發生錯誤時非常實用,有助於偵錯。此外,這類資料也會由不同的工具集取用。
部分發布資訊清單檔案格式
FINI 和發布資訊清單是透過處理名為「部分發布資訊清單」的中繼檔案產生。
部分資訊清單是由 GN 中繼資料集合,透過相同依附樹狀結構中的目標產生。這是一個 JSON 檔案,內含物件「項目」的清單。
系統會使用多種項目類型,說明建構和安裝需求的各個層面。這些資訊清單都會合併為 FINI 或發布資訊清單。
//build/dist/distribution_manifest.py 中的 Python 模組包含用於處理這些檔案的函式。
一般項目
這些項目符合發布資訊清單所用的結構定義,對應於要安裝至指定目的地路徑的簡單來源檔案。
source:來源路徑字串 (必要)。destination:目的地路徑字串 (必要)。label:指向產生來源檔案的目標的 GN 標籤。僅用於偵錯 (選用)。elf_runtime_dir:僅適用於 ELF 可執行檔和可載入的模組,這是選用的目的地目錄路徑,用於指定這個二進位檔的 ELF 依附元件在執行階段應位於何處。預設值為「lib」
用於產生發布資訊清單時,這些檔案會原封不動地複製到輸出檔案中,不會有 elf_runtime_dir 鍵,除非符合下列其中一項條件:
與其他一般項目具有相同來源 (詳情請參閱本節),在這種情況下,系統只會保留其中一個項目。
重新命名的項目使用其來源路徑 (詳情請參閱下文)。
範例:
{
"destination": "bin/foo",
"source": "x64-asan/foo",
"label": "//some/dir:foo",
"elf_runtime_dir": "lib/asan"
},
複製項目。
這些項目用於指出建構作業已將特定檔案複製到新的輸出位置。這項資訊稍後會用於正確處理重新命名的項目 (請參閱下文),否則會遭到忽略。結構定義如下:
copy_from:相對於建構目錄的來源路徑字串 (必要)。copy_to:目的地路徑字串,相對於建構目錄 (必要)。label:指向產生這個項目的目標的 GN 標籤 (選用)。
舉例來說,以下項目用於指出以 ${BUILD_DIR}/x64-asan/foo 中的「asan」建構變化版本建構的「foo」可執行二進位檔,也已複製到 ${BUILD_DIR}/foo。
範例:
{
"copy_from": "x64-asan/foo",
"copy_to": "foo"
"label": "//some/dir:foo"
}
請參閱下方的章節,瞭解複製和重新命名項目之間的互動方式,以及實際範例。
已重新命名的項目
這些項目用於指出特定一般項目應安裝在替代目的地位置。這對某些程式 (例如 busybox) 很有用,因為這些程式的行為會因啟動時使用的程式名稱而異。renamed_binary() GN 範本會依據這些項目運作。其結構如下:
destination:目的地路徑字串 (必要)。renamed_source:與其他規則項目相符的來源路徑 (必要)。label:指向產生這個項目的目標的 GB 標籤 (選用)。keep_original:布林值標記,設為 true 表示仍應在容器中安裝原始的重新命名二進位檔 (選用)。
請注意,重新命名項目只能指向一般項目的 source 路徑,或指向副本項目的 copy_to 路徑。使用不明路徑,或使用其他重新命名項目的目的地路徑,都會導致建構錯誤。
您可以多次重新命名同一個項目。如果需要以不同名稱多次安裝相同的原始二進位檔,這項功能就非常實用。
以下範例說明如何在同一個容器中,將 busybox 二進位檔安裝為 bin/cp、bin/cat 和 bin/ls。請注意,bin/busybox不會安裝至容器。
{
"destination": "bin/busybox",
"source": "busybox",
"label": "//third_party/busybox:busybox"
},
{
"destination": "bin/cp",
"renamed_from": "busybox"
},
{
"destination": "bin/cat",
"renamed_from": "busybox"
},
{
"destination": "bin/ls",
"renamed_from": "busybox"
}
如果任何重新命名項目將 keep_original 旗標設為 true,原始項目就不會從資訊清單中移除,原始二進位檔會保留在資訊清單中,如下所示:
{
"destination": "bin/busybox",
"source": "busybox",
"label": "//third_party/busybox:busybox"
},
{
"destination": "bin/cp",
"renamed_from": "busybox",
"keep_original": true
}
這可確保 bin/busybox 和 bin/cp 都安裝到容器中。
檔案項目
這些項目用於納入其他發布資訊清單檔案,這些檔案可能由其他目標產生。結構定義如下:
file:檔案路徑字串,指向另一個發布資訊清單檔案 (必要)。label:預設的 GN 標籤,如果檔案中包含的所有項目沒有自己的label值,就會套用這個標籤 (選用)。
發布檔案可遞迴包含。
範例:
{
"file": "path/to/other.dist_manifest",
"label": "//some/dir:label"
}
資訊清單檔案中的重複項目
由於 Fuchsia 建構作業的運作方式,資訊清單檔案 (任何格式) 可能會提供使用相同 <destination>path 的多個項目。不過,只要來源路徑或內容相同,這就是有效做法;在這種情況下,系統只會忽略重複項目。
如果多個項目具有相同的目的地路徑,但來源路徑和內容不同,處理指令碼會將此情況視為建構錯誤。
複製和重新命名項目之間的互動
為釐清複製和重新命名項目之間的互動方式,請參考以下範例:假設您使用特定 renamed_binary() 目標重新命名 foo 二進位檔的安裝位置。如果未選取任何建構變化版本,對應的建構資訊清單會包含兩個類似下列的項目:
{
"destination": "bin/foo",
"source": "foo",
"label": "//src:foo",
},
{
"destination": "bin/foo_renamed",
"renamed_from": "foo",
},
第一個一般項目表示 ${BUILD_DIR}/foo 是由預設工具鍊中的 //src:foo 目標建構,且應安裝至容器內的 bin/foo。
第二個複製項目表示,建構為 ${BUILD_DIR}/foo 的二進位檔應安裝至 bin/foo_renamed,而非預設位置 (即 bin/foo)。
從邏輯上來說,這相當於單一項目:
{
"destination": "bin/foo_renamed",
"source": "foo",
"label": "//src/foo",
},
也就是第一個項目,其中只有目的地路徑有所變更。
不過,如果建構相同項目時啟用 asan 變數,資訊清單內容會與先前略有不同:
{
"destination": "bin/foo",
"source": "x64-asan/foo",
"label": "//src:foo(//build/toolchain:x64-asan)",
},
{
"copy_from": "x64-asan/foo",
"copy_to": "foo",
},
{
"destination": "bin/foo_renamed",
"renamed_from": "foo",
},
現在,第一個項目會說明 ${BUILD_DIR}/x64-asan/foo 是由 asan 工具鍊 (//build/toolchain:x64-asan) 中的 //src:foo 目標建構,且仍會預設安裝至 bin/foo。
第二個項目表示 ${BUILD_DIR}/foo 是 ${BUILD_DIR}/x64-asan/foo 的實際副本,因為這是建構系統的運作方式。
第三個項目與先前相同,因為 renamed_binary() 目標不知道用於建構 ${BUILD_DIR}/foo 的工具鍊或變數。
這在邏輯上等同於單一項目,如下所示:
{
"destination": "bin/foo_renamed",
"source": "x64-shared/foo",
"label": "//src/foo(//build/toolchain:x64-asan)",
},
只有在啟用建構變體時,才會使用副本項目,這些項目會將重新命名的項目連結至變體專屬的常規項目。所有這些資訊分散各處的原因是,每個項目都是透過建構圖表中的不同目標產生,而且在 GN 生成階段無法將所有項目連結在一起。