"configure" 기반 오픈 소스 프로젝트들을 Universal Binary들로 만들기
이 기술 문서에서는 몇몇 "configure" 기반의 오픈 소스 프로젝트들을 유니버설 바이너리들로 만드는 방법을 논의하고 있습니다.
소개
Xcode IDE에서는 유니버설 바이너리들을 만드는데 필요한 대부분의 복잡한 과정들을 생략하는 능률적인 제작(build) 시스템을 제공하고 있습니다. 그래서 여러 설정들과 환경 변수들 그리고 실제 제작에 필요한 명령들을 포함한 소스 파일들과의 연결은 미리 지정되어 있는 제작 설정 사항들에 함축되어 있거나, 혹은 Xcode UI를 통해 쉽게 조절할 수 있습니다.
대부분의 오픈 소스 프로젝트들은 실제 제작 시에 실행되는 설정 스크립트를 통해 CPU 유형, word order 그리고 포인터(pointer) 크기와 같은 컴퓨터 정보들과 시스템에 어떤 헤더(header) 파일들과 라이브러리들이 사용가능한지를 포함해서, 프로그램이 컴파일되고 실행될 환경을 결정하게 됩니다. 이러한 스크립트는 보통 하나 혹은 그 이상의 Makefile들과 헤더 파일들을 만들게 됩니다. 이 Makefile들에는 컴파일러와 링커(linker)의 선택 사항들을 포함하고 있으나, Xcode IDE에 있는 자동화된 제작의 이점들을 사용할 수는 없습니다. 이러한 과정으로 생성된 헤더 파일들은 보통 기능 유무 검사들에서 사용되는 상수들을 포함하고 있는데, 예를 들어, 아래는 이미 생성되어 있는 config.h 파일 안에 #define HAVE_UNISTD_H라는 상수가 설정되어 있는 예입니다:
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
이러한 방법은 전통적인 컴파일 환경에서는 잘 작동해서, 여러 오픈 소스 프로젝트들을 Mac OS X로 비교적 쉽게 포트(port)하는 것을 가능케 하였습니다. 하지만 설정 환경에 유니버설 바이너리와 같은 상황을 미리 염두에 두지 않은 상태에서는 문제가 발생할 수도 있습니다.
주의: 이 기술 문서에서는 기존 프로젝트를 인텔 기반의 Macintosh로 이주시키는데 필요할지도 모를 코드의 수정은 다루고 있지 않습니다. 어떠한 코드의 수정이 필요할지는 Universal Binary Programming Guide 문서를 참고하시기 바랍니다.
유니버설 바이너리를 다루고 빌드하는 데에는 주로 두 가지의 접근법이 있습니다. 여기서는 "Hello, World"라는 GNU Hello package로 된 프로그램을 사용해서 어떻게 설정 스크립트를 사용하는지를 알아보는 두 가지의 접근 방법들을 설명하겠습니다. GNU Hello의 소스는 Free Software Foundation을 통해서 내려받을 수 있습니다.
유니버설 바이너리들을 위한 설정
첫 번째 접근 방법으로는 적당한 CFLAGS와 LDFAGS 환경 변수들을 configure에 전달해서 간단하게 유니버설 바이너리로 만드는 법입니다. 이 방법은 간단히 터미널에서 다음과 같은 명령을 주면 됩니다:
env CFLAGS="-O -g -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc" \
LDFLAGS="-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk" \
./configure --prefix=${HOME}/Hello --disable-dependency-tracking
여기서, configure에 --disable-dependency-tracking 설정을 해놓음으로써, 여러 -arch의 하드웨어 목표 환경들에서는 제대로 작동하지 않는 gcc 자체내의 의존적 생성 코드를 사용하지 않게 합니다.
주의: Developer Transition System에서는, 이미 시스템 라이브러리들이 유니버설로 되어 있으며, Intel과 PowerPC 구조들을 모두 지원하므로, CFLAGS 설정으로 -arch i386 -arch ppc만 지정하면 되지만 PowerPC Macintosh에서는 MacOSX10.4u SDK를 꼭 사용해야만 합니다.
configure를 실행한 후에 make로 만들면, 유니버설 바이너리로 된 결과물이 ./src/hello 디렉토리에 있게 됩니다. 여기서 파일 유형은 다음과 같은 명령으로 확인할 수가 있습니다:
file ./src/hello
그러면, 다음과 같은 결과를 얻을 것입니다:
src/hello: Mach-O fat file with 2 architectures
src/hello (for architecture i386): Mach-O executable i386
src/hello (for architecture ppc): Mach-O executable ppc
이 실행 파일은 PowerPC와 Intel 기반의 매킨토시들에서 모두 고유하게(natively) 실행될 것입니다.
다중 제작 결과물들(builds)의 합병
비록 GNU Hello 프로그램은 비슷한 목적으로 쓰여진 것들 중에 가장 복잡한 "Hello, World" 프로그램이지만, 그래도 비교적 간단한 프로그램입니다: byte order도 상관하지 않으며, word size나 pointer 크기에도 관계가 없고, 설정 과정에서 생기는 실행 파일들도 목표로 하는 컴퓨터 환경의 기준에 맞게 알아서 설정 파일들을 생성하게 됩니다. 하지만, 모든 오픈 소스 프로젝트들이 이렇게 간단하지만은 않습니다. 이럴 경우에는, 또 다른 접근 방법으로 lipo 명령을 사용하는 방법이 있습니다.
만약 위에서 설명한 과정을 통해서 GNU Hello 프로그램을 설정하고 빌드하는 것이 불가능 했다면, 적어도 프로그램을 여러 번 설정하고 빌드해서 유니버설 바이너리로 만들 수 있습니다.
Intel과 PowerPC 기반 맥에서 모두 다음과 같이 설정해서 프로그램을 빌드합니다:
./configure --prefix=${HOME}/Hello
make
이렇게 해서 얻어진 src/hello 프로그램들을 하나의 특정 컴퓨터로 복사합니다: 예를 들어, PowerPC 기반 맥에 있는 /tmp 디렉토리에 각기 hello-intel과 hello-ppc 이름으로 복사합니다. 그리고 나서, lipo 명령으로 두 개 모두를 하나로 합칩니다:
lipo -create hello-intel hello-ppc -output hello
전처럼, file 명령으로 파일 속 구성 내용을 확인할 수 있습니다:
file hello
그러면 다음과 같은 결과를 얻습니다
hello: Mach-O fat file with 2 architectures
hello (for architecture i386): Mach-O executable i386
hello (for architecture ppc): Mach-O executable ppc
더 복잡한 프로젝트들의 경우에는, 각각에 맞는 설정으로 설치하고 나서, Mach-O 파일들(라이브러리들과 실행 파일들)의 목록을 생성하고, 각각의 파일들에 lipo 명령을 실행해야 합니다.
주의해야 할 사항들
이 경우에도, 몇 가지 알아두어야 할 사항들이 있습니다:
첫 째로, 모든 구성 파일들은 똑같이 설정되어 있어야 합니다. 만약 어느 한 구성 파일의 설정에는 실행 파일이 /usr/local/etc에 위치하도록 되어있으나, 또 다른 하드웨어 기반의 구성에서는 /etc로 설정되어 있다면, 실행 방식은 서로 다를 겁니다.
두 번째는, 간혹 위와 같은 상황을 피할 수 없을 때가 있습니다. 예를 들자면, 설정 작업에서 실행 디렉토리들에 있는 프로세서의 유형(예, "ppc" 혹은 "i386" 혹은 "i686")을 사용할 경우입니다. 이러한 프로젝트의 바이너리 배포를 위한 빌드 시, 일일이 설치 과정에서 생긴 트리(trees) 구조들을 살펴서 모든 변형들이 최종 배포판에 있는지 확인하거나, 혹은 심볼릭 링크들(symbolic links)을 사용해서 이러한 환경을 연출할 수 있습니다. (예, /usr/local/myproj/etc/i386/input.conf와 /usr/local/myproj/etc/ppc/input.conf가 모두 존재하거나, 혹은 /usr/local/myproj/etc/i386에서 /usr/local/myproj/etc/ppc를 가리키도록 심볼릭 링크를 사용할 수도 있을 것입니다.)
옮긴 글 - Apple Technical Note TN2137: Building Universal Binaries from "configure"-based Open Source Projects