2

我试图找出将图形Qt应用程序分发给 Mac OS X 用户的最佳方式。

我已经了解了pkgbuildproductbuild,并使用它们来创建带有扩展名的平面包。.pkg

但是,当我尝试在 Mac OS X 10.11 上安装这样的平面包时,我看到了一些非常奇怪的行为。看起来这些包的 Mac OS X 安装程序会在我的主目录中搜索我要安装的应用程序。如果它在那里找到了应用程序,那么它实际上窃取了该应用程序,将这些文件的所有权更改为 root,并且它无法将应用程序安装到/Applications我想要安装它的文件夹中。

预期的行为是该包应始终将我的应用程序安装到该/Applications目录中,并且不应修改我的主目录中任何文件的所有权。

这看起来真的很奇怪。发生了什么事,我该如何解决?扁平包看起来不错,但我想保证它们总是将应用程序安装在正确的位置,并且我不希望它们修改用户主目录中的文件。

重现问题的步骤

在您的主目录中安装Homebrew 。

运行brew install qt5以安装 Qt5。

用这三个文件创建一个新目录:

Info.plist.in

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>
    <key>CFBundleExecutable</key>
    <string>main</string>
    <key>CFBundleIconFile</key>
    <string>app.icns</string>
    <key>CFBundleIdentifier</key>
    <string>com.example.abc.app</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>test thing</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>1.1.0</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0.0</string>
    <key>NSHumanReadableCopyright</key>
    <string>public domain</string>
</dict>
</plist>

主.cpp

#include <stdio.h>
int main(int argc, char *argv[])
{
  (void)argc; (void)argv;
  printf("hello\n");
  return 0;
}

测试.sh

c++ -isystem ~/opt/qt5/lib/QtCore.framework/Headers \
  ~/opt/qt5/lib/QtCore.framework/QtCore \
  main.cpp -o main

rm -rf "staging"
mkdir -p "staging/abc.app/Contents/"{MacOS,Resources}
cp main "staging/abc.app/Contents/MacOS/"
cp Info.plist.in "staging/abc.app/Contents/Info.plist"
"$(brew --prefix qt5)/bin/macdeployqt" "staging/abc.app"

pkgbuild --identifier com.example.abc.pkg \
  --version 1.0.0 \
  --root staging \
  --install-location /Applications \
  app.pkg

./test.sh现在通过在终端中输入来运行 test.sh。在我的电脑上,输出看起来像这样:

pkgbuild: Inferring bundle components from contents of staging
pkgbuild: Adding component at abc.app
pkgbuild: Adding component at abc.app/Contents/Frameworks/QtWidgets.framework
pkgbuild: Adding component at abc.app/Contents/Frameworks/QtGui.framework
pkgbuild: Adding component at abc.app/Contents/Frameworks/QtCore.framework
pkgbuild: Adding component at abc.app/Contents/Frameworks/QtPrintSupport.framework
pkgbuild: Wrote package to app.pkg

(显然,pkgbuild 正在检测我的暂存文件夹中的组件。我希望它不会那样做。我希望它只是将所有这些文件安装到用户的/Applications目录中。如果它仅仅因为它们有文件而特别对待这些Info.plist文件,那可能是坏事。)

接下来,通过运行open app.pkg并按照屏幕上的 GUI 安装包:

Mac OS X 平面包的标准 UI

运行ls /Applications/abc.app,您可以看到应用程序没有安装在预期的位置。

运行ls -l stagingor find . -uid root,可以看到里面的文件staging/abc.app现在都归root用户所有了,这是出乎意料的。

现在使用sudo rm -rf staging. 尝试再次安装该软件包。这次,由于安装程序没有在我的主目录中找到该应用程序,因此它已成功将其安装到/Applications.

备择方案

我对仅仅将.app文件夹打包成一个.dmg文件不感兴趣,因为我的应用程序实际上将有一个 GUI 和一个命令行组件,并且很难使用该方法将命令行组件放到用户的路径中。使用平面包,我可以通过将文件添加到/etc/paths.d.

是否有更好的工具来创作 Mac OS X 平面包?

源代码是否pkgbuild可用,以便我可以弄清楚它在做什么?

我可能会尝试这个答案中描述的更复杂的过程,看看是否有帮助。

4

1 回答 1

0

这是我找到的一个解决方案。我不确定它是否是最佳的,但它似乎有效。

首先,生成一个空的组件列表:

pkgbuild --analyze zzz --root nocomponents.plist

(即使zzz目录不存在,此命令实际上也会成功。)

稍后,当您构建包时,将此选项提供给pkgbuild

--components-plist nocomponents.plist
于 2016-02-16T01:09:06.920 回答