Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Project ERROR: Unknown module(s) in QT: multimedia" when building my project with fresh static Qt5.3.0

I have configured and built my own release version of Qt for gcc 64bit on linux, and with static linkage.

The process goes like this (from the README file deliverd with qt):

  1. Download qt-everywhere-* source tarball
  2. Extract qt into a folder "qtdir"
  3. Make a new dir "shadow" beside "qtdir" and go into it
  4. Run "qtdir"/qtbase/configure -prefix "qtdir"/qtbase
  5. Run make
  6. Wait for qt build to complete. Takes a suprisingly short time.
  7. Build my project with the resulting qmake

When I use the resulting qmake on my previously working project, it quits with the message

"Project ERROR: Unknown module(s) in QT: multimedia multimediawidgets

My project file contains the following:

QT += core gui xml network widgets multimedia multimediawidgets svg

My question is thus, what is the correct way to compile qt statically while including all desired modules in the build?

Thanks!

like image 378
Lennart Rolland Avatar asked Jun 18 '14 01:06

Lennart Rolland


1 Answers

It turns out that building qt statically was more difficult than I first expected (hoped?)

In this answer I will outline my journey to finally have a complete working statically linked qt that will compile properly with my project on Qt5/64bit/Linux.

First a list of hints that were crucial for my success:

  1. Make sure to have the 3rd party dependencies that qt require installed. The easiest way to arrange for this is to install the development packages using the package management in your Linux distribution. The more hardcore way is to actually download the sources and build them yourself, making sure to include the appropriate -L and -l options. For a complete list of dependencies, look at the official guide on how to build qt5 from git. It has instructions on exactly which packages are needed by each qt module, and how to install them for several popular distributions. Why? Some modules (such as qtmultimedia) will test the build environment for available dependencies, and will adapt to this. If you are missing some dependencies you will end up with a qtmultimedia module that does not support video or audio or both (missing pulse/alsa/gstreamer dev libs).

  2. There are two fundamental ways to build qt. You can build qt "in-tree" and "out-of-tree". I have found that the "out-of-tree" approach leaves more work on your shoulders while in the end it is the most intuitive for me. I have proceeded with this approach in this answer. "in-tree" means that you rely on the already established folder structure found in your source directory(read: lots of stuff you don't grasp easily). "out-of-tree" means that you make a build directory and start the build process from there. This is also referred to as "shadow build". The reason why I find this more intuitive is that you can look inside the shadow directory to see what files have been made/copied/changed at every step of the way, and if files are missing you know at once that something is wrong.

  3. Some of the configure options will have adverse effects. For example the -fully-process option, while it promised to include everything, broke my build. Read the output of ./configure --help carefully and try to understand what each point actually means.

  4. EDIT ADDED 2016-05-04: Qt build actually produces a bunch of log files that you can inspect to get good info about why modules are missing or why things don't build as expected. I discovered this while filing a somewhat related bug while building Qt 5.6.0 under docker.

  5. You will most likely end up with a configuration that builds only the qtbase module, and the rest of the modules such as qtmultimedia and qtsvg will have to be built after. But do not disappear, doing this is actually simpler than it sounds.

  6. The order in which you decide to build the separate modules matters. Some modules will not build if you have not first built their dependancies. For example qtdeclarative requires qtscript to be built first.

  7. I would strongly advice documenting your progress while building qt. I did this by incrementally improving a shell script that would perform all the steps that worked up this point. I will share my script in this post in the hope that it will be useful as a guide to get you up and running quickly.

Now with those general tips out of the way, here is my complete bash-script for downloading a version of qt5, configuring it and building it to taste:

EDIT: This worked OK on Ubuntu 12.04 x64 but when I replicated the process on Debian 7.0 x64 it failed with an error message: on the same format: "Project ERROR: Unknown module(s) in QT: quick svg multimediawidgets multimedia". After some troubleshooting I found that by running the configure and build steps twice in a row without cleaning solves this problem. Not an elegant solution, I know, but I was kind of hoping for some Qt5 officials/pros submitting an answer to this instead of me trying to figure out things by trial and error. I have submitted a bug report for qt about this here: https://bugreports.qt.io/browse/QTBUG-39733

#!/bin/bash

# Dependencies:
sudo apt-get install build-essential perl python git "^libxcb.*" libx11-xcb-dev libglu1-mesa-dev libxrender-dev  libasound2-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev

# Change this variable to suit your need
VER="5.2.1"


VER2="${VER%.*}"
WSRC="http://download.qt-project.org/official_releases/qt/$VER2/$VER/single/qt-everywhere-opensource-src-$VER.tar.xz"

# Current dir ( allows this script to be called from another dir)
B=$(pwd)
# Base folder for the whole operation
Q="$B/qt"
# The uncompressed source
SRC="$Q/src/$VER"
# The actual shadow dir
O="$Q/build/$VER"
# The tar.xz archive
XZ="$Q/xz/qt-$VER.tar.xz"
# Paralelle make, number of cores
J=$(grep -c ^processor /proc/cpuinfo)
# Build log file
LOG="$O/log.txt"

# My configuration options for qt change to your hearts content, but make sure to clean out your current build before using it.
OPTS=""
OPTS+=" -release"
OPTS+=" -opensource"
OPTS+=" -static" 
OPTS+=" -confirm-license"
#OPTS+=" -fully-process" #Breaks my build
OPTS+=" -c++11"
OPTS+=" -largefile" 
#OPTS+=" -continue"
OPTS+=" -silent"
#OPTS+=" -optimized-qmake" 
#OPTS+=" -reduce-relocations"
OPTS+=" -qpa xcb"
#OPTS+=" -declarative"
OPTS+=" -opengl"
#OPTS+=" -svg"
OPTS+=" -qt-zlib" # ........... Use the zlib bundled with Qt.
OPTS+=" -qt-libpng" # ......... Use the libpng bundled with Qt.
OPTS+=" -qt-libjpeg" # ........ Use the libjpeg bundled with Qt.
OPTS+=" -qt-freetype" # ........ Use the freetype bundled with Qt.
OPTS+=" -qt-harfbuzz" # ........ Use the freetype bundled with Qt.
OPTS+=" -qt-pcre" # ........... Use the PCRE library bundled with Qt.
OPTS+=" -qt-xcb" # ............ Use xcb- libraries bundled with Qt.
OPTS+=" -qt-xkbcommon" # ...... 
OPTS+=" -no-gtkstyle"
OPTS+=" -no-sql-db2" 
OPTS+=" -no-sql-ibase" 
OPTS+=" -no-sql-mysql" 
OPTS+=" -no-sql-oci" 
OPTS+=" -no-sql-odbc" 
OPTS+=" -no-sql-psql" 
OPTS+=" -no-sql-sqlite" 
OPTS+=" -no-sql-sqlite2" 
OPTS+=" -no-sql-tds"
OPTS+=" -no-gif"
OPTS+=" -no-nis"
OPTS+=" -no-cups" 
OPTS+=" -no-iconv"
OPTS+=" -no-dbus"
OPTS+=" -no-eglfs"
OPTS+=" -no-directfb" 
OPTS+=" -no-linuxfb"
OPTS+=" -no-glib"
OPTS+=" -no-kms"
OPTS+=" -nomake examples" 
#OPTS+=" -nomake demos" NOT AVAILABLE ANYMORE
OPTS+=" -nomake tests"
#OPTS+=" -no-openssl"

# The modules that are relevant for me. Please observe that THE ORDER MATTERS! I would add one module at the time and see how it complains when you try to build it.
MODS="qtx11extras qtimageformats qtscript qtquick1 qtdeclarative qtquickcontrols qtsvg qtmultimedia"

# Just echo out the current state before starting the configuration and make
echo "B: $B"
echo "MODS: $MODS"
echo "OPTS: $OPTS"
echo "Q: $Q"
echo "O: $O"
echo "XZ: $XZ"
echo "SRC: $SRC"
echo "J: $J"
echo "LOG: $LOG"

# Create dirs
mkdir -p "$Q"
mkdir -p "$Q/xz"
mkdir -p "$SRC"
mkdir -p "$O"
# Start log
date > $LOG
# Download source archive
[ ! -f $XZ ] && wget "$WSRC" -c -O "$XZ"
# Unpack source archive
[ ! -x $SRC/configure ] && tar pxf "$XZ" --strip=1 -C "$SRC" "qt-everywhere-opensource-src-$VER" 
# Configure qt build
cd "$O"
MAKEFLAGS=-j$J "$SRC/configure" $OPTS

# Build qtbase with new config (results in the basic qt libs plus a new qmake that you can use for building the rest of the modules and your own projects).
# TIP: Don't put make all here
make -j$J >> $LOG

#build your modules with the new qmake, keeping the resulting static libs in each module's shadow build folder where they will be located by qmke during compilation of your projects
for M in $MODS
do
    echo "----------------------------------------- MODULE: $M"
    echo "----------------------------------------- MODULE: $M" >> $LOG
    # Make module dir
    D=$O/$M
    mkdir -p $D
    cd $D
    # Use new qmake to create module makefile
    $O/qtbase/bin/qmake $SRC/$M/
    # Build module
    make -j$J >> $LOG
done

echo "DONE"

To use this script, put it in a new text file such as qt.sh and chmod +x qt.sh to make it executable. Make an empty dir and run the script from there.

After it is complete, the resulting qmake will be under <your dir>/qt/build/<version>/qtbase/bin. You should be able to use this like any other qmake, from commandline, script or QtCreator. Example:

cd ~ # Go to home dir
mkdir lol #Make a temporary dir
cd lol # Go into the temporary dir
<full path to script> # Run the script from this temporary dir
# [ ... wait for script to download, configure and build qt]
cd qt/build/<version> # Go into the output directory
ls # List all module folders
ls -hal qtbase/bin
/qmake # Show details on new qmake binary which should be configured to build your projects with static qt linkage by linking to module libraries from this dir.

If something goes wrong, you can now open the $LOG file using your favourite text editor and look at what happened.

And finally, to verify that your project was compiled with qt linked statically, you can run ldd my_binary and see that the list of dynamically linked libraries contains no mention of qt what-so-ever. WIN!

I don't know if this is the best way to do it, so if you know a better way, or have improvements, please do not hesitate to share!

like image 190
Lennart Rolland Avatar answered Oct 12 '22 07:10

Lennart Rolland