Deploying desktop applications on a Mac, for us Linux guys, can be strange. I didn't even know what the final deliverable file was.

Well, that file is the DMG, or Apple Disk Image.

To create the DMG, you first need to create an intermediate result, the App Bundle.

I assume you're using Scons as your build system. If you're not, which admittedly is quite likely, then go and read another post.

To create the App Bundle you can use an Scons tool from a long time ago which doesn't seem to have a real home at the moment. It'd be a good project to try to rehabilitate this.

In the meantime, I've created a Gist that contains the code for that. Download it and put it in the same directory as your SConstruct.

To use it, you have to bear in mind that it's going to overwrite your environment quite heavily. So I suggest using a totally new environment for it.

Your final SConstruct is going to look something like this:

# SConstruct

import os
from osxbundle import TOOL_BUNDLE

def configure_qt():
    qt5_dir = os.environ.get('QT5_DIR', "/usr")

    env = Environment(
        tools=['default', 'qt5'],
        QT5DIR=qt5_dir
    )
    env['QT5_DEBUG'] = 1
    maybe_pkg_config_path = os.environ.get('PKG_CONFIG_PATH')
    if maybe_pkg_config_path:
        env['ENV']['PKG_CONFIG_PATH'] = maybe_pkg_config_path

    env.Append(CCFLAGS=['-fPIC', '-std=c++11'])
    env.EnableQt5Modules(['QtCore', 'QtWidgets', 'QtNetwork'])

    return env

# A Qt5 env is used to build the program...
env = configure_qt()
env.Program('application', source=['application.cc'])

# ... but a different env is needed in order to bundle it.
bundle_env = Environment()
TOOL_BUNDLE(bundle_env)

bundledir = "the_bundle.app"
app = "application"   # The output object?
key = "foobar"
info_plist = "info_plist.xml"
typecode = 'APPL'

bundle_env.MakeBundle(bundledir, app, key, info_plist, typecode=typecode)

As an explanation of these arguments, bundledir is the output directory, which must always end in .app. app is the name of your executable program (the result of compiling the C++ main function). key is unclear, some other context suggests that it's used for a Java-style reversed domain organization identifier, such as net.solasistim.myapplication.

You can also provide icon_file (a path) and resources (a list) which are then folded into the /Contents/Resources path inside the .app.

Once you've got your .app you now need to create a DMG file. Like this.

$ macdeployqt the_bundle.app -dmg

You should now find the_bundle.dmg floating in your current directory. Nice.