Compilation d'une bibliothèque C++ externe à utiliser avec un projet iOS




objective-c xcode (4)

L’utilisation des bibliothèques C ++ étant totalement nouvelle pour moi, je vous prie d’apprécier que cela soit peut-être un peu spécifique à mon cas (faites-le moi savoir et je pourrai vous fournir plus de détails).

J'ai une bibliothèque externe C ++ que j'essaie d'utiliser avec un projet iOS. La bibliothèque suit un modèle de configuration, make, make pour générer un fichier de bibliothèque .a. Lorsque j'essaie d'ajouter ce fichier de bibliothèque à Xcode, le message d'erreur suivant s'affiche:

En ignorant le fichier /Users/Developer/iOS/TestProj/libpresage.a, le fichier a été créé pour des archives qui ne sont pas l’architecture liée (i386):

/Users/Developer/iOS/TestProj/libpresage.a

Sur la base de cette question , j'ai essayé de transformer la construction de l'architecture active uniquement en NON, et j'obtiens la même erreur. Cela me fait penser que j'ai compilé la bibliothèque pour une architecture incorrecte.

Lancer lipo -info sur le fichier .a donne:

Le fichier d'entrée libpresage.a n'est pas un fichier fat. Fichier non fat: libpresage.a.

est l'architecture: x86_64

Etant donné que ce ne sont pas armv7s, armv7 ou arm64, j’essaie de compiler à nouveau la bibliothèque C ++ avec les paramètres suivants:

1) essayer

./configure CC="gcc -arch armv7s" \
                 CXX="g++ -arch armv7s" \
                 CPP="gcc -E" CXXCPP="g++ -E"

Erreur lors de la compilation, je reçois:

ld: library not found for -lcrt1.3.1.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)

2) essayer

./configure CC="gcc -arch arm64" \
                 CXX="g++ -arch arm64" \
                 CPP="gcc -E" CXXCPP="g++ -E"

Erreur lors de la compilation, je reçois:

ld: warning: ld: warning: ignorant le fichier /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/lib/libSystem.dylib, manquant. file /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib/libSystem.dylib (2 tranches) fichier ignoré /Applications/Xcode.app/Contents/ Developer / Platforms / MacOSX.platform / Developer / SDKs / MacOSX10.10.sdk / usr / lib / libstdc ++. Dylib, architecture requise manquante arm64 dans le fichier /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer /SDKs/MacOSX10.10.sdk/usr/lib/libstdc++.dylib (2 tranches)

