3월 012007
 

아래 글은 마침 혼자 끄적일 목적으로 GCJ관련 자료를 찾아 헤매다가 쓸만한 내용이어서 따라해본 내용입니다. 아래의 내용대로 하면 GCC4.2를 만들 수 있고, 4.1도 약간의 패치로 만들 수 있습니다.
내용이 상당이 유익한 듯하여 번역을 해 봅니다.

원본

소개

이 문서는 Minimalist GNU for Windows (MinGW) 툴킷을 이용한 윈도우용 GNU Compiler for Java (GCJ)를 생성한 과정을 설명한 것이다. 이 글을 쓴 이유는 많은 사람들이 자주 같은 내용에 대해 질문하는 것을 피하고, 또한 윈도우즈용 GCJ를 각자 나름의 구미에 맞게 생성하면서 실험할 수 있도록 독려하기 위해서다.

가장 손쉽게 GCJ를 윈도우즈에서 돌아가도록 생성하는 방법은 MSYS나 Cygwin을 이용하는 것인데, 흔히들 이 방법을 “native” 생성이라고 한다. 이 방법은 필자가 실제로 가장 처음에 시도한 방법인데, 이 방법은 아주 많이 느렸다. 그리고 상당히 불안정 했는데, 그 이유는 MSYS내에 존재하는 많은 오류들 때문이고, 또한 대소문자를 구별하지 않는 윈도우즈 파일 시스템의 특성 때문이다.
GCJ를 포함하고 있는 GNU Compiler Collection (GCC)의 탁월한 디자인 덕분에 필자의 해결책으로 전술한 방법 대신 다음의 두 단계를 통해 성공적으로 GCJ를 생성할 수 있었다.

  1. 리눅스 상에서 리눅스에서 돌아가는 GCJ를 만든다. 그렇지만 이 결과물은 실제로 윈도우용 실행 파일을 만들 수 있다. (흔히들 “cross compiler” 라고 부른다.).
  2. 1단계에서 만든 GCJ를 이용하여, 실제 윈도우즈에서 돌아가는 GCJ를 생성한다. (흔히들 “crossed-native 컴파일러”라고 부른다.)

위의 두 단계는 실제로 전술한 방법보다 월등히 빠르고, 대단히 안정적이다. 필자는 리룩스 상에서 이렇게 생성된 컴파일러를 WINE 이나 QEMU같은 에뮬레이터 상의 윈도우즈에서 PC의 리부팅 없이 아무 무리없이 동작시킬 수 있었다.
아래는 필자가 직접 윈도우즈용 GCJ를 생성한 방법을 적어 놓은 것이다.

주의: 이 절차는 현재 GCC의 메인 라인 소스에만 적용가능한 방법이다. (GCC 4.2로 릴리즈 될 예정임.)

준비해야 할 것들.

제일 먼저 최근의 리눅스 배포본이 돌아갈 만한 정당한 PC가 필요하다. 약 500MB 정도의 디스크 여유공간이 필요하고, 리눅스에 대한 지식과 소스코드에서 소프트웨어를 빌드해본 적절한 경험이 필요하다. 그리고, 리눅스 배포본에는 “개발”용 페키지가 설치 되있어야 하는데 예를 들면, GCC, binutils, make, bison, flex, 등등이 되겠다.

GCC와 binutils의 소스코드를 다운로드 받아야 한다. 필자는 가능하면 최신의 릴리즈 버젼을 미러 사이트에서 다운 받을 것을 권한다. 만약 디스크에 여유가 그리 많지 않고 다운받는 속도가 느리면, GCC의 경우 “core”, “g++”, “java”만 다운로드 받아도 된다. (tar로 압축된 것으로)


$TARGET 은 GCC에 의해 생성된 코드가 실행될 플랫폼이다. 예를 들면, 사용자의 필요에 따라 “mingw32″, “i386-pc-mingw32″ 또는 “i686-pc-mingw32″라고 할 수 있겠다. (따옴표는 빼주세요.) 필자가 이 글을 쓸 때는 “mingw32″는 MinGW 플랫폼을 말하고 이는 “i386-pc-mingw32″에 다른 이름이다. 이는 곧, 32비트의 윈도우즈 실행파일을 의미하고 i386 이상의 어떤 PC에서도 실행할 수 있다. 만일 사용자가 Pentium Pro 이상의 플랫폼 이상을 감안한다면, “i686-pc-mingw32″을 사용하는 것이 좋다.

