Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

GNU make 顯示 jobserver unavailable?加入 -j 前先證明遞迴邊界

子 make 因未繼承協調通道而退回單一工作。找出第一個父配方或包裝器,只修正真正理解 jobserver 的邊界,再量測共享上限。

共享建置 jobserver 與斷線子層的原創示意圖。
Watch at Ease 原創示意:追蹤第一個失去共享通道的子層。 Watch at Ease

GNU make 的「jobserver unavailable: using -j1」表示子 make 未繼承足夠的父層連線,因此改為循序執行。它不證明編譯器失敗,也不代表每層都該有自己的 -j。

先找到協調首次遺失的邊界。真正的遞迴 make 配方使用 $(MAKE),只在辨識需要時使用 +,包裝器必須實作協定才可宣告感知,最後在單一頂層限制下驗證。

1. 擷取第一個遺失邊界

以原頂層命令執行一次受控建置,保存第一個警告、巢狀層級、父命令、版本、產生器、程序樹及 MAKEFLAGS 結構。後續重複通常只是結果,最早遺失點才是責任邊界。

區分直接啟動 make 的配方、shell 指令碼、CMake 自訂命令、語言包裝器和容器入口。報告中不要公開即時描述元或把其值複製到新命令。

2. 把警告視為協調失敗

GNU make 在 MAKEFLAGS 提供存取資訊,並為每個命令保留一個隱含槽位。已辨識的遞迴 make 共同遵守頂層工作上限。

父層若無法確定命令是另一個 make,子層只收到不完整資訊。管道模式因此失去描述元,發出警告並以 -j1 循序繼續。

3. 修正直接遞迴 make 配方

子命令確為 make 時,在配方直接使用 $(MAKE),不要寫死 make。這也保留父層使用的執行檔與 GNU make 的遞迴語意。

前導 + 可標記被間接隱藏的遞迴呼叫,但也影響空跑、touch 與 question 模式。只有 MAKE 無法直接出現或包裝器確實支援協定時使用。

4. 明確處理包裝器與 CMake

包裝器啟動子層時,要確認同時保留 MAKEFLAGS 與即時通道,不能只看環境字串。絕不要偽造 --jobserver-auth 或在父程序外重用描述元。

CMake 可在 JOB_SERVER_AWARE 為真時為支援的 Makefile 產生器加前綴。只對能正確參與協定的命令設定;Ninja 使用不同機制。

5. 拒絕預設的巢狀獨立 -j

不要為了消除警告而替每個子 make 加上 -jN。GNU make 說明強制數字 -j 會停用共享模式,使巢狀樹超出 CPU 或記憶體限制。

盡量只在頂層決定平行度。若外部包裝器需要獨立限制,記錄邊界、產生器、版本與資源上限,不要當成通用修正。

6. 驗證共享限制與建置

以固定頂層 -j 重跑相同乾淨目標。要求第一個警告消失,檢查尖峰程序數與實際重疊,同時比較 CPU、記憶體和耗時,不能只看速度。

執行一般測試與 CI 等價或低記憶體建置,核對空跑行為,保存修正前後命令和淨化後的 MAKEFLAGS 結構以供審查或還原。

開發者追蹤並修復遞迴建置邊界的原創示意圖。
Watch at Ease 原創示意:在責任邊界恢復協調,再量測共享限制。 Watch at Ease