How do you codesign framework bundles for the Mac App Store?
Based on baptr’s answer, I have developed this shell script that codesigns all my frameworks and other binary resources/auxiliary executables (currently supported types: dylib, bundle, and login items):
#!/bin/sh# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! # Verify that $CODE_SIGN_IDENTITY is setif [ -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 fifiif [ -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 fifiITEMS=""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}"fiLOGINITEMS_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}"fiecho "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=$IFSIFS=$(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 fidone# Restore $IFS.IFS=$SAVED_IFS
- Save it to a file in your project. I keep my copy in a
Scripts
subdirectory in my project’s root.- Mine is called
codesign-frameworks.sh
.
- Mine is called
- Add a “Run Script” build phase right after your “Copy Embedded Frameworks” build phase.
- You can call it “Codesign Embedded Frameworks”.
- Paste
./codesign-frameworks.sh
(or whatever you called your script above) into the script editor text field. Use./Scripts/codesign-frameworks.sh
if you store the script in a subdirectory. - Build your app. All bundled frameworks will be codesigned.
Should you still get an “Identity: ambiguous (matches: …” error, please comment below. This should not happen anymore.
Updated 2012-11-14: Adding support for frameworks with special characters in their name (this does not include single quotes) to “codesign-frameworks.sh”.
Updated 2013-01-30: Adding support for special characters in all paths (this should include single quotes) to “codesign-frameworks.sh”.
Updated 2013-10-29: Adding experimental dylib support.
Updated 2013-11-28: Adding entitlements support. Improving experimental dylib support.
Updated 2014-06-13: Fixing codesigning issues with frameworks containing (nested) frameworks. This was done by adding -depth
option to find
, which causes find
to do a depth-first traversal. This has become necessary, because of the issue described here. In short: a containing bundle can only be signed if its nested bundles are signed already.
Updated 2014-06-28: Adding experimental bundle support.
Updated 2014-08-22: Improving code and preventing failure to restore IFS.
Updated 2014-09-26: Adding support for login items.
Updated 2014-10-26: Quoting directory checks. This fixes the “line 31/42: too many arguments” errors and the resulting “ code object is not signed at all” error for paths including special characters.
Updated 2014-11-07: Resolving the ambiguous identity error (like “Mac Developer: ambiguous …”) when using automatic identity resolution in Xcode. You don’t have to explicitly set the identity anymore and can just use “Mac Developer”!
Updated 2015-08-07: Improving semantics.
Improvements welcome!
Your comment shows you signed the objects within the bundle's version directory. The Technote shows to sign the directory itself.
The following matches the Technote better:
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/Acodesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/Acodesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A
This is how I fixed it;
- Enter to the build settings of your target
- Find the line "Other Code Signing Flags"
- Enter --deep value to the release parameter
- Close XCode
- Enter to the derived data folder on your Mac and delete the old derived data (default path is: /Users/YOUR_USER_NAME/Library/Developer/Xcode/DerivedData)
- Open Xcode and build
After the build archive and submit the app again...