App Bundles

App Bundles Overview

An Application Bundle (opens in a new tab) is a folder with a specific structure that is interpreted by the file manager (Finder) as an executable file. It is intended to contain an application complete with all its supporting resources such that the whole application can be moved or deleted by moving or deleting the bundle folder, and can be run from any location.

ravynOS bundles are very similar to macOS bundles with three main differences:

  1. The executable format inside the bundle is ELF instead of Mach-O and hence cannot support multiple architectures (i.e. arm64 and amd64) in one executable yet. Transition to Mach-O is planned.
  2. The executable directory is named ravynOS instead of MacOS
  3. There is a symlink inside the top level to the executable under Contents/ravynOS.

A bundle can target multiple platforms (known as a "fat bundle") by including more than one executable and a set of shared config and resources. This means it is possible to package an app for both macOS and ravynOS in the same bundle.

Many applications are written using Objective-C/C++ to take advantage of Cocoa frameworks. While this is preferred, apps can be written in any language and don't need to use the Foundation or AppKit frameworks. The minimum requirements are as follows.
├── Contents
│   ├── ravynOS
│   │   └── Firefox
│   ├── Info.plist
│   └── Resources
│       └── firefox.icns
├── Firefox -> Contents/ravynOS/Firefox
└── Resources -> Contents/Resources

There are few rules about what goes into Resources. Essentially it should be anything your app needs to run, and your app should know how to locate these resources relative to its runtime location. Apps should never use paths to fixed resource locations like /usr/lib/myapplication/; instead they should use NSBundle, CFBundle or an equivalent to determine their location then construct a path into the Resources folder.

  • Include an icon in Resources in either .icns or .png format and reference it from Info.plist
  • Include an Info.plist in the Contents folder which has at least these mandatory keys:
    • CFBundleExecutable
    • CFBundleIconFile
    • CFBundleIdentifier
    • CFBundleName
    • CFBundlePackageType with value APPL
    • CFBundleShortVersionString
    • CFBundleSignature with a 4-letter code representing your application or OBJC if you don't have one
    • NSPrincipalClass with your application's main class or NSApplication if it doesn't use Objective-C

You should include the CFBundleDocumentTypes dictionary as well if you want LaunchServices to know what kinds of files your application can open or to define new file types.

Other considerations

All apps should follow the Apple Human Interface Guidelines (opens in a new tab) as much as possible. You must implement the standard key bindings and menu structures for any new application. Applications being ported or packaged should make a best effort to follow these.

New applications must include an application menu titled with the app's name. This is the menu seen just to the right of the Apple logo on macOS applications. It contains standard items such as About, Preferences, Quit. This menu is created automatically for Cocoa applications using AppKit.

Menus are automatically placed into the global menu bar for applications using Cocoa. Qt, GTK, and Java support is planned as well. Some applications may need to be patched to support global menus. RavynOS uses the standard Cocoa NSMenu system, compatible with macOS. Cocoa applications that implement an NSMenu will automatically have it appear in the global menu bar when the application becomes active. Support for the dbus-menu (opens in a new tab) spec is likely to happen at some point. This is supported by Qt, GTK, and other frameworks for writing applications that are not using Cocoa.