本頁面著重於撰寫與 Windows 相容的規則、撰寫可攜式規則的常見問題,以及一些解決方案。
路徑
問題:
- 長度限制:路徑長度上限為 259 個字元。 - 雖然 Windows 也支援較長的路徑 (最多 32767 個字元),但許多程式都是以較低的限制建構而成。 - 請注意,您在動作中執行的程式有以下特性。 
- 工作目錄:長度同樣不得超過 259 個字元。 - 程序無法 - cd到長度超過 259 個字元的目錄。
- 區分大小寫:Windows 路徑不區分大小寫,Unix 路徑則區分大小寫。 - 為動作建立命令列時,請注意這點。 
- 路徑分隔符:是反斜線 ( - \`), not forward slash (/`)。- Bazel 會以 Unix 樣式儲存路徑,並使用 - /分隔符。雖然部分 Windows 程式支援 Unix 樣式的路徑,但其他程式則不支援。cmd.exe 中的部分內建指令支援這些字元,部分則不支援。- 為動作建立指令列和環境變數時,建議一律使用 - \` separators on Windows: replace/- with`。
- 絕對路徑:開頭不得為斜線 ( - /)。- Windows 的絕對路徑會以磁碟機代號開頭,例如 - C:\foo\bar.txt。沒有單一檔案系統根目錄。- 如果規則會檢查路徑是否為絕對路徑,請注意這點。絕對路徑通常無法移植,因此應避免使用。 
解決方法:
- 路徑應簡短。 - 避免使用過長的目錄名稱、巢狀結構過深的目錄結構、過長的檔案名稱、過長的工作區名稱和過長的目標名稱。 - 這些都可能成為動作輸入檔案的路徑元件,並可能超出路徑長度限制。 
- 使用簡短的輸出根目錄。 - 使用 - --output_user_root=<path>旗標指定 Bazel 輸出的簡短路徑。建議您為 Bazel 輸出內容 (例如- D:\`), and adding this line to your.bazelrc` 檔案) 專門建立磁碟機 (或虛擬磁碟機):- build --output_user_root=D:/- 或 - build --output_user_root=C:/_bzl
- 使用接合點。 - 從廣義上來說[1],接合點是目錄符號連結。連接點很容易建立,而且可以指向路徑較長的目錄 (位於同一部電腦上)。如果建構動作建立的路徑較短,但目標路徑較長,則路徑長度限制較短的工具可以存取連結目錄中的檔案。 - 在 - .bat檔案或 cmd.exe 中,您可以建立接合點,如下所示:- mklink /J c:\path\to\junction c:\path\to\very\long\target\path- [1]:嚴格來說,接合點並非符號連結,但為了建構動作,您可以將接合點視為目錄符號連結。 
- 在動作 / 環境變數的路徑中,將 - /替換為 ``。- 為動作建立指令列或環境變數時,請使用 Windows 樣式的路徑。範例: - def as_path(p, is_windows): if is_windows: return p.replace("/", "\\") else: return p
環境變數
問題:
- 區分大小寫:Windows 環境變數名稱不區分大小寫。 - 舉例來說,在 Java 中, - System.getenv("SystemRoot")和- System.getenv("SYSTEMROOT")會產生相同結果。(這也適用於其他語言)。
- Hermeticity:動作應盡量減少使用自訂環境變數。 - 環境變數是動作快取金鑰的一部分。如果動作使用經常變更或使用者專屬的環境變數,規則就比較無法快取。 
解決方法:
- 環境變數名稱只能使用大寫字母。 - 這項功能適用於 Windows、macOS 和 Linux。 
- 盡量減少動作環境。 - 使用 - ctx.actions.run時,請將環境設為- ctx.configuration.default_shell_env。如果動作需要更多環境變數,請將所有變數放入字典,然後傳遞至動作。範例:- load("@bazel_skylib//lib:dicts.bzl", "dicts") def _make_env(ctx, output_file, is_windows): out_path = output_file.path if is_windows: out_path = out_path.replace("/", "\\") return dicts.add(ctx.configuration.default_shell_env, {"MY_OUTPUT": out_path})
動作
問題:
- 可執行輸出內容:每個可執行檔都必須有可執行檔副檔名。 - 最常見的副檔名是 - .exe(二進位檔) 和- .bat(批次指令碼)。- 請注意,Shell 指令碼 ( - .sh) 無法在 Windows 上執行,因此您無法將其指定為- ctx.actions.run的- executable。檔案也沒有- +x權限,因此您無法像在 Linux 上一樣執行任意檔案。
- Bash 指令:為確保可攜性,請避免在動作中直接執行 Bash 指令。 - Bash 在類 Unix 系統上廣為使用,但通常無法在 Windows 上使用。Bazel 本身越來越少依賴 Bash (MSYS2),因此日後使用者安裝 Bazel 時,較不可能同時安裝 MSYS2。為方便在 Windows 上使用規則,請避免在動作中執行 Bash 指令。 
- 行尾:Windows 使用 CRLF ( - \r\n),類 Unix 系統則使用 LF (- \n)。- 比較文字檔時,請注意這點。請留意 Git 設定,特別是簽出或提交時的行尾。(請參閱 Git 的 - core.autocrlf設定)。
解決方法:
- 使用不含 Bash 的專用規則。 - native.genrule()是 Bash 指令的包裝函式,通常用於解決簡單問題,例如複製檔案或撰寫文字檔。您可以避免依賴 Bash (並重新發明輪子):看看 bazel-skylib 是否有符合您需求的專用規則。在 Windows 上建構/測試時,這些都不會依附於 Bash。- 建立規則範例: 
- write_file()(source, documentation): 寫入文字檔,並視需要加上行尾 (- auto、- unix或- windows),也可以選擇讓檔案可執行 (如果是指令碼)
- run_binary()(source, documentation): 以指定輸入內容和預期輸出內容執行二進位檔 (或- *_binary規則),做為建構動作 (這是- ctx.actions.run的建構規則包裝函式)
- native_binary()(來源、 說明文件): 將原生二進位檔包裝在- *_binary規則中,您可以在- bazel run中使用,或在- run_binary()的- tool屬性或- native.genrule()的- tools屬性中使用
 - 測試規則範例: - diff_test()(source, documentation): 比較兩個檔案內容的測試
