2010-02-20 3 views
29

J'ai les bibliothèques statiques A, B et C organisées en projets Xcode. A et B dépendent de C. Lorsque je construis un projet iPhone qui dépend de A et B, j'obtiens une erreur de lien qu'un symbole dupliqué (de C) a été détecté dans A et B. Comment puis-je organiser ces trois bibliothèques statiques de sorte que je peut les inclure dans d'autres projets Xcode sans rencontrer cette erreur?Comment puis-je éviter les erreurs de "doublons de symboles" dans xcode avec les bibliothèques statiques partagées?

+0

Lors de la création des cibles de bibliothèque pour A et B, vous devez sûrement inclure uniquement les en-têtes de C. Vous lieriez uniquement à C lors de la création du projet iPhone? –

Répondre

6

Ce problème n'est pas nécessairement lié à Xcode ou à Objective-C. Ne pas lier/archiver les bibliothèques dans d'autres bibliothèques. Un & B dépend uniquement de C au moment de la liaison finale, pas au moment de la construction. Vous voulez:

  1. construire une
  2. build B
  3. build C
  4. build application & lien

Voici un exemple de projet que j'ai fait pour démontrer:

Makefile:

app: main.o a.a b.a c.a 
     gcc $^ -o [email protected] 

%.o: %.c 
     gcc -Wall -c $^ 

%.a: %.o 
     ar -r [email protected] $^ 

clean: 
     rm -rf *.o *.a app 

a.c:

#include <stdio.h> 
void c(void); 

void a(void) 
{ 
    printf("a\n"); 
    c(); 
} 

b.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; 
} 

Générez et exécutez connecter:

$ 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 
+0

Pour autant que je sache, Xcode ne permet pas/supporte cela? Si c'est le cas, je pense que vous devriez corriger votre réponse pour expliquer comment y parvenir (vu que la question originale est marquée "xcode") - Je suis venu ici de Google parce que je ne peux pas obtenir Xcode pour gérer cette configuration simple! Sinon, cette réponse est inutile, car elle ne fait rien pour résoudre la question. – Adam

25

réponse de Carl est juste, mais pour les mauvaises raisons: il n'y a en fait rien de mal à relier les bibliothèques statiques ensemble, comme on peut le voir en utilisant le propre échantillon de Carl. Mise en place du code de l'échantillon de Carl puis faire: (J'utilise libtool parce que c'est ce que XCode utilise)

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$ 

Ce lien A2.a et b2.a avec main.o. Selon Carl, c'est la source du problème d'OP, et app2 ne devrait pas lier. Mais bien sûr que oui. L'éditeur de liens est assez intelligent pour ignorer deux instances du même fichier. Nous pouvons voir que a2.a et b2.a contiennent 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 

Pourtant, il est très bien. Le problème est, je crois, lié aux binaires universels, aux binaires universels PPC/x86, ou aux binaires universels d'armv6/armv7 iPhone. Le problème ici est qu'il y a un bogue avec categories et le correctif (ajouter -all_load aux indicateurs de l'éditeur de liens) est un correctif qui ne fonctionne que pour les architectures uniques. L'utilisation de -all_load casse la capacité des linkers à ignorer les symboles définis pour plusieurs architectures, et vous avez votre erreur de symbole en double.

J'ai écrit à ce sujet here, y compris une meilleure solution que d'utiliser -all_load.

+2

Voici un lien de travail à votre entrée de blog: http://blog.binaryfinery.com/universal-static-library-problem-in-iphone-sd – ThomasW

+0

Non, ce lien est cassé aussi. C'est le "k" final qui continue d'être supprimé. Bug avec SO? Essayer à nouveau: http://binaryfinery.wordpress.com/2010/06/11/universal-static-library-problem-in-iphone-sdk/ – Adam

6

Une alternative à l'utilisation de -all_load consiste à utiliser -force_load "path_to_lib" uniquement pour les bibliothèques où cela est nécessaire. Par exemple, vous pouvez utiliser quelque chose comme: -force_load "$(PROJECT_DIR)/libname". Cela évite ce que vous devez faire pour la solution de Jamie, qui nécessite de modifier les fichiers d'implémentation.

C'est la solution adoptée par le projet Three20: http://groups.google.com/group/three20/browse_thread/thread/ec208be4ff8b4dcb/0dccf992a26850df

modifier: au Xcode 4.3 la nécessité de -all_load et -force_load a été supprimée. Maintenant seulement -ObjC est nécessaire. Voir https://stackoverflow.com/a/2615407/211292 pour plus de détails.

+1

Des mises à jour pour Xcode 4.3? – Klaas

+0

'-all_load' et' -force_load' ne sont plus nécessaires, voir ici: http://stackoverflow.com/a/2615407/211292 – ThomasW

Questions connexes