Cabalising creation of OS X application bundles for GUIs

Andy Gimblett haskell at
Mon Jan 11 11:32:40 EST 2010

Hi there,

I've recently been doing some work on packaging GUIs for OS X, and I'm  
writing to ask:
   a) for assurance that the approach taken is sensible and consonant  
with the Tao of Cabal's, and
   b) a (probably simple) question about making this work nicely cross- 
   c) for any advice anyone wants to give.  :-)

Here's the background:

For a GUI to run nicely under OS X, it needs to be packaged into an  
application bundle, which is a folder containing the executable binary  
and any related resources (such as libraries, icons, etc.) in a  
designated structure, and marked as an app bundle via a tool called  
Rez.  Without being in such a bundle, the executable runs without its  
icon, and doesn't respond to user actions.  Historically, this has  
been solved (in a minimal fashion) by a script called macos-app (see 
, which is included in the wx distribution.  This works, but doesn't  
integrate very prettily into a cabalised build process.

(BTW, are there any gtk2hs/OS X users out there?  My (limited)  
experience suggests that "bare" gtk2hs executables work OK, but don't  
get focus automatically and of course lack nice icons.  Thus, this  
work could be of use to gtk2hs users as well?)

Recently, Eric Kow did some work towards replacing macos-app with  
equivalent Cabal-based machinery, and I've now polished that up a bit,  
cabalised it, and made it public on github ( 
).  I _haven't_ released it on hackage yet, but will do when I'm sure  
it's going in the right direction.

   - We have a package (cabbage?): cabal-macosx
   - It exports a single module: Distribution.MacOSX
   - That exports a post-build hook for creating the app bundle, as  
well as data types for customisation info (e.g. the icon).

and at present that's it.  Installation isn't handled yet: "runghc  
Setup install" just copies the bare executable, which doesn't run  
properly - so I need to fix that.  (Eric's original version did the  
work upon installation, but I needed it at build-time, so I moved it.)

[Another thing I'd like to add: app bundles can carry their own copies  
of shared libraries, which makes distribution much simpler (you just  
publish the whole bundle, and it works, standalone).  To support this,  
I'll need to add some a pre-build hook copying them into the right  
place (and so, building the app bundle will happen even earlier), and  
also insert some linker flags (Cabal can handle this?).]

OK, so that's the picture.  Reasonable so far?

Now comes the question:

Obviously, cabal-macosx is only _really_ a dependency when building on  
OS X.  How can I (indeed, should I?) remove this depedency for other  
platforms?  For example, consider 
  - here, I could make cabal-macosx platform-dependent using, say:

   if os(darwin)
     Build-Depends:        base >= 3 && < 5, cabal-macosx, wx
     Build-Depends:        base >= 3 && < 5, wx

but there is then still an "import Distribution.MacOSX" in Setup.hs  
, so build will still fail on other platforms.

Is the right way to handle this:
a) Just demand cabal-macosx on all platforms, and do the check in  
Setup.hs (as in the above example)?
b) Build platform checks into Setup.hs?  I don't even know if that's  
possible: a platform-specific import?
c) Something else?

All advice and comments appreciated - thanks for reading this far!



Andy Gimblett

More information about the cabal-devel mailing list