【问题标题】:How do you codesign framework bundles for the Mac App Store?您如何为 Mac App Store 设计框架包?
【发布时间】:2011-12-03 14:14:59
【问题描述】:

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

无效签名 - 嵌套应用程序包 (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

技术说明 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

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

任何猜测为什么会被认为是无效的?我使用的证书与我对我的应用程序进行代码签名时使用的证书相同——过去曾使用过的证书。

我唯一的猜测是与现有的 plist(我需要拥有框架的 Info.plist 中的标识符吗?)或权利——有什么建议吗?

【问题讨论】:

  • 我在提交应用程序时也发现了这一点。值得庆幸的是,Apple 没有拒绝它,但指出我们稍后将不得不签署框架。我认为最好在 Growl 谷歌代码问题页面上发帖,很快人们就会遇到同样的问题。
  • 在使用 Growl 框架提交应用时也遇到了这个问题。我猜您必须将 growl.framework 捆绑标识符更改为您拥有的标识符,然后对其进行代码设计。
  • 这很奇怪:我发布了一个应用程序,其中包括两个未签名的框架(CorePlot 和 MacRuby)。我只在应用程序包上运行了一次代码签名命令,并且该应用程序已被接受,并且没有对框架进行任何评论。现在,如果您查看应用程序包 (bit.ly/charterapp),两个框架似乎都已签名。您是否尝试过简单地签署整个应用程序?
  • @p4010,我做到了——他们以前没有签名。例如,咆哮只是他们分发的直接捆绑包。现在,我在商店里有这个应用程序有一段时间了,所以我认为这与新的沙盒技术有关。您何时提交应用?
  • @Andrew,更改捆绑包标识符对您有用吗?

标签: xcode app-store-connect codesign mac-app-store


【解决方案1】:

您的评论显示您在捆绑包的版本目录中签署了对象。技术说明显示对目录本身进行签名。

以下内容更符合技术说明:

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】:

    根据 baptr 的回答,我开发了这个 shell 脚本,它对我的​​所有框架和其他二进制资源/辅助可执行文件(当前支持的类型:dylib、bundle 和登录项)进行了共同设计:

    #!/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. 在“复制嵌入式框架”构建阶段之后添加一个“运行脚本”构建阶段。
      • 您可以将其称为“协同设计嵌入式框架”。
    3. ./codesign-frameworks.sh(或您在上面调用的脚本)粘贴到脚本编辑器文本字段中。如果您将脚本存储在子目录中,请使用 ./Scripts/codesign-frameworks.sh
    4. 构建您的应用程序。所有捆绑的框架都将进行代码签名。

    如果您仍然收到“Identity: ambiguous (matches: ...”错误,请在下方评论。这不应该再发生了。

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

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

    2013 年 10 月 29 日更新:添加实验性 dylib 支持。

    2013 年 11 月 28 日更新:添加权利支持。改进实验性 dylib 支持。

    2014 年 6 月 13 日更新:修复包含(嵌套)框架的框架的代码设计问题。这是通过将-depth 选项添加到find 来完成的,这会导致find 进行深度优先遍历。由于the issue described here,这已成为必要。简而言之:包含的包只有在其嵌套包已经签名时才能被签名。

    2014 年 6 月 28 日更新:添加实验性捆绑包支持。

    2014 年 8 月 22 日更新:改进代码并防止 IFS 恢复失败。

    2014 年 9 月 26 日更新:添加对登录项的支持。

    2014 年 10 月 26 日更新:引用目录检查。这修复了包含特殊字符的路径的“第 31/42 行:参数过多”错误以及由此产生的“代码对象根本没有签名”错误。

    2014-11-07 更新:解决在 Xcode 中使用自动身份解析时出现的身份不明确错误(如“Mac Developer: ambiguous ...”)。您不必再显式设置身份,只需使用“Mac Developer”即可!

    2015 年 8 月 7 日更新:改进语义。

    欢迎改进!

    【讨论】:

    • 感谢您,不过请注意,如果您的目标名称中有空格,则它不起作用。我尝试修复但无法使其正常工作,因此更改了目标。
    • 当 FRAMEWORK_DIR 的名称中包含空格/特殊字符时,现在应该可以使用了。
    • 但是,我还需要通过在 codesign 命令的末尾添加“--timestamp”来禁用时间戳选项。
    • 有趣。 @Elmer Cat 是不是碰巧在未发布的 OS X 版本上执行此操作?手册页描述了具有“系统特定默认行为”的选项。
    • Elmer Cat -- 我不知道您运行的是哪个版本的 Xcode,但我使用的是 5.0.1,它肯定不会自动签署我的框架。在找到这个脚本之前,我一直在扯头发。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      这就是我修复它的方法;

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

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

      【讨论】:

      • 在梦境中“--deep”会按预期工作,但我们不是生活在梦境中……
      猜你喜欢
      • 1970-01-01
      • 2011-06-05
      • 2021-06-30
      • 1970-01-01
      • 2016-01-27
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      相关资源
      最近更新 更多