본문 바로가기
Programming/C++

ARM 크로스 컴파일(Cross Compile)

by 드로니뚜벅이 2023. 5. 26.

ARM 종류는 굉장히 다양하고 안드로이드, iOS 디바이스 등 플랫폼도 다양하기 때문에 해당 기기에 맞게 크로스 컴파일을 해야 합니다. 즉, ELF 64-bit ARM aarch64, Mach-O 64bit ARM aarch64 등 디바이스에서 돌아가게 하려면 맞춰줘야 합니다.

Ubuntu/Debian 리눅스에서 제공하는 ARM 툴체인 환경은 Linaro 툴체인을 바탕으로 만들어져 있어서 두 가지 버전으로 제공됩니다. Hard Floating을 지원하는 버전과 그렇지 않은 버전으로 제공됩니다.

 

ABI(Appication Binary Interface) 표준

응용프로그램간 이진 데이터를 어떻게 교환해야 하는지 다음과 같은 규칙들을 정합니다.

- 데이터 타입과 정렬 방법

- 함수 호출 시 인수 및 결과에 대해 레지스터 교환 방법

- 시스템 콜 호출 방법

- 프로그램 코드의 시작과 데이터에 대한 초기화 방법

- 파일 교환 방법 (ELF 등)

 

EABI(Embedded ABI) 표준

EABI는 임베디드 환경의 ABI를 다룹니다. ARM 아키텍처에서 리눅스 버전에 따라 ABI를 사용하는 방식이 다음 두 가지로 나뉩니다.

arm/OABI

- 커널 v2.6.15(mainline v2.6.16) 이전에 사용되던 ABI 방식

- glibc 2.3.6 까지 사용

- gcc: linux-arm-none-gnu

 

arm/EABI

- 커널 v2.6.16부터 사용되는 ARM EABI 방식

- glibc v2.3.7 및 v2.4부터 사용

- gcc: linux-arm-none-gnueabi

 

ARM 툴 체인 종류

arm-linux-gnueabi

- GNU에서 Soft float을 사용하는 ARMEL 아키텍처를 위해 사용합니다.

- FP(Floating Point)가 없는 ARM 아키텍처에서 Soft float 방식을 사용합니다.

 

arm-linux-gnueabihf

- GNU에서 Hard float를 사용한 ARMHF 아키텍처를 위해 사용합니다.

- 참고로, 응용프로그램을 컴파일하여 구동하는 경우 hardfloat를 사용한 라이브러리도 같이 준비되어 있어야 합니다.

 

arm-bcm2708-linux-gnueabi

- armv7 아키텍처용 softfloat 방식 사용

 

arm-bcm2708hardfp-linux-gnueabi

- armv7 아키텍처용 hardfloat 방식 사용

 

크로스 컴파일 툴체인 설치

개발용 필수 라이브러리 설치

 $ sudo apt install build-essential

hard float(하드웨어 GPU) 가 있는 경우

EABI가 GCC의 -mfloat-abi=hard 옵션으로 생성한다는 의미입니다. 이 의미는 Function Calling Convention이 double, float 사용 시 FPU 레지스터에 올려서 전달하고 반환도 FPU 레지스터를 사용하게 된다는 것입니다.

# gnu c compiler(32bit)
$ sudo apt install gcc-arm-linux-gnueabihf
# gnu c++ compiler(32bit)
$ sudo apt install g++-arm-linux-gnueabihf

hard float(하드웨어 GPU) 가 없는 경우

EABI가 GCC의 -mfloat-abi=soft 혹은 -mfloat-abi=softfp 옵션으로 생성한다는 의미입니다.

# gnu c compiler(32bit)
$ sudo apt install gcc-arm-linux-gnueabi
# gnu c++ compiler(32bit)
$ sudo apt install g++-arm-linux-gnueabi

64bit 버전

$ sudo apt install binutils-aarch64-linux-gnu
# gnu c compiler
$ sudo apt install gcc-aarch64-linux-gnu
# gnu c++ compiler
$ sudo apt install g++-aarch64-linux-gnu

 

gdb-multiarch 설치

$ sudo apt install gdb-multiarch

 

컴파일

Hello, World!

vi hello.cpp
--------------------------
#include <iostream>
using namespace std;

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}
--------------------------

arm-linux-gnueabihf-g++ -g -o hello hello.cpp
file hello
hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV) ......

aarch64-linux-gnu-g++ -g -o hello hello.cpp
file hello
hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV) ......

make

우선 알아야 할 것은 make 가 직접적으로 cross compile 을 지원하는 것이 아니라,
Makefile 에 cross compile 을 지원하도록 설정해야 하는 것입니다.

들여쓰기는 TAB 문자로만 이루어져야 합니다.
공백문자가 있는 경우 오류가 발생합니다.

AR=${CROSS_COMPILE}ar
AS=${CROSS_COMPILE}as
LD=${CROSS_COMPILE}ld
CC=$(CROSS_COMPILE)gcc
CXX=$(CROSS_COMPILE)g++
NM=${CROSS_COMPILE}nm
RANLIB=${CROSS_COMPILE}ranlib

CFLAGS=""
CPPFLAGS=""
LDFLAGS=""
LIBS=""

hello : hello.cpp
        $(CXX) -g -o hello hello.cpp

clean:
        rm hello

make 를 이용하여 컴파일하는 경우, 아래와 같이 환경설정을 추가하고 컴파일하면 됩니다.

# 32bit, GPU 없는 경우
export CROSS_COMPILE=arm-linux-gnueabi-
export ARCH=arm
# 32bit, GPU 있는 경우
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm
# 64bit
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64

make

file hello
hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV) ......

아래 명령을 .bashrc 에 추가해 놓으면 편합니다.

alias armmake='make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- '
alias arm64make='make -j8 ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- '

cmake

샘플로 json-c 라이브러리를 컴파일합니다.

$ git clone https://github.com/json-c/json-c.git
$ cd json-c
$ mkdir build
$ cd build
$ cmake ..
$ make
vi ../toolchain.arm.cmake
-------------------------------
SET(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
SET(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
SET(CMAKE_LINKER ${CROSS_COMPILE}ld)
SET(CMAKE_NM ${CROSS_COMPILE}nm)
SET(CMAKE_OBJCOPY ${CROSS_COMPILE}objcopy)
SET(CMAKE_OBJDUMP ${CROSS_COMPILE}objdump)
SET(CMAKE_RANLIB ${CROSS_COMPILE}ranlib)
-------------------------------
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.arm.cmake -DCROSS_COMPILE=aarch64-linux-gnu- ..

make
file libjson-c.so.5.1.0
libjson-c.so.5.1.0: ELF 64-bit LSB shared object, ARM aarch64, version ......

configure

./configure --host=arm-linux-gnueabi

 

'Programming > C++' 카테고리의 다른 글

glibc 버전을 확인하려면...  (1) 2023.10.26
리눅스 C++ 공유라이브러리 만들기  (0) 2022.09.06
C/C++(gcc/g++) 컴파일러(Compiler) 설치  (0) 2022.04.28
GCC 버전과 C++ 버전 매칭  (0) 2022.04.22
ldconfig  (0) 2022.04.17