ld: les exécutables principaux dynamiques doivent être liés à libSystem.dylib pour l'architecture arm64 clang: erreur: la commande de l'éditeur de liens a échoué avec le code de sortie 1 (utilisez -v pour voir l'invocation)

Y a-t-il quelque chose d'évident qui me manque?

MODIFIER:

Merci pour les réponses. J'ai donc réussi à obtenir la bibliothèque dans Xcode en tant que cible de construction personnalisée, en pointant la commande "make" vers les bibliothèques MakeFile. Cette construction va bien.

Mes pas d'ici:

  • Ajoutez une dépendance de ma cible d'application iOS Objective C à la cible de génération personnalisée.
  • Référencez la bibliothèque et créez un wrapper Objective C ++.
  • Cela semble bien jusqu'à ce que j'aie besoin d'appeler la bibliothèque externe C ++, puis j'obtiens le message d'erreur lors de la compilation:

Symboles non définis pour l'architecture armv7: "Presage :: Presage (PresageCallback *)", référencée depuis: - [PresageBridge init] dans PresageBridge.o "Presage :: ~ Presage ()", référencée: - [PresageBridge init] dans PresageBridge. o ld: symbole (s) non trouvé (s) pour l'architecture armv7 clang: erreur: la commande de l'éditeur de liens a échoué avec le code de sortie 1 (utilisez -v pour voir l'invocation)

  • Mon objectif C ++ wrapper (en reliant l'en-tête de la bibliothèque externe C ++ presage.h):

    #import "PresageBridge.h"
    #include "presage.h"
    
    @implementation PresageBridge
    
    - (instancetype)init
    {
        if(self = [super init])
        {
    
           Presage hello(&callback);
        }
    
        return self;
    }
  • D'après le code ci-dessus, il ne semble pas que l'en-tête me manque, et ce qui est intéressant, c'est que j'ai également essayé de créer une instance d'autres classes dans la bibliothèque externe et qu'elles semblent fonctionner, ce qui suggère que Xcode peut pas lier correctement presage.h pour une raison quelconque.


Étant donné que vous êtes nouveau avec les bibliothèques C ++, je suppose que vous devrez faire un peu plus de recherches.

Cependant, je vais essayer de souligner certaines étapes que vous devez prendre en compte:

  • vous devez vous assurer de compiler pour la même architecture à la fois la bibliothèque statique (.a) et le projet
  • de votre erreur, vous devez compiler votre bibliothèque statique pour i386 OU modifier votre projet en x86_64 (la différence entre ces architectures est un peu plus complexe, mais pour le moment, disons que i386 signifie bureau 32 bits alors que x86_64 signifie bureau 64 bits)
  • Les architectures de bras sont pour iPhone, pas pour votre MacOS (c'est pourquoi il ne parvient pas à trouver des bibliothèques avec une architecture de bras dans le dossier MacOSX)!

Il y a plusieurs façons d'aborder ces problèmes.

Pour le premier, je suggérerais d'inclure dans votre espace de travail la bibliothèque statique et de l'ajouter comme dépendance à votre cible de construction. Pour cela, vous devez comprendre les constructions XCode.

J'imagine que vous essayez en fait de créer une application pour téléphone. Par conséquent, pour la troisième option, vous devez configurer votre version de g ++ de manière à ce qu'elle se penche sur l'iPhoneSDK à partir de XCode lorsque vous liez des cibles armées (recherchez iPhoneOS.platform).

Construire un bras ne fonctionnera que sur les iPhones. Si vous voulez que cela fonctionne sur le simulateur, vous devrez lier votre bibliothèque statique aux bibliothèques à l'intérieur du fichier iPhoneSimulator.platform.

Si vous souhaitez que votre bibliothèque statique fonctionne à la fois pour iPhone et pour le simulateur iPhone, vous devez créer une bibliothèque "fat" (essentiellement une bibliothèque contenant des symboles pour les deux plates-formes).

Si vous manquez ces plates-formes, vous pouvez les télécharger à partir de XCode (mais je crois qu'elles sont là)

Comme vous pouvez le constater, les choses vont devenir de plus en plus complexes en cours de route, donc je recommande fortement d'utiliser XCode pour compiler la bibliothèque statique (c'est toujours faisable avec g ++ tu).

Je crois que les concepts suivants sur lesquels vous seriez utile de rechercher:

  • bras, x86, x86_64
  • bibliothèque statique
  • liaison statique
  • fat lib (bibliothèque universelle)
  • Espace de travail XCode avec plusieurs projets

J'espère que cela t'aides :).


C ++ fonctionne sur iOS, vous pouvez simplement l'ajouter à votre projet. Ou si vous voulez vraiment avoir votre bibliothèque dynamique, vous pouvez la compiler avec Xcode et spécifier votre architecture cible.


Le script de Mobile Ben est génial, à part la dernière ligne codant en dur un nom de fichier de bibliothèque dans le script. Ce qui suit est un remplacement de la dernière commande lipo et utilise de manière dynamique lipo fusionne chaque fichier de bibliothèque créé après la compilation.

Changer la ligne de Mobile Ben:

$LIPO -create $pwd/output/armv7/lib/libpresage.a  $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a

à:

for t in `ls $pwd/output/armv7/lib/*.a` ;
do
        export LIB=`basename $t`
        export ARCHSTRING=""
        for a in `ls $pwd/output`
        do
                export ARCSTRING="$ARCSTRING $pwd/output/$a/lib/$LIB "
        done
        $LIPO -create $ARCSTRING  -output $LIB
done

Remarque: je ne souhaitais pas modifier la réponse de Mobile Ben avec la nouvelle fonctionnalité de code et l'ajouter à la mise en forme d'un commentaire.


Redéfinissez votre architecture par défaut, puis essayez les solutions suivantes. 1. Dans Build Phases-> Link Binary With Libraries, ajoutez les bibliothèques libz.dylib et libxml2.dylib à votre projet. 2. Dans BuildSettings-> Search Paths, définissez Always Search User Paths sur Yes et, sous Framework Search Paths, ajoutez le chemin correct à votre infrastructure. Utilisez terminal pour obtenir le bon chemin de votre framework. 3. Essayez de définir votre "Source du compilateur en tant que" sur C ++ ou utilisez hit et trial et vérifiez toutes les options. Complier Source As est également sous BuildSettings. Utilisez cmd + f pour le rechercher.

Essayez-les et laissez-moi savoir, et dites-moi également à propos du framework ou du sdk que vous essayez d'utiliser dans votre projet.







objective-c++