Nifty fractal

Anatomy of an App Bundle

I recently needed to use CMake to generate macOS app bundles, and I had a really hard time getting the icon to work (macOS 10.14). No matter what I did, the icon just would not show up, although strangely, it did work on my old 10.10 laptop. This led me to a journey into the macOS bundle.

AppName.app/   App bundle directory
   Contents/
   Info.plist See below
PkgInfo Obsolete; only used by Carbon
   Resources/
   AppIcon.icns App icon for 10.12 and before
Assets.car All icons (including app icon) 10.13 and later
image.png
en.lproj/ Localizations
   InfoPlist.strings
Localizable.strings
jp.lproj/
InfoPlist.strings
Localizable.strings
Frameworks/ Any shared libraries included in the bundle
libdependency.dylib
MacOS/ Executables
AppName Main executable
external_tool Helper executable

Required app/document icon sizes

512x512 (1x and 2x)App Store, Finder in icon view
256x256 (1x and 2x)Finder
128x128 (1x and 2x)Finder, Dock
32x32 (1x and 2x)Finder list views
16x16 (1x and 2x)Spotlight

The Info.plist is something like the following:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <!— Boilerplate -->
    <key>CFBundleInfoDictionaryVersion</key> <!— always 6.0 -->
    <string>6.0</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleSupportedPlatforms</key>
    <array>
        <string>MacOSX</string>
    </array>

    <!— Name of bundle. Used if CFBundleDisplayName does not exist.
         Should be 16 characters or less -->
    <key>CFBundleName</key>
    <string>AppName</string>

    <!— Name of executable file (in case the user renames the bundle) -->
    <key>CFBundleExecutable</key>
    <string>AppName</string>

    <key>CFBundleGetInfoString</key>
    <string>${MACOSX_BUNDLE_INFO_STRING}</string>

    <!— Obsolete (macOS 10.12-). Name of the .icns file containing the
         app icon, located in the Resources/ directory. The “.icns” extension
         is not necessary. By default this value is “AppIcon”. -->
    <key>CFBundleIconFile</key>
    <string>AppIcon</string>
    <!— macOS 10.13+: name of the icon in the Resources/Assets.car file.
         If this key exists but the Resources/Assets.car file does not exist,
         the CFBundleIconFile (usually AppIcon.icns) will NOT be used and
         you will get the default application icon. -->
    <key>CFBundleIconName</key>
    <string>AppName</string>

    <key>CFBundleIdentifier</key>
    <string>com.geoffprewett.AppName</string>

    <!— Version keys -->
    <key>CFBundleVersion</key>
    <string>1.0.0</string>
    <key>CFBundleLongVersionString</key>
    <string>1.0.0</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0.0</string>

    <!— Optional; displayed in Finder’s Get Info command -->
    <key>NSHumanReadableCopyright</key>
    <string>Copyright (C) 2020 by Geoff Prewett</string>

    <!— Optional; sets the default language -->
    <key>CFBundleDevelopmentRegion</key>
    <string>en</string>

    <!— Optional; sets the content types that this application can handle -->
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeIconFile</key>
            <string>documentIcon</string> <!— .icns file -->
            <key>CFBundleTypeName</key>
            <string>Comma-separated values</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.comma-separated-values-text</string>
            </array>
            <key>LSHandlerRank</key>
            <string>Owner</string>
        </dict>
    </array>

    <!— Optional; describes existing content types (not defined by this
         application. (The system already knows about CSV files, but this
         is an example of what its definition might look like.) -->
    <key>UTImportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeIdentifier</key>
            <string>public.comma-separated-values-text</string>
            <key>UTTypeConformsTo</key>
            <array>
                <string>public.plain-text</string>
            </array>
            <key>UTTypeDescription</key>
            <string>Comma-separated values</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <array>
                    <string>csv</string>
                </array>
                <key>public.mime-type</key>
                <array>
                    <string>text/csv</string>
                </array>
            </dict>
        </dict>
    </array>
</dict>
</plist>

Helpful information: