End to End GUI Development with Qt5
上QQ阅读APP看书,第一时间看更新

Windows

First, build the solution using the kit of your choice in the Release mode. Once complete, copy the cm-ui.exe and cm-lib.dll application binaries to a new cm/installer/windows/packages/com.packtpub.cm/data directory. This strange directory structure will be explained in the next section—Qt Installer Framework—and we are simply saving ourselves some additional copying later.

Next, let’s remind ourselves of the dependencies we need to consider:

  • Item 1: Custom libraries we’ve written or added to our solution manually (cm-lib)
  • Item 2: The parts of the Qt framework that our application links to
  • Item 3: Any internal dependencies of the Qt framework itself
  • Item 4: Any libraries required by the C++ compiler we have built the application with

The good news is that item 1 is already done! Windows will look for the dependencies of an executable in the same folder that the executable is in. This is really helpful and by simply copying the DLL to the same folder as the executable, we’ve already taken care of that dependency. The Qt Installer framework takes all the files from a given folder and deploys them to the target machine in the same place relative to each other, so we know this will be preserved after deployment too.

The bad news is that the remaining steps are a bit of a nightmare to manage manually. We can have a decent first stab at what parts of Qt we need by reviewing the modules we’ve explicitly added to our *.pro files. This will be qml, quick, and xml from cm-ui and sql, and network and xml from cm-lib core is also included by default. In File Explorer, navigate to <Qt Installation Folder>/5.9.1/<Kit>/bin. In there, you can find all the binaries relating to these modules, for example, Qt5Qml.dll for the qml module.

We can use the approach that we did for cm-lib.dll and simply manually copy each of the Qt DLL files across to the data folder too. This will fulfil item 2 and while deeply tedious, it’s fairly straightforward. However, item 3 is a painful exercise that we really don’t want to do ourselves.

Fortunately, the windeployqt Qt Windows Deployment Tool is just what we need here. It scans an .exe file for Qt dependencies and copies them across to our installer folder for us. The tool is located in the bin folder of the installed kit you have built the application with, for example, /Qt/5.9.1/mingw32/bin.

In a command terminal, execute windeployqt as follows:

$ <Path to bin>/windeployqt.exe --qmldir <Qt Projects>/cm/cm-ui <Qt Projects>/cm/installer/windows/packages/com.packtpub.cm/data/cm-ui.exe --compiler-runtime

Remember to replace the parameters in angle brackets with the full paths on your system (or add the executable paths to your system PATH variable).

The qmldir flag tells the tool where to scan for QML imports and is set to our UI project folder. After we tell the tool which .exe to scan for dependencies, the compiler-runtime flag denotes that we want the compiler runtime files too, so it even takes care of item 4 for us as a bonus!

By default, found dependencies will subsequently be copied to the same folder as the executable being scanned. This is a good reason to copy the compiled binaries to a dedicated installer folder first so that development project output and content for deployment remain separate.

Once executed, you should see a large block of output. Although it’s tempting to think “oh, that’s done stuff so everything must be ok”, it’s a good idea to scan through the output, even if you’re not sure what it’s doing as you can sometimes pick up obvious issues that you can can take action to resolve.

For example, when first deploying a MinGW kit build, I encountered the given line:

Warning: Cannot find GCC installation directory. g++.exe must be in the path.

Although the command had executed successfully, and I can see a whole bunch of Qt dependencies in the installer folder, I was actually missing the GCC dependencies. It was a simple fix to follow the instructions and add <Qt Installation path>/Tools/mingw530_32/bin to the PATH variable in my system environment variables. After restarting the command terminal and running the windeployqt command again, it subsequently completed successfully without the warning, and the GCC files were present as expected in data alongside all the Qt binaries. Without picking up on this quiet little warning, I would have proceeded with some potentially critical missing files.

As you can see, windeployqt is a huge time saver, but unfortunately, it isn’t a silver bullet and sometimes misses the required files. Tools like Dependency Walker exist, which can help analyze the dependency tree in detail, but a good starting point is to just manually launch the cm-ui executable from the data folder and see what happens. In our case, it is this:

The bad news is that it doesn’t work, but the good news is that at least it clearly tells us why it doesn’t work—it is missing the Qt5Sql.dll dependency. We know that we do indeed have a dependency there, because we had to add the sql module to our .pro files when we started doing database work. However, wait, we’ve just executed a command that should pull in all the Qt dependencies for us, right? Right, I don’t know why the tool misses out some dependencies that it really should know about, but it does. I don’t know if it’s a bug, an oversight, or a licensing restriction related to the underlying third-party SQLite implementation, but in any case, the simple solution is that we just need to copy it ourselves.

Head over to <Qt Installation>/5.9.1/<kit>/bin and copy Qt5Sql.dll over to our data folder. Launch the cm-ui.exe again and hurrah, it opens successfully!

One other thing to look out for apart from missing .dll files from the bin directory is missing files/folders from the plugins directory. You will see in our case that several folders have been copied successfully (bearer, iconengines, and such), but sometimes they don’t, and can be very difficult to figure out as you don’t get a helpful error message like we did with the missing DLL. I can only recommend three things in that situation: trial, error, and the internet.

So, we now have a folder containing our lovely application binaries and a whole bunch of similarly lovely other files and folders. What now? Well, we can simply copy the folder wholesale onto our users' machines and get them to launch the executable as we did. However, a neater and more professional solution is to bundle up everything into a pretty installation package, and that is where the Qt Installer Framework tool comes in.