SwiftyTesseract와 OpenCV를 넣으면 "duplicate symbol"버린 이야기

제목 거리. duplicate symbol 가 나와서 면을 먹었으므로 해결책을 비망록으로 남겨 둡니다.

환경 정보




이름
버전


Xcode
12.3 (12C33)

Swift
5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)

SwiftyTesseract
4.0.0

CMake
3.19.3

파이썬
2.7.16

xcode-select
2384

OpenCV
4.5.1


SwiftyTesseract와 OpenCV를 동일한 프로젝트에서 사용



두 프로젝트를 동일한 프로젝트에서 사용하는 절차를 보여줍니다.

SwiftyTesseract를 프로젝트에 추가



2021년 1월 19일 현재 SwiftyTesseract는 Swift Package Manager에서만 추가할 수 있습니다. 그래서 Swift Package Manager에서 추가합니다.

Xcode에서 File> Swift Packages> Add Package Dependency ...를 선택하고
입력란에 다음 GitHub URL을 입력합니다.
https://github.com/SwiftyTesseract/SwiftyTesseract



OpenCV를 프로젝트에 추가



iOS용 빌드



GitHub에서 OpenCV 받기 다음 platform/ios/ 에 있는 다음 명령을 사용하여 iOS용 빌드합니다.
$ ./platform/ios/build_framework.py <output_dir>

빌드된 프레임워크 파일을 프로젝트에 추가



프로젝트 파일을 선택하고 왼쪽 창의 'TARGETS'에서 앱을 선택합니다.
그리고 "Build Phases > Link Binary With Libraries (n items)"를 선택하고 빌드로 출력된 "opencv2.framework"를 드래그 앤 드롭 등으로 추가합니다.


Other Linker Flags에 -all_load 추가



프로젝트 파일을 선택하고 왼쪽 창의 "PROJECT"에서 앱을 선택합니다.
Build Settings를 선택하여 Linking > Other Linker Flags에 -all_load를 추가합니다.


libc++.tbd를 프로젝트에 추가



마찬가지로 프로젝트 파일의 "TARGETS"에서 앱을 선택합니다.
그런 다음 General > Frameworks, Libraries, and Embedded Content를 선택하고 왼쪽 하단의 + 버튼을 누릅니다.

검색창에 「libc++」라고 입력하면 「libc++.tbd」가 나온다고 생각하기 때문에 그것을 추가합니다.


시험에 빌드 해 보지만 ...



시도에 빌드해도이 시점에서는 작동하지 않습니다. 에러를 보면 「509 duplicate symbols for architecture x86_64(시뮬레이터라면×86_64, 실기라면 arm64)」라고 하는 대단한 수의 경합이 일어나고 있는 것을 알 수 있습니다.

해결책이지만 opencv2.framework에서 충돌이 발생한 파일을 삭제하여 해결할 수 있습니다.

충돌이 발생한 파일(.o 파일) 요약



오류에 따라 충돌이 발생하는 파일을 요약합니다. 저자의 환경에서는 다음 파일에서 충돌이 발생했습니다.
jutils.o pngrio.o pngwio.o jdcoefct.o jaricom.o jdmainct.o jdcolor.o pngerror.o jfdctint.o pngget.o pngrutil.o jmemmgr.o jccoefct.o jcmaster.o jidctflt.o pngpread.o jcprepct.o jerror.o pngset.o jctrans.o jcparam.o jdinput.o pngwtran.o jdarith.o jdsample.o jcomapi.o png.o pngrtran.o jchuff.o jddctmgr.o jidctfst.o jfdctfst.o pngwrite.o jfdctflt.o jdatasrc.o jdapistd.o pngmem.o jdapimin.o pngwutil.o jcdctmgr.o jdtrans.o jdhuff.o jdmaster.o jcapistd.o jdatadst.o jquant2.o jdmerge.o jmemnobs.o jccolor.o jdmarker.o jdpostct.o jcmarker.o jidctred.o jcarith.o jcmainct.o pngtrans.o jcinit.o jcsample.o jquant1.o pngread.o jidctint.o jcapimin.o

위의 목록은 나중에 명령에 인수로 먹일 때 사용할 수 있도록 텍스트 파일 등에 써 둡니다.
$ echo "jutils.o pngrio.o ..." > duplicate_lib_list

OpenCV를 아키텍처별로 분해



lipo 명령을 사용하여 프레임워크 폴더의 opencv2를 아키텍처별로 분해합니다.

먼저 무엇이 포함되어 있는지 아래 명령으로 확인하고,
$ cd opencv2.framework
$ lipo -info opencv2
Architectures in the fat file: opencv2 are: armv7 armv7s i386 x86_64 arm64

다음 명령으로 장미합니다.
$ lipo -thin armv7 opencv2 -output opencv2_armv7
$ lipo -thin armv7s opencv2 -output opencv2_armv7s
$ lipo -thin i386 opencv2 -output opencv2_i386
$ lipo -thin x86_64 opencv2 -output opencv2_x86_64
$ lipo -thin arm64 opencv2 -output opencv2_arm64

충돌이 발생한 파일 삭제



버려진 파일에 대해 다음 명령을 실행하여 충돌이 발생한 각 파일을 삭제합니다.
$ cat duplicate_lib_list | xargs ar -dv opencv2_armv7
$ cat duplicate_lib_list | xargs ar -dv opencv2_armv7s
$ cat duplicate_lib_list | xargs ar -dv opencv2_i386
$ cat duplicate_lib_list | xargs ar -dv opencv2_x86_64
$ cat duplicate_lib_list | xargs ar -dv opencv2_arm64

장미된 파일에서 재생성



다음 명령을 실행하여 opencv2를 재생성합시다.
$ lipo -create opencv2_arm64 opencv2_armv7 opencv2_armv7s opencv2_i386 opencv2_x86_64 -output opencv2

그리고는 중간에 만든 텍스트 파일 등의 불필요한 파일을 삭제하고 재빌드합시다.
경합이 해소되어 빌드할 수 있게 되어 있을 것입니다!

참고 기사


  • OpenCV가 Objective-C / Swift에서 사용할 수있게됩니다 & 사용해 보았습니다 - Qiita
  • Xcode로 빌드 할 때 "duplicate symbols"오류를 피하십시오.
  • 좋은 웹페이지 즐겨찾기