Tag Archives: 심볼

iOS Framework의 duplicate symbol 에러 해결하기

Xcode 프로젝트를 개발하다 보면 다양한 Framework를 사용하게 됩니다. 애플에서 기본적으로 제공하는 Framework부터 외부의 개발사가 제공하는 Dynamic 혹은 Static 형태의 Framework를 접하게 되는데요. 프로젝트의 Build Settings – Other Linker Flags-ObjC 또는 -all_load 설정이 존재하게 되면 이 프레임워크들 사이에 사용하고 있는 라이브러리들이 충돌을 일으키게 됩니다.

이때에 접하게 되는 에러가 다음과 같은 duplicate symbol 오류입니다.

스크린샷 2015-08-23 오후 1.01.16

만약의 위의 충돌이 나고 있는 한쪽이 내 프로젝트라면 해당 Class/Library를 제거하면 간단히 해결될 문제이지만 차용하고 있는 두개의 Framework들 사이에 발생하고 있다면 굉장히 난감한 상황이 됩니다. 이경우 한쪽을 분해하여 해당 라이브러리를 제거한 뒤에 사용하는 방법이 있습니다.

위의 경우에는 Unity 프로젝트에서 기본이 되는 라이브러리 libiPhone-lib.aPPAppPlatformKit.framework간에 ioapi.o 라는 라이브러리가 충돌이 나는 경우이며 PPAppPlatformKit.framework에서 ioapi.o를 제거하는 방향으로 해결해 보도록 하겠습니다.

요즘의 프레임워크는 일명 Universal Framework 혹은 Fat Framework라는 이름으로 다양한 아키텍쳐를 동시에 지원하도록 Archiving 되어 제공됩니다. 우선 위의 충돌이 나고 있는 프레임워크로 접근하여 어떤 아키텍쳐들을 지원하고 있는지 확인해 보겠습니다.

$ cd ~/LibraryConflictExample/XCodeProject/PPAppPlatformKit.framework/
$ lipo -i PPAppPlatformKit
Architectures in the fat file: PPAppPlatformKit are: armv7 arm64

lipo를 사용하여 해당 Framework는 armv7arm64 두가지 아키텍쳐를 지원하고 있다는것을 확인하였습니다. 이제 묶여있는 현재의 Framework를 아키텍쳐별로 분리해보도록 하겠습니다.

$ lipo PPAppPlatformKit -thin armv7 -output PPAppPlatformKit.armv7
$ lipo PPAppPlatformKit -thin arm64 -output PPAppPlatformKit.arm64
$ ls -l
total 29496
drwxr-xr-x@ 5 dennis  staff   170B  8 23 12:26 Headers/
-rw-r--r--  1 dennis  staff   773B  8 23 12:26 Info.plist
drwxr-xr-x@ 3 dennis  staff   102B  7 11 18:32 Modules/
-rw-r--r--  1 dennis  staff   7.2M  8 23 12:26 PPAppPlatformKit
-rw-r--r--  1 dennis  staff   3.7M  8 23 12:26 PPAppPlatformKit.arm64
-rw-r--r--  1 dennis  staff   3.4M  8 23 12:26 PPAppPlatformKit.armv7
drwxr-xr-x@ 6 dennis  staff   204B  8 23 12:26 _CodeSignature/
-rw-r--r--@ 1 dennis  staff    12K  7 11 18:32 embedded.mobileprovision

lipo의 -thin 명령을 사용하여 PPAppPlatformKit.armv7PPAppPlatformKit.arm64 두개로 분리하는데 성공하였습니다. 이번에는 분리해낸 각각의 바이너리들이 현재 충돌나고 있는 ioapi.o를 포함하고 있는지 확인해보도록 하겠습니다.

$ ar -t PPAppPlatformKit.armv7
...
ioapi.o
...

$ ar -t PPAppPlatformKit.arm64
...
ioapi.o
...

ioapi.o가 포함되어있는것을 확인하였습니다. 이제 바이너리에서 해당 오브젝트를 제거해보겠습니다.

$ ar -d -sv PPAppPlatformKit.armv7 ioapi.o
d - ioapi.o

ar -d -sv PPAppPlatformKit.arm64 ioapi.o
d - ioapi.o

아키텍쳐별 바이너리에서 각각 ioapi.o를 제거하였습니다. 이제 다시 하나로 합쳐보도록 하겠습니다.

$ mv PPAppPlatformKit PPAppPlatformKit.original // 기존 바이너리 백업
$ lipo PPAppPlatformKit.armv7 PPAppPlatformKit.arm64 -create -output PPAppPlatformKit

Framework로부터 중복되어 충돌나고 있는 오브젝트를 정상적으로 제거하였습니다. 이제부턴 해당 오류가 발생하지 않을것입니다.