Xcodeプロジェクトに編成された静的ライブラリA、B、Cがあります。 AとBはCに依存しています。AとBに依存するiPhoneプロジェクトをビルドすると、AとBで(Cからの)重複するシンボルが検出されたというリンカーエラーが発生します。このエラーが発生せずに他のXcodeプロジェクトにそれらを含めることができますか?
カールの答えは正しいですが、間違った理由があります。実際にカールの独自のサンプルを使用して確認できるように、静的ライブラリをリンクすることには何の問題もありません。 Carlのサンプルコードを設定してから、次のようにします(Xcodeが使用するため、libtoolを使用します)。
neutron:libtest jamie$ libtool -o a2.a a.a c.a
neutron:libtest jamie$ libtool -o b2.a b.a c.a
neutron:libtest jamie$ gcc main.o a2.a b2.a -o app2
neutron:libtest jamie$ ./app2
a
c
b
c
neutron:libtest jamie$
これにより、a2.aおよびb2.aがmain.oにリンクされます。カールによると、これはOPの問題の原因であり、app2はリンクすべきではありません。しかし、もちろんそうです。リンカは、同じファイルの2つのインスタンスを無視できるほどスマートです。 a2.aとb2.aの両方にc.oが含まれていることがわかります。
neutron:libtest jamie$ ar -t a2.a
__.SYMDEF SORTED
a.o
c.o
neutron:libtest jamie$ ar -t b2.a
__.SYMDEF SORTED
b.o
c.o
それでもそれはうまくリンクします。
問題は、PPC/x86ユニバーサルバイナリまたはarmv6/armv7 iPhoneユニバーサルバイナリのいずれかのユニバーサルバイナリにリンクしていると私は考えています。ここでの問題は categories にバグがあり、修正(リンカーフラグに-all_loadを追加)が単一のアーキテクチャでのみ機能する修正であることです。 -all_loadを使用すると、リンカーが複数のアーキテクチャ用に定義されたシンボルを無視する機能が無効になり、重複シンボルエラーが発生します。
私はそれについて書いた here -all_loadを使用するよりも良い解決策を含めました。
この問題は、必ずしもXcodeまたはObjective-Cに関連しているとは限りません。ライブラリを他のライブラリにリンク/アーカイブしないでください。 AとBは、最終リンク時にCにのみ依存し、ビルド時に依存しません。あなたが欲しい:
ここに私がデモンストレーションするために作ったプロジェクトの例があります:
Makefile:
app: main.o a.a b.a c.a
gcc $^ -o $@
%.o: %.c
gcc -Wall -c $^
%.a: %.o
ar -r $@ $^
clean:
rm -rf *.o *.a app
交流:
#include <stdio.h>
void c(void);
void a(void)
{
printf("a\n");
c();
}
紀元前:
#include <stdio.h>
void c(void);
void b(void)
{
printf("b\n");
c();
}
c.c:
#include <stdio.h>
void c(void)
{
printf("c\n");
}
main.c:
#include <stdio.h>
void a(void);
void b(void);
int main(int argc, char *argv[])
{
a();
b();
return 0;
}
ログをビルドして実行します。
$ make
gcc -Wall -c main.c
gcc -Wall -c a.c
ar -r a.a a.o
ar: creating archive a.a
gcc -Wall -c b.c
ar -r b.a b.o
ar: creating archive b.a
gcc -Wall -c c.c
ar -r c.a c.o
ar: creating archive c.a
gcc main.o a.a b.a c.a -o app
rm a.o b.o c.o
$ ./app
a
c
b
c
_-all_load
_を使用する代わりに、必要なライブラリだけに_-force_load
_ "path_to_lib"を使用することもできます。たとえば、-force_load "$(PROJECT_DIR)/libname"
のようなものを使用できます。
これにより、実装ファイルを変更する必要のあるJamieのソリューションに対して行う必要のあることが回避されます。
これは、three20プロジェクトで採用されたソリューションです。 http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df
edit:Xcode 4.3以降、_-all_load
_および_-force_load
_の必要性がなくなりました。今では_-ObjC
_のみが必要です。詳細は https://stackoverflow.com/a/2615407/211292 を参照してください。