可在macOS中用pkgbuild和productbuild等原生工具创建自定义.pkg包:先组织Payload和Scripts,再用pkgbuild生成组件包,接着用productbuild合成带许可证的发行包,最后签名、公证并测试。

如果您需要在macOS系统中创建自定义的.pkg安装包,但缺乏Xcode或命令行工具经验,则可借助系统内置的磁盘映像工具配合pkgbuild和productbuild等原生工具完成构建。以下是实现此目标的具体步骤:
一、准备安装内容与脚本结构
制作pkg包前需明确安装路径、文件组织方式及是否需要预/后安装脚本。pkgbuild要求源目录结构清晰,所有待安装文件须置于统一根目录下,且不能包含绝对路径引用。脚本需具备可执行权限,并遵循Apple的包脚本规范。
1、新建文件夹命名为“Payload”,将所有需安装的文件(如.app、配置文件、二进制工具)放入其中,保持相对路径层级一致。
2、在同级目录下创建“Scripts”文件夹,放入preinstall、postinstall等shell脚本(若需),并执行chmod +x preinstall postinstall赋予执行权限。
3、确保Payload目录内无隐藏文件(如.DS_Store),可运行find Payload -name ".DS_Store" -delete清除。
二、使用pkgbuild生成组件包
pkgbuild是Apple提供的底层打包工具,用于将文件集合封装为可复用的组件包(.pkg),支持指定标识符、版本号及脚本绑定,是构建最终分发包的基础单元。
1、打开终端,切换至Payload所在目录。
2、执行以下命令生成基础组件包:pkgbuild --root Payload --scripts Scripts --identifier com.example.mycustomapp --version 1.0.0 --install-location /Applications MyCustomApp.pkg
3、检查输出文件MyCustomApp.pkg是否存在,可通过pkgutil --expand MyCustomApp.pkg temp_folder验证内容完整性。
三、使用productbuild合并为发行包
当需要添加许可证、自定义安装界面或支持多组件依赖时,必须使用productbuild将pkgbuild生成的组件包整合为可分发的完整安装包(distribution pkg),该格式支持XML描述文件控制安装流程。
1、运行productbuild --synthesize --package MyCustomApp.pkg Distribution.xml生成初始distribution描述文件。
2、用文本编辑器打开Distribution.xml,修改<title>、<description>及<license>节点内容;如需静默安装,添加auth="root"属性至<options>标签内。
3、执行productbuild --distribution Distribution.xml --package-path . FinalInstaller.pkg生成最终可双击运行的安装包。
四、验证签名与公证兼容性
未签名的pkg在macOS Catalina及后续版本中将被Gatekeeper拦截;即使本地测试通过,也需代码签名才能确保用户端正常安装。公证虽非强制,但缺失会导致“无法验证开发者”警告。
1、确认钥匙串中存在有效的“Developer ID Installer”证书,可在“钥匙串访问→我的证书”中查看有效期与扩展密钥用法。
2、对FinalInstaller.pkg执行签名:productsign --sign "Developer ID Installer: Your Name (ABC123XYZ)" FinalInstaller.pkg SignedInstaller.pkg
3、上传SignedInstaller.pkg至Apple Notary Service,使用xcrun notarytool submit SignedInstaller.pkg --keychain-profile "notary" --wait等待公证完成。
五、测试安装行为与路径覆盖
安装包实际行为受目标系统环境影响显著,尤其涉及权限提升、路径写入及符号链接处理。必须在干净的macOS虚拟机或隔离用户账户中验证,避免残留配置干扰判断。
1、在测试账户中双击SignedInstaller.pkg,观察安装向导是否显示预期标题与许可协议。
2、安装完成后,检查/Applications下是否存在对应应用,同时运行ls -la /usr/local/bin/(若含软链接)确认链接目标路径正确且可访问。
3、执行pkgutil --pkg-info SignedInstaller.pkg核对BundleIdentifier、InstallDate及InstallLocation字段是否与构建参数一致,特别注意InstallLocation值必须与pkgbuild中--install-location参数完全匹配。









