2013-06-16 4 views
1

Я использую py2app, чтобы связать приложение Mac и пытаюсь выяснить, как он работает. Основываясь на чтении Bundle Programming Guide, кажется, что CFBundleExecutable является обязательным ключом и что это ключевой OSX использует, чтобы выяснить, какой файл в подпапке MacOS для запуска. Тем не менее, я раздели мой Info.plist файл в дальнейшем, и приложение нагрузки просто отлично:Как Mac OS X запускает пакеты приложений?

<?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 может загрузить мое приложение?

ответ

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) 

Таким образом, вы можете увидеть, что они ищут следующее по порядку:

  1. Ключ CFBundleExecutable.
  2. Ключ NSExecutable, устаревшее название, предшествующее публичной бета-версии OS X.
  3. Если ни один из них не присутствует, откиньтесь назад, используя имя пучка с удаленным расширением пути.

Определив имя исполняемого файла, найденный в нем каталог, в котором он находится, одинаково полон причуд. Я оставлю их открытыми для упражнений для заинтересованных сторон.

+0

о, блестящий! не знал, что я могу просто взглянуть в источник. Поскольку мой пакет назывался 'foo', а исполняемый файл также назывался' foo', кажется, что случай №3 - это то, что заставило его работать. вопрос в том, почему он не отображает окно, если я включаю его имя, но он делает, если я этого не делаю ... – Claudiu