본문 바로가기

취미

Toolchain for SMDK2410X targets HOWTO

Toolchain for SMDK2410X targets HOWTO

이 문서는
http://wiki.falinux.com/wiki.php/CROSSGCC3.3REZ-X5
http://lists.arm.linux.org.uk/pipermail/linux-arm/2003-August/005942.html
http://www.aleph1.co.uk/armlinux/docs/toolchain/toolchHOWTO.pdf
http://blog.naver.com/union_sy.do?Redirect=Log&logNo=80002185314
여기의 내용을 조합하여 정리 하였음을 알려 드립니다.

1) Pre-built Toolchains
binary 형태 또는 rpm(패키지로) 제공되는 cross compiler
1 Native Pre-built Compilers
2 Emdebian
3 LART
4 Compaq

Pre-built Toolchains은 단지 binary 파일을 정해둔 디렉토리로 옮기고 path만 설정하면 사용할 수 있다.
Pre-built Toolchains은 kernel header 파일 포함하여 만들어진 cross compiler이기 때문에 kernel에 영향을 받는 특정 프로그램은 이 cross compiler로 컴파일이 되더라도 board상에서 정확하게 동작 한다고 장담 할 수 없다.

2) Building the Toolchain
아래 설명되는 toolchain을 구축하는 방법은 http://lists.arm.linux.org.uk/pipermail/linux-arm/2003-August/005942.html 문서에 설명되어 있는 script 내용을 기초로 하여 작성 하였으며 The GNU Toolchain for ARM targets HOWTO (Wookey, Chris Rutter, Jeff Sutherland, Paul Webb) 문서를 참조 하였다.

1 필요한 소스 패키지
리눅스를 이용한 개발환경으로 선택했다면 크로스 컴파일 환경을 구축하여야 한다. 이 크로스 컴파일 환경에 포함되는 것은 다음과 같은 패키지가 필요로 하고 이 패키지들의 모음을 일반적으로 cross compile toolchain이라고도 한다.
1) binutils    : 어셈블러 및 로더 기타 툴 ( GNU )
2) glibc        : 크로스 컴파일 구축을 위한 라이브러리 및 일반 라이브러리
3) gcc        : 컴파일러  ( 시그너스 )
4) kernel    : 커널 소스
5) gdb        : 디버거

각각의 버전은 다음과 같다.
1) binutils    : binutils-2.14.90.0.6
2) glibc        : glibc-2.3.2
3) gcc        : gcc-3.3
4) kernel    : linux-2.4.18 (Linu@ SDK에서 제공하는 kernel)
5) gdb        : gdb-6.2.1

2 설치 전 작업
다운 받은 파일 목록을 정리하면
1) binutils-2.14.90.0.6.tar.gz
2) linux-2.4.19-x5-v04.tar.gz
3) gcc-3.3.tar.gz
4) glibc-2.3.2.tar.gz
5) glibc-linuxthreads-2.3.2.tar.gz
6) gdb-6.2.1.tar.gz

등 총 6개가 됩니다. 설치하려고 하는 linux에 다음 디렉토리를 만든다.
#mkdir -p project/toolchain
(이것은 사용하기 위하여 편의상 한 것이지 절대적인 것은 아님)
project/toolchain 에 다운 받은 파일을 가져다 놓는다.

  1. 설치 전 주의 사항 #
이제부터 진행하는 순서는 꼭! 지켜야 한다. 이유는 각 설치되는 패키지들의 의존 관계가 있기 때문이다. 설치는 root 권한으로 하여야 한다.

3 커널설치
여기서는 본격적인 커널 패치에 관련된 내용은 아니다. 단지 크로스 컴파일러를 만들기 위한 커널 설치이다. 크로스 컴파일러를 만들어 가는 과정에서 커널 헤더가 필요하기 때문에 하는 것이다.
kernel 설치에 관한 자세한 내용은 linuette SDK에서 제공하는 설치 가이드 문서를 확인한다.

여기서 기억해야 할 것은 이 커널 디렉토리의 위치이다. 우리는 커널의 위치로
/linuette/target/box/kernel로 설정한 상태이다.

4 GDB 패키지 설치
GDB는 크로스 컴파일 toolchain의 순서와 상관없이 언제든지 설치가 가능하다. 다음과 같이 설치하면 된다.
#tar zxvf gdb-6.2.1.tar.gz
이 명령을 수행하면 gdb-6.2.1 란 디렉토리가 생긴다. 이 디렉토리로 옮긴다.
#cd gdb-6.2.1
환경설정을 한다.
#./configure --target=arm-linux --build=i686-pc-linux-gnu --prefix=/usr
컴파일을 한다.

