如何为Mac App Store配置框架包?

时间:2011-10-08 14:37:55

标签: xcode itunesconnect codesign mac-app-store

最近提交后,我收到了以下错误:

  

无效签名 - 嵌套应用程序包(FooBar.app/Contents/Frameworks/GData.framework)未签名,签名无效,或未使用Apple提交证书签名。有关详细信息,请参阅“代码签名和应用程序沙盒指南”。

     

无效签名 - 嵌套应用程序包(FooBar.app/Contents/Frameworks/Growl.framework)未签名,签名无效,或未使用Apple提交证书签名。有关详细信息,请参阅“代码签名和应用程序沙盒指南”。

     

无效签名 - 嵌套应用程序包libcurl(FooBar.app/Contents/Frameworks/libcurl.framework)未签名,签名无效,或未使用Apple提交证书签名。有关详细信息,请参阅“代码签名和应用程序沙盒指南”。

所以我按照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

Technote 2206说:

  

签署框架

     

看到框架是捆绑包,看起来你可以直接签署框架似乎是合乎逻辑的。然而,这种情况并非如此。为了避免在签署框架时出现问题,请确保签署特定版本而不是整个框架:

     

#这是错误的方式:

     

codesign -s my-signing-identity ../ FooBarBaz.framework

     

#这是正确的方法:

     

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

当我尝试验证结果时,它对我来说很好看:

% 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

为了好玩,我确实尝试直接签署框架包,但它仍被拒绝。但这正是文件所说的不做的。

任何猜测为什么会被视为无效?我正在使用与我用来代码签署我的应用程序相同的证书 - 过去曾经使用过的那个。

我唯一的猜测是与现有的plists有关(我需要在框架的Info.plists中拥有标识符吗?)或权利 - 任何建议?

4 个答案:

答案 0 :(得分:41)

根据baptr的回答,我开发了这个shell脚本,它编码所有我的框架和其他二进制资源/辅助可执行文件(当前支持的类型:dylib,bundle和login items):

#!/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. 将其保存到项目中的文件中。我将我的副本保存在项目根目录的Scripts子目录中。
    • 我叫codesign-frameworks.sh
  2. 在“复制嵌入式框架”构建阶段之后立即添加“运行脚本”构建阶段。
    • 您可以将其命名为“Codesign Embedded Frameworks”。
  3. ./codesign-frameworks.sh(或上面所谓的脚本)粘贴到脚本编辑器文本字段中。如果将脚本存储在子目录中,请使用./Scripts/codesign-frameworks.sh
  4. 构建您的应用。所有捆绑的框架都将进行编码。
  5. 如果你仍然得到“身份:含糊不清(匹配:......”错误,请在下面发表评论。这不应再发生了。

    2012-11-14更新:在“codesign-frameworks.sh”中添加对名称中包含特殊字符(不包括单引号)的框架的支持。

    更新2013-01-30:在“codesign-frameworks.sh”中添加对所有路径中特殊字符的支持(这应包括单引号)。

    2013-10-29更新:添加实验性dylib支持。

    2013-11-28更新:添加权利支持。改善实验性dylib支持。

    2014-06-13更新:修复了包含(嵌套)框架的框架的代码签名问题。这是通过向-depth添加find选项来完成的,这会导致find执行深度优先遍历。由于the issue described here,这已成为必要。简而言之:只有在嵌套包已经签名的情况下才能对包含的包进行签名。

    2014-06-28更新:添加实验包支持。

    2014-08-22更新:改进代码并防止无法恢复IFS。

    2014-09-26更新:添加对登录项的支持。

    2014-10-26更新:引用目录检查。这修复了“31/42行:太多参数”错误,并且包含特殊字符的路径产生的“代码对象根本没有签名”错误。

    2014-11-07更新:在Xcode中使用自动身份识别时解决模糊身份错误(如“Mac Developer:模糊...”)。您不必再明确设置身份,只需使用“Mac Developer”!

    2015-08-07更新:改进语义。

    欢迎改进!

答案 1 :(得分:10)

您的评论显示您已在软件包的版本目录中签署了对象。 Technote显示签署目录本身。

以下与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

答案 2 :(得分:3)

这是我修复它的方式;

  • 输入目标的构建设置
  • 指出“其他代码签名标志”
  • 在发布参数
  • 中输入 - 深
  • 关闭XCode
  • 输入Mac上的派生数据文件夹并删除旧的派生数据(默认路径为:/ Users / YOUR_USER_NAME / Library / Developer / Xcode / DerivedData)
  • 打开Xcode并构建

构建存档后再次提交应用程序......

答案 3 :(得分:0)

我在这里没有提到的一件事是你需要在版本化的框架目录中将Info.plist放在/ Resources中。否则,当您尝试签署版本化目录时,您将收到“捆绑包格式无法识别,无效或不适合”错误。

我在这里提供了更广泛的答案:How to Codesign Growl.framework for Sandboxed Mac App