web-dev-qa-db-ja.com

CocoaPodsで静的ライブラリを構築するときにシンボルの重複を防止

Cocoapodsと静的ライブラリに関する多くの質問を見てきましたが、それらのほとんどは、最終的に静的ライブラリと最終ターゲットアプリを含む単一のワークスペースがあると想定しているようです。

私のシナリオでは、静的ライブラリを構築しています。より具体的には、ユーザーが使用できるようにMyLib.frameworkをハッキングしています。私は本当に MyLib.frameworkの依存関係をCocoapodsで管理するのが好きですが、ライブラリのコンシューマCocoapodsを使用します。

たとえば、私のライブラリには、Cocoapodsで管理するAFNetworking依存関係があります。ライブラリをビルドすると、AFNetworkingといくつかの「ダミー」ファイル/オブジェクトが含まれているlibPods.aにリンクされます。私のフレームワークのユーザーもCocoapodsを使用してtheirアプリをビルドすると、次のようになります。

duplicate symbol _OBJC_METACLASS_$_PodsDummy_Pods in:
    /Users/erikkerber/Dropbox/Projects/MillMain/MyLib.framework/BuddySDK(Pods-dummy.o)
    /Users/erikkerber/Library/Developer/Xcode/DerivedData/MillMain-fngfqhlslygksgcfuciznkpqfrbr/Build/Products/Debug-iphonesimulator/libPods.a(Pods-dummy.o)
duplicate symbol _OBJC_CLASS_$_PodsDummy_Pods in:
    /Users/erikkerber/Dropbox/Projects/MillMain/MyLib.framework/BuddySDK(Pods-dummy.o)
    /Users/erikkerber/Library/Developer/Xcode/DerivedData/MillMain-fngfqhlslygksgcfuciznkpqfrbr/Build/Products/Debug-iphonesimulator/libPods.a(Pods-dummy.o)
ld: 2 duplicate symbols for architecture i386

AFNetworkingの依存関係を追加すると、AFNetworkingに関連するシンボルが重複して取得されると思います。

最終的には、MyLibをCocoapodsとともに配布する予定ですが、MyLib.framework自体も配布できるようにしたいと考えています。

Cocoapodを潜在的なユーザーに対して安全にしながら、ライブラリでCocoapodを使用する方法はありますか?

21
Erik Kerber

つまり、ビルド済みライブラリを配布する唯一の良い方法は、依存関係をnotに含めずに、ユーザーに任せることです。つまりこの例では、ユーザーにAFNetworkingをプロジェクトに追加する方法を指示します。 dummyファイルについても基本的に同じことが言えます。

そうは言っても、もちろん複数のビルド済みのバリアントを使用できます。

  • すべての依存関係を含めます。
  • Libのソースのみを含め、依存関係はユーザーに任せます。

スタンドアロンの静的ライブラリを作成するためのプラグインを作成することについてお話ししてきましたが、それは現時点ではまだ始まっておらず、おそらくもう少し時間がかかるでしょう。 (誰か/誰でも時間があるまで)

回避策として、Podfileの post_installフック ダミーファイルを完全に削除します。 (これらはいずれにしても、Testflightのような非ソースライブラリにのみ必要です。)次のようなもの:

post_install do |installer|
  installer.project.targets.each do |target|
    source_files = target.source_build_phase.files
    dummy = source_files.find do |file|
      # TODO Fix this to the actual filename
      # puts "File: #{file.file_ref.name}"
      file.file_ref.name == 'TheDummyFile.m'
    end
    puts "Deleting source file #{dummy.inspect} from target #{target.inspect}."
    source_files.delete(dummy)
  end
end

これはテストされていないコードです。

post_installフックは、CocoaPodsインストーラーオブジェクトを生成します。CocoaPodsインストーラーオブジェクトから、Pods.xcodeprojターゲットを取得できます。このターゲットについては、ドキュメント here を見つけることができます。そこから、プロジェクトにドリルダウンして好きなことを行うことができます。プロジェクトは、このフックを実行した後にディスクに保存されます。

16
alloy

同じ問題がありました。次のpodfile形式を使用して、cocoapodsでライブラリの依存関係を管理しました。

platform :ios, '6.0'
pod 'AFNetworking'

これにより、私の.aファイルにPods-dummy.oファイルが作成されました。その後、同じpodfile形式を使用してこのライブラリを別のプロジェクトに含めた場合、どちらもPods-dummy.oシンボルを作成し、リンカーエラーが発生しました。解決策は、名前空間付きのポッドダミーシンボルを生成する別のpodfile形式を使用することです。

platform :ios, '6.0'
target "MyProject" do
    pod 'AFNetworking'
end

これにより、Pods-MyProject-dummy.oファイルが生成されます。これにより、シンボルが重複することはありません。

注:プロジェクトを新しいpodfile形式を使用するように切り替える場合は、プロジェクトからlibPods.aをリンク解除してください。これは、新しいポッドライブラリの名前がPods-MyProjectであるため、壊れたリンクとしてハングアップするためです。

10
eliasbagley

それらが同じである場合、以下を使用してそれらをマージできます。

libtool (libtool -o merged.a file1.a file2.a)

これでエラーが解決しない場合は、次のオプションがあります。 http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing- classes-from-static-libraries

5
Jeremiah Smith

http://guides.cocoapods.org/syntax/podfile.html#post_install および http://pdx.esri.com/blog/2013/12/13/からの参照名前空間の依存関係/

私は「すべてのシンボルの名前を手動で変更する」アプローチを使用しています。重複したシンボル_OBJC_METACLASS _ $ _ PodsDummy_Podsが発生していたため、Podfileにpost_installを追加して編集して、重複したシンボルを回避しました

post_install do |installer_representation|
    installer_representation.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited), PodsDummy_Pods=SomeOtherNamePodsDummy_Pods'
        end
    end
end
3
chinweekoh

この問題は、プロジェクトAFNetworkingなどに外部コードを手動で追加し、その後、それを含むポッドを追加したときに発生しました。

自分のプロジェクト(ポッドではない)からAFNetworkingを削除するだけで問題は解決しました。

0
Bill Noto