참조
-?target=arm-linux
target의 이름을 정하는 옵션
arm-linux
Linux/ARM을 지원하는 ELF로 컴파일
그 외에도 arm-linuxaout, arm-aout, arm-coff, arm-elf, arm-thumb 종류가 있다.
processor 종류에 따라
armv2
- ARM v2 architecture를 지원, 특히 26-bit mode code로 강제로 사용하게 한다.
armv3l, armv3b
- ARM v3 architecture (ARM610, ARM710), l -> little-endian b -> big-endian
armv4l, armv4b
- ARM v4 architecture (StrongARM, ARM7TDMI, ARM8, ARM9)
armv5l, armv5b
- ARM v5 architecture (XScale, ARM10)

#make
설치를 한다.
#make install
아마도 별 에러 없이 끝날 것이다.
제대로 설치되었다면 다음과 같은 명령을 치면 아래와 같이 나열된다.
#ls -al /usr/bin/arm-linux*
-rwxr-xr-x    1 root     root      5770628 10월 24 13:55 /usr/bin/arm-linux-gdb*
-rwxr-xr-x    1 root     root      1477505 10월 24 13:55 /usr/bin/arm-linux-run*

Binutils 패키지 설치 #
#tar zxvf binutils-2.14.90.0.6.tar.gz
#cd binutils-2.14.90.0.6
컴파일 환경을 설정한다.
#./configure --target=arm-linux --prefix=/usr --program-prefix=arm-linux-
컴파일 한다.
--program-prefix=arm-linux-
binutils의 파일을 생성할 때 arm-linux-가 붙게 된다.
#make
설치를 한다.
#make install
아마도 별 무리 없이 끝났을 것이다. 이 부분을 수행하고 나면 /usr/arm-linux 란 디렉토리가 생성된다.
#ls -al usr/arm-linux
합계 16
drwxr-xr-x    4 root     root         4096 10월 24 14:04 ./
drwxr-xr-x   19 root     root         4096 10월 24 14:04 ../
drwxr-xr-x    2 root     root         4096 10월 24 14:04 bin/
drwxr-xr-x    3 root     root         4096 10월 24 14:04 lib/

대부분의 실행파일은 /usr/bin에 복사 된다.
#ls /usr/bin/arm-linux-*
/usr/bin/arm-linux-addr2line*    /usr/bin/arm-linux-gdb*
/usr/bin/arm-linux-objdump*    /usr/bin/arm-linux-size*
/usr/bin/arm-linux-ar*        /usr/bin/arm-linux-ld*
/usr/bin/arm-linux-ranlib*    /usr/bin/arm-linux-strings*
/usr/bin/arm-linux-as*        /usr/bin/arm-linux-nm*
/usr/bin/arm-linux-readelf*    /usr/bin/arm-linux-strip*
/usr/bin/arm-linux-c++filt*    /usr/bin/arm-linux-objcopy* 
/usr/bin/arm-linux-run*

5 bootstrap compiler
gcc 초기 컴파일 단계에서 초기 컴파일 과정이 필요한 이유는 gcc cross compiler를 맨 처음 컴파일 할 때 필요한 환경이 제대로 갖춰져 있지 않기 때문이다. target 플랫폼과 관련 있는 각종 헤더 파일과 glibc 라이브러리가 없는 상황에서 gcc cross compiler를 어떻게 컴파일 하겠는가 (x86에서 x86용 gcc컴파일러를 컴파일 할 때는 헤더 파일과 glibc 라이브러리가 이미 있었다.)? 이런 문제를 극복하는 방법이 처음부터 완벽한 gcc교차 컴파일러를 만드는 대신 헤더 파일과 라이브러리를 준비할 수 있는 기능만 탑재한 gcc bootstrap compiler를 만드는 것이다.

이제 실제 크로스 컴파일러를 만든다. 압축을 푼다.
#tar zxvf gcc-3.3.tar.gz
몇 가지 파일을 수정한다.
#cd gcc-3.3
#perl -pi -e 's/^(TARGET_LIBGCC2_CFLAGS.*)/$1 -Dinhibit_libc -D__gthr_posix_h/' gcc/config/arm/t-linux
#echo 'T_CFLAGS = -Dinhibit_libc -D__gthr_posix_h' >> gcc/config/arm/t-linux

이것은 실제로 다음과 같이 파일을 직접 고치는 것과 동일 한 것이다.

==========[ 편집기를 사용했을때 ]==========
#cd gcc/config/arm/
#vi t-linux

TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC    
수정 
TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc
-D__gthr_posix_h

마지막 라인에 추가
T_CFLAGS = -Dinhibit_libc -D__gthr_posix_h
    
========================================

위에 편집 한 내용은 현재 bootstrap gcc를 만들고 있다는 사실을 컴파일러에 알려주기 위해 gcc-3.3/gcc/config/arm/t-linux 환경 설정 파일에 "T_CFLAGS= -Dinhibit_libc-D_gthr_posix_h"를 추가한다. (흔히 이를 inhibit_libc hack으로 부른다.) inhibit_libc는 libc를 사용하지 않겠다는 의미이고, _gthr_posix.h는 pthread 관련 헤더 파일을 찾지 않겠다는 의미이다.

