Xcodeプロジェクトに編成された静的ライブラリA、B、およびCがあります。A と B は C に依存しています。A と B に依存する iPhone プロジェクトをビルドすると、(C からの) 重複したシンボルが A と B で検出されたというリンカー エラーが発生します。このエラーが発生することなく、他の Xcode プロジェクトにそれらを含めることができますか?
3 に答える
Carl の答えは正しいですが、理由は間違っています。Carl 自身のサンプルを使用してわかるように、静的ライブラリをリンクすることに実際には何の問題もありません。Carl のサンプル コードをセットアップして、次のようにします (XCode が libtool を使用するため、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 にリンクされます。Carl によると、これが OP 問題の原因であり、app2 はリンクすべきではありません。しかし、もちろんそうです。リンカーは、同じファイルの 2 つのインスタンスを無視するほどスマートです。a2.a と b2.a の両方に co が含まれていることがわかります。
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 ユニバーサル バイナリのいずれかであるユニバーサル バイナリに関連していると私は信じています。ここでの問題は、カテゴリにバグがあり、修正 (リンカー フラグに -all_load を追加) が単一のアーキテクチャでのみ機能する修正であることです。-all_load を使用すると、複数のアーキテクチャ用に定義されたシンボルを無視するリンカーの機能が壊れ、シンボルの重複エラーが発生します。
-all_load を使用するよりも優れた解決策を含めて、ここでそれについて書きました。
使用する代わりに、必要なライブラリだけに「path_to_lib」-all_load
を使用することもできます。-force_load
たとえば、次のようなものを使用できます-force_load "$(PROJECT_DIR)/libname"
。
これにより、実装ファイルを変更する必要がある Jamie のソリューションで必要なことを回避できます。
これは、three20 プロジェクトで採用されたソリューションです: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df
編集: Xcode 4.3 以降、 と の必要性は-all_load
削除-force_load
されました。今だけ-ObjC
必要です。詳細については、 https://stackoverflow.com/a/2615407/211292を参照してください。
この問題は、必ずしも Xcode または Objective-C に関連しているわけではありません。ライブラリを他のライブラリにリンク/アーカイブしないでください。A & B は、ビルド時ではなく、最終リンク時にのみ C に依存します。あなたがしたい:
- を建てる
- ビルドB
- ビルドC
- アプリのビルドとリンク
これは私がデモンストレーションのために作ったサンプルプロジェクトです:
メイクファイル:
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();
}
cc:
#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