交叉編譯工具打包準則 - Arch Linux 中文维基

跳至內容

# 交叉編譯工具打包準則

出自 Arch Linux 中文维基
Arch 打包準則

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉編譯工具 – KDE – Lisp – Meson – MinGW – 內核模塊 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字體

翻譯狀態：

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

本頁描述了如何打包交叉編譯器工具鏈。另一種交叉編譯的方法是在多種架構上使用 distcc。參見 Distcc#使用 distcc 交叉編譯。

提示：打包交叉編譯器還可使用 crosstool-ng，以完全自動化的方式創建自己的工具鏈。詳情請見 crosstool-ng包。

## 重要提示

受以下軟體包啟發，本文介紹新的打包方法：

- mingw-w64-gcc包 以及 `mingw-w64-*` 系列的其他軟體包
- arm-none-eabi-gcc包 以及 `arm-none-eabi-*` 系列的其他軟體包
- `arm-wince-cegcc-*` 系列的其他軟體包

## 版本兼容性

警告：使用不兼容版本的軟體包編譯工具鏈必然會失敗。一般來說，不同版本之間都不兼容。

建議按照以下策略選擇 gcc、binutils、內核和 C 庫的兼容版本：

- 總則：
  - gcc 和 binutils 的版本相關，建議使用同時發布的版本；
  - 建議使用最新的內核頭文件來編譯 libc，但使用 `--enable-kernel`（只保證適用於 glibc，其他 C 庫可能約定不同）能強制在舊內核上工作；
- 官方倉庫：可能需要額外的修正，但 Arch Linux（或其特定架構的分支）使用的版本很可能可以協同工作；
- 軟體文檔：所有 GNU 軟體都有 `README` 和 `NEWS` 文件，涵蓋了依賴關係的最低版本要求等內容；
- 其他發行版：同樣也進行交叉編譯
- https://trac.clfs.org 涵蓋了構建交叉編譯器的必要步驟以及一些依賴的最新版本。

## 構建交叉編譯器

構建交叉編譯器的一般方法是：

1. binutils：構建為目標架構連結、處理的 cross-binutils。
2. 頭文件：安裝目標架構的 C 庫和內核頭文件。
   1. 參考 linux-api-headers包，並將 `ARCH=target-architecture` 參數傳給 make
   2. 打包 libc 頭文件 (此處描述了 Glibc 的處理方法)
3. gcc 第 1 階段：構建基本的（第 1 階段）gcc 交叉編譯器。這將被用來編譯 C 庫，但是幾乎不能編譯其他任何東西（因為無法連結不存在的 C 庫）。
4. libc：構建交叉編譯的 C 庫（使用第 1 階段的交叉編譯器）。
5. gcc 第 2 階段：構建完整的（第 2 階段）C 交叉編譯器。

頭文件和 libc 的原始碼因平台而異。

提示：根據需求的不同，具體操作步驟也不盡相同。例如，如果想創建內核和 glibc 版本與 Arch Linux 系統相同的 "克隆版"，可不構建頭文件直接將 `--with-build-sysroot=/` 傳給 `configure`。

## 軟體包命名

軟體包名稱不應以 `cross-` 開頭（之前建議使用前綴 `cross-`，但可能由於包名太長，在正式的軟體包中未被採用），而應由軟體包名稱組成，前綴為 GNU triplet，不含廠商欄位或在廠商欄位中含 "unknown"。例如：`arm-linux-gnueabihf-gcc`。如果存在更短的命名規則（例如：`mips-gcc`），可以使用但並不建議。

## 放置文件

最新版本的 gcc 和 binutils 對系統根目錄和庫使用不衝突的路徑。可執行文件應放在 `/usr/bin/` 中。為防止衝突，應在所有文件前加上架構名稱。

通常來說，`./configure` 應至少含以下參數：

    _target=your_target
    _sysroot=/usr/lib/${_target}
    ...
    ./configure \
        --prefix=${_sysroot} \
        --sysroot=${_sysroot} \
        --bindir=/usr/bin

其中 `your_target` 可自行修改，例如修改為 "i686-pc-mingw32"。

## 示例

此處以 MinGW 的 binutils 的 PKGBUILD 為例。需要注意的是：

