web-dev-qa-db-fra.com

Comment codez-vous des bundles de framework pour le Mac App Store?

Après une soumission récente, j'ai eu l'erreur suivante:

Signature non valide - le bundle d'applications imbriquées (FooBar.app/Contents/Frameworks/GData.framework) n'est pas signé, la signature n'est pas valide ou n'est pas signée avec un Apple certificat de soumission. Reportez-vous à au Guide de signature de code et de sandbox d'application pour plus d'informations.

Signature non valide - le bundle d'applications imbriquées (FooBar.app/Contents/Frameworks/Growl.framework) n'est pas signé, la signature n'est pas valide ou elle n'est pas signée avec un Apple certificat de soumission. Reportez-vous à au Guide de signature de code et de sandbox d'application pour plus d'informations.

Signature non valide - le bundle d'applications imbriquées libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) n'est pas signé, la signature n'est pas valide ou n'est pas signée avec un Apple. Reportez-vous au Guide de signature de code et de sandbox d'application pour plus d'informations.

J'ai donc signé tous les bundles de framework par Technote 2206 :

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libcurl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libssh2.1.dylib
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A/Growl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A/GData

La note technique 2206 dit:

Cadres de signature

Étant donné que les frameworks sont des bundles, il semble logique de conclure que vous pouvez signer directement un framework. Cependant, ce n'est pas le cas. Pour éviter les problèmes lors de la signature des frameworks, assurez-vous de signer une version spécifique par opposition à l'ensemble du framework:

# C'est la mauvaise façon:

codesign -s ma-signature-identité ../FooBarBaz.framework

# C'est le bon chemin:

codesign -s my-signature-identity ../FooBarBaz.framework/Versions/A

Et quand j'essaie de vérifier les résultats, ça me semble bien:

% codesign -vvv FooBar.app/Contents/Frameworks/libcurl.framework
FooBar.app/Contents/Frameworks/libcurl.framework: valid on disk
FooBar.app/Contents/Frameworks/libcurl.framework: satisfies its Designated Requirement
% codesign -vvv FooBar.app/Contents/Frameworks/Growl.framework
FooBar.app/Contents/Frameworks/Growl.framework: valid on disk
FooBar.app/Contents/Frameworks/Growl.framework: satisfies its Designated Requirement

Pour le plaisir, j'ai essayé de signer directement le bundle de framework et il a toujours été rejeté. Mais c'est exactement ce que la documentation dit de ne pas faire.

Avez-vous deviné pourquoi cela serait considéré comme invalide? J'utilise le même certificat que j'utilise pour coder mon application - celle qui a fonctionné dans le passé.

Ma seule supposition serait quelque chose à voir avec les listes existantes (dois-je posséder les identifiants dans les infos.plists du cadre?) Ou les droits - des suggestions?

80
csexton

Sur la base de la réponse de baptr, j'ai développé ce script Shell qui code tous mes frameworks et autres ressources binaires/exécutables auxiliaires (types actuellement pris en charge: dylib, bundle et éléments de connexion):

#!/bin/sh

# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! 

# Verify that $CODE_SIGN_IDENTITY is set
if [ -z "${CODE_SIGN_IDENTITY}" ] ; then
    echo "CODE_SIGN_IDENTITY needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

if [ -z "${CODE_SIGN_ENTITLEMENTS}" ] ; then
    echo "CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

ITEMS=""

FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -d "$FRAMEWORKS_DIR" ] ; then
    FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle" | sed -e "s/\(.*framework\)/\1\/Versions\/A\//")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${FRAMEWORKS}"
fi

LOGINITEMS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/"
if [ -d "$LOGINITEMS_DIR" ] ; then
    LOGINITEMS=$(find "${LOGINITEMS_DIR}" -depth -type d -name "*.app")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${ITEMS}"$'\n'"${LOGINITEMS}"
fi

# Prefer the expanded name, if available.
CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
    # Fall back to old behavior.
    CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
fi

echo "Identity:"
echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"

echo "Entitlements:"
echo "${CODE_SIGN_ENTITLEMENTS}"

echo "Found:"
echo "${ITEMS}"

# Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below.
SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")

# Loop through all items.
for ITEM in $ITEMS;
do
    echo "Signing '${ITEM}'"
    codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" --entitlements "${CODE_SIGN_ENTITLEMENTS}" "${ITEM}"
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        echo "Failed to sign '${ITEM}'."
        IFS=$SAVED_IFS
        exit 1
    fi
done

# Restore $IFS.
IFS=$SAVED_IFS
  1. Enregistrez-le dans un fichier de votre projet. Je conserve ma copie dans un sous-répertoire Scripts à la racine de mon projet.
    • Le mien s'appelle codesign-frameworks.sh.
  2. Ajoutez une phase de construction "Exécuter le script" juste après votre phase de construction "Copier les cadres intégrés".
    • Vous pouvez l'appeler "Frameworks intégrés à la conception de codes".
  3. Coller ./codesign-frameworks.sh (ou ce que vous avez appelé votre script ci-dessus) dans le champ de texte de l'éditeur de script. Utilisation ./Scripts/codesign-frameworks.sh si vous stockez le script dans un sous-répertoire.
  4. Créez votre application. Tous les cadres groupés seront codés.

Si vous obtenez toujours une erreur " Identité : ambiguë (correspond à:…", veuillez commenter ci-dessous. Cela ne devrait plus se produire.

Mise à jour le 2012-11-14: Ajout de la prise en charge des frameworks avec des caractères spéciaux dans leur nom (cela n'inclut pas les guillemets simples) dans "codesign-frameworks.sh".

Mise à jour du 2013-01-30: Ajout de la prise en charge des caractères spéciaux dans tous les chemins (cela doit inclure des guillemets simples) à "codesign-frameworks.sh".

Mise à jour du 2013-10-29: Ajout du support expérimental de dylib.

Mise à jour du 2013-11-28: Ajout de la prise en charge des droits. Amélioration du support expérimental de dylib.

Mise à jour du 2014-06-13: Correction des problèmes de signature de code avec les cadres contenant des cadres (imbriqués). Cela a été fait en ajoutant -depth option à find, ce qui oblige find à effectuer une traversée en profondeur d'abord. Cela est devenu nécessaire, à cause de le problème décrit ici . En bref: un bundle contenant ne peut être signé que si ses bundles imbriqués sont déjà signés.

Mise à jour le 2014-06-28: ajout de la prise en charge expérimentale des bundles.

Mise à jour le 2014-08-22: Amélioration du code et prévention de l'échec de la restauration d'IFS.

Mise à jour du 2014-09-26: Ajout de la prise en charge des éléments de connexion.

Mise à jour le 2014-10-26: Citations des vérifications de répertoires. Cela corrige les erreurs "ligne 31/42: trop d'arguments" et l'erreur "objet code n'est pas du tout signée" qui en résulte pour les chemins comprenant des caractères spéciaux.

Mise à jour le 2014-11-07: Résolution de l'erreur d'identité ambiguë (comme "Développeur Mac: ambiguë…") lors de l'utilisation de la résolution d'identité automatique dans Xcode. Vous n'avez plus besoin de définir explicitement l'identité et vous pouvez simplement utiliser "Développeur Mac"!

Mise à jour du 2015-08-07: Amélioration de la sémantique.

Améliorations bienvenues!

41
JanX2

Votre commentaire montre que vous avez signé les objets dans le répertoire de version du bundle. La Technote montre de signer le répertoire lui-même.

Ce qui suit correspond mieux à la Technote:

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A
10
baptr

C'est ainsi que je l'ai corrigé;

  • Entrez dans les paramètres de construction de votre cible
  • Fing la ligne "Autres drapeaux de signature de code"
  • Entrez - deep valeur pour le paramètre de libération
  • Fermer XCode
  • Accédez au dossier de données dérivées sur votre Mac et supprimez les anciennes données dérivées (le chemin par défaut est:/Users/YOUR_USER_NAME/Library/Developer/Xcode/DerivedData)
  • Ouvrez Xcode et construisez

Après l'archive de génération et soumettez à nouveau l'application ...

3
emreoktem

Une chose que je ne vois pas mentionnée ici est que vous devez avoir votre Info.plist dans/Resources dans le répertoire du framework versionné. Sinon, vous obtiendrez l'erreur "format de paquet non reconnu, invalide ou inapproprié" lorsque vous essayez de signer le répertoire versionné.

J'ai fourni une réponse plus détaillée ici: Comment coder Growl.framework pour Sandboxed Mac App

0
Ross Bencina