FreezingBlue Software
Developing A QtCreator App for the Mac App Store
12/10/2011

Here are the steps that it took me to deploy an app using QtCreator for the Mac App Store. Information here was pieced together from multiple blogs/google searches/documentation. See also Apple's Release Notes. There were many obscure errors I needed to correct to get this to build. My username is david in the steps below. Hopefully it will help anyone else.

The current Qt version I am using is 4.7.4. The stock download is incompatible with the app store due to some files being saved that are named incorrectly. So,

  • Step 1: Install the 4.7.4 source.
    Run the tool /Users/david/QtSDK/QtSources/SDKMaintenenceTool. Select Package Manager. Select Continue, then make sure Qt SDK->Miscellaneous->Qt Sources->Qt 4.7.4 Source is selected and continue to install in the default location.
  • Step 2: Patch the source code.
    There needs to be several patches applied to the source code to correct some errors. They are located here: Patches. Download, at the top, 3 files
    mac-settings-in-app-area.diff
    mac-hide-showall-menu-item.diff
    mac-app-store-cache-location.diff

    Find the file at the top of each diff file referenced in your source code, /Users/david/QtSDK/QtSources/4.7.4/ and rename it with a .orig extension. Next run the patch command - make sure that your paths are correct so that your patched files are in the correct directory.
    patch qsettings_mac.cpp.orig -i mac-settings-in-app-area.diff -o qsettings_mac.cpp

    You should now have a patched qsettings_mac.cpp file. Do that for the other 2.

    (Possible Error: If you rename to a .orig extension on the Mac Finder, make sure the Finder is not hiding extensions, otherwise file not found).

  • Step 3: Configure and make the source.
    When building for the app store, no PPC code should be there, so set -arch to x86. Additionally, make sure you add the -prefix so you are using your custom build. I also removed items I didn't need to cut the binary size down by using -no-* commands. (dwarf-2) is set by default in the configure app so no need to set that explicitly.

    cd /Users/david/QtSDK/QtSource/4.7.4/
    make confclean
    ./configure -prefix /Users/david/QtSDK/QtSources/4.7.4 -arch "x86 x86_64" -no-qt3support -no-xmlpatterns -no-phonon -no-phonon-backend -no-svg -no-scripttools -no-openssl -no-declarative
    make
    sudo make install

    (Possible Error: failed to detect the ABIs used by the qt version.
    ??? Clean and reconfigure and remake all source. Seemed to fix the problem.)

  • Step 4: Make your app.
    Next build your release app. This requires several pieces.

    In my .pro file, I needed to add several mac specific settings:

    mac {
        # only intel binaries are accepted to force this
        CONFIG += x86
        
        # minimum OS version for submission is 10.6.6
        QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
        
        # i think this will work. my custom plist
        QMAKE_INFO_PLIST = Info.plist
        
        # Icon is mandatory for submission
        ICON = heart.icns
    }

    Additionally, I created a custom Info.plist that contains several values needed by the app store. See http://developer.apple.com/library/mac/#releasenotes/General/SubmittingToMacAppStore/_index.html

    <?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>CFBundleIconFile</key>
        <string>heart.icns</string>
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleGetInfoString</key>
        <string>David Skelly</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleExecutable</key>
        <string>Hearts</string>
        <key>CFBundleIdentifier</key>
        <string>com.dskelly.hearts</string>
        <key>CFBundleShortVersionString</key>
        <string>1.0</string>
        <key>NSHumanReadableCopyright</key>
        <string>2011 David Skelly</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.card-games</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.6.0</string>
    </dict>
    </plist>

    Note this plist requires an appstore application category. It also links to a .icns file that I created with /Developer/Applications/Utilities/Icon Composer.app

    In your main file, this must be added to call your patched code so that qt creates the properly named files:

    extern "C++" {
        void qt_force_trolltech_settings_to_app_area( bool bVal );
    }

    int main(int argc, char *argv[])
    {
    #ifdef __APPLE__
        qt_force_trolltech_settings_to_app_area(true);
    #endif

        QCoreApplication::setApplicationName( "hearts" );
        QCoreApplication::setOrganizationName( "DavidSkelly" );
        QCoreApplication::setOrganizationDomain( "dskelly.com" );

    My app when built was about 3 megs. You must then run the macdeployqt command on it. Open a terminal, cd to the directory below and then run that on your app. The app grew in size for me to about 44 megs.

    cd /Users/david/QtSDK/QtSources/4.7.4/bin
    ./macdeployqt "path to .app file"

  • Step 5: Code sign your app.
    You will need to code sign all of the binaries in your app (or Apple recommends it anyways). First you need to set up your certificates properly. Follow Apple's instructions for that, see http://developer.apple.com/certificates/index.action.
    Next I created myself a shell script that will sign everything I need. Node that I am code signing with my Application certificate. Here is the script I run codesign.sh. The first line contains example, next lines all contain truncated examples, last line contains the final code sign

    codesign -f -s "3rd Party Mac Developer Application" "/Projects/hearts/qt/qthearts-build-desktop-Desktop_Qt_4_7_4_for_GCC__Qt_SDK__Release/Hearts Card Game.app/Contents/Frameworks/QtCore.framework/Versions/4/QtCore"

    /Contents/Frameworks/QtDeclarative.framework/Versions/4/QtDeclarative
    /Contents/Frameworks/QtGui.framework/Versions/4/QtGui
    /Contents/Frameworks/QtNetwork.framework/Versions/4/QtNetwork
    /Contents/Frameworks/QtScript.framework/Versions/4/QtScript
    /Contents/Frameworks/QtSql.framework/Versions/4/QtSql
    /Contents/Frameworks/QtWebkit.framework/Versions/4/QtWebkit
    /Contents/Plugins/accessible/libqtaccessiblewidgets.dylib
    /Contents/Plugins/bearer/libqcorewlanbearer.dylib
    /Contents/Plugins/bearer/libqgenericbearer.dylib
    /Contents/Plugins/codecs/libqcncodecs.dylib
    /Contents/Plugins/codecs/libqjpcodecs.dylib
    /Contents/Plugins/codecs/libqkrcodecs.dylib
    /Contents/Plugins/codecs/libqtwcodecs.dylib
    /Contents/Plugins/imageformats/libqgif.dylib
    /Contents/Plugins/imageformats/libqico.dylib
    /Contents/Plugins/imageformats/libqjpeg.dylib
    /Contents/Plugins/imageformats/libqmng.dylib
    /Contents/Plugins/imageformats/libqtiff.dylib
    /Contents/Plugins/qmltooling/libqmldbg_tcp.dylib
    /Contents/Plugins/graphicssystems/libqtracegraphicssystem.dylib

    codesign -f -s "3rd Party Mac Developer Application" "/Projects/hearts/qt/qthearts-build-desktop-Desktop_Qt_4_7_4_for_GCC__Qt_SDK__Release/Hearts Card Game.app"

    I had to change the name of my app after it was rejected from the app store. That caused my codesign to break. So:
    (Possible Error: codesign object file format invalid or unsuitable
    Make sure the 'Executable Name' (CFBundleExecutable) entry in your target's info.plist matches the 'Product Name' specified in your target settings.)

  • Step 6: package your app.
    Next package your app using productbuild. Note that I used the Developer Installer certificate here, and I did not use the --product option.
    cd /Developer/usr/bin
    ./productbuild --component "/Projects/hearts/qt/qthearts-build-desktop-Desktop_Qt_4_7_4_for_GCC__Qt_SDK__Release/Hearts Card Game.app" /Applications --sign "3rd Party Mac Developer Installer" "/Users/david/Desktop/Hearts Card Game.pkg"

    (Possible Error: productutil was missing for some reason. Link it in to where it actually exists. Application loader gives this error: "the productutil binary must exist and must be executable.")
    cd /usr/libexec
    sudo ln -s /Developer/user/libexec/productutil productutil

  • Step 7: Submit app.
    Use the Application Loader app to submit the .pkg to Apple.
    /Developer/Applications/Utilities/Application Loader.app

  • Step 8: Complete!
    Hearts
Developing A QtCreator App for the Ubuntu Linux App Store
12/10/2011

Here are the steps that it took me to deploy an app using QtCreator for the Linux Ubuntu App Store. Here are some notes that I took while resolving some obscure errors. Note that I did a lot of reading on documentation and I'm not even entirely sure of the correct way to do things, but this is what I came up with:

  • Step 1: Qt Installer hangs.
    Yep, very first step dies. Run the installer from the command line using cleanlooks style:

    SDK_Lin32_offline_v1_1_3_en.run -style cleanlooks

    This is the error in the terminal of the hung process, for reference:
    (Qt_SDK_Lin32_offline_v1_1_3_en.run:3126): Gtk-CRITICAL **: IA__gtk_widget_style_get: assertion `GTK_IS_WIDGET (widget)' failed

  • Step 2: Install the code and create static libraries
    Run the tool /home/david/QtSDK/QtSources/SDKMaintenenceTool. Select Package Manager. Select Continue, then make sure Qt SDK->Miscellaneous->Qt Sources->Qt 4.7.4 Source is selected and continue to install in the default location.

    To deploy, Qt should be compiled as a static library. I don't know if this is entirely accurate, but I am going off http://doc.qt.nokia.com/latest/deployment-x11.html. Note that I use webkit. Cd to the source dir /home/david/QtSDK/QtSources/4.7.4/ and run the configure.
    Special flags include -static, -prefix to make sure we are using the correct dir, -webkit, and -no-xrandr. The rest of -no-* were added to reduce size.

    // make a static library including webkit - no xrandr
    make confclean
    ./configure -static -prefix /home/david/QtSDK/QtSources/4.7.4 -no-qt3support -no-xmlpatterns -no-phonon -no-phonon-backend -no-svg -no-scripttools -no-openssl -no-declarative -no-xrandr -webkit
    make sub-src

    Make sure make is with sub-src. Also no need to make install on linux.

  • Step 3: My app crashed with the same problem as the QtInstaller, so I had to set the app itself to cleanlooks.
    In my main source file,

    // on ubuntu unity we crash so just set style to cleanlooks
    QApplication::setStyle("cleanlooks");

  • Step 4: Build app
    Things aren't exactly clear here, but these are the steps I use to build my app. Deploying on X11.
    // cd to Hearts.pro dir
    make clean
    PATH=/home/david/QtSDK/QtSources/4.7.4/bin:$PATH
    export PATH
    qmake -config release
    make

    Make sure no qt libraries are linked in. You can use this by using
    ldd "app name" to check the output and see what libraries are linked in. If it shows the path to your qt sources in there, you didn't build the static library properly.

    (Possible error:
    /usr/bin/ld: cannot find -ljscore
    collect2: ld returned 1 exit status

    // solution is to copy them from where-ever you find them to the libs dir
    cd /
    sudo find . | grep libjscore
    cp /home/david/QtSDK/QtSources/4.7.4/src/3rdparty/webkit/JavaScriptCore/release/libjscore.a /home/david/QtSDK/QtSources/4.7.4/lib
    cp /home/david/QtSDK/QtSources/4.7.4/src/3rdparty/webkit/JavaScriptCore/release/libjscore.prl /home/david/QtSDK/QtSources/4.7.4/lib
    )

    (Possible error for QT 4.8.0:
    /usr/bin/ld: cannot find -lwebcore (also see similar ljscore above)
    collect2: ld returned 1 exit status

    cp /home/david/QtSDK/QtSources/4.8.0/src/3rdparty/webkit/Source/WebCore/release/webcore.a /home/david/QtSDK/QtSources/4.8.0/lib
    cp /home/david/QtSDK/QtSources/4.8.0/src/3rdparty/webkit/Source/WebCore/release/webcore.prl /home/david/QtSDK/QtSources/4.8.0/lib
    )

  • Step 6: Submit to Ubuntu App Store
    Despite the fact that the FAQ asks this explicit question What am I expected to upload when submitting an app through the developer portal? I find their answer very unclear.

    What I have is a single executable from the above steps, Hearts. I tar that up and upload that.
    tar czf hearts.tar.gz Hearts

  • Step 6: Complete!
    Hearts.

© David Skelly