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 |