The CFBundleExecutable
key is required in the sense that you really should have it, but CoreFoundation will do its best to deal with its absence. By looking at the source of CFBundle we can get an idea how it deals with this key:
static CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) {
CFStringRef executableName = NULL;
// …
if (infoDict) {
// Figure out the name of the executable.
// First try for the new key in the plist.
executableName = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleExecutableKey);
// Second try for the old key in the plist.
if (!executableName) executableName = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleOldExecutableKey);
if (executableName && CFGetTypeID(executableName) == CFStringGetTypeID() && CFStringGetLength(executableName) > 0) {
CFRetain(executableName);
} else {
executableName = NULL;
}
}
if (!executableName && url) {
// Third, take the name of the bundle itself (with path extension stripped)
So you can see that they look for the following in order:
- The CFBundleExecutable key.
- The NSExecutable key, a legacy name predating OS X public beta.
- If neither is present, fall back to using the name of the bundle with the path extension removed.
Having determined the executable name, the manner in which the directory that it lives in is found is equally full of quirks. I'll leave discovering those as an exercise for interested parties.