标签存档: Mac OS X

在 Sandboxed Mac App 中嵌入第三方可执行文件

之前开源了 一个 gitstats 的 GUI 应用 GitStatX,在提交到 GitHub (GitStatX) 之后,又准备提交到 Mac App Store。

在提交到 Mac App Store 之后,出现了一些问题,程序中包含的第三方可执行文件没有签名,导致苹果拒绝了提交的程序包:

App sandbox not enabled – The following executables must include the “com.apple.security.app-sandbox” entitlement with a Boolean value of true in the entitlements property list. Refer to the App Sandbox page for more information on sandboxing your app.

  • GitStatX.app/Contents/Resources/git/bin/git
  • GitStatX.app/Contents/Resources/gnuplot/gnuplot

但是 GitStatX 所包含的 git 以及 gnuplot,并不是我程序中的代码,也没有 Xcode 工程去使用一个 entitlements 文件来指定它为启用 sandbox 状态。

所幸在网上搜索的时候,找到了可以使用 codesign 工具来进行签名的方法。

检查可执行文件是否启用 sandbox

codesign --display --entitlements - ./commandlinetool

给可执行文件签名并启用 sandbox

先在命令行工具同目录创建一个 entitlements.plist:

< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true></true>
    <key>com.apple.security.inherit</key>
    <true></true>
</dict>
</plist>

这里设置了 com.apple.security.app-sandbox 为 true 来启用 sandbox。

然后使用 codesign 进行签名:

codesign -s "3rd Party Mac Developer Application: Your Name" --entitlements ./entitlements.plist ./commandlinetool

记得把 “3rd Party Mac Developer Application: Your Name” 替换为实际的证书名称。

问题

在给 gnuplot 签名之后,提交到 Mac App Store,苹果还是会自动验证并发邮件说 gnuplot 没有签名,于是在本地直接导出 GitStatX.app,并检查了一下,发现 gnuplot 的 entitlements 又没有了,但是 git 的 entitlements 还是保留的。在 gnuplot 同目录下,有一个 _CodeSignature 目录,可能是在打包的时候会自动处理。

为了避免这个问题,我就把 gnuplot 也放到了一个 bin 目录下,然后再打包并检查,发现 gnuplot 已经是正确签名并且保留有 entitlements 的了。

当然,GitStatX 最终也正确提交到 Mac App Store,并且程序进入了 Waiting For Review 状态。

参考资料

  1. Mac OS app, sandbox with command line tool?
  2. Checking Code Signing and Sandboxing Status in Code
  3. Entitlement Key Reference

— EOF —

一个修正 Mach-O 文件加载共享库路径的脚本

在 Mac 上用到一些开源的程序,经常需要自己编译,这个时候一般会使用 macports 所提供的工具链进行编译。

在编译的过程中,开源程序所引用的各种其他库,例如 libssl、libz、libgd 之类的,一般都会在 /opt/local/lib 下,而如果把这个编译好的二进制文件给其他人用时,如果其他人没有安装 macports,那么就会缺失这些共享库,从而导致编译好的二进制程序无法运行。

具体原因就是因为 Mac 下链接共享库时,会在链接时将共享库的路径写入到最终的二进制文件中,而默认情况下,这个路径是绝对路径,例如 /opt/local/lib/libz.1.dylib。

所幸苹果提供了 install_name_tool 这个工具来修改共享库的路径。

下面这个脚本就是用来批量替换二进制文件中的共享库路径。

这个脚本会在当前目录下创建 lib 目录,将二进制文件所依赖的 /opt/local/lib 中的共享库复制到 lib 目录中,并修改二进制文件中保存的共享库的路径。

脚本的使用方法,将上面的脚本保存为 fixlibpath.sb,并加上可执行权限,放到要修正的二进制文件所在的目录:

chmod +x fixlibpath.sh
./fixlibpath.sh mybinary

还有共享库会依赖其他共享库的情况,所以也需要对 lib 中复制过来的共享库进行同样的处理:

for f in lib/*; do
    ./fixlibpath.sh $f
done

可以观察一下脚本的输出,如果输出的内容中,每个共享库所依赖的库路径中不存在 /opt/local/lib,那就表示处理完成了。每个共享库都会有一个 /opt/local/lib 路径的,但是名称与这个共享库一样的路径,这个是不用处理的。

要测试处理完成的二进制文件是否正常,可以将该二进制文件和 lib 目录复制到一台没有安装 macports 或者没有 macports 安装相关共享库的机器上运行,如果能正常运行就表示处理成功了。

参考资料

  1. http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html
  2. http://stackoverflow.com/questions/4677044/how-to-use-dylib-in-mac-os-x-c#answer-11585225

— EOF —

HostsManager for Mac OS X v0.4.2 Released

更新日志

HostsManager for Mac OS X v0.4.2 更新

  • 修正在 Mac OS X Lion 下启动失败的bug
  • 在 Mac 系统中,使用 \n 作为 hosts 文件的行分隔符

下载

HostsManager for Mac OS X v0.4.2

注意: 此次仅更新 Mac OS X 版本,HostsManager for Windows 版本没有更新

Snow Leopard Server 上配置 Gitosis 笔记

为了迁移项目 Git 仓库到 Mini Server 上,需要在 Snow Leopard Server 上配置一下 Gitosis,但是 Mac OS X 和 Linux 不太一样,有些地方需要特殊处理一下。

安装 Gitosis

Gitosis 的安装就不多说,在参考文档2中有。

添加 Git 用户组及用户

添加用户可以用参考文档1中的方法来创建,没有尝试直接用 OSX 的用户管理来创建是否可用。

# 这里的用户组和用户ID 用 401,但是实际用时需要根据服务器上的情况来创建
# 我在使用时 401 这个 gid 就已经被占用了,可以使用以下两个命令看看要用的
# ID 是否已经被用了。
sudo dscl . list /Users uid
sudo dscl . list groups gid
 
# 创建用户组 git
sudo dscl . create groups/git
sudo dscl . create groups/git gid 401
 
# 创建用户 git
sudo dscl . create users/git
sudo dscl . create users/git uid 401
sudo dscl . create users/git NFSHomeDirectory /Users/git
sudo dscl . create users/git gid 401
sudo dscl . create users/git UserShell /bin/bash
sudo dscl . create users/git Password '*'
 
# 创建用户主目录,Git 仓库就要放在里面
sudo mkdir /Users/git
sudo chown git /Users/git
sudo chgrp git /Users/git
 
# 下面这一句是把 git 用户添加到可以使用 ssh 访问的用户组里面
# 如果不执行这句的话,git push 或者 git pull 等等的时候会出错
sudo dscl . -append /Groups/com.apple.access_ssh GroupMembership git

配置 Gitosis

这个在参考文档2中都有详细说明。

参考文档

  1. git hosting with Leopard, Ian White
  2. 权限管理器 Gitosis, Pro Git
  3. Adduser for Mac OS X = dscl + niutil + nicl, otaku ramblings