리눅스에서 gcc를 사용해서 코드를 컴파일하고 있는데, 뜬금없는 에러가 나왔습니다. 경고(Warning)를 에러(Error)로 취급해서 빌드를 멈춘다는 메시지였는데요, 아래와 같습니다.

cc1plus: all warnings being treated as errors

make[1]: *** 끝나지 않은 작업을 기다리고 있습니다....

사실 정확한 해결책은 경고(Warning)가 발생하는 코드를 수정하는 것이지만... 경고가 발행하는 곳이 한 두 군데가 아니라서 경고를 에러로 처리하는 옵션을 끄기로 했습니다. 사실 끄는 방법은 아주 간단한데요, gcc의 컴파일 옵션에 -Wno-error를 추가해주면 됩니다. 아래처럼 말이죠 ^^)/~

root> gcc -o a.elf -Wno-error a.c

Makefile을 이용해서 빌드한다면 CFLAG 옵션에다 추가하면 더 간단히 해결할 수 있습니다.

그럼 좋은 하루 되세요 ^^

제 책 "64비트 멀티코어 OS 원리와 구조"가 나온지도 벌써 2달 이상 지났습니다. ^^;;; 책이 출간됨과 동시에 가장 많이 질문을 받는 것이 OS 제작을 위한 환경 구축 방법인데요... 얼마전부터 환경 구축에 어려움을 겪는 분들이 많아지셔서 Cygwin 최신 버전을 다운 받아서 빌드를 해봤습니다. ^^;;; 실제로 빌드를 진행하다보니 한가지 변경점이 보이더군요. ㅠㅠ 그래서 그 내용을 여기다가 정리해놓습니다. ㅠㅠ


<출처 - yes24.com>


