Wie können Sie Framework-Bundles für den Mac App Store codieren?

81

Nach einer kürzlich eingereichten Meldung habe ich folgenden Fehler erhalten:

Ungültige Signatur - Das verschachtelte App-Bundle (FooBar.app/Contents/Frameworks/GData.framework) ist nicht signiert, die Signatur ist ungültig oder es ist nicht mit einem Apple-Übermittlungszertifikat signiert. Weitere Informationen finden Sie im Code Signing and Application Sandboxing Guide.

Ungültige Signatur - Das verschachtelte App-Bundle (FooBar.app/Contents/Frameworks/Growl.framework) ist nicht signiert, die Signatur ist ungültig oder es ist nicht mit einem Apple-Übermittlungszertifikat signiert. Weitere Informationen finden Sie im Code Signing and Application Sandboxing Guide.

Ungültige Signatur - Das verschachtelte App-Bundle libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) ist nicht signiert, die Signatur ist ungültig oder es ist nicht mit einem Apple-Übermittlungszertifikat signiert. Weitere Informationen finden Sie im Code Signing and Application Sandboxing Guide.

Also habe ich alle Framework-Bundles gemäß Technote 2206 signiert :

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

Technote 2206 sagt:

Signing Frameworks

Da Frameworks Bundles sind, erscheint es logisch zu folgern, dass Sie ein Framework direkt signieren können. Dies ist jedoch nicht der Fall. Um Probleme beim Signieren von Frameworks zu vermeiden, stellen Sie sicher, dass Sie eine bestimmte Version im Gegensatz zum gesamten Framework signieren:

# Das ist der falsche Weg:

Codesign -s meine-Signatur-Identität ../FooBarBaz.framework

# Das ist der richtige Weg:

Codesign -s meine-Signatur-Identität ../FooBarBaz.framework/Versions/A

Und wenn ich versuche, die Ergebnisse zu überprüfen, sieht es für mich gut aus:

% 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

Zum Spaß habe ich versucht, das Framework-Bundle direkt zu signieren, und es wurde immer noch abgelehnt. Aber genau das soll die Dokumentation nicht tun.

Irgendwelche Vermutungen, warum das als ungültig angesehen wird? Ich verwende dasselbe Zertifikat, mit dem ich meine App mit einem Code signiere - das, das in der Vergangenheit funktioniert hat.

Meine einzige Vermutung wäre etwas mit den vorhandenen Plists (muss ich die Bezeichner in den Info.plists des Frameworks besitzen?) Oder Berechtigungen zu tun - irgendwelche Vorschläge?

csexton
quelle
Das habe ich auch schon früher entdeckt, als ich meine App eingereicht habe. Zum Glück lehnte Apple dies nicht ab, stellte jedoch fest, dass wir später Frameworks unterzeichnen müssen. Ich denke, es ist besser, auf der Seite mit Google Code-Problemen von Growl zu posten, und sehr bald werden die Leute auf dasselbe Problem stoßen.
Koo
2
Auch beim Senden einer App mit dem Growl-Framework ist dieses Problem aufgetreten. Ich vermute, dass Sie die Bundle-ID von growl.framework in eine eigene ändern und dann mit einem Codesign versehen müssen.
Andrew
Das ist seltsam: Ich habe eine App veröffentlicht, die zwei Frameworks (CorePlot und MacRuby) enthält, die beide nicht signiert sind. Ich führe den Codezeichenbefehl nur einmal im App-Bundle aus, und die App wurde ohne Kommentar zum Framework akzeptiert. Wenn Sie sich nun das App-Bundle ( bit.ly/charterapp ) ansehen , scheinen beide Frameworks signiert zu sein. Haben Sie versucht, einfach die gesamte App zu signieren?
p4010
@ p4010, ich habe - sie waren zuvor nicht signiert. Knurren zum Beispiel war nur das gerade Bündel, das sie verteilen. Jetzt habe ich diese App für eine Weile im Laden, also nehme ich an, dass dies mit dem neuen Sandbox-Zeug zu tun hat. Wann hast du deine App eingereicht?
Csexton
@ Andrew, hat das Ändern der Bundle-ID für Sie funktioniert?
Csexton

Antworten:

44

Basierend auf der Antwort von baptr habe ich dieses Shell-Skript entwickelt, das alle meine Frameworks und anderen binären Ressourcen / ausführbaren Zusatzdateien (derzeit unterstützte Typen: Dylib-, Bundle- und Login-Elemente) codiert:

#!/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. Speichern Sie es in einer Datei in Ihrem Projekt. Ich behalte meine Kopie in einemScripts Unterverzeichnis im Stammverzeichnis meines Projekts.
    • Meins heißt codesign-frameworks.sh.
  2. Fügen Sie direkt nach der Erstellungsphase "Embedded Frameworks kopieren" eine Erstellungsphase "Skript ausführen" hinzu.
    • Sie können es "Codesign Embedded Frameworks" nennen.
  3. Fügen Sie ./codesign-frameworks.sh(oder wie auch immer Sie Ihr Skript oben genannt haben) in das Textfeld des Skripteditors ein. Verwenden./Scripts/codesign-frameworks.sh Sie diese wenn Sie das Skript in einem Unterverzeichnis speichern.
  4. Erstellen Sie Ihre App. Alle gebündelten Frameworks werden mit einem Code versehen.

