Skip to content
Tom edited this page Jul 26, 2021 · 2 revisions

A "bundle" is Apple's system of packaging applications. To users, bundles look like single files, but they are actually collections of all the program code and resources the app needs to run. Often, Mac developers use Xcode, Apple's own IDE, which handles bundles itself.

(Apple reference: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html)

Fortunately for us, an app bundle is basically just a directory ending in .app with some special contents. It has this basic structure:

MyApp.app/
    Contents/
        MacOS/
            MyApp
        Resources/
            MyApp.icns
        Info.plist

Your app's executable goes in Contents/MacOS, an Apple "iconset" (see below) goes in Contents/Resources, and the metadata file Info.plist goes in Contents.

Info.plist

The bundle metadata is stored in Contents/Info.plist. See Info.plist for details on its contents.

Creating an iconset (.icns)

Fortunately it's very easy to convert to Apple's icon file format with portable tools. If you install libicns, you get a program called png2icns which converts a series of PNGs into an iconset. Here's a short guide by Jens Reimann.

Accessing the Resources directory

As well as the iconset, Contents/Resources is intended to hold resources and data files for your application. But how do you get its path?

In my searching I couldn't find a macOS C API for this; you have to use their Objective-C API. However, it is possible to write a small wrapper which can be called from C. In fact, SDL2 has a function SDL_GetBasePath which on macOS returns a path to the Resources directory.

Bundling libraries

The macOS linker doesn't support dynamically changing the search path. However, you can change the link path of individual executables and libraries after compilation, so they can be loaded from within the bundle. dylibbundler can do this automatically for you, and is available on Homebrew.