依附元件

回報問題 查看來源 夜間 7.2 7.1 7.0 6.5 6.4

如果 A 在建構或建構時需要 B,則目標 A「取決於」目標 B 執行時間。取決於關係 有向非循環圖 (DAG) 取代目標,也稱為依附元件圖表

目標的「直接」依附元件是指可透過路徑連上的其他目標 依附元件圖表中。目標的「遞移」依附元件為 透過圖表中任何長度的路徑來判定的指定目標。

事實上,在建構作業中,有兩種依附元件圖表 「實際依附元件」和「宣告的依附元件」圖表。大部分 這兩個圖表很相似,因此無須做出這項區別,但 這對於進行下方的討論會很有幫助。

實際和宣告的依附元件

如果必須含有 Y,目標 X實際上取決於目標 Y。 以便確保 X 能正確建構。已打造 均產生、處理、編譯、連結、封存、壓縮、執行,或是 任何在建構期間經常執行的作業。

如果有依附元件,目標 X 在目標 Y 上具有宣告的依附元件 X 套件中的邊緣從 XY

如要正確建構,實際依附元件 A 的圖表必須是 宣告依附元件 D 的圖表。也就是說 直接連結節點 x --> y (位於 A) 也必須 D:儘管 DA高估值,

BUILD 檔案寫入者必須明確宣告 對建構系統而言,每個規則的依附元件都不相同。

如果未觀察到這項原則,會導致未定義的行為:建構作業可能會失敗 但更糟的是,建構作業可能會依賴之前的作業 指定要套用的依附元件Bazel 檢查是否缺少 依附元件和回報錯誤,但無法執行這項檢查 而且應該在所有情況下完成

您不一定要 (也不要) 嘗試列出所有間接匯入的、 即使在執行時由 A 需要也一樣。

在目標 X 建構期間,建構工具會檢查整個遞移性 關閉 X 的依附元件,確保這些目標的任何變更 並視情況重新建構中繼資訊。

依附元件的遞移性質會導致常見錯誤。有時候, 某個檔案中的程式碼可以使用「間接」依附元件提供的程式碼, 宣告的依附元件圖表中並未直接呈現邊緣,而非直接的邊緣間接 BUILD 檔案中未顯示依附元件。由於規則 直接依供應商而定,但無法追蹤變更,如以下所示: 以下的時間軸範例:

1. 宣告的依附元件與實際依附元件相符

首先是一切都能正常運作套件 a 中的程式碼使用套件 b 中的程式碼。 套件 b 中的程式碼使用套件 c 中的程式碼,因此會間接 a 依附於 c

a/BUILD b/BUILD
rule(
    name = "a",
    srcs = "a.in",
    deps = "//b:b",
)
      
rule(
    name = "b",
    srcs = "b.in",
    deps = "//c:c",
)
      
a / a.in b / b.in
import b;
b.foo();
    
import c;
function foo() {
  c.bar();
}
      
已宣告的依附元件圖,內含連接 a、b 和 c 的箭頭
已宣告依附元件圖表
與宣告依附元件相符的實際依附元件圖
                  含有連接 a、b 和 c 的箭頭的圖表
實際依附關係圖

宣告的依附元件高於實際依附元件。一切都很好。

2. 新增未宣告的依附元件

當使用者在 a 中新增程式碼,而該物件會建立 直接使用 c 的「實際」依附元件,但忘記在建構檔案中宣告 a/BUILD

a / a.in  
        import b;
        import c;
        b.foo();
        c.garply();
      
 
已宣告的依附元件圖,內含連接 a、b 和 c 的箭頭
已宣告依附元件圖表
實際的依附關係圖,以及一個連接 a、b 和 c 的箭頭。一個
                  箭頭現在也會將 A 連結至 C。這與
                  宣告的依附元件圖
實際依附關係圖

宣告的依附元件不再高估實際依附元件。 這比較合理,因為這兩個圖形的遞移性是平等的 但掩飾一個問題:ac 上確實有實際但未宣告的依附元件。

3. 宣告的依附元件與實際依附元件圖表之間的差異

當有人重構 b,使其不再仰賴時,便會顯示危險 c,意外破壞 a 到 否 造成的損害

  b/BUILD
 