이제 환경 설정과 컴파일을 수행한다.
#./configure --target=arm-linux --prefix=/usr
--with-headers=/linuette/target/box/kernel/include --disable-shared --disable-threads --enable-languages="c" --nfp --without-fp -?with-cpu=arm9
--with-softfloat-support=internal

s3c2410은 arm920t 임으로 ?with-cpu=arm9으로 줘야 하며 ?-with-headers 옵션의 kernel header의 경로는 자신이 target board에 올리는 kernel 경로에 맞게 작성한다.
thread 지원을 끄기 위해 disable-threads 옵션을 주며 enable-languages에 c를 지정한다. bootstrap gcc 컴파일 과정에서 c컴파일러 이외에 다른 컴파일러는 만들 수 없다.

컴파일을 한다.
#make
인스톨을 한다.
#make install
인스톨까지 정상적으로 수행 되었다. 확인을 위해서 다음과 같이 수행해 본다.
#ls /usr/bin/arm-linux-*
/usr/bin/arm-linux-addr2line*    /usr/bin/arm-linux-gcc*
/usr/bin/arm-linux-ld*        /usr/bin/arm-linux-readelf*
/usr/bin/arm-linux-ar*        /usr/bin/arm-linux-gcc-3.3*
/usr/bin/arm-linux-nm*        /usr/bin/arm-linux-run*
/usr/bin/arm-linux-as*        /usr/bin/arm-linux-gccbug*
/usr/bin/arm-linux-objcopy*    /usr/bin/arm-linux-size*
/usr/bin/arm-linux-c++filt*    /usr/bin/arm-linux-gcov*
/usr/bin/arm-linux-objdump*    /usr/bin/arm-linux-strings*
/usr/bin/arm-linux-cpp*        /usr/bin/arm-linux-gdb*
/usr/bin/arm-linux-ranlib*    /usr/bin/arm-linux-strip*

6 glibc 패키지 설치
가장 문제가 되는 glibc 패키지의 컴파일을 한다. 압축을 푼다.
#tar zxvf glibc-2.3.2.tar.gz
#tar -C glibc-2.3.2 -zxf glibc-linuxthreads-2.3.2.tar.gz
디렉토리를 이동한다.
#cd glibc-2.3.2
몇 가지를 수정한다.
./sysdeps/unix/sysv/linux/arm/sysdep.h 파일에서
    
161              : "a1", "memory");             \
의 내용을 
161              : "memory");               \
로 바꾼다.
     
./stdio-common/sscanf.c 파일에서 
    
30 sscanf (s, format)
31      const char *s;
32      const char *format;
    

    
30 sscanf (const char *s, const char *format, ...)
로 바꾼다.
    
./linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h 파일에서 

37   ENTRY (name)                              \

37   ENTRY (name);                             \
로 바꾼다.

빌드할 디렉토리를 만든다.
#mkdir ../glibcbuild
#cd ../glibcbuild
환경 설정을 한다.
#CC=arm-linux-gcc ../glibc-2.3.2/configure arm-linux --build=i686-pc-linux-gnu
--with-headers=/linuette/target/box/kernel/include --enable-add-ons --enable-shared --prefix=/usr/arm-linux --with-cpu=arm9 --without-fp --enable-kernel=2.4.18

linuette에서 제공하는 kernel은 2.4.18이다.

컴파일을 한다.
#make
설치를 한다.
#make install


7 gcc 재설치
이제 마지막으로 gcc를 재설치 하여야 한다. 물론 옵션이 달라진다. 나중에 컴파일 할 때 라이브러리 의존성 문제가 생기므로 사전에 링크를 걸어 준다.
#cd /usr/arm-linux/lib
#ln -s ../../lib/* .

#sed -e '/*** BUG/d' /usr/arm-linux/lib/libc.so > /usr/arm-linux/lib/libc.so.new
#mv -f /usr/arm-linux/lib/libc.so.new -f /usr/arm-linux/lib/libc.so
#sed -e '/*** BUG/d' /usr/arm-linux/lib/libpthread.so >
/usr/arm-linux/lib/libpthread.so.new
#mv -f /usr/arm-linux/lib/libpthread.so.new -f /usr/arm-linux/lib/libpthread.so

#cd project/toolchain
기존에 내용을 모두 지운다.
#rm -rf gcc-3.3    
다시 압축을 푼다.
#tar zxvf gcc-3.3.tar.gz
#cd gcc-3.3
이제 환경 설정과 컴파일을 수행합니다. 환경을 설정한다.
#./configure --target=arm-linux --prefix=/usr --program-prefix=arm-linux-
--with-headers=/linuette/target/box/kernel/include/ --with-cpu=arm9
--with-softfloat-support=internal --enable-languages=c,c++ --nfp
컴파일을 한다.
#make
인스톨을 한다.
#make install