Пакет Mac OS X изменяет файлы в моем домашнем каталоге вместо установки в приложения
Я пытаюсь найти лучший способ распространения графического приложения 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>
main.cpp:
#include <stdio.h>
int main(int argc, char *argv[])
{
(void)argc; (void)argv;
printf("hello\n");
return 0;
}
test.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
и следуя экранному графическому интерфейсу:
Бежать ls /Applications/abc.app
и вы можете видеть, что приложение не было установлено в ожидаемом месте.
Бежать ls -l staging
или же find . -uid root
и вы можете видеть, что файлы в staging/abc.app
теперь все они принадлежат пользователю root, что является неожиданным.
Теперь удалите промежуточный каталог с помощью sudo rm -rf staging
, Попробуйте установить пакет еще раз. На этот раз, так как установщик не нашел приложение в моем домашнем каталоге, он успешно установил его в /Applications
,
альтернативы
Я не заинтересован в упаковке .app
папка в .dmg
файл, потому что мое приложение на самом деле будет иметь графический интерфейс и компонент командной строки, и было бы трудно получить компонент командной строки на пути пользователя с этим методом. С плоскими пакетами я могу легко получить компонент командной строки по пути, добавив файл в /etc/paths.d
,
Существуют ли лучшие инструменты для создания плоских пакетов Mac OS X?
Является ли исходный код pkgbuild
доступно, чтобы я мог понять, что он делает?
Я мог бы попробовать более сложную процедуру, описанную в этом ответе, чтобы посмотреть, поможет ли это.
1 ответ
Вот одно решение, которое я нашел. Я не уверен, что это оптимально, но, похоже, работает.
Сначала создайте пустой список компонентов:
pkgbuild --analyze zzz --root nocomponents.plist
(Эта команда на самом деле успешно, хотя zzz
Каталог не существует.)
Позже, когда вы создаете свой пакет, предоставьте эту опцию pkgbuild
:
--components-plist nocomponents.plist