- 指定交叉編譯環境的根目錄
- 使用 `${_pkgname}` 、`${_target}` 和 `${_sysroot}` 能使代碼更易讀
- 刪除重複或衝突的文件

    # Maintainer: Allan McRae <allan@archlinux.org>

    # cross toolchain build order: binutils, headers, gcc (pass 1), w32api, mingwrt, gcc (pass 2)

    _target=i686-pc-mingw32
    _sysroot=/usr/lib/${_target}

    pkgname=${_target}-binutils
    _pkgname=binutils
    pkgver=2.19.1
    pkgrel=1
    pkgdesc="MinGW Windows binutils"
    arch=('i686' 'x86_64')
    url="http://www.gnu.org/software/binutils/"
    license=('GPL')
    depends=('glibc>=2.10.1' 'zlib')
    options=('!libtool' '!distcc' '!ccache')
    source=(http://ftp.gnu.org/gnu/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2)
    md5sums=('09a8c5821a2dfdbb20665bc0bd680791')

    build() {
      cd ${srcdir}/${_pkgname}-${pkgver}
      mkdir binutils-build && cd binutils-build

      ../configure --prefix=${_sysroot} --bindir=/usr/bin \
        --with-sysroot=${_sysroot} \
        --build=$CHOST --host=$CHOST --target=${_target} \
        --with-gcc --with-gnu-as --with-gnu-ld \
        --enable-shared --without-included-gettext \
        --disable-nls --disable-debug --disable-win32-registry
      make
      make DESTDIR=${pkgdir}/ install

      # clean-up cross compiler root
      rm -r ${pkgdir}/${_sysroot}/{info,man}
    }

注意：在交叉編譯工具鏈構建過程中，每次都從獨立的目錄中執行 `configure` 和 make 命令（所謂的樹外編譯），並在 PKGBUILD 發生變化後刪除整個 `src` 目錄（即使變化很小）。

## 疑難解答

### 為什麼不安裝到 /opt？

有以下兩個原因：

1. 首先，根據文件系統層次結構標準 (FHS)，這些文件只位於 `/usr` 的某個位置。
2. 其次，安裝到 `/opt` 是退而求其次的選擇。

### "路徑外的可執行文件 (out-of-path executables)" 是什麼？

這看起來很奇怪，但能讓交叉編譯更容易。有時項目的 Makefile 不使用 `CC` 或其他變量，而是直接使用 gcc 。在嘗試交叉編譯這樣的項目時，編輯 Makefile 可能會很麻煩。然而，將 `$PATH` 改為優先使用我們的可執行文件即可解決此問題，只需將 `make` 改為執行 `PATH=/usr/arch/bin/:$PATH make`。

## 故障排除

### 編譯失敗但沒有明確的提示應該如何解決？

如果是在運行 `configure` 時發生的錯誤，參見 `$srcdir/pkgname -build/config.log`。如果是在編譯過程中發生的錯誤，請向上滾動控制台日誌或搜索 "error" 一詞。

### [error message] 錯誤意味著什麼？

很可能犯了一些不明顯的錯誤：

- 配置標誌位過多或過少。嘗試使用已證明有效的標誌位。
- 依賴關係被破壞。例如，binutils 文件放錯位置或丟失，可能導致 gcc 配置過程中出現晦澀難懂的錯誤信息。
- 未在 `build()` 函數中添加 `export CFLAGS=""`（參見 GCC Bugzilla 中的 bug 25672）。
- 某些 `--prefix` 或 `--with-sysroot` 參數組合可能要求目錄可寫。
- 系統根目錄缺少內核頭文件或 libc 頭文件。
- 如果通過搜尋引擎仍無法解決，建議立刻放棄當前配置，嘗試更穩定、更成熟的配置。

### 為什麼文件安裝位置會不正確？

執行 `make install` 命令的各種方法會產生不同的結果。例如，有些 make 目標可能不提供 `DESTDIR` 支持，而是要求使用`install_root`。對於 `tooldir`、`prefix` 和其他類似參數也是如此。有時提供參數而不是環境變量，例如

    ./configure CC=arm-elf-gcc

而不是

    CC=arm-elf-gcc ./configure

反之亦然，可能會導致不同的結果（通常是因為 configure/make 遞歸地調用自身）。

## 另請參閱

- https://wiki.osdev.org/GCC_Cross-Compiler (English)

分類：​

- Arch 打包準則

交叉編譯工具打包準則
新增話題