Importer CommonCrypto dans un framework Swift

184

Comment importer CommonCryptodans un framework Swift pour iOS?

Je comprends comment utiliser CommonCryptodans une application Swift: vous ajoutez #import <CommonCrypto/CommonCrypto.h>à l'en-tête de pontage. Cependant, les frameworks Swift ne prennent pas en charge les en-têtes de pontage. La documentation dit:

Vous pouvez importer des frameworks externes qui ont une base de code Objective-C pure, une base de code Swift pure ou une base de code en langage mixte. Le processus d'importation d'un framework externe est le même que le framework soit écrit dans une seule langue ou contienne des fichiers des deux langues. Lorsque vous importez une infrastructure externe, assurez-vous que le paramètre de construction Définit le module pour l'infrastructure que vous importez est défini sur Oui.

Vous pouvez importer un framework dans n'importe quel fichier Swift au sein d'une cible différente en utilisant la syntaxe suivante:

import FrameworkName

Malheureusement, l'importation CommonCryptone fonctionne pas. Ni l'ajout #import <CommonCrypto/CommonCrypto.h>à l'en-tête du parapluie.

hpique
la source
CommonCrypto est un framework basé sur C, pas un framework Objective-C.
rmaddy
1
@rmaddy Objective-C est un sur-ensemble C. Êtes-vous en train de dire que nous ne pouvons pas utiliser CommonCrypto de Swift?
hpique
4
@rmaddy J'ai juste réussi à faire fonctionner CommonCrypto en utilisant des cartes de modules. Je peaufinerai la solution et la publierai plus tard dans la journée.
hpique
si vous trouvez cela pratique et que ce que vous recherchez est déjà implémenté, vous pouvez essayer CryptoSwift
Marcin
1
Apple vient d'ouvrir CommonCrypto. Peut-être que nous pouvons le faire fonctionner si nous avons les sources.
eyeballz

Réponses:

137

Quelque chose d'un peu plus simple et plus robuste consiste à créer une cible d'agrégation appelée "CommonCryptoModuleMap" avec une phase d'exécution de script pour générer automatiquement la carte du module et avec le chemin Xcode / SDK correct:

entrez la description de l'image ici entrez la description de l'image ici

La phase d'exécution du script doit contenir cette bash:

# This if-statement means we'll only run the main script if the CommonCryptoModuleMap directory doesn't exist
# Because otherwise the rest of the script causes a full recompile for anything where CommonCrypto is a dependency
# Do a "Clean Build Folder" to remove this directory and trigger the rest of the script to run
if [ -d "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap" ]; then
    echo "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap directory already exists, so skipping the rest of the script."
    exit 0
fi

mkdir -p "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap"
cat <<EOF > "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap/module.modulemap"
module CommonCrypto [system] {
    header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}
EOF

L'utilisation du code shell et ${SDKROOT}signifie que vous n'avez pas à coder en dur le chemin Xcode.app qui peut varier d'un système à l'autre, en particulier si vous utilisez xcode-selectpour passer à une version bêta, ou si vous construisez sur un serveur CI où plusieurs versions sont installées dans des endroits non standard. Vous n'avez pas non plus besoin de coder en dur le SDK, cela devrait donc fonctionner pour iOS, macOS, etc. Vous n'avez pas non plus besoin d'avoir quoi que ce soit dans le répertoire source de votre projet.

Après avoir créé cette cible, faites en sorte que votre bibliothèque / structure en dépende avec un élément Target Dependencies:

entrez la description de l'image ici

Cela garantira que la carte du module est générée avant la création de votre framework.

Remarque macOS : si vous prenez également en charge macOS, vous devrez ajouter macosxau Supported Platformsparamètre de construction sur la nouvelle cible d'agrégation que vous venez de créer, sinon il ne placera pas la carte de module dans le bon Debugdossier de données dérivées avec le reste du produits de cadre.

entrez la description de l'image ici

Ensuite, ajoutez le répertoire parent de la mappe de module,, au ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMapparamètre de construction "Import Paths" sous la section Swift ( SWIFT_INCLUDE_PATHS):

entrez la description de l'image ici

N'oubliez pas d'ajouter une $(inherited)ligne si vous avez des chemins de recherche définis au niveau du projet ou de xcconfig.

