我正在使用py2app
捆绑Mac应用程序,并试图弄清楚它是如何工作的。基于阅读Bundle Programming Guide,似乎CFBundleExecutable
是必需的密钥,这是OSX用来确定要运行的MacOS
子文件夹中的哪个文件的关键。但是,我将Info.plist
文件剥离到以下内容,应用程序加载正常:
<?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>PyMainFileNames</key>
<array>
<string>__boot__</string>
</array>
<key>PyRuntimeLocations</key>
<array>
<string>@executable_path/../Frameworks/Python.framework/Versions/2.7/Python</string>
</array>
</dict>
</plist>
怎么会这样?鉴于确切的plist
文件,OSX如何加载我的应用程序?
答案 0 :(得分:3)
CFBundleExecutable
键是你真正需要的,但是CoreFoundation会尽力处理它的缺席。通过looking at the source of CFBundle,我们可以了解它如何处理此密钥:
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)
所以你可以看到他们按顺序寻找以下内容:
确定了可执行文件名后,找到它所在目录的方式同样充满了怪癖。我会把这些发现作为有兴趣的各方的练习。