Friday, April 10, 2015

Sorting out the MacOS Bundle options

I spent about 3 hours yesterday and 2 hours today working on the Nuitka failure. It compiles all the code; builds the bundle; the bundle contents look very similar to the bundle built by PyInstaller; but it won't start. There's something wrong with the way that QApplication loads plugins that causes the app to either die or hang up and need force-killing. I finally wrote a note to the list detailing the failure and basically kissing it off. "I may try Nuitka on Linux some time."

With that out of the way, how shall I bundle PPQT2 for MacOS? For V1, I was pleased to be able to use PyInstaller on all three platforms, and I had a near-religious assumption that it was good to use the same tool on all platforms. But really, that isn't necessary. If I end up using cxFreeze on one, py2exe on another, who cares? The key is, do they build a bundle that runs; and if so, which builds the smallest bundle?

PyInstaller

I've got it working on MacOS with two small issues. One, when you launch the app from inside the folder, there's a stream of console messages apparently listing the different dylibs as they load. No idea why. And it has the problem that the app comes up and opens its window, but its menu bar does not appear until you click in another app, then click back to your app. Then you have a menu bar. There's a pull request with a purported fix; I need to get that onto the Python3 branch and try it.

Also as I noted a few days ago, it builds a bundle that zips to 69MB.

cxFreeze

I succeeded in getting it to bundle PPQT2 with about an hour's work of reading and experimenting. It does not do as good a job as the others do, of tracing out the implicit PyQt imports. I had to tell it specifically to include QtWidgets and QtPrintSupport; otherwise the app died looking for those. But once that was out of the way, it worked. Well, almost! It has the identical problem that PyInstaller apps have with the menu bar not appearing right away.

Bundle size as a zip file? 88MB. Ooops. So no reason to prefer it over PyInstaller.

py2app

The Python3 version of PyInstaller actually uses a big chunk of code written by Ronald Oussoren for his py2app package. So why not try it? I have to say that it does a good job, up to a point. It is the only one of the four (counting Nuitka as a bundler) that actually builds a MacOS app bundle with a proper icon. The others make an ordinary folder. The user has to go into the folder and double-click the PPQT2 file icon, which is an ordinary "unix executable" icon. While the app is running, that is also its icon in the dock.

py2app offers two modes. It recommends -Alias build mode for development; in this mode it makes an app bundle but populates it mostly with symlinks to the dependency files. This goes fast and takes little space, but of course isn't portable. In this mode it works well and the resulting app bundle bears my chosen icon, and while running, shows my icon in the dock.

Way back when I made the icon I want, but was never able to use it with V1. I feel a bit of trepidation about using it, but it's so cool... and with py2app, I can have it.

So what's the problem? Well, when I run py2app not in -Alias mode, it starts to build a complete self-contained app bundle and of course crashes with some stupid error. So I sigh opened an issue on Oussoren's bitbucket page. If he responds in reasonably short order, I'd prefer to use py2app. Oh, the size of its zipped-up bundle? 62MB, and it hadn't quite finished building when it quit. So, about the same as PyInstaller.

That does it for Mac. Tomorrow I am determined to make something, something work on Linux.

No comments: