ReactNativeの開発をしていて、SDKをCocoaPodsからインストールした時にビルドができない
duplicate symbol エラーに遭遇してえらい苦労したので備忘録。
環境
- ReactNative: 0.49.3
- GVRKit (GVRSDK): 1.100.0
duplicate symbol とは?
buildすると、こんなエラーが出ました。
duplicate symbol __ZN3fLI9FLAGS_novE in:
/foo/ios/Pods/GVRSDK/Libraries/libGVRSDK.a(vlog_is_on.o)
/foo/ios/build/Build/Products/Debug-iphonesimulator/libReact.a(vlog_is_on.o)
duplicate symbol __ZN3fLI7FLAGS_vE in:
/foo/ios/Pods/GVRSDK/Libraries/libGVRSDK.a(vlog_is_on.o)
/foo/ios/build/Build/Products/Debug-iphonesimulator/libReact.a(vlog_is_on.o)
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
** BUILD FAILED **
The following build commands failed:
Ld build/Build/Products/Debug-iphonesimulator/foo.app/foo normal x86_64
(1 failure)
どうやら、GVRSDKの libGVRSDK.a とReactNativeの libReact.a のライブラリファイルが同じsymbol(vlog_is_on.o)を重複して読み込んでいるということらしい。
困っている人は他にもいるようです。
https://stackoverflow.com/questions/44838800/react-native-incompatible-with-google-vr-sdk
Symbolの重複を解消する!
ライブラリはバイナリファイルだけど、 lipo コマンドで分解可能。
分解したファイルから重複したシンボルを削除して、ar コマンドで再結合。
実際は libGVRSDK.a が四つのアーキテクチャ向けファイルに分解されるので、それぞれから vlog_is_on.o のシンボルを削除、最後にまた合体しています。
#!/bin/bash
cd ./Pods/GVRSDK/Libraries/
lipo -info libGVRSDK.a
# Divide to each platform
lipo -thin armv7 libGVRSDK.a -output libGVRSDK_armv7
lipo -thin i386 libGVRSDK.a -output libGVRSDK_i386
lipo -thin x86_64 libGVRSDK.a -output libGVRSDK_x86_64
lipo -thin arm64 libGVRSDK.a -output libGVRSDK_arm64
# Delete duplicate file
chmod 777 libGVRSDK_armv7
chmod 777 libGVRSDK_i386
chmod 777 libGVRSDK_x86_64
chmod 777 libGVRSDK_arm64
ar -dv libGVRSDK_armv7 vlog_is_on.o
ar -dv libGVRSDK_i386 vlog_is_on.o
ar -dv libGVRSDK_x86_64 vlog_is_on.o
ar -dv libGVRSDK_arm64 vlog_is_on.o
# rm libGVRSDK.a
lipo -create libGVRSDK_armv7 libGVRSDK_i386 libGVRSDK_x86_64 libGVRSDK_arm64 -output libGVRSDK.a
# Delete media
rm libGVRSDK_armv7
rm libGVRSDK_i386
rm libGVRSDK_x86_64
rm libGVRSDK_arm64
cd ../../../
これで、buildが通るようになりました。
ですが、Podをリセットしたりすると再発するし、毎回やるのはあまりにも骨。であれば、自動化しましょう。
上記をシェルスクリプトにして、Podfile の post_install で実行するように加えます。これでPodがupdateされるたびにコンフリクトするシンボルを削除します。
post_install do |installer|
system(". ./pod_post_install.sh")
end
全てCocoaPodsで管理すればこのような依存問題はないのかもしれませんが、ReactNativeはnpmでインストールされているため問題が起きたのかな、と予想しています。
##参考リンク
http://venture-blog.blogspot.jp/2013/04/duplicate-symbol-objcclassxxx.html
https://github.com/googlevr/gvr-ios-sdk/issues/163