> ## Content Index
> Fetch the complete content index at: https://www.smallstepsystems.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Benefits of a Relocatable Qt
- URL: https://www.smallstepsystems.com/benefits-of-a-relocatable-qt/
- Published: 2020-02-23T14:17:22.000Z
- Updated: 2026-01-25T13:33:06.000Z
- Author: Burkhard Stubert

Bob builds Qt for the development team on a fast compute server. He packs Qt into a tarball and hands the tarball to his teammates. Alice installs the Qt tarball on her PC in a directory that differs from the installation directory used by Bob. As the target embedded system runs on an AMD Ryzen SoC with x86\_64 architecture like the build server and the development PC, Alice installs Qt on the target system - yet in another directory. She can then try out the latest changes of her app directly on the target system. As [Qt is relocatable](https://www.qt.io/blog/qt-is-relocatable?ref=smallstepsystems.com) since version 5.14, Alice's and Bob's jobs have become quite a bit easier.

## Building Qt on a Compute Server

Bob builds Qt 5.14 on a fast compute server running Ubuntu 16.04 on an Intel x86\_64 CPU. As the target system runs Ubuntu 18.04 on an AMD Ryzen CPU with x86\_64 architecture, he uses Docker for the build.

Bob builds a Docker container based on Ubuntu 18.04 (see my post [Using Docker Containers for Yocto Builds](https://www.smallstepsystems.com/using-docker-containers-for-yocto-builds/) for how to install Docker and how to create a suitable *Dockerfile*). Bob creates a working directory, say */public/Work/RelocatableQt*, on the compute server and downloads the *Dockerfile*.

```
$ mkdir -p /public/Work/RelocatableQt
$ cd /public/Work/RelocatableQt
$ wget https://raw.githubusercontent.com/bstubert/embeddeduse/master/BlogPosts/RelocatableQt/Dockerfile
```

Bob builds the container with the command

```
$ docker build --no-cache --tag "qt-ubuntu-18.04-ryzen" .
```

Bob downloads the source tarball of Qt 5.14.1 and unpacks it in the work directory.

```
$ wget http://download.qt.io/official_releases/qt/5.14/5.14.1/single/qt-everywhere-src-5.14.1.tar.xz
$ tar xf qt-everywhere-src-5.14.1.tar.xz
```

The source tarball is unpacked into the sub-directory *qt-everywhere-src-5.14.1*. Bob is ready to run the container, in which he will build Qt 5.14.1 from sources.

```
$ docker run -it --rm -v $PWD:/RelocatableQt qt-ubuntu-18.04-ryzen
```

The contents of the host work directory */public/Work/RelocatableQt* are visible in the container at the location */RelocatableQt*. The *bash* prompt inside the container is denoted by `@`.

Bob performs a shadow build of Qt in the container.

```
@ mkdir build-qt-5.14.1
@ cd build-qt-5.14.1
@ ../qt-everywhere-src-5.14.1/configure \
      -opensource -confirm-license -release -strip \
      -feature-relocatable -prefix /RelocatableQt/qt-5.14.1 \
      -qt-xcb -qpa xcb -icu -no-gstreamer -rpath \
      -no-libudev -no-xcb-xinput -nomake examples -nomake tests -v \
      -skip qtcharts -skip qtgamepad -skip qtlottie -skip qtwayland \
      -skip qt3d -skip qtspeech -skip qtlocation -skip qtpurchasing \
      -skip virtualkeyboard -skip qtwebengine -skip qtwebchannel \
      -skip qtwebglplugin -skip qtwebsockets -skip qtwebview
@ make -j 32
@ make install
```

The option `-feature-relocatable` enables the relocation of Qt. The option is enabled on Linux by default. The command `configure -list-features` lists the feature as

```
relocatable ............. Enable the Qt installation to be relocated.
```

(Note: I couldn't find this entry in the configure log of Qt 5.14.1\. A reader of my newsletter, Pablo Rogina, confirmed that the entry shows up in the log of Qt 5.14.2\. Thanks, Pablo ????)

The build installs Qt in the directory */RelocatableQt/qt-5.14.1* as given by the option `-prefix`. For other development PCs and target systems, Bob will build a different set of Qt modules.

Back on the host system, Bob packs Qt into the tarball *qt-5.14.1-ubuntu-18.04-ryzen.tgz* and hands this tarball over to Alice.

```
$ cd /public/Work/RelocatableQt
$ tar czf qt-5.14.1-ubuntu-18.04-ryzen.tgz qt-5.14.1
```

When Bob automates the Qt build, he will move the commands for downloading the Qt source tarball and for building Qt into the *Dockerfile*. Then, Qt is built when the container is built. The resulting container could be the basis for automated builds of Qt applications.

## Relocating Qt to Developers' PCs

Alice has set up a PC running Ubuntu 18.04 on an Intel x86\_64 CPU. She has installed the same packages as given in Bob's *Dockerfile* and probably some more. Alice has cloned the project repository into *\~/Work*. She works on the application in the directory *\~/Work/embeddeduse/BlogPosts/RelocatableQt*.

```
$ mkdir ~/Work
$ cd ~/Work
$ git clone https://github.com/bstubert/embeddeduse.git
```

Alice unpacks the tarball from Bob in the directory *\~/Qt*.

```
$ mkdir ~/Qt
$ cd ~/Qt
$ tar xf /media/alice/usb5/qt-5.14.1-ubuntu-18.04-ryzen.tgz
```

Alice's installation path */home/alice/Qt/qt-5.14.1* is totally different to Bob's installation path */RelocatableQt/qt-5.14.1*. This doesn't matter any more, because Qt is relocatable.

In QtCreator, Alice opens the dialog *Tools > Options > Qt Versions*. She presses the button *Add...* and selects the executable */home/alice/Qt/qt-5.14.1/bin/qmake*. She calls the Qt version *Relocatable Qt 5.14.1*. On the neighbouring dialog *Tools > Options > Kits*, she selects *Relocatable Qt 5.14.1* for the field *Qt version*.

When Alice opens the project *\~/Work/embeddeduse/BlogPosts/RelocatableQt*/CMakeLists.txt for the first time, QtCreator asks her to configure the project. She selects the kit *Relocatable Qt 5.14.1*. When she has configured the project with another Qt version before, she goes to *Projects > Build & Run > Build Settings* and selects the kit *Relocatable Qt 5.14.1* there. She switches from the old kit to the new one. She can now build and run the application *SimpleApp*.

Alice need not specify an `*LD_LIBRARY_PATH*` when running the application. CMake automatically adds the path `*/home/alice/Qt/qt-5.14.1/lib*` as a run-time link path.

Relocating a version older than Qt 5.14 fails. If Alice added qmake from an older version, QtCreator would flag this Qt version with a white exclamation mark on a red circle and with the error *Invalid Qt version*. CMake would emit the error message Cannot read */RelocatableQt/qt-5.12.7/mkdspecs/linux-g++/qmake.conf: No such file or directory*.

## Relocating Qt to the Target System

Alice wants to try out her changes on the target system, which is a Ubuntu 18.04 system running on an AMD Ryzen SoC with x86\_64 architecture. The directory structure on the target system looks like this, where *kea* is the company or project name.

```
/home/user/kea
    bin
        SimpleApp
    qt
        lib
        phrasebooks
        plugins
        qml
        translations
```

The other Qt subdirectories *bin*, *doc*, *include* and *mkspecs* are only required for building the application. They need not be deployed to the target system.

Alice adds the following installation commands to *CMakeLists.txt* \- after the `add_executable` command.

```
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/../staging/kea)

install(TARGETS ${PROJECT_NAME} RUNTIME
    DESTINATION bin)

set(qt_base_dir ${Qt5Core_DIR}/../../..)
install(DIRECTORY ${qt_base_dir}/lib ${qt_base_dir}/phrasebooks
    ${qt_base_dir}/plugins ${qt_base_dir}/qml 
    ${qt_base_dir}/translations
    DESTINATION qt USE_SOURCE_PERMISSIONS)
```

The `install` commands install files and directories relative to *${`CMAKE_INSTALL_PREFIX`}*, which evaluates to *\~/Work/embeddeduse/BlogPosts/staging/kea*. The first `install` copies the executable from the build directory to *${CMAKE\_INSTALL\_PREFIX}/bin*. The second `install` copies the directory trees starting at */home/alice/Qt/qt-5.14.1/lib*, */home/alice/Qt/qt-5.14.1/plugins* and so on to *${CMAKE\_INSTALL\_PREFIX}/qt/lib*, *${CMAKE\_INSTALL\_PREFIX}/qt/plugins* and so on, respectively. The staging directory structure below *${CMAKE\_INSTALL\_PREFIX}* looks the same as the target directory structure below */home/user/kea*.

It is important that the *DESTINATION* directories in the `install` commands are relative (here: *bin* and *qt*). Absolute destination directories don't work.

The above `install` commands are only executed, if the *install* target is built. Alice goes to the page *Projects > Build & Run > Build Settings*. She clones the *Release* configuration and renames it into *Final Release*. She clicks on the button *Add Build Step > Build* and checks *install* in the *Targets* list. Then she builds the application. The staged files and directories can be found in *\~/Work/embeddeduse/BlogPosts/staging/kea*.

When Alice looks at the link command, she notices that the run-time link path still points to the Qt location on her PC */home/alice/Qt/qt-5.14.1* and not to the Qt location on the target system */home/user/kea/qt/lib*. So, the application wouldn't run on the target system without setting the *LD\_LIBRARY\_PATH*. Fortunately, Alice knows how to set the CMake variables related to *rpath*. These four `set` commands must be placed before `add_executable`. Otherwise, they have no effect.

```
set(CMAKE_SKIP_BUILD_RPATH true)
set(CMAKE_BUILD_WITH_INSTALL_RPATH false)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH false)
set(CMAKE_INSTALL_RPATH /home/user/kea/qt/lib)
```

If *CMAKE\_SKIP\_BUILD\_RPATH* is set to true, the linker doesn't add the buid rpath (here: */home/alice/Qt/qt-5.14.1/lib*). As the directory structure for the build and installation differ, the variables *CMAKE\_BUILD\_WITH\_INSTALL\_RPATH* and *CMAKE\_INSTALL\_RPATH\_USE\_LINK\_PATH* must be set to false. The variable *CMAKE\_INSTALL\_RPATH* specifies the run-time paths used by the executable when it is run on the target system.

The linker doesn't write the run-time path into the executable. Instead, it reserves enough space in the executable with the option `-Wl,-rpath,:::::::`. The *install* step replaces the colons in the executable with the actual run-time path (here: */home/user/kea/qt/lib*).

Alice packs the directory structure below kea into a tarball.

```
$ cd ~/Work/embeddeduse/BlogPosts/staging
$ tar czf kea.tgz kea
```

She copies the tarball *kea.tgz* onto the target system and unpacks it there.

```
# cd /home/user
# tar xf kea.tgz
```

Finally, Alice runs her QML application on the target system.

```
# DISPLAY=:0 ./SimpleApp -platform xcb -plugin evdevtouch
```

## Also Interesting

The trigger for my post was the official announcement by The Qt Company that [Qt is relocatable](https://www.qt.io/blog/qt-is-relocatable?ref=smallstepsystems.com) from version 5.14\. Before Qt 5.14, your best chance to relocate Qt seemed to be [qt.conf](https://doc.qt.io/qt-5/qt-conf.html?ref=smallstepsystems.com). As I haven't tried it, I don't know whether this works.

My post [Using Docker Containers for Yocto Builds](https://www.smallstepsystems.com/using-docker-containers-for-yocto-builds/) describes how to install Docker and how to write a *Dockerfile* to build embedded Linux systems. The *Dockerfile* is very similar to the one used in this post.

My knowledge about configuring run-time paths comes from *Chapter 25.2.2 RPATH* of the book [Professional CMake - A Practical Guide](https://crascit.com/professional-cmake/?ref=smallstepsystems.com) (5th edition) by Craig Scott.