Ça y est, vous devriez maintenant pouvoir import CommonCrypto

Mise à jour pour Xcode 10

Xcode 10 est maintenant livré avec une carte de module CommonCrypto rendant cette solution de contournement inutile. Si vous souhaitez prendre en charge à la fois Xcode 9 et 10, vous pouvez effectuer une vérification dans la phase Exécuter le script pour voir si la carte du module existe ou non, par exemple

COMMON_CRYPTO_DIR="${SDKROOT}/usr/include/CommonCrypto"
if [ -f "${COMMON_CRYPTO_DIR}/module.modulemap" ]
then
   echo "CommonCrypto already exists, skipping"
else
    # generate the module map, using the original code above
fi
Mike Weller
la source
8
Cette réponse devrait être au top. Simple et élégant
Abdullah Saeed
1
Tard dans le jeu sur celui-ci - mais cela devrait être la réponse choisie. C'est simple et il est plus facile pour les autres développeurs travaillant sur le même projet de voir l'exigence.
fatuous.logic
1
Très bonne réponse. Merci!
Klaus Busse
1
Si je fais cela dans mon .framework, devrais-je faire de même dans les projets où j'inclus ce framework?
Ravi Kiran
2
@IanDundas J'ai mis à jour le code ci-dessus avec un correctif pour le problème de
recompilation
91

Vous pouvez en fait créer une solution qui "fonctionne juste" (pas besoin de copier un module.modulemap et des SWIFT_INCLUDE_PATHSparamètres dans votre projet, comme requis par d'autres solutions ici), mais cela vous oblige à créer un framework / module factice que vous ' ll importer dans votre cadre proprement dit. Nous pouvons également assurer qu'il fonctionne quelle que soit la plate - forme ( iphoneos, iphonesimulatorou macosx).

  1. Ajoutez une nouvelle cible de framework à votre projet et nommez-la après la bibliothèque système, par exemple , "CommonCrypto". (Vous pouvez supprimer l'en-tête parapluie, CommonCrypto.h .)

  2. Ajoutez un nouveau fichier de paramètres de configuration et nommez-le, par exemple "CommonCrypto.xcconfig". (Ne cochez aucune de vos cibles pour l'inclusion.) Remplissez-le avec les éléments suivants:

    MODULEMAP_FILE[sdk=iphoneos*]        = \
        $(SRCROOT)/CommonCrypto/iphoneos.modulemap
    MODULEMAP_FILE[sdk=iphonesimulator*] = \
        $(SRCROOT)/CommonCrypto/iphonesimulator.modulemap
    MODULEMAP_FILE[sdk=macosx*]          = \
        $(SRCROOT)/CommonCrypto/macosx.modulemap
  3. Créez les trois fichiers de mappage de modules référencés ci-dessus et remplissez-les avec les éléments suivants:

    • iphoneos.modulemap

      module CommonCrypto [system] {
          header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
          export *
      }
    • iphonesimulator.modulemap

      module CommonCrypto [system] {
          header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h"
          export *
      }
    • macosx.modulemap

      module CommonCrypto [system] {
          header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/CommonCrypto/CommonCrypto.h"
          export *
      }

    (Remplacez "Xcode.app" par "Xcode-beta.app" si vous exécutez une version bêta. Remplacez 10.11par votre SDK OS actuel si vous n'exécutez pas El Capitan.)

  4. Dans l' onglet Info des paramètres de votre projet, sous Configurations , définissez les configurations de débogage et de publication de CommonCrypto sur CommonCrypto (faisant référence à CommonCrypto.xcconfig ).

  5. Dans l' onglet Phases de construction de votre cible de framework , ajoutez le framework CommonCrypto aux dépendances cibles . Ajoutez également libcommonCrypto.dylib à la phase de création de lien binaire avec bibliothèques .

  6. Sélectionnez CommonCrypto.framework dans Produits et assurez-vous que son adhésion cible pour votre wrapper est définie sur Facultatif .

Vous devriez maintenant pouvoir construire, exécuter et import CommonCryptodans votre framework wrapper.

Pour un exemple, voyez comment SQLite.swift utilise un factice sqlite3.framework .

stephencelis
la source
4
Fonctionne pour moi sans étape (5). Avec lui, j'obtiens une erreur de construction:ld: cannot link directly with /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.2.sdk/usr/lib/system/libcommonCrypto.dylib. Link against the umbrella framework 'System.framework' instead. for architecture x86_64
stannie
4
Excellent! Utilisé ceci pour faire github.com/soffes/Crypto que je n'ai pas eu à lier System.frameworkcependant. Il est à noter que vous devez créer un framework de wrapper séparé pour Mac et iOS si votre framework est multiplateforme.
Sam Soffes
32
Comment et où les gens découvrent-ils des trucs comme ça?
hola
5
Juste une note précise que vous devez sélectionner Objective-C comme langage à l'étape 1. Ceci est facilement négligé. Aussi, peut-être parce que je n'avais pas de .dylib, j'avais besoin d'ajouter le .framework à l'étape 5.
Teo Sartori
7
c'est horrible. J'ai un zoo de Xcodes, chacun cassé de manière différente et avoir les chemins absolus vers les en-têtes partout est un vomissement. Quelque chose ne va vraiment pas à Cupertino, ou du moins avec celui qui est en charge de ce désordre de modulemap
Anton Tropashko
82

J'ai trouvé un projet GitHub qui utilise avec succès CommonCrypto dans un framework Swift: SHA256-Swift . En outre, cet article sur le même problème avec sqlite3 était utile.

Sur la base de ce qui précède, les étapes sont les suivantes:

1) Créez un CommonCryptorépertoire dans le répertoire du projet. À l'intérieur, créez un module.mapfichier. La carte des modules nous permettra d'utiliser la bibliothèque CommonCrypto en tant que module dans Swift. Son contenu est:

module CommonCrypto [system] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    link "CommonCrypto"
    export *
}

2) Dans Paramètres de construction, dans Swift Compiler - Search Paths , ajoutez le CommonCryptorépertoire à Import Paths ( SWIFT_INCLUDE_PATHS).

Paramètres de construction

3) Enfin, importez CommonCrypto dans vos fichiers Swift comme tout autre module. Par exemple:

