Deploying to Linux with CMake
December 22, 2022 by Jörg Bornemann | Comments
A while ago, I blogged about our CMake deployment API that allows you to enhance the cmake --install
step with instructions that deploy Qt libraries, plugins and assets. At the time of writing, Linux was not supported yet. But not anymore: Qt 6.5 comes with deployment support for Linux!
Quick recap how it looks like to deploy a simple Qt application. Consider the following project.
cmake_minimum_required(VERSION 3.22)
project(MyApp)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()
qt_add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE Qt::Widgets)
Now, we install the application and enhance the installation step. Our goal is to have a (mostly) self-contained directory after installation.
# Install the executable into "${CMAKE_INSTALL_PREFIX}/bin".
install(TARGETS MyApp
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
# Generate the deployment script for the target MyApp.
qt_generate_deploy_app_script(
TARGET MyApp
FILENAME_VARIABLE deploy_script
NO_UNSUPPORTED_PLATFORM_ERROR
)
# Call the deployment script on "cmake --install".
install(SCRIPT ${deploy_script})
We build and install the project:
$ qt-cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/tmp/my-application ..
[output omitted]
$ cmake --build .
[output omitted]
$ cmake --install .
-- Install configuration: "Release"
-- Installing: /tmp/my-application/bin/myapp
-- Set runtime path of "/tmp/my-application/bin/myapp" to "$ORIGIN:$ORIGIN/../lib"
-- Writing /tmp/my-application/bin/qt.conf
-- Running generic Qt deploy tool on /home/someone/playground/myapp/build/myapp
-- Installing: /tmp/my-application/lib/libQt6Core.so.6
-- Installing: /tmp/my-application/lib/libQt6Core.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6DBus.so.6
-- Installing: /tmp/my-application/lib/libQt6DBus.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6EglFSDeviceIntegration.so.6
-- Installing: /tmp/my-application/lib/libQt6EglFSDeviceIntegration.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6EglFsKmsSupport.so.6
-- Installing: /tmp/my-application/lib/libQt6EglFsKmsSupport.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6Gui.so.6
-- Installing: /tmp/my-application/lib/libQt6Gui.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6OpenGL.so.6
-- Installing: /tmp/my-application/lib/libQt6OpenGL.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6Widgets.so.6
-- Installing: /tmp/my-application/lib/libQt6Widgets.so.6.6.0
-- Installing: /tmp/my-application/lib/libQt6XcbQpa.so.6
-- Installing: /tmp/my-application/lib/libQt6XcbQpa.so.6.6.0
-- Installing: /tmp/my-application/plugins/egldeviceintegrations/libqeglfs-emu-integrat...
-- Installing: /tmp/my-application/plugins/egldeviceintegrations/libqeglfs-kms-egldevic...
-- Installing: /tmp/my-application/plugins/egldeviceintegrations/libqeglfs-x11-integrat...
-- Installing: /tmp/my-application/plugins/imageformats/libqgif.so
-- Installing: /tmp/my-application/plugins/imageformats/libqico.so
-- Installing: /tmp/my-application/plugins/imageformats/libqjpeg.so
-- Installing: /tmp/my-application/plugins/xcbglintegrations/libqxcb-egl-integration.so
-- Installing: /tmp/my-application/plugins/xcbglintegrations/libqxcb-glx-integration.so
-- Installing: /tmp/my-application/plugins/platforms/libqxcb.so
After the myapp
executable is installed into /tmp/my-application/bin/
, the deployment script handles the following tasks:
- Create a
qt.conf
file next to the executable that contains information about the directory layout. This is needed at runtime to find the plugins and assets. See the qt.conf documentation for details. - Inspect the executable and used Qt plugins with CMake's built-in file(GET_RUNTIME_DEPENDENCIES) to determine which Qt libraries to deploy.
- Install the necessary Qt plugins and Qt libraries.
The installation directory can now be copied to a different machine, and the application should still work.
Packaging the installation folder
After installation, we have a nice self-contained directory that can be packaged and shipped. For the sake of example, we'll create a .deb
package using cpack
.
Add the following at the end of the project file:
set(CPACK_PACKAGE_NAME my-app)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My amazing application")
set(CPACK_PACKAGE_VENDOR "My Company")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_VERBATIM_VARIABLES ON)
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/myapp")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Manfred Maintainer <mm@example.com>")
set(CPACK_DEBIAN_PACKAGE_DEPENDS libc6 libstdc++6 libgcc-s1)
include(CPack)
Re-configure the project and run cpack
:
$ cpack -G DEB
CPack: Create package using DEB
CPack: Install projects
CPack: - Install project: MyApp []
CPack: Create package
CPack: - package: /home/someone/projects/myapp/build/my_app-1.0-Linux.deb generated.
That's already it. The package has been wrapped and is ready to be shipped.
You can inspect the content of the package with dpkg -c my_app-1.0-Linux.deb
and install with
.
sudo dpkg -i my_app-1.0-Linux.deb
Summary
We have seen how to deploy a simple Qt application on Linux using Qt 6.5's CMake deployment API. There's no dedicated linuxdeployqt tool. The current solution wholly relies on CMake's built-in functionality.
These are the platforms that are covered by Qt's CMake deployment API:
- Windows
- macOS
- Linux
For Android and iOS there's still the need to call androiddeployqt / macdeployqt manually - or you let Qt Creator handle these details.
The relocatable installation folder can be conveniently wrapped into a package using tools like cpack
.
Please report any issues you find while playing with this at our bug tracker.
Blog Topics:
Comments
Subscribe to our newsletter
Subscribe Newsletter
Try Qt 6.8 Now!
Download the latest release here: www.qt.io/download.
Qt 6.8 release focuses on technology trends like spatial computing & XR, complex data visualization in 2D & 3D, and ARM-based development for desktop.
We're Hiring
Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.