iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0

本日內容

  • Toolchain 是什麼?
  • 安裝 crosstool-NG
  • 設定 Toolchain
  • Build Toolchain
  • 預告

Day 27 - Colab

Toolchain 是什麼?

Toolchain, 就像他的名字一樣, 就是一堆 tools 將彼此的 input 和 output 串起來, 最終產生該平台的 binary

說起來簡單, 但實際上到底有哪些東西呢?
詳細內容可以參考 crosstool-NG 文章, 這邊僅簡單敘述

下面的每個工具的 output, 都會是下一個工具的 input
換句話說, 較後面的工具會 depends 前一個工具, 最終變成一大串肉粽
也就是 toolchain 所需要的 cross compiler

  1. GMP
  2. MPFR
  3. MPC
  4. binutils
  5. core pass 1 compiler
  6. kernel headers
  7. C library headers and start files
  8. core pass 2 compiler
  9. complete C library
  10. final compiler

從 2-pass compiler 開始就是 platform-dependent 了

總而言之, 為了達成 cross compile 的目的
我們需要釐清這串肉粽的依賴鏈, 才能知道不同平台需要哪些工具, 而這些工具又 depends 哪些工具 (好繞口...)

詳細如何 build 出 cross compiler 請見 此文章

好在這些事情已經有人幫我們處理了, 就是今天 demo 會使用的 crosstool-NG!

crosstool-NG 提供了很多平台的 config 檔 (下面會介紹)
讓我們根據這些 config 檔 build 出不同平台的 cross toolchain

下面會用 x86_64-ubuntu16.04-linux-gnu 作為範例
從安裝 crosstool-NG 開始到最後 build 出 toolchain 完整操作一遍!

安裝 crosstool-NG

詳細安裝步驟請見 官方文件

  1. 官網 下載 crosstool-ng, 這邊我們下載 txz 版本
wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.25.0.tar.xz
  1. 解壓縮
tar xf crosstool-ng-1.25.0.tar.xz
  1. 在 crosstool 下 configure
    Colab 還需要裝 gperf, bison, help2man, libtool-bin, libtool-doc, flex, texinfo 才能正常設定
apt-get install -y \
  libtool-bin \
  libtool-doc \
  help2man \
  gperf \
  bison \
  flex \
  texinfo \
  gawk
cd crosstool-ng-1.25.0
./configure --prefix=/usr/local
  1. Compile 並安裝到系統
make && sudo make install
  1. 安裝成功後, 我們就可以用 ct-ng 來設定 toolchain package 啦!!!
ct-ng --version

設定 Toolchain

我們可以設定

  • 想要的 Toolchain
  • 安裝路徑
  • Architecture
  • Processors
  • Components 版本

有兩種方法: GUI (Linux-kernel style) 和 CLI

GUI

可以用 ct-ng menuconfig 來叫出 gui 來設定, 清楚明瞭
這種方法適合想要客製化 toolchain config 的人
https://ithelp.ithome.com.tw/upload/images/20230928/20161950V4j2f89AU5.png

不過因為我們是用 Colab 環境, 比較不方便用 GUI, 這邊就略過不介紹了

所以我們會用第二種方法: 從 CLI 設定

CLI

crosstool-ng 提供了很~多 toolchain 的 config samples 在 samples/ 底下, 我們可以用 CLI 看

$ ct-ng list-samples
...
[G..X]   tic6x-uclinux
[G...]   x86_64-centos6-linux-gnu
[G...]   x86_64-centos7-linux-gnu
[G...]   x86_64-multilib-linux-gnu
[G..X]   x86_64-multilib-linux-musl
[G...]   x86_64-multilib-linux-uclibc
[G..X]   x86_64-w64-mingw32,x86_64-pc-linux-gnu
[G...]   x86_64-ubuntu14.04-linux-gnu
[G...]   x86_64-ubuntu16.04-linux-gnu
[G...]   x86_64-unknown-linux-gnu
[G...]   x86_64-unknown-linux-uclibc
[G..X]   x86_64-w64-mingw32
[G..X]   xtensa-fsf-elf
[G...]   xtensa-fsf-linux-uclibc
 L (Local)       : sample was found in current directory
 G (Global)      : sample was installed with crosstool-NG
 X (EXPERIMENTAL): sample may use EXPERIMENTAL features
 B (BROKEN)      : sample is currently broken
 O (OBSOLETE)    : sample needs to be upgraded

