distcc
distcc 是一個將 C、C++、Objective C 或 Objective C++ 等程序的編譯任務分發到網絡中多個主機的程序。distcc 力求實現和本地編譯相同的結果,安裝、使用都很方便,而且通常比本地編譯快很多。distcc 也可以與 Arch 原生的編譯工具,比如 makepkg,很好搭配使用。
名詞定義[編輯 | 編輯原始碼]
- 客戶機
- 啟動編譯的計算機。
- 志願機
- 接受客戶機發送的編譯請求的計算機。一個 distcc 編譯集群可以包含一台或多台志願機。
開始使用[編輯 | 編輯原始碼]
將整個編譯集群中的計算機都安裝軟體包 distcc包。如果是其他的發行版,甚至包括使用 Cygwin 的 Windows 作業系統,請閱讀 distcc 文檔或 distcc(1) 和 distccd(1) 的手冊頁。請保持 distcc 使用的埠暢通(默認是TCP 3632 埠),參見Category:Firewalls。
配置[編輯 | 編輯原始碼]
工作模式[編輯 | 編輯原始碼]
Distcc 可以在普通模式(默認模式)或泵模式下使用。簡單來講,這兩個模式的核心區別在於如何處理預處理過的原始碼。普通模式會傳遞預處理器展開過的原始碼和編譯選項,由客戶機負責預處理,而泵模式會把預處理和編譯工作全部分發到 distcc 編譯集群中,通常會更快、效率更高。更多細節請參見手冊頁 man distcc
。
志願機配置[編輯 | 編輯原始碼]
志願機的配置文件儲存在 /etc/conf.d/distccd
處。最簡單的例子,是添加 --allow-private 選項,這樣就能夠覆蓋整個 ipv4 區域網的範圍。保存日誌到文件也是排錯時經常需要的:
DISTCC_ARGS="--allow-private --log-file /tmp/distccd.log"
如果設備有很多網卡,請考慮添加 --listen <監聽地址>。其它設置請參考 distccd(1)。
在所有志願機上啟動服務 distccd.service
。要使服務開機自啟,請啟用此服務。
客戶機配置[編輯 | 編輯原始碼]
makepkg 編譯選項[編輯 | 編輯原始碼]
編輯/etc/makepkg.conf
的這些部分:
- 確保 BUILDENV 數組中的 distcc 沒有被禁用(即前面沒有感嘆號)
- 取消注釋並編輯DISTCC_HOSTS行 ,加入可以使用的志願機的 IP 地址或主機名。可以加上一個正斜槓("/")以及最大使用線程數。不同 IP 地址用空白隔開,這個清單應該按照處理器性能從高到低排列。
- 修改 MAKEFLAGS 中的 -jN 為所有使用線程數的和的兩倍。在下面的示例為 2x(9+5+5+3)=44。
CFLAGS
和 CXXFLAGS
中不能使用 -march=native
選項,否則 distccd 不會將編譯任務發給其它機器。另外,沒有一個萬能配置能夠覆蓋全部(尤其是線程數與 MAKEFLAGS 的並行線程數)。請一個一個測試您的參數,並與其他參數的結果做比較,以獲取最優的配置。下面是一些例子。
普通模式例子[編輯 | 編輯原始碼]
BUILDENV=(distcc fakeroot color !ccache check !sign) MAKEFLAGS="-j44" DISTCC_HOSTS="localhost/9 192.168.10.2/5 192.168.10.3/5 192.168.10.4/3"
泵模式例子[編輯 | 編輯原始碼]
BUILDENV=(distcc fakeroot color !ccache check !sign) MAKEFLAGS="-j70" DISTCC_HOSTS="localhost/9 192.168.10.2,cpp,lzo 192.168.10.3,cpp,lzo 192.168.10.4,cpp,lzo"
請注意以下事項:
- 並行數高的話,泵模式的表現通常更好。
- 在泵模式下,IP 地址或主機名會跟上指示泵模式所需要的",cpp,lzo"的後綴。此處的本機localhost沒有加上這個後綴,這意味著,distcc會按照普通模式嚴格向localhost安排9個任務,並激進地以泵模式向志願機分發其他任務,這是一個大集群中的通常實踐:客戶機通常不希望編譯任務阻塞他們,以此限制客戶機的任務數。如果您一視同仁,也可以加上這個後綴。
- 正如提到的那樣,沒有一個萬能配置能夠覆蓋全部情況。如何選擇一個最優的設置通常需要一些經驗。
非 makepkg 編譯選項[編輯 | 編輯原始碼]
普通模式例子[編輯 | 編輯原始碼]
下面的最小 distcc 客戶機配置包括了志願者設置,並將他們附加到PATH環境變量上。
$ export PATH="/usr/lib/distcc/bin:$PATH" $ export DISTCC_HOSTS="localhost/9 192.168.10.2/5 192.168.10.3/5 192.168.10.4/3"
泵模式例子[編輯 | 編輯原始碼]
$ export PATH="/usr/lib/distcc/bin:$PATH" $ export DISTCC_HOSTS="localhost/9 192.168.10.2,cpp,lzo 192.168.10.3,cpp,lzo 192.168.10.4,cpp,lzo"
編譯[編輯 | 編輯原始碼]
makepkg 編譯[編輯 | 編輯原始碼]
普通模式[編輯 | 編輯原始碼]
只要按照上面的過程配置好 /etc/makepkg.conf
就可以了。正常運行 makepkg 即可。
泵模式[編輯 | 編輯原始碼]
用戶必須在編譯前啟動分發泵。因為分發泵pump程序會在啟動時檢查DISTCC_HOSTS是否正確配置,因此我們需要先定義一個 DISTCC_HOSTS 搪塞過去。makepkg 會使用 /etc/makepkg.conf
裡定義的變量,因此不會影響。
$ export DISTCC_HOSTS="localhost,cpp,lzo" $ eval `pump --startup`
然後正常運行 makepkg 即可。
結束時,執行以下指令把分發泵關掉:
$ pump --shutdown
非 makepkg 編譯[編輯 | 編輯原始碼]
普通模式[編輯 | 編輯原始碼]
按照#非 makepkg 編譯選項章節配置好需要的變量後,直接調用編譯器即可:
$ make -j44
有些程序可能需要定義CC 和/或 CXX 變量才能正常工作:
$ make -j44 CC=distcc CXX=distcc
泵模式[編輯 | 編輯原始碼]
按照上面一節方法操作分發泵。其他內容和普通模式相同。
CMake 編譯[編輯 | 編輯原始碼]
使用以下 CMake 選項來使用 distcc 編譯一個使用 CMake 管理的項目:
$ cmake -DCMAKE_C_COMPILER_LAUNCHER=distcc -DCMAKE_CXX_COMPILER_LAUNCHER=distcc ...
監視進度[編輯 | 編輯原始碼]
軟體包 distcc包 提供了一個命令行界面的監視器 distccmon-text
來檢查編譯進度。
如果在調用這個命令行界面監視器加上一個空格和一個等待秒數,就可以按照秒數不斷更新顯示。
$ distccmon-text 3 29291 Preprocess probe_64.c 192.168.10.2[0] 30954 Compile apic_noop.c 192.168.10.2[0] 30932 Preprocess kfifo.c 192.168.10.2[0] 30919 Compile blk-core.c 192.168.10.2[1] 30969 Compile i915_gem_debug.c 192.168.10.2[3] 30444 Compile block_dev.c 192.168.10.3[1] 30904 Compile compat.c 192.168.10.3[2] 30891 Compile hugetlb.c 192.168.10.3[3] 30458 Compile catalog.c 192.168.10.4[0] 30496 Compile ulpqueue.c 192.168.10.4[2] 30506 Compile alloc.c 192.168.10.4[0]
使用 distcc 交叉編譯[編輯 | 編輯原始碼]
交叉編譯也可使用 distcc 助力。
- 客戶機必須運行在目標架構上。
- 其他架構的志願機可以協助編譯,但必須安裝對應的工具鏈,並配置 distcc。
ARM 架構 Arch Linux 客戶機與 x86_64 架構的志願機[編輯 | 編輯原始碼]
下面一節介紹了如何使用 x86_64 架構的志願機來幫助 Arch Linux ARM 架構設備編譯。只需要一台 x86_64 架構的志願機就能夠加快 2 到 4 倍的編譯速度,具體可以參見這些測試。
志願機[編輯 | 編輯原始碼]
Arch ARM 開發者強烈推薦使用並在 x86_64 架構的志願機上安裝官方的工具鏈。與其手動配置,AUR提供了所有的工具鏈、配置文件,和系統服務:
這些工具鏈的配置過程和#志願機配置一節完全相似,除了配置文件和系統服務文件對應包名有所更改。比如 armv7h 的配置文件是 /etc/conf.d/distccd-armv7h
,systemd 服務文件是 distccd-armv7h.service
。
注意這些工具鏈的埠都不同,使得他們可以共存而不衝突。請一定保持他們使用的埠暢通。(參見Category:Firewalls 和手冊頁 distcc(1))
目標架構 | distcc 埠 |
---|---|
armv7h | 3635 |
armv8h/aarch64 | 3636 |
客戶機[編輯 | 編輯原始碼]
配置 Arch ARM 客戶機的最簡單辦法是使用distccd-arch-armAUR包。這個包提供了針對Arch ARM架構的所有四個配置文件和系統服務配置文件。比如說如果運行的是armv7h固件,只需要配置 /etc/conf.d/distccd-armv7h
文件並按照上述內容編輯默認值。再啟動 distccd-armv7h.service
服務以編譯。
更詳細的介紹,請參見使用示例。
如果希望不使用AUR包而手動配置客戶機,可以按照通用的方法配置客戶機,但需要更改如下兩個內容來更改默認埠。例如(埠假設是按照上面的表格):
/etc/conf.d/distcc
: armv7h 示例:DISTCC_ARGS="--allow-private --log-level info --log-file /tmp/distccd-armv7h.log --port 3635"
/etc/makepkg.conf
: armv7h 示例:DISTCC_HOSTS="192.168.10.2/5:3635 192.168.10.3/5:3635"
x86_64 架構的 Arch Linux 客戶機與 ARM 架構志願機[編輯 | 編輯原始碼]
下面一節介紹了如何使用 ARM 架構的志願機來幫助x86_64 架構客戶機編譯。只需要一台 x86_64 架構的志願機就能夠顯著加快編譯速度,兩台設備就能翻倍。具體可以參見這些測試。
客戶機[編輯 | 編輯原始碼]
可以按照通用的方法配置客戶機,其對應的標準埠是 3632。
志願機[編輯 | 編輯原始碼]
distccd-x86_64AUR 提供了裝在 Arch ARM 設備上的交叉編譯工具。
附加工具鏈[編輯 | 編輯原始碼]
- EmbToolkit: 創建交叉編譯工具鏈的工具;支持 ARM 和 MIPS 架構;支持創建LLVM工具鏈
- crosstool-ng:和EmbToolkit相似,支持更多架構(更多信息參見其網站)
- Linaro:提供了ARM開發的工具鏈
EmbToolkit
有一個很好看的配置工具鏈的圖形配置菜單(make xconfig
)。
故障排除[編輯 | 編輯原始碼]
編譯 Arch Linux 內核包時的奇怪現象[編輯 | 編輯原始碼]
如果使用官方的PKGBUILD來編譯內核,distcc 將無法工作,因為內核硬編碼使用了一些GCC插件,因為一些技術原因distccd不能夠支持他們。
可以通過編輯內核、刪掉這些對 GCC 插件的要求來迂迴。可以在編譯前在 PKGBUILD 中用一行 sed 命令搞定:
sed -i '/HAVE_GCC_PLUGINS/d' arch/x86/Kconfig
如果不這樣就無法編譯。參見 FS#64275。
另一種辦法是編譯時傳遞 CC=distcc 和 CXX=distcc 變量:
make all CC=distcc CXX=distcc
編譯 chromium 包時的奇怪現象[編輯 | 編輯原始碼]
編譯 chromium包 會使用 clang,目前受到issue#386的影響。規避這個bug可以在PKGBUILD的_flags
數組中添加這些:
'is_cfi=false' 'use_gold=false' 'clang_use_default_sample_profile=false' 'chrome_pgo_phase=0'
Journalctl[編輯 | 編輯原始碼]
使用 journalctl
查看什麼地方出錯了:
# journalctl $(which distccd) -e --since "5 min ago"
調整日誌記錄等級[編輯 | 編輯原始碼]
通常來說,distcc會把log寫到 /var/log/messages.log
裡。一個技巧(這個是distccd的手冊頁推薦的)是寫到其他文件裡面,比如寫到內存(通過 /tmp)裡去。另一個技巧是提高日誌記錄等級,只記錄錯誤信息。這個等級可以是任何標準系統日誌等級,即critical、error、warning、notice、info,或者debug。
在客戶機上按照這些參數啟動distcc,或修改志願機的/etc/conf.d/distccd
文件的DISTCC_ARGS參數:
DISTCC_ARGS="--allow 192.168.10.0/24 --log-level error --log-file /tmp/distccd.log"
修改 $HOME/.distcc 文件夾位置以減少硬碟讀寫[編輯 | 編輯原始碼]
distcc 默認會創建 $HOME/.distcc
文件夾來暫時保存節點編譯相關的信息。下面的命令可以減少不必要的硬碟讀寫,尤其對 SSD 友好:
$ export DISTCC_DIR=/tmp/distcc
distccd-alarm 相關[編輯 | 編輯原始碼]
沒有那個文件或目錄[編輯 | 編輯原始碼]
與下例類似的錯誤表明用戶錯誤地啟動了 distcc包 而不是 distccd-alarm 包(即distccd-alarm-armv7hAUR,或 distccd-alarm-armv8AUR)提供的distccd。
請一定針對目標架構啟動正確的服務。
distcc[25479] (dcc_execvp) ERROR: failed to exec armv7l-unknown-linux-gnueabihf-g++: No such file or directory
另請參見[編輯 | 編輯原始碼]
- icecreamAUR - 一個更好配置的 distcc 分支。