distcc - Arch Linux 中文维基

跳至內容

# distcc

出自 Arch Linux 中文维基

相關文章

- TORQUE
- Slurm

翻譯狀態：

- 本文（或部分內容）譯自 Distcc，最近一次同步於 2021-04-15，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

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`的這些部分：

1. 確保 BUILDENV 數組中的 distcc 沒有被禁用(即前面沒有感嘆號)
2. 取消注釋並編輯DISTCC_HOSTS行 ，加入可以使用的志願機的 IP 地址或主機名。可以加上一個正斜槓（"/"）以及最大使用線程數。不同 IP 地址用空白隔開，這個清單應該按照處理器性能從高到低排列。
3. 修改 MAKEFLAGS 中的 -jN 為所有使用線程數的和的兩倍。在下面的示例為 2x(9+5+5+3)=44。

注意：雖然 IP 地址或主機名都可以描述志願機，但如果使用 devtools 的編譯腳本，現在仍然不支持主機名解析，此時請使用 IP 地址代替。另外，每次編譯都進行的主機名解析可能會塞滿一些DNS設備的日誌（比如pi-hole），此時指定 IP 地址就不會有這些麻煩。
注意： `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提供了所有的工具鏈、配置文件，和系統服務：

- distccd-alarm-armv7hAUR
- distccd-alarm-armv8AUR

這些工具鏈的配置過程和#志願機配置一節完全相似，除了配置文件和系統服務文件對應包名有所更改。比如 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包而手動配置客戶機，可以按照通用的方法配置客戶機，但需要更改如下兩個內容來更改默認埠。例如（埠假設是按照上面的表格）：

1. `/etc/conf.d/distcc`: armv7h 示例： `DISTCC_ARGS="--allow-private --log-level info --log-file /tmp/distccd-armv7h.log --port 3635"`
2. `/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

## 另請參見

- https://github.com/distcc/distcc

- icecreamAUR - 一個更好配置的 distcc 分支。

分類：​

- 包開發
- 分布式計算
- 網絡
- 開發

distcc
新增話題