将PackageMaker命令行构建安装程序移植到pkgbuild



我一直试图将Mac PackageMaker命令行构建移植到pkgbuild和productbuild,但我被卡住了。不幸的是,除了这篇StackOverflow文章以及pkgbuild和productbuild手册页之外,我没有发现太多关于这些新程序如何工作的文档。

这是我的问题。我创建了一个根安装目录,其中包含以下文件:

/some_path/Applications
                       /MyProgram.app
          /Library
                  /Frameworks
                             /MyFramework.framework
                                                   /[library files...]

下面的命令行调用对PackageMaker非常有效。它创建了一个安装程序,安装了上面的所有文件。

$ /Developer/usr/bin/packagemaker 
    --title "My Program" 
    --root /some_path 
    --version 1.0.0 
    --filter ".DS_Store" 
    --resources ./resources/ 
    --scripts ./scripts/ 
    --root-volume-only 
    --domain system 
    --verbose 
    --no-relocate 
    --target 10.5 
    --id com.my_company.pkg 
    --out MyProgram.pkg

现在我正试图用pkgbuild写这篇文章,但遇到了一个大问题。我使用以下呼叫:

$ pkgbuild 
    --root /some_path 
    --version 1.0.0 
    --install-location "/" 
    --scripts "./scripts/" 
    --identifier "com.my_company.pkg" 
    MyProgram.pkg

此命令构建一个安装程序,将MyProgram.framework目录复制到/Library/Frameworks中。但是,它不会将MyProgram.app文件安装到/Applications目录中。当我查看安装程序日志时,我会看到以下消息:

Applications/MyProgram.app重新定位到/some_path/Applications/MyProgram.app

有人能解释一下为什么没有像PackageMaker那样将MyProgram.app文件添加到/Applications目录中吗?

不幸的是,这个问题的答案并不是我想要的。我不知道如何从这个过程中删除PackageMaker。然而,有一个解决方案包括pkgutil和PackageMaker,可以完全在命令行上创建带有自定义欢迎消息、许可证和背景图像的安装程序。PackageMaker GUI不是必需的。步骤如下:

  1. 在特殊的目录结构上运行packagemaker命令行可执行文件。此目录结构反映了Mac文件系统。阅读更多老的但可靠的"PackageMaker如何"教程
  2. 运行pkgutil(pkgutil --expand)以提取包内容
  3. 看一看内容,确定您想要更改的内容。一些选项包括欢迎信息、许可证和背景图像
  4. 通过命令行添加命令以更改这些文件。查看"自动化苹果的PackageMaker"教程了解更多信息。最简单的方法就是运行这样的echo '<background file="your_background.png">'
  5. 运行pkgutil(pkgutil --flatten)以重新生成包

首先,您确定需要安装程序吗?您可以将框架放入应用程序中。至少可以说,安装程序和pkgbuild有点不稳定。

现在来谈谈手头的问题:重新定位与用户可以将应用程序从/Applications移动到/WorkApplications/PrivateApplications这一事实有关。在您的情况下,安装程序可能会在构建文件夹中找到您的应用程序,并将其安装在此文件夹上。

我认为安装程序使用Application Bundle Identifier和Spotlight进行重新定位,因此为了进行测试,您可以将构建文件夹添加到Spotlight忽略列表中。

您可以在元件特性列表BundleIsRelocatable中进行定义。如果你真的必须安装一个框架全局,这是一个你想将BundleIsReloadable设置为false的捆绑包。

您引用的问题几乎包含了完全消除PackageMaker所需的所有内容。我添加的一件事是在productbuild --synthesize ...调用之后使用sed将行插入到分发文件中。例如,以下是我在构建组件包后使用的一些终端命令:

productbuild --synthesize --package "components/SubPackage.pkg" "distribution.xml"
sed -i "" 
-e '$ i
    <title>Installer Title</title>' 
-e '$ i
    <background file="background.png" alignment="left" scaling="proportional" />' 
-e '$ i
    <welcome file="welcome.rtf" />' 
"distribution.xml"
productbuild --distribution "distribution.xml" --resources "resources/" --package-path "components/" "Installer.pkg"

这避免了必须使用pkgutil --expandpkgutil --flatten来修改安装程序。

创建组件plist文件,该文件具有可重定位属性的值。

pkgbuild --analyze --root "$dst_src_root" "$installer_root/Components.plist"

编辑组件plist并将"BundleIsReloadable"设置为false。这在我的项目中做了一次,因为安装程序的内容不会改变(一个应用程序和一个插件)。我每次都重复使用相同的组件plist来创建内容包。

sudo pkgbuild --root "$dst_src_root" --component-plist "$installer_root/Components.plist" --identifier "com.company.app" --version "1.0" --scripts "$dst_scpt_root" "$dst_pkg_root/InstallPackage/cisContents.pkg" 

然后使用productbuild,我们可以创建最终的包

最新更新