在各個 toolchain folder 底下都會有 crosstool.config config 檔
我們將想要 cross compile 的目標 config 複製為 .config 並存到當前的路徑底下
這邊以 x86_64-ubuntu16.04-linux-gnu 為例 (x86_64-ubuntu16.04-linux-gnu 稱為 target tripe, 長相如下
<arch>[<endian>][-<vender>]-<kernel>[-<os>])

cp samples/x86_64-ubuntu16.04-linux-gnu/crosstool.config .config

再用 yes "" | ct-ng oldconfig 進行設定 (這裡我們用 yes 直接套用所有默認的設定)

設定完成後, 我們可以用 ct-ng show-config 確認剛剛環境是否設定成功
如果成功的話, 應該要看到我們剛剛選擇的環境設定

$ ct-ng show-config

[l...]   x86_64-ubuntu16.04-linux-gnu
    Languages       : C,C++
    OS              : linux-4.4.302
    Binutils        : binutils-2.38
    Compiler        : gcc-11.2.0
    C library       : glibc-2.23
    Debug tools     :
    Companion libs  : gettext-0.21 gmp-6.2.1 isl-0.24 libiconv-1.16 mpc-1.2.1 mpfr-4.1.0 ncurses-6.2 zlib-1.2.12
    Companion tools : autoconf-2.71 automake-1.16.1

這樣就設定成功啦!

Build Toolchain

先確認 toolchain 需要的 dependencies 是否能正常下載, 沒問題後再開始 build toolchain

ct-ng source

:::warning
目前在下載 zlib 時存在已知問題: crosstool-ng#1337
Workaround 是我們需要手動去下載 toolchain 需要的 tarball

wget https://zlib.net/fossils/zlib-1.2.12.tar.gz
cp zlib-1.2.12.tar.gz .build/tarballs/

之後就可以開始 build toolchain 了!
:::

:::warning
因為我們是用 Colab, 需要額外一些設定

  1. Allow run as root
    修改 .config, 加入以下幾個設定
CT_EXPERIMENTAL=y
CT_ALLOW_BUILD_AS_ROOT=y
CT_ALLOW_BUILD_AS_ROOT_SURE=y
printf 'CT_EXPERIMENTAL=y\nCT_ALLOW_BUILD_AS_ROOT=y\nCT_ALLOW_BUILD_AS_ROOT_SURE=y' >> .config
  1. 清掉 LD_LIBRARY_PATHLIBRARY_PATH
export LD_LIBRARY_PATH=
export LIBRARY_PATH
import os
if 'LD_LIBRARY_PATH' in os.environ:
  del os.environ['LD_LIBRARY_PATH']
if 'LIBRARY_PATH' in os.environ:
  del os.environ['LIBRARY_PATH']

:::

處理完必要的設定後, 就可以開始 build toolchain 啦!

ct-ng build

我們可以從以下部分 output 看出 ct-ng 幫我們 build 了哪些 tools
因為是整條 toolchain 都要 build, 所以需要很多時間

