# Build Tool : Cross Compile 交叉編譯與紀錄
## 概念
交叉編譯 ( Cross Compilation ) 是指**在一台電腦上編譯可以在另一種電腦上執行的程式**,舉個例子 : 你用 Windows 系統的電腦,寫了一個程式是給 Raspberry Pi (樹莓派,使用 ARM 架構) 跑的,在編譯時候正常來說編譯出的執行檔案只能在 Windows 上執行,如果要移植到樹梅派上就無法執行,因為在編譯過後的二進制檔案會受到系統與 CPU 架構影響
* 在 Windows PC 上,利用 ADS(ARM 開發環境),使用 armcc 編譯器,則可編譯出針對 ARM CPU 的可執行程式碼
* 在 Linux PC 上,利用 arm-linux-gcc 編譯器,可編譯出針對 Linux ARM 平臺的可執行程式碼
* 在 Windows PC 上,利用 cygwin 環境,執行 arm-elf-gcc 編譯器,可編譯出針對 ARM CPU 的可執行程式碼。
## 確認目標平台
- CPU 架構
ARM、x86
- 作業系統
Linux、Android、Windows
- 交叉編譯器
GCC、Android NDK、Yocto Project
## 動態連結 v.s. 靜態連結
### 靜態連結 Static Link
在使用靜態連結的時候,將其他檔案也一起包裝起來,讓使用者一併載下來,這樣目標對象就算沒有那個環境也能夠執行,但缺點就是體積比較大,以空間換取時間,在 Linux 上為 `.a` 檔案
### 動態連接 Dynamic Link
動態連接解決了靜態函數庫的缺點,另外也解決不需要調用函式庫占用記憶體的時間,以時間換取空間,在 Linux 上為 `.so` 檔案,則在 Window 上為 `.dll`
## 實際案例
### 1. 確認目標作業系統與 CPU 架構
在工作實際案例上,我需要將 Raspberry Pi 開發的程式碼編譯到一台虛擬機器上,首先我們要先透過指令來確認 CPU 架構以及作業系統
```bash
uname -a
```
可以輸出當前電腦的系統資訊
```bash!
Linux raspberrypi 6.6.31+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.6.31-1+rpt1 (2024-05-29) aarch64 GNU/Linux
```
- Kernel Name
`Linux`
- Hostname
`raspberrypi`
- Kernel Version
`6.6.31+rpt-rpi-2712`
- Build info
`#1 SMP PREEMPT Debian 1:6.6.31-1+rpt1 (2024-05-29)`
- CPU ARC
`aarch64`
- Operating System
`GNU/Linux`
接著我們需要確認對方電腦資訊
```bash!
Linux (none) 5.10.144 #1 SMP Thu Apr 10 12:45:39 CST 2025 armv7l GNU/Linux
```
在這邊要注意對方 CPU 架構為 `armv7l`,作業系統為 `GUN/Linux`
### 2. 安裝交叉編譯器
```bash
sudo apt install g++-arm-linux-gnueabihf
```
### 3. 設定 MakeFile
由於專案是由透過 CMakeTool 進行建置與安裝的,首先先創建 `armv7-toolchain.cmake`
```cmake!
# armv7-toolchain.cmake
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_PROCESSOR arm)
# Cross-Compile
SET(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# Option : static
SET(CMAKE_EXE_LINKER_FLAGS "-static")
```
### 4. 執行 CMake 指令
```bash!
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-static-libgcc -static-libstdc++" \
-DCMAKE_EXE_LINKER_FLAGS="-static -pthread" \
-DCMAKE_TOOLCHAIN_FILE=../armv7-toolchain.cmake ..
```
- `-pthread` : 確保線程相關程式碼能夠運作正確
- `-static-libgcc -static-libstdc++` : 增強可移植性,靜態鏈接 C++ 標準函式庫,靜態鏈接 GCC 的 Runtime library,這樣目標電腦就不需要安裝這些函示庫跟 Library,但會造成靜態檔案變大