2

For context, I am using Qt 5.3.1 with Xcode 5.1.1 on OSX 10.9.

After some struggle, I was finally able to get my application's PKG file to upload through Application Loader and appear in my "Prerelease" build list for my App in iTunes Connect. However, once I add the build to the app and click "Submit for Review" I get the following slew of errors:

ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
The nested bundle must contain an executable that matches the CFBundleExecutable key in the Info.plist of the nested bundle .
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.
ITC.apps.assetvalidation.DESKTOP_MISSING_NESTED_BUNDLE_IDENTIFIER.error.message
The Info.plist of the nested bundle must contain a valid CFBundleExecutable key.

I am applying the notes mentioned in this answer: Sign a Framework for OSX 10.9

Basically, I build my application through Xcode (in Release mode) and then I use a little Python script I wrote to help automate the prep for the app store. A gist of the script is here:

import os
import shutil
import subprocess
import sys

bundleFolder = '/path/to/the/bundle/app'
qtFolder = '/path/to/qt/et/al'
entitlements = '/path/to/entitlesments/file'

print 'Bundle folder: ', bundleFolder
print 'Qt Folder: ', qtFolder

print 'Executing macdeploy'
subprocess.call([qtFolder + '/bin/macdeployqt', bundleFolder + '/Program.app'])

frameworks = ['QtConcurrent', 'QtCore', 'QtGui', 'QtMultimedia', 'QtMultimediaWidgets', 'QtNetwork', 
    'QtOpenGL', 'QtPositioning', 'QtPrintSupport', 'QtQml', 'QtQuick', 'QtSensors', 'QtSql',
    'QtWebKit', 'QtWebKitWidgets', 'QtWidgets', 'QtXml', 'QtXmlPatterns']

for fwork in frameworks : 
    print ('Copying Info.plist to frameworks: ' + fwork)
    fworkFolder = qtFolder + '/lib/' + fwork + '.framework/Contents/Info.plist'
    destFolder = bundleFolder + '/Program.app/Contents/Frameworks/' + fwork + '.framework/Resources/'

    if (os.path.exists(destFolder)) :
        print 'Copying ' + fworkFolder + ' to ' + destFolder
        shutil.copy(fworkFolder,destFolder)

print ('Deleting unnecessary PlugIns')
rmFiles = ['accessible','audio', 'mediaservice', 'printsupport']

for rmFile in rmFiles : 
    fullFile = bundleFolder + r'/Program.app/Contents/PlugIns/' + rmFile
    if (os.path.exists(fullFile)) : 
        print ('Deleting directory: ' + fullFile)
        shutil.rmtree(fullFile)

print ('Signing Qt Executables')
for fwork in frameworks : 
    subprocess.call([r'/usr/bin/codesign', 
        r'--deep',
        r'--force',
        r'--verify',
        r'--verbose',
        r'--sign',
        r'3rd Party Mac Developer Application: [valid info]',   
        r'--entitlements',
        entitlements,
        bundleFolder + '/Program.app/Contents/Frameworks/' + fwork + '.framework/Versions/5/' + fwork   
    ])

print ('Signing Bundle')
subprocess.call([r'/usr/bin/codesign', 
    r'--deep',
    r'--force',
    r'--verify',
    r'--verbose',
    r'--sign',
    r'3rd Party Mac Developer Application: [valid info]',   
    r'--entitlements',
    entitlements,
    bundleFolder + '/Program.app',
])

print ("Building PKG")
subprocess.call([r'/usr/bin/productbuild', 
    r'--component',
    bundleFolder + '/Program.app',
    r'/Applications',
    r'Program-Installer.pkg'
])

print ("Building Signed PKG")
subprocess.call([r'/usr/bin/productsign', 
    r'--sign',
    r'3rd Party Mac Developer Installer: [valid info]',
    r'Program-Installer.pkg',
    r'Program-Installer-Signed.pkg'
])

I'm guessing the problem lies within the Info.plist files for each individual Qt*.framework but when I look inside them, the info looks valid as far as I can tell, for example:

<?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>CFBundlePackageType</key>
    <string>FMWK</string>
    <key>CFBundleShortVersionString</key>
    <string>5.3</string>
    <key>CFBundleGetInfoString</key>
    <string>Created by Qt/QMake</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleExecutable</key>
    <string>QtConcurrent</string>
    <key>NOTE</key>
    <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>
</plist>