Cross Compiler를 만들려면 먼저 Cygwin 사이트(http://www.cygwin.com/install.html)로 이동해서 Cygwin Installer를 다운로드 받습니다. Setup.exe 파일을 다운하면 됩니다. ^^;;;

다운로드 후 파일을 실행하면 어떻게 설치할 것이고 패키지 소스는 어디에서 다운 받을 것인지 선택하는 부분이 나오는데,

책에 나와있는 카이스트 사이트(ftp://ftp.kaist.ac.kr)가 더이상 유효하지 않으니 다른 사이트를 선택해야합니다.

우리나라 근처에 있는게 아무래도... 속도도 빠르니 가까운 일본 주소인 ftp://ftp.jaist.ac.jp를 선택하면 됩니다. ^^;;;

패키지 소스를 다운 받을 주소를 선택하고 난 뒤에는 "Select Package" 화면이 나올 때까지 적당히 Next를 선택해주면 됩니다. ^^;;;

"Select Package" 화면이 나오면 아래의 항목들을 설치해줍니다. 책을 쓸 때는 C++ 관련 항목이 없어도 정상적으로 빌드가 되었지만, 지금은 C++ 컴파일러를 설치하지 않으니 configure 중에 오류가 발생하더군요. ㅠㅠ 가장 아래쪽에 있는 libmpc-devel이 변경된 부분입니다.

+Devel  
    + binutils - 2.21.53-2 버전, 소스 및 바이너리 모두 설치  
    + bison - 2.4-2-1 버전, 바이너리만 설치  
    + flex - 2.5.35-1 버전, 바이너리만 설치  
    + gcc4-core - 4.3.4-3 버전, 소스 및 바이너리 모두 설치  
    + gcc4-g++ - 4.3.4-4 버전, 바이너리만 설치  
    + libiconv - 1.14-1 버전, 바이너리만 설치  
    + libtool - 2.2.7a-15 버전, 바이너리만 설치  
    + make - 3.81-2 버전, 바이너리만 설치  
    + patchutils - 0.3.1-1 버전, 바이너리만 설치  
+Libs  
    + libgmp-devel - 4.3.2-1 버전, 바이너리만 설치  
    + libmpfr-devel -3.0.1-1 버전, 바이너리만 설치
    + libmpc-devel - 0.8-1 버전, 바이너리만 설치

위의 항목이 설치되고 나면 binutils부터 차례대로 빌드를 시작하면 됩니다.


binutils를 빌드하려면 /usr/src 디렉터리 아래에 있는 binutils 디렉터리로 이동해서 다음과 같은 순서로 커맨드를 입력하면 빌드와 설치가 끝납니다.

// 디렉터리 이동 후 아래 작업 수행

$> cd /usr/src/binutils-2.21.53-2  <== 디렉터리 이름은 binutils 버전에 따라 다를 수 있음
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared --disable-nls  
$> make configure-host  
$> make LDFLAGS="-all-static"  
$> make install  

// 아래는 테스트를 위한 부분 커맨드를 실행했을 때 x86\_64 관련 항목이 보이면 제대로 된 것입니다. ^^;;;;  
$> /usr/cross/bin/x86\_64-pc-linux-ld --help | grep "supported "  
/usr/cross/bin/x86\_64-pc-linux-ld: supported targets: elf64-x86-64 elf32-i386 a.  
out-i386-linux efi-app-ia32 efi-bsdrv-ia32 efi-rtdrv-ia32 efi-app-x86\_64 efi-bsd  
rv-x86\_64 efi-rtdrv-x86\_64 elf64-little elf64-big elf32-little elf32-big srec sy  
mbolsrec tekhex binary ihex  
/usr/cross/bin/x86\_64-pc-linux-ld: supported emulations: elf\_x86\_64 elf\_i386 i38  
6linux  

binutils 빌드 및 설치가 끝났다면 gcc를 cross compile할 차례입니다. gcc는 아래와 같은 순서로 입력하면 빌드와 설치가 완료됩니다. ^^;;;

// 압축 해제, 파일명은 cygwin에서 다운받은 GCC 버전에 따라서 다를 수 있으니 실제 디렉터리를 확인하여 입력해야 합니다. ^^;;; 아래 패치 파일도 모두 마찬가지 입니다.  
$> cd /usr/src

$> tar -xvf gcc-4.3.4.tar.bz2  
$> patch -p1 < gcc4-4.3.4-3.src.patch  
$> patch -p1 < gcc4-4.3.4-3.cygwin.patch  
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> export PATH=$PREFIX/bin:$PATH

// 압축 해제가 끝났으니 소스가 있는 디렉터리 이동 후 나머지 작업 수행  
$>cd /usr/src/gcc-4.3.4 <== 디렉터리 이름은 GCC 버전에 따라 다를 수 있음

$> ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --without-headers --disable-shared --enable-multilib  
$> make configure-host  
$> cp /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.dll.a /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.a  
$> cp /lib/libmpfr.dll.a /lib/libmpfr.a  
$> cp /lib/libgmp.dll.a /lib/libgmp.a  
$> make all-gcc  
$> make install-gcc  

// 테스트용입니다. 아래와 같이 입력했을 때 m64가 보이면 정상적으로 설치된 것입니다.  
$> /usr/cross/bin/x86\_64-pc-linux-gcc -dumpspecs | grep -A1 multilib\_options  
    *multilib\_options:  
    m64/m32  

자, 이제 64비트 바이너리를 생성할 수 있는 gcc가 생성되었으니,
즐거운 OS 프로그래밍하세요 ;)

윈도우에서 Cygwin을 사용하여 개발 환경을 설정하신 분들이 꽤 되실겁니다. 저 역시 MINT64 OS의 개발 환경을 cygwin으로 구성했습니다. ^^;;;

그런데 Cygwin을 설치한 뒤에 윈도우 콘솔창(cmd.exe)을 실행시켜 gcc를 입력하면, "액세스가 거부되었습니다."라는 메시지가 표시됩니다. 이는 /usr/bin 디렉터리에 있는 gcc.exe 파일이 실제로는 /etc/alternative/gcc에 연결된 링크 파일이기 때문인데요, 이 파일은 다시 /usr/gcc-4.exe에 연결되어 있습니다. ^^;;;
 



따라서 윈도우 콘솔창에서 gcc를 직접 실행하려면 gcc-4를 입력하면 됩니다.아니면 Grampus님이 하신 방법처럼 윈도우에서 심볼 링크를 걸어주셔도 됩니다.(지나다가님, Grampus님 제보 감사합니다. ^^;;;) 

C:\Cygwin\bin>mklink gcc.exe gcc-4.exe

단, makefile을 이용해서 make를 실행하는 경우는 gcc를 사용해도 괜찮습니다.  ^^


cygwin에서 윈도우 폴더에 접근하는 방법은 루트 디렉터리 아래에 있는 cygdrive로 이동하시면 됩니다. cygdrive 아래에는 윈도우 드라이브들이 존재하는데, 이 드라이브로 이동하면 해당 드라이브에 들어있는 파일들이 아래와 같이 표시됩니다.
 


 따라서 원하시면 cygwin 쉘에서 윈도우 디렉터리에 접근하여 작업을 진행할 수도 있습니다. ^^

그럼 좋은 하루 되세요 ;)

 
 Cywin에서 크로스 컴파일러를 만들기위해서는 먼저 소스 패키지를 설치해야합니다. setup.exe 를 실행해서 Devel 부분의 Binutil gcc-core 의 소스 패키지를 선택하고 설치를 수행하면 소스가 /usr/src 폴더에 설치될 겁니다. ^^

