1

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 如何加载我的应用程序?

4

1 回答 1

3

密钥是必需的CFBundleExecutable,因为您确实应该拥有它,但 CoreFoundation 将尽最大努力处理它的缺失。通过查看 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)

因此,您可以看到他们按顺序查找以下内容:

  1. CFBundleExecutable 键。
  2. NSExecutable 键,一个早于 OS X 公共测试版的旧名称。
  3. 如果两者都不存在,则回退到使用已删除路径扩展名的捆绑包名称。

在确定了可执行文件名之后,找到它所在目录的方式同样充满了怪癖。我将把发现这些作为对感兴趣的各方的练习。

于 2013-06-22T09:08:55.310 回答