[INFO ]  Performing some trivial sanity checks
[INFO ]  Build started 20230927.124446
[INFO ]  Building environment variables
[WARN ]  Directory '/root/src' does not exist.
[WARN ]  Will not save downloaded tarballs to local storage.
[EXTRA]  Preparing working directories
[EXTRA]  Installing user-supplied crosstool-NG configuration
[EXTRA]  =================================================================
[EXTRA]  Dumping internal crosstool-NG configuration
[EXTRA]    Building a toolchain for:
[EXTRA]      build  = x86_64-pc-linux-gnu
[EXTRA]      host   = x86_64-pc-linux-gnu
[EXTRA]      target = x86_64-ubuntu16.04-linux-gnu
[EXTRA]  Dumping internal crosstool-NG configuration: done in 0.12s (at 00:01)
[INFO ]  =================================================================
[INFO ]  Retrieving needed toolchain components' tarballs
[EXTRA]    Retrieving 'linux-4.4.302'
[EXTRA]    Verifying SHA512 checksum for 'linux-4.4.302.tar.xz'
[EXTRA]    Retrieving 'ncurses-6.2'
[EXTRA]    Verifying SHA512 checksum for 'ncurses-6.2.tar.gz'
[EXTRA]    Retrieving 'libiconv-1.16'
[EXTRA]    Verifying SHA512 checksum for 'libiconv-1.16.tar.gz'
[EXTRA]    Retrieving 'gettext-0.21'
[EXTRA]    Verifying SHA512 checksum for 'gettext-0.21.tar.xz'
[EXTRA]    Retrieving 'glibc-2.23'
[EXTRA]    Verifying SHA512 checksum for 'glibc-2.23.tar.xz'
[INFO ]  Retrieving needed toolchain components' tarballs: done in 7.22s (at 00:09)
[INFO ]  =================================================================
[INFO ]  Extracting and patching toolchain components
[EXTRA]    Extracting linux-4.4.302
[EXTRA]    Patching linux-4.4.302
[EXTRA]    Extracting ncurses-6.2
[EXTRA]    Patching ncurses-6.2
[EXTRA]    Extracting libiconv-1.16
[EXTRA]    Patching libiconv-1.16
[EXTRA]    Extracting gettext-0.21
[EXTRA]    Patching gettext-0.21
[EXTRA]    Extracting glibc-2.23
[EXTRA]    Patching glibc-2.23
[INFO ]  Extracting and patching toolchain components: done in 35.60s (at 00:44)
[INFO ]  =================================================================
[INFO ]  Installing ncurses for build
[EXTRA]    Configuring ncurses
[EXTRA]    Building ncurses
[EXTRA]    Installing ncurses
[INFO ]  Installing ncurses for build: done in 48.22s (at 01:33)
[INFO ]  =================================================================
[INFO ]  Installing zlib for host
[EXTRA]    Configuring zlib
[EXTRA]    Building zlib
[EXTRA]    Installing zlib
[INFO ]  Installing zlib for host: done in 11.21s (at 01:44)
[INFO ]  =================================================================
[INFO ]  Installing GMP for host
[EXTRA]    Configuring GMP
[EXTRA]    Building GMP
[EXTRA]    Installing GMP
[INFO ]  Installing GMP for host: done in 83.08s (at 03:07)
[INFO ]  =================================================================
[INFO ]  Installing MPFR for host
[EXTRA]    Configuring MPFR
[EXTRA]    Building MPFR
[EXTRA]    Installing MPFR
[INFO ]  Installing MPFR for host: done in 56.22s (at 04:03)
[INFO ]  =================================================================
[INFO ]  Installing ISL for host
[EXTRA]    Configuring ISL
[EXTRA]    Building ISL
[EXTRA]    Installing ISL
[INFO ]  Installing ISL for host: done in 85.82s (at 05:29)
[INFO ]  =================================================================
[INFO ]  Installing MPC for host
[EXTRA]    Configuring MPC
[EXTRA]    Building MPC
[EXTRA]    Installing MPC

build 完後就可以在 ~/x-tools 底下看到我們 Linux 的 toolchain x86_64-ubuntu16.04-linux-gnu 了🎉🎉🎉

https://ithelp.ithome.com.tw/upload/images/20230928/20161950vN9njfUZUD.png

為什麼有兩個 Toolchain Folder?

從上圖可以看到, 我們的 toolchain folder x86_64-ubuntu16.04-linux-gnu 底下還有另外一個相同名稱的 folder, 這兩個有什麼區別呢?

外層的 Folder

從這一層開始就是 cross compile 會用到的地方了
這一層又叫做 Toolchain Directory, 可以看作是當前系統和目標系統的中介 (cross build)

ls -lh ~/x-tools/x86_64-ubuntu16.04-linux-gnu

