2.1 介紹
2.1.1 工具鏈簡介
一個編譯工具鏈模塊是允許為系統編譯代碼的一組工具。它由一個編譯器(在我們的例子中是 gcc)、像匯編器和鏈接器這樣的二進制 utils(一般是 binutils)和一個C標准庫(例如 GNU Libc, uClibc-ng)組成。
一個交叉編譯工具鏈是可有在主機上運行的,但是編譯出來的二進制文件只能運行在目標板或機器上。在我們的宿主機上也有工具鏈,它只能編譯適用於我們的宿主機,編譯出來的程序也只能運行在我們的宿主機上。
當前我們要使用 buildroot 編譯出來一個交叉編譯工具鏈,適用於我們的目標板。
目標板是 S3C2440,它是 ARM 架構的,arm920t 的核心。
2.1.2 buildroot 的工具鏈工具
buildroot 提供了兩種建立交叉編譯工具鏈的方式:
- 內部工具鏈后端,在配置接口中稱為 Buildroot 工具鏈。
- 外部工具鏈后端,在配置接口中稱為外部工具鏈。
使用工具鏈菜單中的工具鏈類型選項來選擇這兩種解決方案。一旦選擇了一個解決方案,就會出現許多配置選項。
在 根目錄下使用 make menuconfig,Toolchain--->Toolchain type
2.1.3 內部工具鏈
內部工具鏈是 Buildroot 在為目標嵌入式系統構建用戶空間應用程序和庫之前,自行構建的交叉編譯工具鏈。
此交叉編譯工具鏈支持幾種 C 庫:uClibc-ng, glibc 和 musl。
一旦選擇這個類型的工具鏈后,大量的選項將出現。最重要的選項如下:
- 更改構建工具鏈需要的內核頭文件版本。
- 在構建交叉編譯工具鏈的過程中,C 庫也在被構建。這個庫提供了用戶空間應用程序和 Linux 內核之間的接口。為了知道如何與 Linux 內核“對話”,C 庫需要訪問Linux內核頭文件(即來自內核的.h文件),它定義了用戶空間與內核之間的接口(系統調用、數據結構等)。
- 由於此接口是向后兼容的,因此用於構建工具鏈的 Linux 內核頭的版本不需要與我們打算在嵌入式系統上運行的 Linux 內核的版本完全匹配。它們只需要有一個與我們要運行的 Linux 內核版本相同或更老的版本。
- 如果我們使用的內核頭文件比我們在嵌入式系統上運行的 Linux 內核更新,那么C 庫可能使用的接口不是我們的 Linux 內核提供的。
- 在構建交叉編譯工具鏈的過程中,C 庫也在被構建。這個庫提供了用戶空間應用程序和 Linux 內核之間的接口。為了知道如何與 Linux 內核“對話”,C 庫需要訪問Linux內核頭文件(即來自內核的.h文件),它定義了用戶空間與內核之間的接口(系統調用、數據結構等)。
- 更改 GCC 編譯器、binutils 和 C 庫的版本
- 選擇編譯器選項(只有使用 uClibc 的時候需要)
- 工具鏈是否應該有 RPC 支持(主要用於 NFS)、寬字符支持、語言環境支持(用於國際化)、c++ 支持或線程支持。
- 根據我們選擇的選項,Buildroot 菜單中可見的用戶空間應用程序和庫的數量將會改變:許多應用程序和庫需要啟用某些工具鏈選項。
- 當需要某個工具鏈選項來啟用那些包時,大多數包都會顯示注釋。如果需要,可以通過運行 make uClibc -menuconfig 進一步優化 uClibc 配置。
- 但是請注意,Buildroot中 的所有包都是根據內置的默認 uClibc 配置進行測試的:如果通過刪除 uClibc 的特性而偏離了這個配置,那么一些包可能不再構建。
值得注意的是,每當修改其中一個選項時,就必須重新構建整個工具鏈和系統。
這種方式也有好處:與 Buildroot 有很好的集成並且快速,只構建必要的內容
缺點是:make clean 后需要重新構建工具鏈,這需要時間。如果我們試圖減少構建時間,可以考慮使用外部工具鏈。
2.1.4 外部工具鏈
外部工具鏈允許使用現有的預先構建的交叉編譯工具鏈。
Buildroot知道許多著名的交叉編譯工具鏈(來自用於 ARM 的 Linaro、用於 ARM 的 Sourcery CodeBench、x86-64、PowerPC 和 MIPS),並且能夠自動下載它們,或者指向一個定制的工具鏈,可以下載,也可以在本地安裝。
我們有三種方式使用一個外部工具鏈:
- 使用預定義的外部工具鏈配置文件,並讓 Buildroot 下載、提取和安裝工具鏈。Buildroot 已經知道一些 CodeSourcery 和 Linaro 工具鏈。從可用的工具鏈中選擇工具鏈配置文件。這絕對是最簡單的解決方案。
- 使用預定義的外部工具鏈配置文件,但不是讓 Buildroot 下載和提取工具鏈,我們可以告訴 Buildroot 我們的工具鏈已經安裝在系統的哪個位置。只需通過可用的工具鏈選擇工具鏈配置文件,自動取消選擇下載工具鏈,並用交叉編譯工具鏈的路徑填充工具鏈路徑
- 使用一個完全的自定義的外部交叉編譯工具鏈。
- 這對於使用crosstool-NG或使用Buildroot本身生成的工具鏈特別有用。
- 要做到這些,首先要在 Toolchain 配置選項中選擇 Custom toolchain
- 我們需要填寫 Toolchain path, Toolchain prefix 和 External toolchain C library 選項
- 接着需要必須告訴 Buildroot 我們的外部工具鏈支持什么。如果外部工具鏈使用 glibc 庫,只需要知道工具鏈是否支持 c++ 以及它是否有內置的 RPC 支持。如果外部工具鏈使用 uClibc 庫,那么您必須告訴 Buildroot 它是否支持 RPC、寬字符、語言環境、程序調用、線程和c++。
- 在執行的開始,Buildroot 會告訴我們所選選項是否與工具鏈配置匹配。
- 這對於使用crosstool-NG或使用Buildroot本身生成的工具鏈特別有用。
如果想為自己的項目生成一個定制的工具鏈,它可以在 Buildroot中 使用外部工具鏈,建議使用 Buildroot 或 crosstool-NG 來構建它。
- 這種構建工具鏈的方式的好處是:
- 允許使用眾所周知且經過良好測試的交叉編譯工具鏈。
- 避免交叉編譯工具鏈的構建時間,這在嵌入式Linux系統的總體構建時間中通常非常重要。
- 允許使用眾所周知且經過良好測試的交叉編譯工具鏈。
- 壞處是:
- 如果預先構建的外部工具鏈有錯誤,可能很難從工具鏈供應商那里得到修復,除非使用Buildroot或Crosstool-NG自己構建外部工具鏈。
2.2 構建工具鏈
2.2.1 使用 buildrtoo 構建外部工具鏈
內置的內部工具鏈選項可以用來創建外部工具鏈。下面是構建內部工具鏈並將其打包以供Buildroot自身(或其他項目)重用的一系列步驟。
make menuconfig 進入配置菜單
Target options 選擇 CPU 架構:
ToolChain 中選擇配置交叉編譯工具鏈的一系列選項:
- Toolchain type:選擇 Buildroot toolchain
- custom toolchain vendor name:buildroot 構建的交叉編譯工具鏈的名字是 <arch>-<vendor>-<os>-<libc>,這個選項對應 vendor 名字,配置成 s3c24x0,那么我們生成的工具鏈是 arm-s3c24x0-linux-glibc
- C library:選擇 glibc
- Kernel Headers:內核頭文件,選擇手動指定,或者選擇里面提供的內核版本,我這里選擇手動指定 Manually specified Linux version
- linux version:Linux 版本,填入 4.4.174
- Custom kernel headers series:自定義內核頭文件系列,選擇 4.4.x
- Install glibc utilities:啟用這個選項將為目標編譯和安裝 getconf、ldconfig、ldd 和 locale glibc實用程序。按需要選擇
- Binutils Version:binutils 版本,保持默認
- Additional binutils options:額外的 binutils 選項,保持為空
- GCC compiler Version:GCC 編譯器版本,選擇為 gcc 8.x
- Additional gcc options:額外的 GCC 選項,保持默認為空就好,如果需要,就自己填寫
- 語言支持:可以支持 C++ ,Fortran,支持 C++即可
- Enable compiler link-time-optimization support:此選項支持gcc中的鏈接時間優化(LTO)。
- Enable compiler OpenMP support:為編譯器啟用 OpenMP 支持。主要是在編譯時采用並行處理
- Enable graphite support:此選項啟用編譯器中的石墨優化。這個選項看不懂
- Build cross gdb for the host:構建一個運行在主機上的交叉 gdb,並調試運行在目標機上的程序。它需要在目標上安裝'gdbserver',即 BR2_PACKAGE_GDB_SERVER(Target packages-> Debugging, profiling and benchmark-> gdb )
- TUI support:此選項為gdb啟用終端用戶界面(TUI)
- Python support:此選項支持交叉 gdb 中的 Python 支持。
- Simulator support:此選項啟用了交叉 gdb 中的模擬器支持。
- GDB debugger Version:版本選擇 gdb 8.2.x
- Copy gconv libraries:gconv 庫用於在不同字符集之間進行轉換。如果需要存儲和/或顯示不同的字符集,請使用'y'。
- Gconv libraries to copy:設置為要復制的gconv庫列表。為空以復制所有gconv庫。只指定庫的基本名稱,忽略。so擴展。如:IBM850 ISO8859-15 UNICODE。注意,gconv 庫占用 8 M(在 ARM 上)。
- Extra toolchain libraries to be copied to target:如果工具鏈提供了需要復制到目標文件系統的額外庫,請在這里輸入它們,以空格作為分割符分割。如 "libasan liblsan libtsan libubsan"
- Enable MMU support: MMU 支持
- Target Optimizations:為目標主機構建時使用的優化。注意:gcc優化級別是在構建選項中定義的。一般不會選擇
- Target linker options:為目標構建時要傳遞給鏈接器的額外選項。
- Register toolchain within Eclipse Buildroot plug-in:這個選項告訴 Buildroot 生成必要的配置文件,通過 Eclipse Buildroot 插件使工具鏈出現在 Eclipse 中。
System configuration 中需要禁用掉系統初始化選項和 /bin/sh:
- Init system:選擇 none
- /bin/sh :設置為 none
Target packages 中要禁用 busybox:
- busybox:選項設為空
Build options 中,需要設置一下源的路徑,在執行構建的過程中,需要從不同的源地址下載各種不同的包,由於國內的和諧,所以需要更改為國內鏡像:
- Mirrors and Download locations
- Kernel.org mirror:https://mirrors.tuna.tsinghua.edu.cn/kernel
- GNU Software mirror:https://mirrors.tuna.tsinghua.edu.cn/gnu
- Kernel.org mirror:https://mirrors.tuna.tsinghua.edu.cn/kernel
Filesystem images 中禁用 tar the root filesystem
配置完成后,保存退出,然后執行命令 make sdk,編譯完成后,如下:
SDK 的壓縮包存放再 $(O)/images 下,如果指定了 $(O),就是指定的目錄,未指定則是根目錄下output 目錄。壓縮包名為 arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz:
保存這個 tarball,因為它現在是一個工具鏈,我們可以在其他 Buildroot 項目中重用它作為外部工具鏈。
在 buildroot 下建立自己的工作源碼目錄 source,雖然可以按 buildroot 的架構去添加包之類的,但是太過麻煩,每次只有在編譯后,才能去看源碼,在開發中,更多的是便開發邊修改邊編譯。
mkdir source cd source cp ../output/images/arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz ./ mkdir toolchain mv arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz ./toolchain
cd toolchain
tar -zxvf arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
rm -rf arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
現在要單獨保存一下 toolchain 的配置文件:
- 若是之前未使用 xxx_defconfig 生成的 .config 配置文件,根目錄下執行 make savedefconfig 會在當前根目錄下生成一個 defconfig 文件
- 若是使用的 xxx_defconfig 生成的 .config,則執行 make update-defconfig 會自動更新 xxx_defconfig 文件
- 生成 defconfig 后,保存到根目錄下的 configs 文件夾下, cp defconfig configs/s3c24x0ToolSDK_defconfig,在自己的 source 中也保存一份 cp defconfig source/s3c24x0ToolSDK_defconfig
保存后,執行一下 make clean,同時修改一下根目錄下的 Makefile,在執行 make distclean 的時候,不要刪除 dl 目錄,當然如果每次都想重新下載源碼包的另說,不用改。
1070 行中,帶 dl 的刪除掉即可。
同時若是使用的 git 托管代碼,需要修改 .gitignore,將 dl 那一行刪除即可。
修改完成后,執行一下 make distclean,后面需要針對自己的工程進行配置,我們可以直接使用我們編譯出來的工具鏈,作為外部工具鏈使用。
make menuconfig 進入配置。
- Target options 中的配置與交叉編譯工具鏈的配置相同
- Toolchain 中,
- 將 Toolchain type 改為 External toolchain,
- Toolchain 選擇成 Custom toolchain
- Toolchain origin 改為 Pre-installed toolchain
- Toolchain path 填寫為我們的路徑:$(TOPDIR)/source/ arm-s3c24x0-linux-gnueabi_sdk-buildroot.tar.gz
- External toolchain gcc version:改為我們編譯的版本 8.x
- External toolchain kernel headers series:頭文件改為 4.4.x
- External toolchain C library:改為 glibc
- Toolchain has SSP support?:勾選上
- Toolchain has SSP strong support?:選上
- Toolchain has RPC support?:勾選上
- Toolchain has C++ support:勾選上
- 其他的選項都保持和編譯工具鏈的時候一致。
使用外部工具鏈比較坑的是,執行 make 的時候,工具鏈又被編譯了一遍。這個問題再看看
指定 make savedefconfig 保存配置:
mv defconfig configs/s3c24x0_defconfig
執行 make distclean,上傳至 gitee 或是 github。
gitee 工程地址:https://gitee.com/cocosleep/project