Mac .app and .framework bundle building
irene.knapp at icloud.com
Thu Jun 6 00:04:35 CEST 2013
The other day, I created an issue over on GitHub with my thoughts on a family of related features that I have now begun implementing, to support the building of Mac bundles. As anyone who's used the platform probably knows, these are a way of distributing libraries and applications as specially-structured directory trees. They are particularly important because the Mac's GUI API, Cocoa, *requires* a .app wrapper around any executable which uses the display. Command-line programs which attempted to access the display used to behave strangely and never take focus, but since Mountain Lion introduced sandboxing, they no longer even run. This makes libraries such as SDL and its peer glow rather pointless for Haskell developers, unless we can build them into bundles.
I have specific thoughts on implementation, which I wrote up on the ticket, but as I've begun work on this I've additionally noticed some related features which, since I'm now doing this "for real" and not "just for me" like my previous work in this area, really need discussion before being implemented. I've linked to the ticket below, but for those on their phones, :), I'm also summarizing and repeating most of what I said there, here.
I'll put the most controversial part first: I'm doing this as two new top-level components, Framework and App respectively, as peers to Library, Executable, TestSuite, and all our other favorites. This allows a single .cabal file to contain instructions for both regular Unix-style and fancy Mac-style, and even to install both side-by-side if desired. This is particularly important in the case that one wants to build a .app bundle which contains some command-line support tools, which is not a hugely uncommon pattern in software designed for developers.
It does create some duplication of information; for example, if one wants to build a Library on non-Mac platforms, but instead build a Framework on the Mac, then one must include all the options for both, keep ithem in synch, and conditionalize the buildable: option based on the platform. However, I don't see this duplication as being any worse than what most .cabal files in the wild already do for test suites. I will note that somebody else might wish to work on a feature to define variables in a .cabal file, with sets of option-value pairs as their values, with the goal of reducing duplication... but I don't have time myself.
A subsidiary feature is the building of Apple's Interface Builder .xib documents into .nib documents (.xib is a source file and .nib is its compiled form), by shelling out to Apple's command-line tool. This is one of the things I've already gotten working and just need to forward-port from my two-year-old fork to my current fork, so it shouldn't be a big deal or raise major design questions.
Another issue is Apple's Info.plist files, which are XML in a well-documented format, that goes inside the bundle. The last time I worked on this, Duncan expressed a strong desire for them to be generated; I believe his argument reduced to wanting Cabal, as a matter of pride, to be the authoritative owner of package metadata. They do overlap slightly with what we currently have, mostly in the authorship information. They also have version numbers, but I don't think offhand that they're in a compatible format with ours. Mostly, however, they contain Apple-specific information such as category in their store; bundle identifier in reverse-DNS style; document-type definitions which include identifiers, filename extension mappings, and the like; ... They are fairly complex in that way. It would be a pain to describe them in our .cabal file, and the information would be useless for other component-types. So, I'm not inclined to do this.
I expect to have no difficulty with .app bundles, because those also I previously had working. However, .framework bundles present a different can of worms. It is certainly of some use to create a .framework which contains Haskell code intended to be used from a C application. But, it would be really nice if we could actually use our own .frameworks from Haskell. To do this, the .hi and installed-package-info files need to reside inside the .framework directory... and need to use relative paths, which I haven't looked into the feasibility of, since the point of a .framework is that it can be relocated in the filesystem. I think that if this can be done, that will be sufficient to make these beasts load properly, but does anybody see any other obstacles?
My old patches for C-side main() and other supporting things I don't remember regarding hybrid C-Haskell programs will also be needed, but I'm fairly sure those got merged recently. (I wasn't involved, since I had long since given up getting them through review, so I'm not sure exactly which patches made it.)
Another point - I've been operating under the assumption that Framework components will have names, unlike Library components. I can't easily use the package name for them, as is done for Library components, because the Unix convention is lower-case and the Mac convention is uppercase, and you will recall that I consider it important to support both component types in one .cabal file. But this makes things inconsistent and I'd rather like it if that inconsistency were resolved by allowing multiple Library components, with names. It would be useful to me personally; I've got another project that is broken into several pieces, which right now each have their own .cabal files out of necessity, but which I would rather merge together to make their building and testing (drastically) simpler. I'm willing to do that work, once I'm done with the rest of this, but I wouldn't hold up the merge of bundles on it; it's not crucial to them. What do people think?
Having written all this, it has actually made me think twice about the wisdom of making Haskell-package .framework bundles at all - it might be better to stick with just .app bundles. But I really, really wanted to not try to run without a .nib in my fork of glfw and its Haskell wrapper, because running without a .nib is both buggy and rather hard to maintain, since it unnecessarily puts things into imperative code that are better done through GUI tools. Does anybody have an opinion?
Since obviously nobody is waiting eagerly for this, I see no reason to push out a release with just .app support; I'd rather get everything working before merging, even the hard bits. The brave can experiment with my new fork anyway in the meantime, since it's on GitHub.
Whew! Thank you for reading this far. :) I should make this shorter, but I'm in a rush to get home just at the moment...
-- Irene Knapp
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the cabal-devel