转载博客文章http://blog.youkuaiyun.com/vaintwyt/article/details/42043269,对于解决在mac appstore外分发应用程序有参考价值,亲测可用。
相关命令,访问控制设置:spctl;编译包,xcodebuild;打包安装包 pkgbuild,productbuild;代码签名:codesign,productsign;
Mac安装或者第一次打开软件,经常会出现下面对话框
从用户角度,有两种方法解决这个问题。
1.修改安全性与隐私设置,选择任何来源(系统偏好设置-安全性与隐私)
2.右键-打开
从开发者的角度,则要复杂一些了。
首先看看导致这种现象的原因。简单来说是Mac系统的GateKeeper在安装和打开软件时,对软件的来源和开发者进行校验。校验的内容是软件的签名,即软件内部的_CodeSignature目录内容。这是我的理解哈。
然后,就应该从软件的签名入手。
签名需要证书,有多种类型:Developer ID Application,Developer ID Installer,3rd Party Mac Developer Application,3rd Party Mac Developer Installer等。证书的生成,这里不做介绍,因为本人也不是很了解。
经验证,对于App,需要使用Developer ID Application进行签名,否则在第一次打开会提示未知开发者。而对于pkg安装包,则要使用Developer ID Installer进行签名,否则在安装的时候,会提示未知开发者。这里证书的选择还是比较重要的,不然,不管你签名是否成功,都过不了GateKeeper那关。LZ就是因为证书选择错了,浪费了好几天时间。
签名可以通过下面命令行实现(如果是Xcode项目,可以直接在Xcode中配置code sign):
- # App签名
- codesign --timestamp=none -f -v -s "Developer ID Application" test.app
- # pkg签名
- productsign --timestamp=none --sign "Developer ID Installer" ./test.pkg ./test_sign.pkg
官方给出了 验证签名的方法,只有当结果为accepted的时候,软件才能正常呗打开或者安装
- # App
- spctl -a -v --type exec ./test.app
- # pkg
- spctl -a -v --type install ./test_sign.pkg
关于软件打包,这里有两个纠结的地方。
以前我都是用PackageManager来打包bundle,生成mpkg文件。虽然现在的Xcode没有附带PackageManager,不过还是可以通过下载旧版Xcode来获得。
我将mpkg文件进行签名,正常来说,安装包应该使用Developer ID Installer证书来签名,但是却一直报错。而当我用Developer ID Application证书来签名时,签名是成功了,却没能解决图一的问题。所以后来只能用命令行来打包。
一开始使用productbuild,将两个bundle作为组建,添加到一个pkg中很顺利,而且也可以正常安装这个pkg。但是,安装对话框中,没有标题显示。所以需要在外部包多一个pkg,通过distribution文件来定义标题和其他属性。
完整命令
- export CODE_SIGN="Developer ID Installer"
- productbuild --component ./a.bundle /Library/Internet\ Plug-Ins --component ./b.bundle /Library/Internet\ Plug-Ins --sign "${CODE_SIGN}" test.pkg
- productbuild --distribution distribution.xml --sign "${CODE_SIGN}" ./installer.pkg
distribution.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <installer-gui-script minSpecVersion="1">
- <title>软件标题</title>
- <organization>com.example</organization>
- <options customize="never" allow-external-scripts="no" rootVolumeOnly="false"/>
- <!-- List all component packages -->
- <pkg-ref id="com.example.plugin" version="2005" auth="root" onConclusion="none">test.pkg</pkg-ref>
- <!-- List them again here. They can now be organized as a hierarchy if you want. -->
- <choices-outline>
- <line choice="com.example.plugin"/>
- </choices-outline>
- <!-- Define each choice above -->
- <choice id="com.example.plugin" visible="false" start_visible="false" title="plugin" description="plugin" enabled="false" start_selected="true" selected="true">
- <!--customLocation="false"-->
- <pkg-ref id="com.example.plugin"/>
- </choice>
- <pkg-ref id="com.example.plugin">
- <bundle-version/>
- </pkg-ref>
- </installer-gui-script>
这时候,令人蛋疼的事情出现了:test.pkg could not be loaded。Google了很久都没有找到解决办法,也尝试在其他电脑上执行上面的命令,也不行。(如果有解决方案,请告诉我。。。)
所以后来混用pkgbuild和productbuild来解决这个问题
- export CODE_SIGN="Developer ID Installer"
- pkgbuild --identifier "com.example.plugin" --component ./a.bundle --install-location /Library/Internet\ Plug-Ins --component ./b.bundle --install-location /Library/Internet\ Plug-Ins --sign "${CODE_SIGN}" ./test.pkg
- productbuild --distribution distribution.xml --sign "${CODE_SIGN}" ./installer.pkg
总结的时候,感觉不是很难,但是这个问题纠结了好几天,坑。Apple的官方文档说的不明不白的感觉,难道是我英文太差了吗。。。