C 語言編譯之交叉編譯

1、什麼是交叉編譯

嵌入式開發過程中,由於嵌入式平臺不一定有操作系統,也就運行不了編譯程序(如 gcc 和 llvm)。即便能運行,受限於 CPU 性能,編譯效率也會比較 “感人”。

編譯過程是將源碼轉化爲目標平臺二進制指令的過程,並不涉及二進制的執行,所以本身不存在對目標平臺的硬件依賴,因此編譯過程和執行過程可以是不同的平臺。考慮到開發效率,構建環境可以是 PC 或者服務器環境,完成編譯過程後再將二進制下載到嵌入式單板執行。這種構建環境和運行環境(主要是操作系統、處理器架構和型號)不同的情況,就涉及交叉編譯。參考維基百科中對交叉編譯的定義:交叉編譯是指在一個平臺生成另一個平臺可執行文件的過程。

2、交叉編譯的使用

1)交叉編譯器的選擇

以在 x86 Linux 環境構建 arm64 平臺下的可執行文件爲例,第一步就需要在構建環境中安裝交叉編譯器。一般在對應體系結構的官網上可以找到對應的交叉編譯器。如 arm 平臺交叉 gcc 編譯器的下載路徑爲:

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

在該頁面看到有很多個版本,這裏需要根據交叉編譯器的命名規則選擇適合自己的版本。一般來說,交叉編譯器的命名規則爲:

arch[-vendor][-os]-abi

arch:目標平臺的架構,如 arm,aarch64(arm64 ),riscv32,x86,x86_64 等。

vendor:提供編譯工具鏈的廠商,如 mingw-w64。

os:目標平臺的操作系統,如 linux。指示編譯器使用哪些庫和如何使用系統調用。

abi:用於指示編譯器使用的二進制接口(Application Binary Interface)類型,如 gnueabi 表示 GNU 的 EABI(Embedded Application Binary Interface)。gnueabihf 在 gnieabi 的基礎上指示編譯器使用硬件浮點單元進行浮點運算(不帶 hf 的編譯器使用軟件浮點)。abi 相同的二進制可以進行互操作。

並不是所有的編譯器都會嚴格按照這個規則命名,還有的命名規則中將 vendor 替換爲了 core,用於指示具體的 CPU 型號,如 arm-cortex_a8-linux-gnueabi。

常見的交叉編譯器:

arm-none-eabi:arm 架構,不含 vendor,目標平臺不帶 OS(裸機系統),使用 ARM 的 eabi。

aarch64-none-linux-gnueabihf:aarch64 架構,不含 vendor,目標平臺爲 Linux 系統,使用支持硬件浮點的 GNU EABI。

x86_64-w64-mingw32:x86_64 架構,廠商爲 mingw-w64(w64 = mingw-64),二進制接口爲 mingw32(Minimalist GNU for windows)。

arm-elf-eabi:arm 架構,不含 vendor,構建可以跑在任何支持 elf 文件並且支持 EABI 的系統上。

arm-elf:用於構建操作系統無關的 arm 體系結構下通用的 elf 文件。

通過以上介紹,就可以根據自己的構建環境在 arm 官網選擇適合自己的工具鏈了。

2)交叉編譯器的使用

選擇完合適的交叉編譯器後,還需要通過編譯選項給編譯器傳遞目標平臺的更多信息,方便編譯器生成正確且高效的可執行文件。這些選項往往和體系結構相關,需要查看編譯器手冊中對應體系結構相關的描述使用。以 aarch64 體系結構爲例爲例,和交叉編譯相關的編譯選項有:

-mabi=name

用於指定特定的數據模型,比如可以通過 "ilp32" 指示編譯器將 int、long 和 pointer 都按照 32 位處理。

-mbig-endian/-mlittle-endian

用於指定生成大端 / 小端的代碼。

-march=name

用於指定特定的體系結構,編譯器據此決定如何生成彙編指令。aarch64 下可選的體系結構有:armv8-a、armv8.1-a、armv8.2-a…armv8.7-a、armv9-a、armv8-r 等。

-mtune=name/-mcpu=name

用於指定具體的 CPU 型號,編譯器可據此執行更具體的優化。可選的型號有:generic、cortex-a35、cortex-a53、cortex-a55、cortex-a57、cortex-a72、cortex-a73、cortex-a75、cortex-a76、cortex-a77、cortex-a78、cortex-a78ae、cortex-r82、cortex-x1、cortex-x2、cortex-a510、cortex-a710 等。還可指定爲 cortex-a57.cortex-a53、cortex-a72.cortex-a53、cortex-a73.cortex-a35、cortex-a75.cortex-a55、cortex-a76.cortex-a55 等指示編譯器針對 big.LITTLE 架構進行優化。還可以指定爲 native,編譯器可以根據構建環境的 CPU 型號進行優化。

當 march、mtune 和 mcpu 均未指定時,編譯器將盡可能生成通用的指令。而如果 多個選項均提供且存在衝突時,march 和 mtune 選項的設置將擁有更高的優先級。

march 和 mcpu 選項可以根據 CPU 支持的特性類型通過 arch/cpu{+[no]feature} 的形式對某些特性進行開關設置。相關的特性有:crc(使能 CRC 擴展)、crypto(使能 crypto 擴展)、fp(使能硬件浮點單元)、simd(使能 SIMD 指令)、sha2(使能 sha2 擴展)、sha3(使能 sha3 擴展)、sm4(使能 sm4 擴展)。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/W35ERQNmYMO_lror5HI0xg