I'm developing a GUI app in Python. I use cx_Freeze
to turn my app into .app/
/ .dmg
files for OS X users. So, for instance I can use python setup.py bdist_dmg
to make cx_Freeze create a .dmg
file that my users can use to install my app.
I now want my app to update itself automatically. Esky seems to be a promising framework for doing this. I can do python setup.py bdist_esky
to create a version of my app that updates itself. It produces the following directory structure:
myapp
myapp-0.1/
myapp
The top-level myapp
is Esky's bootstrapping executable. It looks in the current directory, finds myapp-0.1/
as the latest version and then launches myapp-0.1/myapp
.
How do I package this into a .dmg
file which I can ship to my users? After my modifications to setup.py
to get bdist_esky
to work, bdist_dmg
no longer works. The impression I get is that Esky is simply not meant to be used with bdist_dmg
. Its documentation doesn't mention DMG
files at all and I also couldn't find anything on Google.
As a first step, I tried to manually turn the files generated by Esky into an OS X .app/
bundle:
myapp.app/
Contents/
Info.plist
MacOS/
myapp
myapp-0.1/
myapp
Info.plist
contains the minimum amount of necessary information to get OS X to run myapp
. When I try to run myapp.app
however, I get:
Traceback (most recent call last):
File "<string>", line 318, in bootstrap
File "<string>", line 442, in get_best_version
FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/Temp/myapp.app/appdata'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 689, in <module>
File "<string>", line 335, in bootstrap
RuntimeError: no usable frozen versions were found
Looking at Esky's source code, it appears to have some special handling for OS X bundles in its appdir_from_executable(...)
function. To make Esky happy, I tried to rearrange my files so appdata/
actually exists:
myapp.app/
appdata/
myapp-0.1/
myapp
Contents/
Info.plist
MacOS/
myapp
Unfortunately, this results in another error:
Traceback (most recent call last):
File "<string>", line 689, in <module>
File "<string>", line 336, in bootstrap
File "<string>", line 363, in chainload
File "<string>", line 425, in _chainload
UnboundLocalError: local variable 'exc_value' referenced before assignment
Is this really that difficult? Am I the only one who wants to use Esky and ship files to users in the (standard) .dmg
format? What am I missing?
Michael, I saw your comment in the github issue as well. Let me answer it here.
I had the same requirement and resolved in a similar way but I think I didn't use cx_Freeze. Another difference could be that I used Python 2.7.x. The best way to help you is to show you a few relevant files which worked well for me for creating .app and .dmg.
1) The main setup file of the python project: https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/setup_esky.py
2) The utility script I used to prepare some data files etc https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/prepare_setup.py
3) The main shell script I used to create app and DMG. That is, this script will call everything else, and it's the only script I used from command line directly. https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/package.sh
4) The dmg-setup script which will create DMS from .app file. It's just a simple wrapper script to call create-dmg, an open souce project. https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/dmg-setup
Please try and let me know in case you have any other questions or issues.