1.Binary Utility Build

 제일 먼저 해야할 일은 binutil을 빌드하는 일입니다. x86_64용 크로스컴파일러를 빌드하기 위해서는 x86_64용 ld와 as 등등 각종 링커와 어셈블러들이 필요하기 때문이지요 ;) bintul을 빌드하는 방법은 아래와 같습니다.
  • export PREFIX=/usr/cross
  • export TARGET=x86_64-pc-linux
  • ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared
  • make configure-host
  • make LDFLAGS="-all-static"
  • make install
 위와 같이 실행하고나면 정상적으로 build된 경우 /usr/cross 라는 폴더가 생성되어있을 겁니다. 그 폴더에 들어가보시면 빌드 결과물을 확인할 수 있습니다. ;) 현재 x86_64 용 glib가 생성되어있지 않은 상태이므로, 공유라이브러리를 사용하지 않도록 --disable-shared-all-static 옵션을 줘야합니다. 주지 않을 경우 나중에 gcc 빌드할 때 문제가 발생합니다. ㅜ_ㅜ crti.o가 없다고 계속 에러가... ㅠㅠ

2. GCC Build

 그 다음 해야할 일은 gcc를 생성하는 일입니다. cygwin에 포함된 gcc 소스에는 소스 파일과 패치파일을 포함하고 있습니다. 정상적으로 빌드하기위해서는 패치를 수행해야 하는데, 다행이도 gcc-3.4.4.sh 라는 스크립트가 있습니다. 아래의 빌드를 수행하기 전에 먼저 아래와 같이 입력해서 패치를 수행합니다.
  • gcc-3.4.4.sh prepare
 위 과정이 정상적으로 끝나고나면 gcc-3.4.4-3 이라는 폴더로 이름이 변경될겁니다. 그럼 해당 폴더로 이동해서  아래의 순서대로 실행합니다.
  • export PATH=$PREFIX/bin:$PATH
  • ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --with-newlib --without-headers --disable-shared --disable-threads
  • make configure-host
  • make LDFLAGS="-static" all-gcc
  • make install-gcc
 위와 같이 실행하고나면 /usr/cross에서 gcc관련 파일들을 보실 수 있습니다.

 이 간단한걸 하려고 며칠을 해매었는지 모르겠군요. ㅜ_ㅜ)-b
 다른 분들은 이런 걸로 고생 안하셨으면 합니다. ㅜ_ㅜ
 아아 이거 또 실패했습니다. ㅜ_ㅜ ln 까지는 갔으나... crti.o를 자꾸 찾는 바람에.... ㅜ_ㅜ cygwin에서 컴파일하는데 저 파일을 찾는 걸 보니 --target=x86_64-linux 옵션으로 줘서 그런 것 같습니다.