import CommonCrypto

extension String {

    func hnk_MD5String() -> String {
        if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        {
            let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))
            let resultBytes = UnsafeMutablePointer<CUnsignedChar>(result.mutableBytes)
            CC_MD5(data.bytes, CC_LONG(data.length), resultBytes)
            let resultEnumerator = UnsafeBufferPointer<CUnsignedChar>(start: resultBytes, length: result.length)
            let MD5 = NSMutableString()
            for c in resultEnumerator {
                MD5.appendFormat("%02x", c)
            }
            return MD5
        }
        return ""
    }
}

Limites

L'utilisation du framework personnalisé dans un autre projet échoue au moment de la compilation avec l'erreur missing required module 'CommonCrypto'. Cela est dû au fait que le module CommonCrypto ne semble pas être inclus dans le cadre personnalisé. Une solution de contournement consiste à répéter l'étape 2 (paramètre Import Paths) dans le projet qui utilise l'infrastructure.

La carte du module n'est pas indépendante de la plate-forme (elle pointe actuellement vers une plate-forme spécifique, le simulateur iOS 8). Je ne sais pas comment rendre le chemin de l'en-tête par rapport à la plate-forme actuelle.

Mises à jour pour iOS 8 <= Nous devrions supprimer le lien de ligne "CommonCrypto" , pour obtenir la compilation réussie.

METTRE À JOUR / MODIFIER

J'ai continué à recevoir l'erreur de construction suivante:

