https://wiki.openttd.org/Compiling_on_Mac_OS_X 공식 웹사이트에 컴파일을 한 파일을 배포하면 개발과 상관없는 사람이 실행했을 때 ‘문제가 있기 때문에 OpenTTD을(를) 열 수 없습니다.’ 라는 오류가 발생했다고 뜨는 현상이 발생한다. 이는 거의 대부분 실행에 필요한 라이브러리가 설치되어 있지 않기 때문이며, 컴파일할 때 –enable-static 옵션을 주어도 필요한 라이브러리 중 일부가 바이너리 파일(실행 파일)에 포함되지 않기 때문에 발생하는 오류이다. 오류가 발생했을 때 리포트를 클릭하고 세부사항 보기를 누르면 Dyld Error Message에 Library not loaded에 표시된 파일을 읽어올 수 없다고 표시가 뜰 것이다. 정확한 이유는 모르겠지만 일부 아리브러리 중에서 static으로 컴파일 할 수 없는 라이브러리가 있어서 그런 것이라 파악되고 이러한 라이브러리를 직접 컴파일 한 후 OpenTTD를 컴파일 할 수 있는 방법을 소개하고자 한다.
또한 최신버전에서 컴파일을 한 경우 이전 macOS 버전에서 실행이 안될 수 도 있는 경우도 있는데 이에 대해서도 같이 설명한다.
사전준비(선택사항)
- Git을 다룰 수 있는 도구(개인적으로는 SourceTree를 추천. git으로 배포하고 있는 일부 라이브러리를 쉽게 받아오기 위함. zip 파일로 받아서 컴파일할 수도 있음)
- 대부분의 macOS에서 실행할 수 있는 바이너리를 만들기 위한 조건. 아래의 항목중 하나
- 현재 애플에서 공식 지원중인 운영체제 중 가장 낮은 버전. (2019년 5월 19일 기준 10.11 시에라가 2019년 9월에 공식 지원 중단 예정)
XcodeLegacy.sh (https://github.com/devernay/xcodelegacy)로 낮은 운영체제의 SDK를 다운 후 설치(아래에서 자세히 기술)
홈페이지에서 안내하는대로 컴파일 하기
홈페이지에서 안내한 대로 컴파일을 하고 실행하면 정상적으로 실행될 것이다. 이제 만들어진 실행파일에서 종속성이 무엇이 있는지 확인해본다.
$ otool -L <바이너리 파일>
를 실행하면 openttd에 종속된 라이브러리 목록이 나타난다.
$ otool -L openttd
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 23.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
/System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox (compatibility version 1.0.0, current version 492.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/local/opt/xz/lib/liblzma.5.dylib (compatibility version 8.0.0, current version 8.4.0)
/usr/local/opt/lzo/lib/liblzo2.2.dylib (compatibility version 3.0.0, current version 3.0.0)
/usr/local/opt/libpng/lib/libpng16.16.dylib (compatibility version 54.0.0, current version 54.0.0)
/usr/local/opt/freetype/lib/libfreetype.6.dylib (compatibility version 24.0.0, current version 24.0.0)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.50.111)
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 50.1.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1575.12.0)
/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (compatibility version 64.0.0, current version 1260.2.0)
/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1575.12.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
참고로 OpenTTD 1.9.1 공식 배포판의 종속성은 다음과 같다.
$ otool -L openttd
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 22.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 158.0.0)
/System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox (compatibility version 1.0.0, current version 492.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1561.60.100)
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 50.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1454.93.0)
/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (compatibility version 64.0.0, current version 1161.21.2)
/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 822.37.0)
/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1454.93.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
공식 배포판과 비교하였을 때 새로 추가된 종속성은 ‘liblzma’, ‘liblzo2’, ‘libpng16’, ‘libfreetype’ 이렇게 될 것이고 이 종속성은 컴파일 시 어떤 옵션을 주었느냐에 따라 조금씩 달라진다.
배포판과 동일한 종속성을 가지기 위해 dylib 파일을 이름을 바꾸어 인식 못하게 하면 컴파일러는 무조건 static으로 컴파일하게 된다.
MacPorts로 라이브러리를 설치했다면 ‘/opt/local/lib/’ 폴더안에 관련된 라이브러리의 dylib 파일이 있을 것이다. 삭제하면 나중에 port로 재설치할 때 매우 귀찮아지니 이름과 확장자 뒤에 ‘.bak’만 추가하도록 하자.(이상한게 dylib파일의 이름 뒤에 .bak을 추가하면 전체 파일이름이 *.dylib.bak.dylib’ 이런식으로 바뀐다.)
공식 OpenTTD 바이너리에 비해 직접 컴파일일 했을 때 추가된 종속성에 해당하는 dylib 파일의 이름을 변경했다면 OpenTTD를 새로 컴파일 한다.
$ ./configure --enable-static
$ make clean
$ make && make bundle
새로 컴파일된 바이너리의 종속성을 otool로 확인해보면 공식 빌드와 차이가 없게 되어있을 것이다. 이렇게 만들어진 바이너리를 배포하면 어느 Mac에서든지 잘 실행될 수 있을것이다.
자신의 컴퓨터에서 잘 실행되는지 테스트 해보려면 아래의 명령어로 brew, ports로 설치한 모든 라이브러리를 다 지우고 해보면 될 것이다.
$ sudo port -fp uninstall installed
$ brew remove --force --ignore-dependencies $(brew list)
추가(거의 모든 종속성 삭제)
zlib, libbz2, libiconv 종속성 또한 없엘 수 있긴 한데 zlib와 libbz2는 이름을 변경해도 상관없으나 libiconv는 pkg-config라는 라이브러리의 위치를 알아내는 실행파일이 사용하는 중요한 라이브러리라 이름을 바꾸면 ./configure 단계에서 zlib을 찾을 수 없다고 바로 실패할 것이다.(처음에는 zlib가 없는 오류인줄 알고 한참 헤맸다) 종속성의 경로를 바꾸는 명령어가 있으니 이로 pkg-config의 종속성을 일부 변경하면된다.
$ install_name_tool -change <변경할 라이브러리 경로> <변경된 라이브러리의 경로> <변경할 바이너리의 경로>
그리고 pkg-config 바이너리의 경로를 which를 통해 구하면 된다.
$ which pkg-config
/opt/local/bin/pkg-config
그럼 위의 예시에서 확인된 libiconv의 경로를 참고하여 libiconv파일의 이름을 변경하고 libiconv.2.dylib -> libiconv.2.dylib.bak.dylib 아래의 명령어를 통해 pkg-config의 종속성을 수정하여 정상적으로 실행하게 한다.
$ install_name_tool -change /usr/lib/libiconv.2.dylib /usr/lib/libiconv.2.dylib.bak.dylib /opt/local/bin/pkg-config
pkg-config를 실행해서 잘 실행되는지 확인해본다. 이상태에서 다시 새로 컴파일하는 절차를 따라하면 된다.