一次搞定 Arm Linux 交叉編譯

交叉編譯

爲何要交叉編譯

交叉編譯實際上是相對於本地編譯(native build)來講的,我相信你們最開始學習 C/C++ 這些語言的時候,都是在電腦上寫程序,而後在電腦上編譯生成可執行文件,最後在電腦上運行。程序的編輯——》編譯——》運行,整個過程都是在一臺 X86 電腦上。linux

當咱們開始接觸嵌入式開發後,事情變的不同了,你在電腦上寫程序,在電腦上編譯出可執行文件,最後這個可執行文件須要下載到你的開發板上運行。程序最後運行的環境變了,好比你的開發板是基於 Arm 的——程序在 X86 上編輯,編譯,最終運行在另外一個和 X86 徹底不一樣的架構的 Arm 芯片上。git

之因此整個流程變成了這個樣子,這是由嵌入式系統的特性決定的:通常嵌入式系統裏面使用的芯片性能都比較弱,並且絕大部分都不能像 X86 同樣運行 Windows/Ubuntu 桌面系統,即便能運行,性能也很弱,沒法給你提供一個在開發板上寫代碼、編譯代碼的環境。因此咱們仍是離不開 X86 電腦強大高效的桌面環境進行軟件開發。bash

可是這樣有一個問題,X8六、Arm、MIPS、RISC-V 這些芯片,它們的指令集是由不一樣的組織或者公司設計的,彼此並不兼容——Arm 和 MIPS 的 CPU 沒法運行以 X86 的指令集編碼的程序,反之亦然。因此咱們要在 X86 的電腦上編譯出可以在 Arm 上運行的程序,咱們必須明確告訴編譯器,編譯生成的可執行文件須要以 Arm 指令集的標準編碼。爲了讓這個流程變得簡單,開發者們爲不一樣的芯片開發了不一樣的編譯器,好比針對 Arm 平臺的 arm-linux-gcc,針對 mips 平臺的 mips-linux-gnu-gcc,這些編譯器都是基於 GCC 針對具體的架構指令集進行對應配置,因此它們在運行的時候就就會生成和該目標平臺對應的可執行文件。微信

這篇文章主要講 Arm 的交叉編譯,因此這裏後面都以 Linux 開發環境下的 Arm gcc 爲例。架構

工具鏈的種類

GCC 的命名規則爲: arch [-vendor] [-os] [-(gnu)eabi]-gcc工具

好比 arm-linux-gnueabi-gccarm-none-eabi-gccaarch64-linux-gnu-gcc 性能

  • 帶 [] 的是可選部分。
  • arch: 芯片架構,好比 32 位的 Arm 架構對應的 arch 爲 arm,64 位的 Arm 架構對應的 arch 爲 aarch64。
  • vendor :工具鏈提供商,大部分工具鏈名字裏面都沒有包含這部分。
  • os :編譯出來的可執行文件(目標文件)針對的操做系統,好比 Linux。

arm-none-eabi-gcc 通常適用用於 Arm Cortex-M/Cortex-R 平臺,它使用的是 newlib 庫。學習

arm-linux-gnueabi-gcc 和 aarch64-linux-gnu-gcc 適用於 Arm Cortex-A 系列芯片,前者針對 32 位芯片,後者針對 64 位芯片,它使用的是 glibc 庫。能夠用來編譯 u-boot、linux kernel 以及應用程序。優化

另外須要補充一點的是,32 位的 Arm 和 64 位的 Arm,它們的指令集是不一樣的,因此須要使用不一樣的工具鏈。固然,Arm64 爲了保證前向兼容,提供了一個 32 位的兼容模式,因此咱們用 arm-linux-gnueabi-gcc 編譯的應用程序也是能夠直接在Arm64 的系統上運行的,可是 Linux Kernel 和 U-Boot 就不行,除非你提早把 CPU 切換到 32 位模式。曾經有個項目使用了一顆四核的 Arm64 芯片,可是內存只有64M,爲了節省空間,在 CPU 運行到 U-Boot 以前,咱們就把它切到了 32 位模式,後面的 U-Boot、Linux Kernel,應用所有都用 32 位編譯,加上 Thumb 指令集,節省了很多空間。網站

工具鏈的下載安裝

下載地址

如今 Arm 平臺上用的最普遍的工具鏈是 Linaro 發佈的,你們能夠到 Linaro 官網下載,地址以下:

http://releases.linaro.org/components/toolchain/binaries/

同時我發現 Linaro 申明稱後續新版本的工具鏈會經過 Arm 官方發佈。

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain

4.九、6.三、7.4 這些是工具鏈的版本號,理論上越新的版本,性能越好。

在一次優化 u-boot 大小的時候我發現 6.3 版本的工具鏈生成的二進制文件要比 4.9 版本生成的小几百個字節,進一步對比分析後發現是由於 6.3 版本的工具鏈把代碼中沒用到的一些字符串所有過濾掉了,雖然 4.9 的版本也有過濾,可是沒有 6.3 作的乾淨。

目前用的多的版本應該是 6.x,固然我也看到有些開發組織在使用 7.x 的工具鏈,好比 Armbian 目前在用 7.4 編譯內核。

另外目前最新版本的 U-Boot 已經強制必須使用 6.0 以上版本的 GCC 進行編譯。

這兩個網站下載可能會比較慢,能夠考慮使用國內的鏡像下載:

https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/

下載

能夠直接點擊下載,也能夠經過命令行用 wget 命令下載:

wget https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz
wget https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/_toolchains/gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz

下載了兩個,arm 針對是是 32 位的, aarch64 針對 Arm64.

安裝

解壓:

xz -d gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar.xz 
xz -d gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz

安裝到 /usr/local/toolchain/ 目錄下,固然也能夠放在其餘任何你喜歡的地方:

sudo mkdir -p /usr/local/toolchain
tar -xvf gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf.tar -C /usr/local/toolchain/
sudo tar -xvf gcc-linaro-6.4.1-2017.11-x86_64_aarch64-linux-gnu.tar -C /usr/local/toolchain/

成功後執行 ls 命令,能夠看到兩個 toolchain 都被安裝到 /usr/local/toolchain/ 目錄下了。

添加環境變量

只有把可執行文件對應的路徑加入到 PATH 環境變量裏,系統才能夠認到這些命令。

這裏的路徑就是上面截圖中 pwd 命令顯示的路徑,能夠添加到 ~/.bashrc 文件的最後:

PATH=$PATH:/usr/local/toolchain/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin:/usr/local/toolchain/gcc-linaro-6.4.
1-2017.11-x86_64_aarch64-linux-gnu/bin

注意: 兩個獨立的路徑之間用 冒號: 隔開。

執行 source ~/.bashrc 命令讓配置生效,而後咱們就能夠在命令行裏執行這些命令了:

好比 arm-linux-gnueabihf-gcc -vaarch64-linux-gnu-gcc -v 查看編譯器版本:

能看到如圖的信息,說明已經大功告成了。

編譯內核

這裏下載 imx 的官方內核:

git clone https://source.codeaurora.org/external/imx/linux-imx

切換到 4.19 版本:

git checkout -b imx_v2019.04_4.19.35_1.0.0  origin/imx_v2019.04_4.19.35_1.0.0

編譯:

make ARCH=arm imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

若是你電腦上其餘的依賴庫都安裝的完整,就能順利編譯成功。

更多原創請掃碼關注微信公衆號:HackforFun

相關文章
相關標籤/搜索