Support for building Mac .framework and .app bundles
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
The Mac has the concept of a bundle, which is a directory structure that can contain multiple versions of a library or an executable, along with all the resources needed by it. It would be wonderful if it were possible to build these automatically from cabal. At present I fill this need with my own fork of cabal (!), following some frustration a couple years ago with trying to get this functionality in. But I feel like with everything that's changed since then, the time might be ripe for trying it again, so here's my proposal, which I'm going to immediately start work on implementing, optimistically. :)
Add two new "components" to the .cabal format - that is, top-level items that are peers of Library, Executable, etc. They will look like this:
``` cabal
Framework SomeLibrary
-- Has everything that Library has, plus:
info-plist: Info.plist
resource-dir: Mac
xibs: SomeWindow.xib
other-resources: Something.png
App SomeApp
-- Has everything that Executable has, plus:
info-plist: Info.plist
resource-dir: Mac
xibs: MainMenu.xib,
SomeWindow.xib
other-resources: Application.icns,
Something.png
```
There are some design issues here.
There is an existing mechanism for attaching data files such that the installed components can find them by using compiled-in paths (actually there is a slight security hole there, since an environment variable allows these to be overridden... but never mind). It might be desirable to merge this mechanism with the "resources" mechanism, which puts files in a specific place within the created directory structure such that Cocoa API calls can find them. But this is done at the whole-project level as things stand, so it's not suitable, and I'm hesitant to redesign an existing feature for the benefit of a new one. The two don't conflict, so I think the best thing in the short term is to allow both to exist in parallel, even though they serve similar purposes.
In practice, very few people actually want to build only an App or only a Framework. They actually want to build an App or Framework on platforms that support it, and an Executable or Library on platforms that don't. Essentially, by the way, platforms that support it are just the Mac, but there's also Cocotron, which is a clean reimplementation of many Mac APIs for Win and Lin, and it bears thinking about... for another day. Now, the way I would propose to implement this at present is by using the buildable: option in each component, inside a platform test. The only argument against this that I see is that it does create a lot of duplication - but we ALREADY have a lot of duplication in .cabal files, and probably need a more-general mechanism to clean it up. (First-class sets of option flags which could be given names and included by reference in arbitrary places come to mind. But, another day!)
It could be argued that the Framework component's name should be implicit, like Library's is. But frameworks conventionally have upcase names, and Unix libraries conventionally have downcase ones...
The last time around, @dcoutts argued strongly that it would be wonderful if we could include the information that needs to go in the Info.plist into the .cabal, so that we could generate the Info.plist instead of requiring programmers to create it by hand. However, almost all of it needs to be manually set by the developer, which would necessitate a great many additional options in these new components. It's also very prone to change. One could argue that we don't want to require people to use Apple's tools - but it's actually just an XML file in a particular well-documented format. The genesis of the generate-for-them line of thinking seems to be a misconception that Info.plist contains build information... It does not. It contains mostly deployment information. There is a small amount of overlap with metadata that we also have, mostly the authorship and versioning information, but the burden is fairly light.
Biggest issue last. Why new components? Because last time around, using existing components lead to numerous long, unproductive philosophical discussions on which existing features to merge with, which to reimplement, and so forth. The result of this was that the work got done but never passed review. If we want to actually have these features, it seems prudent to do them in a way that breaks as little as possible.
What I'm really looking for is feedback on whether it's worth doing this in cabal, or whether I should pursue other options. That is, I'd like some encouragement that the design is in principle acceptable, and that the work will eventually be reviewed. Thanks!
Contributor guide
Assessment
This issue has not been assessed yet.