Sollten Sie weiterhin den Fehler " Identität : mehrdeutig (Übereinstimmungen: ...") erhalten, kommentieren Sie dies bitte unten. Dies sollte nicht mehr passieren.

Aktualisiert am 14.11.2012: Hinzufügen von Unterstützung für Frameworks mit Sonderzeichen im Namen (dies schließt keine einfachen Anführungszeichen ein) zu „Codesign-frameworks.sh“.

Aktualisiert am 30.01.2013: Unterstützung für Sonderzeichen in allen Pfaden (dies sollte einfache Anführungszeichen enthalten) zu „Codesign-frameworks.sh“ hinzugefügt.

Aktualisiert am 29.10.2013: Hinzufügen einer experimentellen Dylib-Unterstützung.

Aktualisiert 28.11.2013: Unterstützung für Berechtigungen hinzufügen. Verbesserung der experimentellen Dylib-Unterstützung.

Aktualisiert am 13.06.2014: Behebung von Codesignierungsproblemen mit Frameworks, die (verschachtelte) Frameworks enthalten. Dies wurde durch Hinzufügen einer -depthOption zu erreicht find, wodurch eine findTiefenüberquerung durchgeführt wird. Dies ist aufgrund des hier beschriebenen Problems notwendig geworden . Kurz gesagt: Ein enthaltendes Bundle kann nur signiert werden, wenn seine verschachtelten Bundles bereits signiert sind.

Aktualisiert am 28.06.2014: Hinzufügen von experimenteller Bundle-Unterstützung.

Aktualisiert am 22.08.2014: Verbesserung des Codes und Verhinderung eines Fehlers bei der Wiederherstellung von IFS.

Aktualisiert am 26.09.2014: Unterstützung für Anmeldeelemente hinzugefügt.

Aktualisiert 26.10.2014: Verzeichnisprüfungen zitieren. Dies behebt den Fehler "Zeile 31/42: Zu viele Argumente" und den resultierenden Fehler "Codeobjekt ist überhaupt nicht signiert" für Pfade mit Sonderzeichen.

Aktualisiert am 07.11.2014: Behebung des mehrdeutigen Identitätsfehlers (wie „Mac Developer: mehrdeutig…“) bei Verwendung der automatischen Identitätsauflösung in Xcode. Sie müssen die Identität nicht mehr explizit festlegen und können einfach "Mac Developer" verwenden!

Aktualisiert am 07.08.2015: Verbesserung der Semantik.

Verbesserungen willkommen!

JanX2
quelle
Vielen Dank dafür, nur eine Anmerkung, es funktioniert nicht, wenn Ihr Ziel ein Leerzeichen im Namen hat. Ich habe versucht, das Problem zu beheben, konnte es jedoch nicht zum Laufen bringen. Daher wurde das Ziel geändert.
Craig
Sollte jetzt funktionieren, wenn FRAMEWORK_DIR Leerzeichen / Sonderzeichen enthält.
JanX2
Ich musste jedoch auch die Zeitstempeloption deaktivieren, indem ich "--timestamp" am Ende des Codesign-Befehls hinzufügte.
Elmer Cat
Interessant. Tun Sie @Elmer Cat zufällig auf einer unveröffentlichten Version von OS X? In der Manpage wird diese Option für "systemspezifisches Standardverhalten" beschrieben.
2. Januar,
1
Elmer Cat - Ich weiß nicht, welche Version von Xcode Sie ausführen, aber ich bin auf 5.0.1 und es signiert meine Frameworks definitiv NICHT automatisch. Ich riss mir die Haare aus, bis ich dieses Drehbuch fand.
Bryan
11

Ihr Kommentar zeigt, dass Sie die Objekte im Versionsverzeichnis des Bundles signiert haben. Der Technote zeigt an, das Verzeichnis selbst zu signieren.

Folgendes passt besser zum 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
baptr
quelle
4

So habe ich es behoben;

  • Geben Sie die Build-Einstellungen Ihres Ziels ein
  • Suchen Sie die Zeile "Andere Code Signing Flags"
  • Geben Sie --deep ein value als Freigabeparameter ein
  • Schließen Sie XCode
  • Rufen Sie den Ordner für abgeleitete Daten auf Ihrem Mac auf und löschen Sie die alten abgeleiteten Daten (Standardpfad lautet: / Users / YOUR_USER_NAME / Library / Developer / Xcode / DerivedData)
  • Öffnen Sie Xcode und erstellen Sie

Nach dem Build-Archiv und senden Sie die App erneut ...

emreoktem
quelle
3
In einer Traumwelt würde "--deep" wie erwartet funktionieren, aber wir leben nicht in einer Traumwelt ...
Mike
0

Eine Sache, die ich hier nicht erwähnt sehe, ist, dass Sie Ihre Info.plist in / Resources im versionierten Framework-Verzeichnis haben müssen. Andernfalls wird der Fehler "Bundle-Format nicht erkannt, ungültig oder ungeeignet" angezeigt, wenn Sie versuchen, das versionierte Verzeichnis zu signieren.

Ich habe hier eine ausführlichere Antwort gegeben: So codieren Sie Growl.framework für die Sandboxed Mac App

Ross Bencina
quelle