【问题标题】:How does Mac OS X run app bundles?Mac OS X 如何运行应用程序包?
【发布时间】:2013-06-16 19:30:08
【问题描述】:

我正在使用py2app 捆绑一个 Mac 应用程序,并试图弄清楚它是如何工作的。根据阅读Bundle Programming GuideCFBundleExecutable 似乎是必需的密钥,这是 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 如何加载我的应用程序?

【问题讨论】:

    标签: macos bundle nsbundle


    【解决方案1】:

    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)
    

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

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

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

    【讨论】:

    • 哦,太棒了!不知道我可以去寻找源头。由于我的包被称为foo,而可执行文件也被称为foo,看来案例#3 是让它工作的原因。现在的问题是:如果我包含名称,为什么它不显示窗口,但如果我不包含它...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-22
    • 2016-01-04
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多