This upcoming webinar will explore functions that assist developers in both packaging and deploying their Qt applications on the desktop. We will present the Qt Installer Framework and the Qt Desktop deployment tools as well as ways to customize an installer and tools that keep your Qt application continuously updated online.
We will also expand on the subject with a concrete example and illustrate the ease of use of CPack, presenting common tricks to debug, customize both an offline and online installer, ensure that we provide an adequate uninstaller and write to Windows Registry.
2. www.ics.com
About ICS
Delivering Smart Devices for a Connected World
● Founded in 1987
● Largest source of independent Qt expertise in North America
● Trusted Qt Service Partner since 2002
● Exclusive Open Enrollment Training Partner in North America
● Provides integrated custom software development and user experience (UX) design
● Embedded, touchscreen, mobile and desktop applications
● HQ in Waltham, MA with offices in California, Canada, Europe
Boston UX
● Part of the ICS family, focusing on UX design
● Designs intuitive touchscreen interfaces for high-impact embedded
and connected medical, industrial and consumer devices
2
3. www.ics.com
What is the Qt Installer Framework?
● A set of tools to create installers on Linux, Windows and Mac.
● Installers can be offline and online
● The program binarycreator creates the installer
● If the installer is online, the pgm repogen generates a repository folder to be
uploaded to an http server
● Qt Installer Framework is distributed through Qt’s own installer in the tools
section.
3
5. www.ics.com
● CPack is a packaging system for software distributions integrated with CMake;
● Linux RPM, deb, Windows MSI and more..
● For each packaging format, CPack has a generator
● CPack DEB Generator
● CPack DragNDrop Generator
● CPack External Generator
● CPack FreeBSD Generator
● CPack IFW Generator
● CPack NSIS Generator
● CPack RPM Generator
● The IFW generator is the one that uses the Qt Installer Framework
● Set in the CMakeLists.txt
Starting Point: CPack
set(CPACK_GENERATOR "IFW")
5
6. www.ics.com
Before Starting
6
● Set the following variables in the CMakeLists.txt file
● Commands to configure, build and package (invoking CPack)
cmake.exe -S. -Bbuild -DCPACK_IFW_ROOT=C:/Qt/Tools/QtInstallerFramework/4.2
cmake.exe --build <PROJECTBUILDDIR> --target all package
set(CPACK_PACKAGE_NAME "Example-Utility")
set(CPACK_GENERATOR "IFW")
if(NOT CPACK_IFW_ROOT)
set(CPACK_IFW_ROOT "C:/Qt/Tools/QtInstallerFramework/4.2")
endif()
7. www.ics.com
install(TARGETS ${BIN_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${COMPONENT_NAME_MAIN})
● CPack will bundle into the install the components specified with the CMake
install directive
● The component can have a description and can be further configured with the
following commands
Specifying the CMake project to create an installer
7
cpack_add_component(${COMPONENT_NAME_MAIN})
cpack_ifw_configure_component(${COMPONENT_NAME_MAIN}
VERSION ${CMAKE_PROJECT_VERSION}
SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/installscript.qs)
8. www.ics.com
Some CPACK_IFW variables that can be set
All these variables map to a config element provided by the Qt Installer
Framework and specified here:
https://doc.qt.io/qtinstallerframework/ifw-globalconfig.html
Customize the installer
#set(CPACK_IFW_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/Example.ico")
set(CPACK_IFW_TARGET_DIRECTORY "@ApplicationsDir@/Example-Utility")
#set(CPACK_PACKAGE_FILE_NAME "GreatInstallerName" )
set (CPACK_IFW_PACKAGE_NAME "Example Utility")
set (CPACK_IFW_PACKAGE_TITLE "Example-Utility Title ${CMAKE_PROJECT_VERSION}")
set (CPACK_IFW_PACKAGE_PUBLISHER "Example Company")
set (CPACK_IFW_PACKAGE_WIZARD_STYLE "Aero")
set (CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST OFF)
set (CPACK_IFW_PACKAGE_CONTROL_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/controller.qs)
8
9. www.ics.com
Controller scripting allows:
● Thee modification of the some of the properties of the installer’s page
● The removal of some the installer’s page
● Simulate Button Clicks to control the flow of pages
Further Customization with Controller Scripting
9
function Controller()
{ console.log("-----------This is the entry point---------------")
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.installationFinished.connect(this, this.installationFinished);
console.log("------------------------------")
}
Controller.prototype.installationFinished = function()
{ gui.clickButton(buttons.FinishButton);
}
Controller.prototype.IntroductionPageCallback = function()
{ var widget = gui.currentPageWidget(); // get the current wizard page
widget.MessageLabel.setText("Hey how's it going."); // set the welcome text
}
11. www.ics.com
Further Customization with Scripting
Some good documentation and tutorial:
https://doc.qt.io/qtinstallerframework/noninteractive.html
Use the examples provided by the Qt Installer Framework
https://doc.qt.io/qtinstallerframework/qtifwexamples.html
Qt Installer Framework Examples are located:
<QTDIR>ToolsQtInstallerFramework4.4examples
11
12. www.ics.com
Further Customization with Component
● In the CMakeLists.txt the command cpack_ifw_configure_component allows for
can specify how the component is installed as well as changes to the UI
● Every option of this command is mapped to an element of the package.xml
specified here
https://doc.qt.io/qtinstallerframework/ifw-component-description.html#summary-of-package-information-file-elements
● As an example
In the CMakeLists.txt,
cpack_ifw_configure_component([LICENSES <display_name> <file_path> ...] ..)
maps to
<Licenses>
<License name="License Agreement" file="license.txt" />
</Licenses>
12
13. www.ics.com
Further Customization with Component Scripting
13
cpack_ifw_configure_component(${COMPONENT_NAME_MAIN}
VERSION ${CMAKE_PROJECT_VERSION}
SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/installscript.qs)
● One of those options is SCRIPT that specifies a component script
● This allows further customization on modifying how the component is
installed as well as adding pages to the installer
● Uses the same API as controller scripting
14. www.ics.com
Further Customization with Component Scripting
● Reimplementation of the createOperations function allows to modify
how the component is installed
● Possible operations are listed here
https://doc.qt.io/qtinstallerframework/operations.html#summary-of-operations
14
Component.prototype.createOperations = function () {
// call default implementation
component.createOperations();
var targetDirectory = installer.value("TargetDir");
var windowsTargetDir = targetDirectory.replace(///g,'')
component.addOperation("GlobalConfig",
"HKEY_CLASSES_ROOTDirectoryBackgroundshell",
"Example",
""); …
15. www.ics.com
Adding Pages to the Installer
● Using Qt Designer create a ui file specify the ui of the page
● The cpack_ifw_configure_component command has the option
cpack_ifw_configure_component(...[USER_INTERFACES <file_path> <file_path> ...] )
● In the component script
15
cpack_ifw_configure_component(...USER_INTERFACES target.ui… )
Component.prototype.installerLoaded = function () {
if (installer.addWizardPage(component, "TargetWidget", QInstaller.TargetDirectory)) {
var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
if (widget != null) {
widget.targetChooser.clicked.connect(this, Component.prototype.chooseTarget);
widget.targetDirectory.textChanged.connect(this, Component.prototype.targetChanged);
widget.targetDirectory.text = Dir.toNativeSparator(installer.value("TargetDir"));
}
}
16. www.ics.com
Some Debugging tips
● Run the installer with -d or --verbose option
● The console.log() command will display debugging information
16
function Component() {
console.log("-----------This is the entry point for Component Scripting---------------")
console.log( component.value("Version") )
}
17. www.ics.com
Deployment Issues
17
set(WINDEPLOYQT "@WINDEPLOYQT@")
set(COMPONENT_NAME_MAIN "@COMPONENT_NAME_MAIN@")
set(CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@")
execute_process(COMMAND ${WINDEPLOYQT} --no-translations --no-opengl-sw --no-svg --no-system-d3d-compiler
--no-quick-import ${COMPONENT_NAME_MAIN}/data/bin WORKING_DIRECTORY
${CPACK_TEMPORARY_INSTALL_DIRECTORY}/packages)
● An installed application linking with Qt needs the Qt dependencies to run
● For Qt, windeployqt (distributed with Qt in the bin folder) can help as it creates
a deployable folder with the Qt dependencies.
● With CPack this means to create deploy-qt-windows.cmake.in file with the following
● The CMakeLists.txt
set (CPACK_IFW_PACKAGE_CONTROL_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/controller.qs)
find_program(WINDEPLOYQT windeployqt HINTS "${_qt_bin_dir}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/deploy-qt-windows.cmake.in"
"${CMAKE_CURRENT_SOURCE_DIR}/deploy-qt-windows.cmake" @ONLY)
set(CPACK_PRE_BUILD_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/deploy-qt-windows.cmake)