$GCC_SRC_DIR 와 $BU_SRC_DIR는 GCC 와 binutils의 소스코드가 풀릴 디렉토리를 말한다. (역주: 사용자는 어떤 디렉토리로 할 것인지 정한다. gcc-src 또는 binutils-src ??? 등등)

MinGW SourceForge 소스저정소에서 “mingw-runtime” 와 “w32api”의 최신 바이터리 패키지를 다운받는다.

GCC를 빌드할 때, 아래의 쉘스크립트를 사용할 것이므로 다운받아 저장한 다음 필히 실행가능하도록 권한을 바꿔준다.

  1. cfgxbu.sh – Linux 에서 Windows용 cross-binutils을 만들기 위한 설정용 스크립트.
  2. cfgxgcc.sh – Linux 에서 Windows용 cross-GCC를 만들기 위한 설정용 스크립트.
  3. cfgwbu.sh – Windows용 cross-native-binutils을 만들기 위한 설정용 스크립트.
  4. cfgwgcc.sh – Windows용 crossed-native-GCC를 만들기 위한 설정용 스크립트.
  5. buildit.sh – 생성된 설정을 이용하여 빌드하기 위한 스크립트.

중요: 각 스크립트의 첫부분에 몇몇개의 환경 변수들이 있는데, 이 값들은 반드시 빌드하려는 각자의 디렉토리 구조와 같도록 값을 바꿔줘야 한다. 이 디렉토리들은 실행할 binutils 디렉토리와 GCC의 소스코드가 있는 디렉토리, 그리고 만들어진 소프트웨어가 설치될 디렉토리의 위치에 대한 정보이다. 이 디렉토리 설정이 정확하지 않으면 당연히 이 모든 과정이 실패할 것이다.

마지막으로 이 모든 과정은 시간이 상당히 소요되므로, 인내심이 필요한 작업이 되겠다.

알아둬야 할 것들

아래의 내요은 중요하므로 꼭 확인해야 한다.

  1. “mingw-runtime” 와 “w32api”는 꼭 바이너리 패키지이다. 소스코드 패키지가 아니다.
  2. GCC 또는 binutils 가 만들어지는 디렉토리와 최종적으로 이것들이 설치될 디렉토리는 소스가 풀려있는 디렉토리와는 완전이 다른 디렉토리여야 한다. GCC는 현재 소스코드가 있는 디렉토리 또는 그 하위 디렉토리에서는 적절하게 컴파일되지 않기 때문이다. 이는 cross컴파일러나 native컴파일러는 만드는 모든 과정에 해당된다.
  3. GCC 나 binutils을 본격적으로 만들기 전에, “sys-root”라는 디렉토리를 만들어진 GCC 와 binutils을 설치할 디렉토리 밑에 만들어야 한다. “mingw”를 “sys-root”디렉토리 밑에 만들고, 다운 받았던 “mingw-runtime”와 “w32api” 바이터리 패키지를 이 디렉토리에 압축을 풀어놓는다. 그러면, “mingw”디렉토리 밑에 “include” 와 “lib” 같은 하위 디렉토리들이 생길 것이다.
  4. 아래 첫 과정에서 cross-binutils를 만들고 설치하고 난 후에, 가장 먼저 해야할 것은, cross-binutils의 “bin” 디렉토리가 PATH 환경변수의 맨 처음에 나오도록 설정하는 것이다. 물론 앞의 스크립트를 사용한다면, 그 스크립트안에 이 내용이 포함되어 있으니, 수동으로 설정하지 않아도 된다.
  5. 스크립트 속에는 타겟 플랫폼을 “i686-pc-mingw32″로 해놓았다. 만일 다른 타겟을 원한다면 (예:”i386-pc-mingw32″), 스크립트를 실행하기 전에, 스크립트 속의 “TARGET” 변수를 수정해야 한다.
  6. 최소한 binutils-2.16.1를 이용하여, cross 그리고 crossed-native binutils가 반드시 빌드되야 된다. 이 버젼에서 파일 시스템의 hard link가 지원되기 때문인데, 그래야 GCC에서 문제가 생기지 않는다.
  7. binutils를 컴파일하기 위해서는 YACC 와 Lex (또는 GNU의 bison 과 flex 같은 것들)가 시스템에 설치되어 있어야 한다. 

Cross Compiler 컴파일 하기

일단 먼저 리눅스 상에서 도는 GCC를 만들어야한다. 그렇지만 요 GCC는 Windows용 실행파일을 만들 수 있다. 만약에 굳이 윈도우에서 도는 GCC가 필요치 않고 Linux가 더 편하다면, 이 단계만으로도 Windows 개발 환경을 갖출 수 있다.