So, I cannot figure out why the Mac App Store is complaining. Does anyone have any thoughts?

Thank you!

Community
  • 1
  • 1
Addy
  • 2,414
  • 1
  • 23
  • 43
  • Same here. I thought it might be a new requirement to have executable name of the main app in the nested bundle's plist files (i.e. YouApp.app instead of framework name), yet I can not confirm this idea true or false since iTunesConnect doesn't allow me to update the build. I remove an old build, upload a new one, but I still have only a single build on the server (upload seceded). Should you know how to re-upload the binary - I could try my idea and report back. – Gobra Sep 06 '14 at 00:28
  • I accomplished uploading a new binary by incrementing the build number. – Addy Sep 06 '14 at 01:12
  • I can not see new build in the iTunes even after changing the build number, but for each upload I receive a mail with the same issues list. So, I guess, my idea doesn't work. – Gobra Sep 06 '14 at 10:35

1 Answers1

3

I finally got though it. It seems like Qt Info.plist files are corrupt, i.e. they do not have enough info and the last-step validation on Apple server fails.

In order to solve the issue I took an Info.plist file from a regular XCode-compiled framework that was included in a native Mac app and passed validation before. The content was like this:

<?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>BuildMachineOSBuild</key>
    <string>13E28</string>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>BUNDLE_NAME</string>
    <key>CFBundleIdentifier</key>
    <string>BUNDLE_IDENTITY</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>BUNDLE_NAME</string>
    <key>CFBundlePackageType</key>
    <string>FMWK</string>
    <key>CFBundleShortVersionString</key>
    <string>BUNDLE_VERSION</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>BUNDLE_VERSION</string>
    <key>DTCompiler</key>
    <string>com.apple.compilers.llvm.clang.1_0</string>
    <key>DTPlatformBuild</key>
    <string>5B1008</string>
    <key>DTPlatformVersion</key>
    <string>GM</string>
    <key>DTSDKBuild</key>
    <string>12F37</string>
    <key>DTSDKName</key>
    <string>macosx10.8</string>
    <key>DTXcode</key>
    <string>0511</string>
    <key>DTXcodeBuild</key>
    <string>5B1008</string>
</dict>
</plist>

I have replaced bundle version, name and identifier of the original file with placeholder strings, than I used this file as Info.plist for Qt frameworks, replacing the placeholders with correct values via Perl script.

Having some additional fixes like proper symlinks conforming this article, I finally got my Qt 4.8 app passed for review, I believe you should be able to get same result with Qt 5+.

Gobra
  • 4,263
  • 2
  • 15
  • 20
  • This finally worked from me, my app has finally been approved for review. Thanks! – Addy Sep 09 '14 at 12:58
  • 1
    Thanks! If anyone else is wondering what strings to use for the placeholders (example QtCore 4.8): BUNDLE_NAME -> QtCore, BUNDLE_IDENTITY -> QtCore, BUNDLE_VERSION -> 4 – Hyndrix Sep 13 '14 at 09:26
  • I have the same problem, But applying a new plist is not solving it still it says bad CFBundleExecuitable key. Can you please give more information regarding how you fixed this error ? – SatheeshCK17 Oct 06 '14 at 18:07
  • Hyndrix has stated some proper (sample) values for my placeholders including one for CFBundleExecuitable key. This key should contain exact framework name i.e. "QtCore" for code framework, "QtXML" for xml one and so on. – Gobra Oct 06 '14 at 20:37
  • thank you verymuch for the suggestion. I have put QtCore as CFBundleExecuitable, But still appstore is giving this error. Very much confused. Can you please give some pointers? – SatheeshCK17 Oct 07 '14 at 05:25
  • Now I am seeing I am getting an error "Bad bundle executable" Not sure what it means, googling also not helping. Following is the complete error "parameter ErrorMessage = ERROR ITMS-9000: "Bad Bundle Executable. You must include a valid CFBundleExecutable key in the nested bundle QtCore [App.app/Contents/Frameworks/QtCore.framework] property list file." – SatheeshCK17 Oct 07 '14 at 05:36
  • Sorry for the stupid question, but do you put those data into the .plist files of the frameworks. In Mac OS app the app itself and each framework owns an Info.plist file, the fix explained above must be applied to each and every framework. I.e. you must fix QtCore, QtXML, QtGl and whatever else you have. – Gobra Oct 07 '14 at 08:31