Сейчас все удобнее становится использовать HTML и JavaScript в интерфейсах приложений. И именно такая задача недавно появилась передо мной, с одним важным условием — на выходе должно быть полностью standalone приложение, не требующее установки дополнительных библиотек и способное запуститься в обычном пользовательском окружения.
В силу своего природного обаяния в качестве основного языка был выбран Python + PySide c WebKit на борту, для сборки app-бандла использовался py2app.
Проблемы появились, при первой же попытке запустить приложение на чистой системе — обнаружилось большое количество внешних зависимостей, которые py2app не смог самостоятельно разрешить. Под катом пошаговая инструкция как эта проблема была решена.
В попытках понять почему py2app не включает в бандл все необходимые библиотеки, в одной статье была найдена мысль, что создание полностью автономного приложения с встроенным в Mac OS интерпретатором невозможно и нужно пользовать MacPort. Так и поступим.
Подготовка
Итак, нам потребуется:
- XCode
- MacPorts
- Python
- virtualenv
- Qt4
- PySide
- py2app
XCode
Несет в себе как средства разработки под Mac OS, так и нужный нам gcc.
Я использовал последнюю версию — 4.2, но и с более ранними (3.Х) проблем быть не должно.
Если еще нет, то брать с установочных дисков Mac OS или с сайта Apple (потребуется бесплатная регистрация)
MacPorts
Менеджер пакетов, который позволяет ставить на мак много полезных тулов и библиотек.
Устанавливается стандартным способом (pkg). Брать с MacPorts.org.
После установки можно на всякий случай обновить:
$ sudo port selfupdate
Python
Ставим из MacPorts:
$ sudo port install python27
Если используете другую версию питона, просто замените здесь и далее.
virtualenv
Тул, позволяющий создавать изолированные окружения для питона. Очень удобно, когда нужно иметь несколько версий питона или разные проекты требуют различных библиотек, упрощает дальнейший деплоймент. В нашем случае мы с помощью virtualenv создадим «автономную песочницу» из которой и появится standalone приложение.
$ sudo easy_install virtualenv
В нагрузку ставим virtualenvwrapper, который упрощает работу с окружением:
$ sudo easy_install virtualenvwrapper
Qt4
Ставим с оф. сайта, я использовал Cocoa: Mac binary package for Mac OS X 10.5 — 10.6
PySide
Библиотека для Python, позволяющая использовать всю мощь и силу Qt из привычного языка программирования.
Пытался установить PySide сразу в виртуальное окружение через pip или easy_install (что было бы логичнее), но выяснилось, что PySide не поставляется в необходимом для этих менеджеров пакетов виде, в результате чего куча времени была убита на попытки скомпилировать библиотеку… остановился через пару дней, когда поймал себя за тем, что сидел и правил исходники какой-то сторонней либы =)
В результате идем путем установки предоставляемого разработчиками пекеджа.
Настройка окружения
Подготовительная часть на этом закончена, переходим непосредственно к созданию виртуального окружения и его наполнению.
Создаем виртуальное окружение
Выбираем место где будет жить окружение, для этого в ~/.bash_profile добавляем
export WORKON_HOME=~/Envs
source /usr/local/bin/virtualenvwrapper.sh
Создаем окружение
$ . ~/.bash_profile
$ mkdir -p $WORKON_HOME
$ mkvirtualenv --no-site-packages --python=/opt/local/bin/python2.7 py27
# --no-site-packages - говорит, что виртуальное окружение не будет использовать системные пекеджи
# --python=/opt/local/bin/python2.7 - какой интерпретор будет использоваться
# py27 - название окружения
После этого в $WORKON_HOME/py27 будет создана базовая структура каталогов и необходимые файлы. Кроме того окружение станет активным, в начале командной строки появится (py27). В дальнейшем, для активации нужно будет выполнить
$ workon py27
Можно вызвать питон, убедиться, что запустилась правильная версия.
(py27) $ python
Python 2.7.2 (default, Jul 21 2011, 01:27:20)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
Теперь нужно перенести в новое окружение все библиотеки и модули:
# PySide packages
$ cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages
$ mv PySide/ ~/Envs/py27/lib/python2.7/site-packages/
$ mv pysideuic/ ~/Envs/py27/lib/python2.7/site-packages/
# PySide libs
$ cd /usr/lib/
$ sudo mv libpyside-python2.7.* ~/Envs/py27/lib/
# Необходимая для PySide библиотека
$ sudo mv libshiboken-python2.7.* ~/Envs/py27/lib/
# Qt4 libs
$ cd /Library/Frameworks/
$ cp -pR Qt* ~/Envs/py27/lib/
$ cp -pR phonon.framework ~/Envs/py27/lib/ #Обратите внимание на отсутствие слеша после framework!
# Остатки Qt нам не нужны, удаляем
$ sudo /Developer/Tools/uninstall-qt.py
Так, почти все готово, осталась финальная полировка и проверка.
virtualenvwrapper кроме удобного способа создания и активации окружений предоставляет хуки на различные события — preactivate, postactivate, predeactivate, postdeactivate и прочие (полный список). Нас сейчас интересует postactivate, в который мы добавим переменные, которые будут говорить где искать в нашем окружении библиотеки и разные модули.
$ vi ~/Envs/py27/bin/postactivate
# Добавляем туда
export DYLD_FRAMEWORK_PATH=~/Envs/py27/lib/
export DYLD_LIBRARY_PATH=~/Envs/py27/lib/
Быстрая проверка:
$ workon py27
(py27) $ python
Python 2.7.2 (default, Jul 21 2011, 01:27:20)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import PySide
>>> PySide
<module 'PySide' from '/Users/smaant/Envs/py27/lib/python2.7/site-packages/PySide/__init__.pyc'>
>>>
Если вы все сделали правильно — то результат должен быть примерно таким. Если словили кучу ошибок, то… возможны варианты :)
py2app и проверка боем
Теперь все готово к написанию тестового приложения — qt_test.py:
#!/usr/bin/env python
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *
app = QApplication(sys.argv)
web = QWebView()
web.load(QUrl("http://www.pyside.org/"))
web.show()
sys.exit(app.exec_())
Проверяем
$ workon py27
(py27) $ python qt_test.py
py2app
Пришла очередь py2app, который поможет собрать наше приложение в полноценный бандл. Кроме прочего разработчики virtualenv заботливо положили в наше виртуальное окружение еще один менеджер пакетов pip, с помощью которого мы и поставим py2app:
$ workon py27
(py27) $ pip install py2app
Для генерации бандла py2app использует специальный файл — setup.py. Как его создать с нуля хорошо рассказано в доке, а мы воспользуемся уже готовым:
from setuptools import setup
APP = ['qt_test.py']
OPTIONS = {'argv_emulation': False,
'includes' : ('PySide.QtNetwork', ),
'semi_standalone': 'False',
'compressed' : 'True',
'frameworks' : ('libpyside-python2.7.1.0.dylib', 'libshiboken-python2.7.1.0.dylib'),
}
setup(
app=APP,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
В папочке dist появится app-бандл, который вы непременно можете запустить! )
Весь алгоритм проверялся на Mac OS X 10.6.8, а получившийся бандл тестировался на такой же, но чистой системе.
Если вы хотите использовать PyQt, то последовательность действий будет точно такой же, только ставится pyqt и в исходных файла все PySide заменяются на PyQt. Так же, возможно, потребуется установить SIP, аналогичным образом перенести его в виртуальное окружение и добавить в includes в setup.py.
Ссылки
Ниже полный список тулов и библиотек, которые я использовал, с их версиями:
- XCode 4.2
- MacPorts 1.9.2
- Python 2.7.2
- virtualenv 1.6.3
- virtualenvwrapper 2.7.1
- Qt4 4.7.3
- PySide 1.0.4-r1
- py2app 0.6.3
Две статьи, которые мне сильно помогли:
How to make standalone OS X application bundles from PyQt apps using py2app
Multiple Python Versions on OSX with Virtualenv and Macports