ld: bibliothèque introuvable pour -lCommonCrypto pour l'architecture x86_64 clang: erreur: la commande de l'éditeur de liens a échoué avec le code de sortie 1 (utilisez -v pour voir l'invocation)

Sauf si j'ai supprimé la ligne link "CommonCrypto"du module.mapfichier que j'ai créé. Une fois que j'ai supprimé cette ligne, elle s'est bien construite.

hpique
la source
30
Gee, Apple veut vraiment rendre les choses difficiles. Est-ce que ça tuerait les Swifties de simplement nous laisser importer des fichiers / frameworks sans avoir à passer par tout ce BS?
zaph le
4
C'est exaspérant car la $SDKROOTvariable est censée vous permettre des chemins indépendants de la plate-forme, mais je ne sais pas comment y arriver dans Swift.
danimal
2
Pour moi, cela n'a pas fonctionné jusqu'à ce que j'aie supprimé le link "CommonCrypto"fichier module.map.
Teo Sartori
1
Quelqu'un peut-il confirmer que cela fonctionne sur Xcode 7.3? Cette solution a cessé de fonctionner pour moi après la mise à jour.
Nikita Kukushkin
1
Correnction: ça marche bien quand je construis pour le simulateur, mais échoue @ liaison quand je construis pour un appareil iOS 9.3 avec "ld: bibliothèque introuvable pour -lCommonCrypto pour l'architecture arm64"
Nikita Kukushkin
50

Cette réponse explique comment le faire fonctionner dans un cadre, et avec Cocoapods et Carthage

🐟 approche modulemap

J'utilise modulemapdans mon wrapper autour de CommonCrypto https://github.com/onmyway133/arcane , https://github.com/onmyway133/Reindeer

Pour ceux qui obtiennent header not found, veuillez jeter un coup d'œil sur https://github.com/onmyway133/Arcane/issues/4 ou exécutezxcode-select --install

  • Créer un dossier CCommonCryptocontenantmodule.modulemap

      module CCommonCrypto {
        header "/usr/include/CommonCrypto/CommonCrypto.h"
        export *
      }
  • Allez dans Paramètres construits -> Chemins d'importation

      ${SRCROOT}/Sources/CCommonCrypto

🌳 Cocoapods avec approche modulemap

🐘 approche d'en-tête publique

🐏 Cocoapods avec approche d'en-tête public

🐝 Articles connexes intéressants

onmyway133
la source
1
Hou la la! À ma grande surprise, le chemin de l'en-tête de l'approche supérieure (création du fichier module.modulemap) fonctionnait très bien alors que les fichiers modulemap posaient auparavant de nombreux problèmes. J'avais du mal avec cela pendant un certain temps en utilisant un fichier module.modulemap avec un chemin absolu vers l' /CommonCrypto/CommonCrypto.hintérieur Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS...., ce qui nécessitait une modification manuelle pour les personnes qui ont renommé XCode. Changer cette ligne pour regarder "/usr/include/CommonCrypto/CommonCrypto.h"semble fonctionner correctement pour une équipe avec plusieurs versions de XCode. Merci beaucoup!
Natalia
3
Je crée un pod, j'ai défini SWIFT_INCLUDE_PATHS et preserve_paths. Quand je cours pod lib lint, mais que la construction a échoué avec une erreur: aucun module de ce type «CommonCrypto». Comment puis-je y faire face.
Klein Mioke
1
Pas lié au problème mais j'adore l'utilisation des emoji comme balles! 😊
Fomentia
2
@ onmyway133 L'utilisation du pod de développement local fonctionne si vous remplacez $(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCryptopar $(PODS_TARGET_SRCROOT)/Sources/CCommonCrypto. PODS_TARGET_SRCROOTest correctement défini pour les pods locaux.
Orkhan Alikhanov
Excellente réponse, m'a sauvé la vie! Merci un million
Hassan Shahbazi
45

Bonnes nouvelles! Swift 4.2 (Xcode 10) fournit enfin CommonCrypto!

Ajoutez simplement import CommonCryptovotre fichier Swift.

mxcl
la source
Bonne nouvelle! Pouvez-vous ajouter le lien vers la documentation?
Kryštof Matěj
Je n'ai pas de lien vers la documentation, j'ai découvert cela en essayant de compiler un projet où j'avais l'une des solutions de contournement ici avec Xcode 10. Il s'est plaint qu'il pouvait trouver deux CommonCryptomodules, soupçonnant ainsi Apple maintenant à condition que j'ai supprimé ma solution de contournement et «voilà! C'était vrai. J'ai tweeté à ce sujet et un ingénieur Apple a répondu en confirmant que c'était prévu.
mxcl le
1
L'App Store ne me montre que 9.4.7 comme mise à jour disponible, comment avez-vous obtenu Xcode 10?
Hammad Tariq
1
Il est en version bêta comme vous l'aurait dit une recherche triviale sur Google.
mxcl
1
@SomoyDasGupta oui. Supprimez simplement l'importation précédente et compilez-la à nouveau. En d'autres termes, vous n'avez pas à suivre les étapes de la réponse de MikeWeller
COLD ICE
7

AVERTISSEMENT: iTunesConnect peut rejeter les applications qui utilisent cette méthode.


Un nouveau membre de mon équipe a accidentellement cassé la solution donnée par l'une des principales réponses, j'ai donc décidé de la consolider dans un petit projet de wrapper appelé CommonCryptoModule . Vous pouvez l'installer manuellement ou via Cocoapods:

pod 'CommonCryptoModule', '~> 1.0.2'

Ensuite, il ne vous reste plus qu'à importer le module là où vous en avez besoin CommonCrypto, comme ceci:

import CommonCryptoModule

J'espère que quelqu'un d'autre trouvera cela utile.

Nikita Kukushkin
la source
Attention: votre candidature sera rejetée si vous utilisez cette méthode!
Segabond
Oui, nous avons également été rejetés, très bizarres, car nous téléchargions sans problème pendant plusieurs mois en utilisant cette méthode.
Nikita Kukushkin
5

Je pense que j'ai une amélioration par rapport à l'excellent travail de Mike Weller.

Ajoutez une phase Run Script avant la Compile Sourcesphase contenant cette bash:

# This if-statement means we'll only run the main script if the
# CommonCrypto.framework directory doesn't exist because otherwise
# the rest of the script causes a full recompile for anything
# where CommonCrypto is a dependency
# Do a "Clean Build Folder" to remove this directory and trigger
# the rest of the script to run

FRAMEWORK_DIR="${BUILT_PRODUCTS_DIR}/CommonCrypto.framework"

if [ -d "${FRAMEWORK_DIR}" ]; then
echo "${FRAMEWORK_DIR} already exists, so skipping the rest of the script."
exit 0
fi

mkdir -p "${FRAMEWORK_DIR}/Modules"
cat <<EOF > "${FRAMEWORK_DIR}/Modules/module.modulemap"
module CommonCrypto [system] {
    header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}
EOF

ln -sf "${SDKROOT}/usr/include/CommonCrypto" "${FRAMEWORK_DIR}/Headers"

Ce script construit un framework simple avec le module.map au bon endroit, puis s'appuie sur la recherche automatique de Xcode BUILT_PRODUCTS_DIRpour les frameworks.

J'ai lié le dossier d'inclusion CommonCrypto d'origine en tant que dossier Headers du framework afin que le résultat fonctionne également pour les projets Objective C.

jjrscott
la source
Voir la réponse de dvdblk pour une amélioration qui couvre l'utilisation dans CocoaPods.
jjrscott
5

Pour tous ceux qui utilisent swift 4.2 avec Xcode 10 :

Le module CommonCrypto est maintenant fourni par le système, vous pouvez donc l'importer directement comme n'importe quel autre framework système.

import CommonCrypto
kubrick G
la source
Duplicata de la réponse de @ mxcl: stackoverflow.com/a/50690346/9988514
Rainer Schwarz
4

@mogstad a eu la gentillesse d'envelopper la solution @stephencelis dans un Cocoapod:

pod 'libCommonCrypto'

Les autres pods disponibles ne fonctionnaient pas pour moi.

Jacob Jennings
la source
4

Les solutions modulemap peuvent être bonnes et résistantes aux modifications du SDK, mais je les ai trouvées difficiles à utiliser dans la pratique, et pas aussi fiables que je le souhaiterais lorsque je les distribue à d'autres. Pour essayer de rendre tout cela plus infaillible, je suis allé d'une manière différente:

Copiez simplement les en-têtes.

Je sais, fragile. Mais Apple n'apporte presque jamais de changements significatifs à CommonCrypto et je vis le rêve qu'ils ne le changeront pas de manière significative sans finalement faire de CommonCrypto un en-tête modulaire.

Par «copier les en-têtes», je veux dire «couper et coller tous les en-têtes dont vous avez besoin dans un en-tête massif de votre projet, comme le ferait le préprocesseur». À titre d'exemple que vous pouvez copier ou adapter, consultez RNCryptor.h .

Notez que tous ces fichiers sont sous licence APSL 2.0, et cette approche maintient intentionnellement les avis de copyright et de licence. Mon étape de concaténation est sous licence MIT, et cela ne s'applique que jusqu'au prochain avis de licence).