아래의 과정을 차례로 실행해야 한다.

  1. cross compiler가 설치될 디렉토리 (이 후로 $XGCC_DIR 라 부를 것임) 를 $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다.
  2. “sys-root” 디렉토리를 $XGCC_DIR 아래에 만든다. “mingw” 디렉토리를 만들어진 “sys-root” 아래에 만들고, “mingw-runtime” 와 “w32api” 바이터리 패키지를 “$XGCC_DIR/sys-root/mingw” 아래 풀어놓는다.
  3. cross-binutils를 만들 디렉토리를 (이 후로 $XBU_BUILD_DIR 라 부를 것임) $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다.
  4. “cfgxbu.sh” 스크립트 안에 BU_SRC_DIR와 PREFIX 변수 속에 사용되고 있는 $XGCC_DIR을 적절한 값으로 수정한다.
  5. $XBU_BUILD_DIR로 이동아여 “cfgxbu.sh”를 실행한다.
  6. “buildit.sh”의 XGCC_DIR값을 수정한다.
  7. $XBU_BUILD_DIR로 이동하여 “buildit.sh”을 실행한다. 그러면, cross-binutils가 만들어지고 $XGCC_DIR에 설치가 된다.
  8. cross-GCC를 만들 디렉토리를 (이 후로 $XGCC_BUILD_DIR 라 부를 것임) $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다. 만일 디스크 공간을 절약하고 싶다면, $XBU_BUILD_DIR의 내용물을 삭제한 후 이 디렉토리를 재사용해도 된다.
  9. “cfgxgcc.sh” 스크립트 안의 GCC_SRC_DIR 값을 수정하고 PREFIX 값이 $XGCC_DIR의 값을 갖도록 수정한다.
  10. $XGCC_BUILD_DIR로 이동해서 “cfgxgcc.sh”를 실행한다.
  11. $XGCC_BUILD_DIR로 이동해서 “buildit.sh” 를 실행한다. 그러면, cross-GCC가 만들어지고 $XGCC_DIR에 설치된다.

이 모든 과정이 잘 진행 된다면, 리눅스에서 돌아가면서 C, C++, Java로 윈도우즈 실행파일을 생성할 수 있는 완전한 크로스 컴파일러가 만들어진다. 이 크로스 컴파일러의 실행파일들은 $XGCC_DIR/bin 디렉토리 안에, $TARGET-gcc, $TARGET-g++ 등등의 이름으로 되어있다. 

Crossed-Native 컴파일러 만들기

이제부터는 지금까지 만든 cross-GCC를 이용해서 윈도우즈용 native GCC를 만들 것이다. 이것은 만약에 윈도우즈 상에서 컴파일하고 시험하기를 원하는 경우에 필요하다.

아래의 과정을 따라하면 된다.

  1. crossed-native GCC가 설치될 디렉토리 (이 후로 $WGCC_DIR 라 부를 것임) 를 $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다.
  2. “sys-root” 디렉토리를 $WGCC_DIR 아래에 만든다. “mingw” 디렉토리를 만들어진 “sys-root” 아래에 만들고, “mingw-runtime” 와 “w32api” 바이터리 패키지를 “$WGCC_DIR/sys-root/mingw” 아래 풀어놓는다.
  3. crossed-native-binutils를 만들 디렉토리를 (이 후로 $WBU_BUILD_DIR 라 부를 것임) $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다. 디스크 공간을 절약하고 싶다면, $XGCC_BUILD_DIR를 비운 다음 재활용해도 된다.
  4. “cfgwbu.sh” 스크립트 안에 BU_SRC_DIR와 XGCC_DIR 변수 값을 올바른 값을 바꾼다. PREFIX 변수 속에 사용되고 있는 $WGCC_DIR을 적절한 값으로 수정한다.
  5. $WBU_BUILD_DIR로 이동아여 “cfgwbu.sh”를 실행한다.
  6. “buildit.sh”의 XGCC_DIR값을 수정한다.
  7. $WBU_BUILD_DIR로 이동하여 “buildit.sh”을 실행한다. 그러면, crossed-native-binutils가 만들어지고 $WGCC_DIR에 설치가 된다.
  8. 윈도우즈용 GCC가 만들어질 디렉토리를 (이 후로 $WGCC_BUILD_DIR 라 부를 것임) $BU_SRC_DIR 또는 $GCC_SRC_DIR가 아닌 다른 밖의 디렉토리에 만든다. 만일 디스크 공간을 절약하고 싶다면, $WBU_BUILD_DIR의 내용물을 삭제한 후 이 디렉토리를 재사용해도 된다.
  9. “cfgwgcc.sh” 스크립트 안의 GCC_SRC_DIR와 XGCC_DIR 값을 수정하고 PREFIX 값이 $WGCC_DIR의 값을 갖도록 수정한다.
  10. $WGCC_BUILD_DIR로 이동해서 “cfgwgcc.sh”를 실행한다.
  11. $WGCC_BUILD_DIR로 이동해서 “buildit.sh” 를 실행한다. 그러면, 윈도우즈용 GCC가 만들어지고 $WGCC_DIR에 설치된다.