total 808K
dr-xr-xr-x 2 root root 4.0K Sep 27 14:10 bin/
-r--r--r-- 1 root root 784K Sep 27 14:10 build.log.bz2
dr-xr-xr-x 2 root root 4.0K Sep 27 14:09 include/
dr-xr-xr-x 4 root root 4.0K Sep 27 14:09 lib/
dr-xr-xr-x 3 root root 4.0K Sep 27 14:09 libexec/
dr-xr-xr-x 4 root root 4.0K Sep 27 14:10 share/
dr-xr-xr-x 8 root root 4.0K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu/

bin 包含了產生目標系統 binary 所需要的 cross toolchain

ls -lh ~/x-tools/x86_64-ubuntu16.04-linux-gnu/bin

total 60M
-r-xr-xr-x 1 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-addr2line*
-r-xr-xr-x 2 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-ar*
-r-xr-xr-x 2 root root  2.1M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-as*
-r-xr-xr-x 2 root root  1.2M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-c++*
lrwxrwxrwx 1 root root    32 Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-cc -> x86_64-ubuntu16.04-linux-gnu-gcc*
-r-xr-xr-x 1 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-c++filt*
-r-xr-xr-x 1 root root  1.2M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-cpp*
-r-xr-xr-x 1 root root  5.1K Sep 27 12:44 x86_64-ubuntu16.04-linux-gnu-ct-ng.config*
-r-xr-xr-x 1 root root   43K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-elfedit*
-r-xr-xr-x 2 root root  1.2M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-g++*
-r-xr-xr-x 2 root root  1.2M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcc*
-r-xr-xr-x 2 root root  1.2M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcc-11.2.0*
-r-xr-xr-x 1 root root   35K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcc-ar*
-r-xr-xr-x 1 root root   35K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcc-nm*
-r-xr-xr-x 1 root root   35K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcc-ranlib*
-r-xr-xr-x 1 root root  793K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcov*
-r-xr-xr-x 1 root root  565K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcov-dump*
-r-xr-xr-x 1 root root  593K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gcov-tool*
-r-xr-xr-x 1 root root  1.4M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-gprof*
-r-xr-xr-x 4 root root  2.7M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-ld*
-r-xr-xr-x 4 root root  2.7M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-ld.bfd*
-r-xr-xr-x 1 root root   15K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-ldd*
-r-xr-xr-x 1 root root   28M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-lto-dump*
-r-xr-xr-x 2 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-nm*
-r-xr-xr-x 2 root root  1.5M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-objcopy*
-r-xr-xr-x 2 root root  2.7M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-objdump*
-r-xr-xr-x 1 root root   11K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-populate*
-r-xr-xr-x 2 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-ranlib*
-r-xr-xr-x 2 root root 1003K Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-readelf*
-r-xr-xr-x 1 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-size*
-r-xr-xr-x 1 root root  1.3M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-strings*
-r-xr-xr-x 2 root root  1.5M Sep 27 14:10 x86_64-ubuntu16.04-linux-gnu-strip*

內層的 Folder

包含目標系統的 headers 和 libraries, 給 cross compiler 使用
且讓 toolchain folder 和目標系統的 libraries 分開, 避免被污染

ls -lh ~/x-tools/x86_64-ubuntu16.04-linux-gnu/x86_64-ubuntu16.04-linux-gnu

total 24K
dr-xr-xr-x 2 root root 4.0K Sep 27 14:10 bin/
dr-xr-xr-x 2 root root 4.0K Sep 27 12:44 debug-root/
dr-xr-xr-x 3 root root 4.0K Sep 27 14:10 include/
dr-xr-xr-x 3 root root 4.0K Sep 27 12:54 lib/
dr-xr-xr-x 2 root root 4.0K Sep 27 14:10 lib64/
dr-xr-xr-x 7 root root 4.0K Sep 27 13:35 sysroot/

預告

呼~做完了 cross compile 的準備後, 接著就讓我們開始在 Linux cross compile Windows binary 吧!


上一篇
[Day 26] Ninja
下一篇
[Day 28] Cross Compile Windows Binaries
系列文
30 天 CMake 跨平台之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言