Je ne dis pas que c'est une belle solution, mais jusqu'à présent, cela semble avoir été une solution incroyablement simple à mettre en œuvre et à soutenir.

Rob Napier
la source
J'ai trouvé cela pour compiler de manière fiable et c'est tout simple. L'application utilisant le framework doit-elle être liée à quelque chose de spécial ou CommonCrypto est-il toujours disponible?
codingFriend1
1
Je pense que Security.frameworkc'est automatiquement lié (ça fait un petit moment depuis qu'un nouveau projet a commencé). Si vous obtenez des erreurs, c'est le cadre à lier.
Rob Napier
Cela semble être la solution la plus simple et cela fonctionne très bien sur une machine, mais chaque fois que j'utilise le framework dans un autre framework, ou application, sur une autre machine, j'obtiens l'erreur «module manquant».
richever
2

Je sais que c'est une vieille question. Mais je trouve une autre façon d'utiliser la bibliothèque dans le projet Swift, ce qui pourrait être utile pour ceux qui ne veulent pas importer le cadre introduit dans ces réponses.

Dans le projet Swift, créez un en-tête de pontage Objective-C, créez une catégorie NSData (ou une classe personnalisée pour utiliser la bibliothèque) dans Objective-C. Le seul inconvénient serait que vous deviez écrire tout le code d'implémentation en Objective-C. Par exemple:

#import "NSData+NSDataEncryptionExtension.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (NSDataEncryptionExtension)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
    //do something
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
//do something
}

Et puis dans votre en-tête de pont objective-c, ajoutez ceci

#import "NSData+NSDataEncryptionExtension.h"

Et puis en classe Swift, faites la même chose:

public extension String {
func encryp(withKey key:String) -> String? {
    if let data = self.data(using: .utf8), let encrypedData = NSData(data: data).aes256Encrypt(withKey: key) {
        return encrypedData.base64EncodedString()
    }
    return nil
}
func decryp(withKey key:String) -> String? {
    if let data = NSData(base64Encoded: self, options: []), let decrypedData = data.aes256Decrypt(withKey: key) {
        return decrypedData.UTF8String
    }
    return nil
}
}

Cela fonctionne comme prévu.

Terence
la source
Cela fonctionne très bien et vous permet même de garder les internes internes ( NSData+NSDataEncryptionExtension.hne doit pas nécessairement être public).
Raphael
Mais avec quel cadre de système d'exploitation dois-je lier pour utiliser cette chose? Contrairement à d'autres - je dois travailler avec CommonCrypto dans un projet Obj-C, et cela seul casse sur Xcode 9 avec le SDK MacOS-10.13
Motti Shneor
@MottiShneor Liez n'importe quel système d'exploitation à partir de la version 10.9 ou supérieure. Je travaille sur le même environnement et cela fonctionne très bien.
Terence le
2

J'ai ajouté de la magie des cocoapodes à la réponse de jjrscott au cas où vous auriez besoin d'utiliser CommonCrypto dans votre bibliothèque de cocoapodes.


1) Ajoutez cette ligne à votre podspec:

s.script_phase = { :name => 'CommonCrypto', :script => 'sh $PROJECT_DIR/../../install_common_crypto.sh', :execution_position => :before_compile }

2) Enregistrez-le dans le dossier de votre bibliothèque ou où vous le souhaitez (mais n'oubliez pas de modifier le script_phase en conséquence ...)

# This if-statement means we'll only run the main script if the
# CommonCrypto.framework directory doesn't exist because otherwise
# the rest of the script causes a full recompile for anything
# where CommonCrypto is a dependency
# Do a "Clean Build Folder" to remove this directory and trigger
# the rest of the script to run
FRAMEWORK_DIR="${BUILT_PRODUCTS_DIR}/CommonCrypto.framework"

if [ -d "${FRAMEWORK_DIR}" ]; then
echo "${FRAMEWORK_DIR} already exists, so skipping the rest of the script."
exit 0
fi

mkdir -p "${FRAMEWORK_DIR}/Modules"
echo "module CommonCrypto [system] {
    header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h"
    export *
}" >> "${FRAMEWORK_DIR}/Modules/module.modulemap"

