我试图找出将图形Qt应用程序分发给 Mac OS X 用户的最佳方式。
我已经了解了pkgbuild、productbuild,并使用它们来创建带有扩展名的平面包。.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 安装包:
运行ls /Applications/abc.app
,您可以看到应用程序没有安装在预期的位置。
运行ls -l staging
or find . -uid root
,可以看到里面的文件staging/abc.app
现在都归root用户所有了,这是出乎意料的。
现在使用sudo rm -rf staging
. 尝试再次安装该软件包。这次,由于安装程序没有在我的主目录中找到该应用程序,因此它已成功将其安装到/Applications
.
备择方案
我对仅仅将.app
文件夹打包成一个.dmg
文件不感兴趣,因为我的应用程序实际上将有一个 GUI 和一个命令行组件,并且很难使用该方法将命令行组件放到用户的路径中。使用平面包,我可以通过将文件添加到/etc/paths.d
.
是否有更好的工具来创作 Mac OS X 平面包?
源代码是否pkgbuild
可用,以便我可以弄清楚它在做什么?
我可能会尝试这个答案中描述的更复杂的过程,看看是否有帮助。