여 기까지 잘 진행이 되면, 윈도우즈용 crossed-native GCC가 만들어질 것이다. 이제 이 것을 이용하면, C, C++, Java를 이용해서 윈도우즈 상에서 윈도우즈용 실행 파일을 만들수 있다. $WGCC_DIR 디렉토리의 모든 내용물을 윈도우환경으로 옮겨놓고 사용하면 된다.

주의: $WGCC_DIR로 binutils를 설치할 때, 파일들이 $WGCC_DIR/bin와 $WGCC_DIR/$TARGET/bin에 중복되서 깔리게 된다. 디스크 공간을 절약하기 위해서, 이 과정은 하드 링크로 생성된게 되는데, $WGCC_DIR의 내용물을 윈도우즈로 옮길 때, $WGCC_DIR/$TARGET/bin 디렉토리와 내용물이 있는지 확인해야 한다. 그렇지 않으면, GCC는 자동으로 필요한 binutils를 찾을 수 없게 되고, 수동으로 PATH 환경변수에 이 디렉토리를 추가해야 한다.

Native 컴파일러 만들기

필자가 예전에 MSYS를 이용해서 MinGW용 GCC에서 C, C++컴파일러를 만들기는 했지만, 여러가지 이유로 GCJ는 만들어 보지 못했다. MSYS를 이용해서 MinGW용 GCC를 만들때는 몇가지 주지해야만 할 것들이 있다.

  • 일단 아무 문제 없는 MinGW가 설치 되어있어야 한다. MSYS 는 MinGW가 설치된 디렉토리를 “/mingw” 디렉토리로 매핑하고 있다는 것을 기억해야 한다.
  • GCC를 반드시 상대 경로로 설정해야 한다. 절대경로로 설정하면 안된다. (예를 들면, “/d/src/gcc/configure” or “e:/gcc/configure” 대신에 “../gcc/configure” 식으로 )
  • prefix 설정은 반드시 “/mingw”로 해야 한다. (예를 들면 “–prefix=/mingw”). 만약에 이를 다른 곳에 설치하고 싶다면, 일단 모든 컴파일 후에 예를 들어 “make DESTDIR=/foo/bar install” 커맨드를 실행해야 한다. (컴파일러는 “mingw” 디렉토리 아래 “/foo/bar”에 설치가 된다.
  • 설정시 “–disable-werror”를 반드시 사용해야한다. 그래야 warning이 error로 처리 되지 않고 컴파일 할 수 있다.
  • 컴파일러를 만들 때, “make bootstrap”를 반드시 사용해야 한다.
  • GCC 소스 코드를 공식 릴리즈 된 버젼 대신 SVN mainline에서 가져왔다면, GNU bison 파서 생성기와 Flex 구문 분석기가 있어야 한다. 이는 MinGW용 이어야 하고, the GNU-Win32 project 다운 받을 수 있다. 일단 설치한 후에 MSYS를 다시 시작해야 한다.

Further Hacking

이제 GCJ를 이용해서 프로그램을 만들고 실행할 수 있다. 만일 어떤 문제가 생기면, GCJ의 메일링 리스트(java@gcc.gnu.org)에 자세한 내용과 함께 문의바라니다. 그렇지만 질문 이전에 GCJ 문서 와 GCJ mailing list
를 검색해 볼 것을 권한다. 

GCC/GCJ는 Free Software이고, 소스코드가 완전히 공개되어있으니, 문제점이 있다면 스스로 고칠 수 있고, 패치를 할 수도 있다. 이 경우, 그 패치를 java-patches@gcc.gnu.org 로 보내 다른 사람들과 공유할 것을 권한다. 만일 이런 패치가 처음이라면, 어떻게 패치를 생성하고 보내는지에 대한 정보를 “How to Create Patches“에서 찾을 수 있다.

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)