- native_test()(來源、 說明文件): 將原生二進位檔包裝在- *_test規則中,您可以- bazel test
 
- 在 Windows 上,請考慮使用 - .bat指令碼處理瑣事。- 您可以使用 - .bat指令碼解決瑣碎的工作,不必再使用- .sh指令碼。- 舉例來說,如果您只需要執行空白指令碼、列印訊息,或以固定錯誤代碼結束,簡單的 - .bat檔案就已足夠。如果規則傳回- DefaultInfo()供應器,- executable欄位可能會參照 Windows 上的- .bat檔案。- 由於 macOS 和 Linux 不會理會副檔名,因此即使是殼層指令碼,您一律可以使用 - .bat做為副檔名。- 請注意,空白的 - .bat檔案無法執行。如需空白指令碼,請在其中輸入一個空格。
- 以有原則的方式使用 Bash。 - 在 Starlark 建構和測試規則中,使用 - ctx.actions.run_shell以動作形式執行 Bash 指令和 Bash 指令碼。- 在 Starlark 巨集中,將 Bash 指令碼和指令包裝在 - native.sh_binary()或- native.genrule()中。Bazel 會檢查 Bash 是否可用,並透過 Bash 執行指令碼或指令。- 在 Starlark 存放區規則中,請盡量避免使用 Bash。Bazel 目前無法在存放區規則中,以有原則的方式執行 Bash 指令。 
刪除檔案
問題:
- 檔案開啟時無法刪除。 - 根據預設,您無法刪除開啟的檔案,嘗試刪除時會收到「存取遭拒」錯誤訊息。如果無法刪除檔案,可能是因為執行中的程序仍開啟該檔案。 
- 無法刪除執行中程序的運作目錄。 - 程序具有工作目錄的開啟控制代碼,且在程序終止前無法刪除目錄。 
解決方法:
- 在程式碼中,嘗試盡早關閉檔案。 - 在 Java 中,請使用 - try-with-resources。在 Python 中,請使用- with open(...) as f:。原則上,請盡快關閉控制代碼。