xcode 您如何为 Mac App Store 设计框架包?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7697508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you codesign framework bundles for the Mac App Store?
提问by csexton
After a recent submission I have gotten the following error:
最近提交后,我收到以下错误:
Invalid Signature - the nested app bundle (FooBar.app/Contents/Frameworks/GData.framework) is not signed, the signature is invalid, or it is not signed with an Apple submission certificate. Refer to the Code Signing and Application Sandboxing Guide for more information.
Invalid Signature - the nested app bundle (FooBar.app/Contents/Frameworks/Growl.framework) is not signed, the signature is invalid, or it is not signed with an Apple submission certificate. Refer to the Code Signing and Application Sandboxing Guide for more information.
Invalid Signature - the nested app bundle libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) is not signed, the signature is invalid, or it is not signed with an Apple submission certificate. Refer to the Code Signing and Application Sandboxing Guide for more information.
无效签名 - 嵌套的应用程序包 (FooBar.app/Contents/Frameworks/GData.framework) 未签名、签名无效或未使用 Apple 提交证书签名。有关更多信息,请参阅代码签名和应用程序沙盒指南。
无效签名 - 嵌套的应用程序包 (FooBar.app/Contents/Frameworks/Growl.framework) 未签名、签名无效或未使用 Apple 提交证书签名。有关更多信息,请参阅代码签名和应用程序沙盒指南。
无效签名 - 嵌套的应用程序包 libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) 未签名、签名无效或未使用 Apple 提交证书签名。有关更多信息,请参阅代码签名和应用程序沙盒指南。
So I signed all the framework bundles per Technote 2206:
所以我根据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 says:
技术说明 2206 说:
Signing Frameworks
Seeing as frameworks are bundles it would seem logical to conclude that you can sign a framework directly. However, this is not the case. To avoid problems when signing frameworks make sure that you sign a specific version as opposed to the whole framework:
# This is the wrong way:
codesign -s my-signing-identity ../FooBarBaz.framework
# This is the right way:
codesign -s my-signing-identity ../FooBarBaz.framework/Versions/A
签名框架
将框架视为捆绑包,因此得出您可以直接签署框架的结论似乎是合乎逻辑的。然而,这种情况并非如此。为避免签署框架时出现问题,请确保您签署特定版本而不是整个框架:
# 这是错误的方式:
codesign -s my-signing-identity ../FooBarBaz.framework
# 这是正确的方法:
codesign -s my-signing-identity ../FooBarBaz.framework/Versions/A
And when I try to verify the results, it looks good to me:
当我尝试验证结果时,对我来说看起来不错:
% 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
For fun, I did try signing the framework bundle directly and it was still rejected. But that is exactly what the documentation said not to do.
为了好玩,我确实尝试过直接签署框架包,但它仍然被拒绝。但这正是文档所说的不要做的。
Any guesses why that would be considered invalid? I am using the same cert that I use to code sign my app -- the one that has worked in the past.
任何猜测为什么会被认为是无效的?我使用的证书与我用来对我的应用程序进行代码签名的证书相同 - 过去一直有效的证书。
My only guess would be something to do with the existing plists (do I need to own the identifiers in the framework's Info.plists?) or entitlements -- any suggestions?
我唯一的猜测是与现有的 plists(我是否需要拥有框架的 Info.plists 中的标识符?)或权利有关 - 有什么建议吗?
采纳答案by JanX2
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):
根据 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\)/\/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
- 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.
- 将其保存到项目中的文件中。我将副本保存
Scripts
在项目根目录的子目录中。- 我的叫做
codesign-frameworks.sh
。
- 我的叫做
- 在“复制嵌入式框架”构建阶段之后立即添加“运行脚本”构建阶段。
- 您可以将其称为“代码设计嵌入式框架”。
- 粘贴
./codesign-frameworks.sh
(或任何您在上面调用的脚本)到脚本编辑器文本字段中。使用./Scripts/codesign-frameworks.sh
,如果你存储脚本的子目录。 - 构建您的应用程序。所有捆绑的框架都将进行代码设计。
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”.
2012 年 11 月 14 日更新:向“codesign-frameworks.sh”添加对名称中带有特殊字符(不包括单引号)的框架的支持。
Updated 2013-01-30: Adding support for special characters in all paths (this should include single quotes) to “codesign-frameworks.sh”.
2013 年 1 月 30 日更新:在“codesign-frameworks.sh”中添加对所有路径中特殊字符的支持(这应该包括单引号)。
Updated 2013-10-29: Adding experimental dylib support.
2013 年 10 月 29 日更新:添加实验性 dylib 支持。
Updated 2013-11-28: Adding entitlements support. Improving experimental dylib support.
2013-11-28 更新:添加权利支持。改进实验性 dylib 支持。
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.
2014 年 6 月 13 日更新:修复包含(嵌套)框架的框架的代码设计问题。这是通过将-depth
选项添加到 来完成的find
,这会导致find
进行深度优先遍历。由于此处描述的问题,这已成为必要。简而言之:一个包含的包只有在它的嵌套包已经被签名的情况下才能被签名。
Updated 2014-06-28: Adding experimental bundle support.
2014 年 6 月 28 日更新:添加实验性捆绑支持。
Updated 2014-08-22: Improving code and preventing failure to restore IFS.
2014 年 8 月 22 日更新:改进代码并防止无法恢复 IFS。
Updated 2014-09-26: Adding support for login items.
2014-09-26 更新:添加对登录项的支持。
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.
2014-10-26 更新:引用目录检查。这修复了包含特殊字符的路径的“第 31/42 行:参数过多”错误和由此产生的“代码对象根本没有签名”错误。
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”!
2014 年 11 月 7 日更新:解决在 Xcode 中使用自动身份解析时出现的身份不明确错误(如“Mac Developer: ambiguous ...”)。您不必再明确设置身份,只需使用“Mac Developer”即可!
Updated 2015-08-07: Improving semantics.
2015-08-07 更新:改进语义。
Improvements welcome!
欢迎改进!
回答by baptr
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:
以下内容更符合 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
回答by emreoktem
This is how I fixed it;
这就是我修复它的方式;
- Enter to the build settings of your target
- Find the line "Other Code Signing Flags"
- Enter --deepvalue 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
- 进入目标的构建设置
- 找到“其他代码签名标志”这一行
- 在 release 参数中输入--deep值
- 关闭 XCode
- 进入Mac上的派生数据文件夹,删除旧的派生数据(默认路径为:/Users/YOUR_USER_NAME/Library/Developer/Xcode/DerivedData)
- 打开Xcode并构建
After the build archive and submit the app again...
在构建存档并再次提交应用程序之后...
回答by Ross Bencina
One thing I don't see mentioned here is that you need to have your Info.plist inside /Resources inside the versioned framework directory. Otherwise you'll get the "bundle format unrecognized, invalid, or unsuitable" error when you try to sign the versioned directory.
我在这里没有看到的一件事是,您需要将 Info.plist 放在版本化框架目录中的 /Resources 中。否则,当您尝试对版本化目录进行签名时,您将收到“无法识别的捆绑格式、无效或不合适”错误。
I provided a more extended answer here: How to Codesign Growl.framework for Sandboxed Mac App
我在这里提供了一个更扩展的答案:How to Codesign Growl.framework for Sandboxed Mac App