사용자 삽입 이미지

 크윽... 왜 Cygwin Package에는 64bit로 크로스 컴파일하는 옵션이 없을까요... ㅜ_ㅜ --target=x86_64-cygwin 요런거라도 있으면 좋을 텐데 말입니다. ㅜ_ㅜ

 당체 이 삽질을 언제 끝낼 수 있을지... 크윽... ㅜ_ㅜ 눈물이 앞을 가립니다. 흑흑...



 아아~ 이거 주말을 다 날렸습니다. 결국 cygwin으로 옮겨타고 나서야 binutil을 컴파일 할 수 있었는데... gcc를 컴파일 하려니 이것 저것 문제가 많아서 결국 실패했습니다. ㅜ_ㅜ

 컴파일을 한참 진행하다보니 거의 마지막 단계인 nm을 사용하는 부분과 ar을 사용하는 부분이 문제인것 같던데... makefile 안에 있는 아래와 같은 부분이 정상적으로 동작하지 않는 것 같습니다.

AR_FOR_TARGET = ` \
  if [ -f $(objdir)/../binutils/ar ] ; then \
    echo $(objdir)/../binutils/ar ; \
  else \
    if [ "$(host)" = "$(target)" ] ; then \
      echo ar; \
    else \
       t='$(program_transform_name)'; echo ar | sed -e $$t ; \
    fi; \
  fi`
AR_FLAGS_FOR_TARGET =
AR_CREATE_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) rc
AR_EXTRACT_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) x

RANLIB_FOR_TARGET = ` \
  if [ -f $(objdir)/../binutils/ranlib ] ; then \
    echo $(objdir)/../binutils/ranlib ; \
  else \
    if [ "$(host)" = "$(target)" ] ; then \
      echo $(RANLIB); \
    else \
       t='$(program_transform_name)'; echo ranlib | sed -e $$t ; \
    fi; \
  fi`

NM_FOR_TARGET = ` \
  if [ -f ./nm ] ; then \
    echo ./nm ; \
  elif [ -f $(objdir)/../binutils/nm-new ] ; then \
    echo $(objdir)/../binutils/nm-new ; \
  else \
    if [ "$(host)" = "$(target)" ] ; then \
      echo nm; \
    else \
       t='$(program_transform_name)'; echo nm | sed -e $$t ; \
    fi; \
  fi`

 원래의 의도대로라면 if else에 의해서 x86_64-linux-nm 이나 x86_64-linux-ar과 같이 치환되어야할 것들이 그대로 쉘에 출력되어 난데없는 rc.exe가 실행되는 안습인 상황이 벌어지더군요. ㅡ_ㅡa... 쉘이 문제인지 makefile이 문제인지 확실하게 모르겠습니다만... 정상적으로 실행이 안되는 것은 사실인 것 같습니다. ㅎㅎ

 아아~ 이거 주말을 다 날렸네요. ㅜ_ㅜ 내일은 꼭 성공해야할텐데... 큰일입니다. ㅜ_ㅜ
 그럼 좋은 밤 되세요 ;)

ps) cygwin에서 x86_64로 크로스 컴파일 해보신 분 있으시면 팁 좀 부탁 드립니다. (_ _)


 32bit 윈도우라서 64bit 코드를 생성하는게 상당히 힘들군요. ㅜ_ㅜ 되도록이면 Open Source를 사용하려고 MinGW나 Cygwin을 보고 있습니다만... 다들 m64 옵션이 먹지 않는 것 같네요. ㅜ_ㅜ

 MinGW에 GCC 소스를 받아서 컴파일 해보니 이것도 에러가 발생... ㅜ_ㅜ... 아놔 천지 쉬운게 없군요. 이거 하루종일했는데, 결국 실패했습니다.

 어디 m64 옵션 먹게 컴파일된 GCC 없나요? ㅜ_ㅜ


 크윽... 이럴수가... 64bit 코드를 생성할 일이 있어서 MinGW를 설치했는데, m64 옵션이 먹지 않더군요. ㅜ_ㅜ 구글을 뒤져보니 디폴트로 컴파일되서 32bit 만 지원하나 봅니다. ㅜ_ㅜ

 결국 한 2시간을 찾아 해매다가... 결국 gcc 소스를 받아서 새로 컴파일하기로 했습니다. 어휴... 이거 초장부터 쉽지 않습니다. ㅜ_ㅜ... 아흑... 오늘 하루종일하겠군요.

 일단 컴파일되서 테스트까지 끝나면 포스팅하겠습니다. ;)
 다들 즐거운 주말 되시길 ^^)/~


+ Recent posts