ln -sf "${SDKROOT}/usr/include/CommonCrypto" "${FRAMEWORK_DIR}/Headers"

Fonctionne comme un charme :)

dvdblk
la source
Pouvez-vous fournir une démonstration ou un exemple de projet de cadre pour le même avec le fichier de spécification du pod?
Gowtham
0

Je ne sais pas si quelque chose a changé avec Xcode 9.2 mais c'est maintenant beaucoup plus simple d'y parvenir. Les seules choses que j'avais à faire étaient de créer un dossier appelé "CommonCrypto" dans le répertoire de mon projet de cadre et de créer deux fichiers à l'intérieur, l'un appelé "cc.h" comme suit:

#include <CommonCrypto/CommonCrypto.h>
#include <CommonCrypto/CommonRandom.h>

Et un autre appelé module.modulemap:

module CommonCrypto {
    export *
    header "cc.h"
}

(Je ne sais pas pourquoi vous ne pouvez pas référencer les fichiers d'en-tête de la zone SDKROOT directement dans un fichier modulemap mais je n'ai pas pu le faire fonctionner)

La troisième chose est de trouver le paramètre "Import Paths" et de le définir sur $ (SRCROOT). En fait, vous pouvez le définir dans le dossier dans lequel vous souhaitez placer le dossier CommonCrypto, si vous ne le souhaitez pas au niveau racine.

Après cela, vous devriez pouvoir utiliser

import CommonCrypto

Dans n'importe quel fichier swift et tous les types / fonctions / etc. sont disponibles.

Un mot d'avertissement cependant - si votre application utilise libCommonCrypto (ou libcoreCrypto), il est exceptionnellement facile pour un pirate pas trop sophistiqué d'attacher un débogueur à votre application et de découvrir quelles clés sont passées à ces fonctions.

Dylan Nicholson
la source
0

Dans le cas où vous rencontrez le problème ci-dessous:

ld: bibliothèque introuvable pour -lapple_crypto clang: erreur: la commande de l'éditeur de liens a échoué avec le code de sortie 1 (utilisez -v pour voir l'invocation)

Dans Xcode 10, Swift 4.0. CommonCrypto fait partie du framework.

Ajouter

 import CommonCrypto

Retirer

  • Fichier CommonCrpto lib du binaire de liaison avec les bibliothèques des phases de construction
  • import CommonCrypto de l'en-tête de pont

Cela a fonctionné pour moi!

SKSN
la source
-1

Cela m'est arrivé après la mise à jour de Xcode. J'ai essayé tout ce que je pouvais faire, comme réinstaller les cocoapodes et nettoyer le projet, mais cela n'a pas fonctionné. Maintenant, il a été résolu après le redémarrage du système.

Joey
la source
-13

C'est très simple. Ajouter

#import <CommonCrypto/CommonCrypto.h>

dans un fichier .h (le fichier d'en-tête de pontage de votre projet). Par convention, vous pouvez l'appeler YourProjectName-Bridging-Header.h.

Accédez ensuite aux paramètres de construction de votre projet et recherchez Swift Compiler - Génération de code. En dessous, ajoutez le nom de votre en-tête de pont à l'entrée "Objetive-C Bridging Header".

Vous avez terminé. Aucune importation requise dans votre code Swift. Tous les en-têtes Objective-C publics répertoriés dans ce fichier d'en-tête de pontage seront visibles par Swift.

Juanjo Conti
la source
votre méthode renvoie une erreur: l'utilisation d'en-têtes de pontage avec des cibles de framework n'est pas prise en charge
gorgi93
5
@ gorgi93 Vous ne pouvez pas utiliser un en-tête de pontage dans une cible de framework, comme le suggère l'erreur. La seule option est de le mettre dans le fichier d'en-tête principal du framework, malheureusement.
Charles A.
1
Si vous aviez réellement rouge le titre de ce fil, vous auriez vu que le gars veut importer la bibliothèque CommonCrypto dans un framework Swift. Vous ne pouvez pas utiliser d'en-têtes de pontage dans les frameworks, et vous ne pouvez pas importer le framework CommonCrypto dans l'en-tête parapluie.
miken.mkndev