rule(
    name = "b",
    srcs = "b.in",
    deps = "//d:d",
)
      
  b / b.in
 
      import d;
      function foo() {
        d.baz();
      }
      
已宣告的依附關係圖,以及一個連接 a 和 b 的箭頭。
                  b 無法再連線到 c,導致與 c 的連線中斷
已宣告依附元件圖表
實際依附關係圖,顯示連結至 b 和 c。
                  但是 b 無法再連線到 c
實際依附關係圖

所宣告的依附元件圖表現在與實際資料 依附元件可能會失敗

確保實際的依附元件 在步驟 2 中導入的 ca 已在 BUILD 檔案中正確宣告。

依附元件類型

大多數的建構規則都有三個屬性,可用來指定不同種類的 一般依附元件:srcsdepsdata。說明如下:適用對象 如需詳細資訊,請參閱 所有規則通用的屬性

許多規則也針對特定規則的類型有額外屬性 依附元件,例如 compilerresources詳細說明請見 建構百科全書

srcs 項依附元件

直接由輸出來源檔案的規則或規則使用的檔案。

deps 項依附元件

指向提供標頭檔案的個別編譯模組的規則。 符號、程式庫、資料等

data 項依附元件

建構目標可能需要一些資料檔案才能正確執行。這些資料檔案 ,因為它們不會影響目標的建構方式。舉例來說 單元測試可能會比較函式輸出內容與檔案內容。當您 建構單元測試不需要檔案,但執行時 需要用到 進行測試。同樣的原則也適用於執行期間啟動的工具。

建構系統會在獨立目錄中執行測試,其中僅列出下列檔案: 您可以改用 data。因此,如果二進位檔/程式庫/測試需要一些檔案才能執行 可在 data 中指定這些 API,或包含那些物件的建構規則。例如:

# I need a config file from a directory named env:
java_binary(
    name = "setenv",
    ...
    data = [":env/default_env.txt"],
)

# I need test data from another directory
sh_test(
    name = "regtest",
    srcs = ["regtest.sh"],
    data = [
        "//data:file1.txt",
        "//data:file2.txt",
        ...
    ],
)

您可以使用相對路徑 path/to/data/file 存取這些檔案。在測試中 您可以彙整測試來源的路徑來參照這些檔案 目錄和 Workspace 相關路徑 ${TEST_SRCDIR}/workspace/path/to/data/file

使用標籤參照目錄

查看 BUILD 檔案時,您可能會發現一些 data 標籤 參照目錄這些標籤結尾是 /./ (像這些範例)、 請不要使用:

不建議使用 - data = ["//data/regression:unittest/."]

不建議使用 - data = ["testdata/."]

不建議使用 - data = ["testdata/"]

這看起來很方便,特別是用於測試,因為可以測試 使用目錄中的所有資料檔案。

但請盡量不要這麼做。為確保正確執行漸進式重建作業 ( 重新執行測試) 後,建構系統必須知道 完整的檔案組合,這是建構 (或測試) 的輸入內容。如果指定 ,只有在目錄本身時,建構系統才會執行重新建構。 變更 (由於新增或刪除檔案),但偵測不到 編輯個別檔案,因為這些變更不會影響該目錄內的檔案。 與其將目錄指定為建構系統的輸入內容, 明確或使用 glob() 函式。(使用 ** 即可強制執行 glob() 設為遞迴)。

建議使用 - data = glob(["testdata/**"])

不幸的是,在某些情況下必須使用目錄標籤。 舉例來說,如果 testdata 目錄包含檔案名稱 符合標籤語法 然後明確列舉檔案或使用 glob() 函式會產生無效的標籤 錯誤。在此情況下,您必須使用目錄標籤。不過請留意 上述錯誤重建作業的相關風險。

請注意,若必須使用目錄標籤,則無法參照 具有相對 ../ 路徑的父項套件。建議您改用 //data/regression:unittest/.

如有任何外部規則 (例如測試) 需要使用多個檔案,則必須 明確宣告所有依附元件的依附性。您可以使用 filegroup() 執行下列操作: 在 BUILD 檔案中將檔案分組:

filegroup(
        name = 'my_data',
        srcs = glob(['my_unittest_data/*'])
)

然後,您就可以在測試中參照標籤 my_data 做為資料依附元件。

製作檔案 瀏覽權限