0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftyTesseractとOpenCVを入れたら「duplicate symbol」しまくった話

Posted at

タイトルの通り。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
Python 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...」と選択して、1.png
入力欄に以下のGitHubのURLを入力します。

https://github.com/SwiftyTesseract/SwiftyTesseract

2.png

OpenCVをプロジェクトに追加する

iOS用にビルドする

GitHubからOpenCVを入手して、platform/ios/にある以下のコマンドでiOS用にビルドします。

$ ./platform/ios/build_framework.py <output_dir>

ビルドしたframeworkファイルをプロジェクトに追加する

プロジェクトファイルを選んで、左ペインの「TARGETS」からアプリを選択します。
そして「Build Phases > Link Binary With Libraries (n items)」と選択して、ビルドで出力された「opencv2.framework」をドラッグ&ドロップなどで追加します。
3.png

Other Linker Flagsに-all_loadを追加する

プロジェクトファイルを選んで、左ペインの「PROJECT」からアプリを選択します。
「Build Settings」を選択して、「Linking > Other Linker Flags」に-all_loadを追加します。
6.png

libc++.tbdをプロジェクトに追加する

同じくプロジェクトファイルの「TARGETS」からアプリを選択します。
そして「General > Frameworks, Libraries, and Embedded Content」と選択して、左下の「+」ボタンを押します。
4.png
検索窓に「libc++」と入力すると「libc++.tbd」が出てくると思うのでそれを追加します。
5.png

試しにビルドしてみるが…

試しにビルドしてもこの時点ではうまくいきません。エラーを見ると「509 duplicate symbols for architecture x86_64(シミュレータなら×86_64、実機ならarm64)」というものすごい数の競合が起きていることがわかります。
7.png
解決方法ですが、__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

あとは途中作ったテキストファイルなどの余計なファイルを削除してリビルドしましょう。
競合が解消されてビルドできるようになっているはずです!

参考記事

  1. OpenCV が Objective-C / Swift で使えるようになります & 使ってみた - Qiita
  2. Xcodeでビルドした時の”duplicate symbols”エラーを回避する
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?