Skip to content

Instantly share code, notes, and snippets.

@thomashope
Created October 19, 2021 00:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomashope/40d688ae9833443a3fe1bb0cc83240a3 to your computer and use it in GitHub Desktop.
Save thomashope/40d688ae9833443a3fe1bb0cc83240a3 to your computer and use it in GitHub Desktop.
Defining Mac App Info.plist in code

Having to build an app and bundle it with an Info.plist can sometimes be inconvenient.

A while ago I found out it is possible to bundle your Info.plist directly into a section in the executable by adding the following to your linker options:

-sectcreate __TEXT __info_plist ../../source/Mac/Info.plist

With some trial and error it seems that it is possible to create such a section directly in code using the __attribute__ syntax.

Note that when you include an Info.plist normally you can use variables $(PRODUCT_NAME) which get expanded at some point during the bundling process, if you decided to use this for real you’d have to work around that?

Further questions:

  1. How problematic is it in practice to not have $(PRODUCT_NAME) etc. variables / what workarounds are there?
  2. If you have Info.plist data both in the executable and the .app bundle, which takes precedence?
  3. Is this a terrible idea, what problems can it cause?
// Add this to some compilation unit that gets built with your executable
//
// For a while I tried doing `const char*` which doesn't work. I think because only the pointer is stored
// in the specified section. Instead use `const char []`
//
// You can verify the data made it into the binary with `otool -P path/to/binary/executable`
const char __attribute__((used, section("__TEXT,__info_plist"))) info_plist[] =
R"(<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
</dict>
</plist>)";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment