Use CMAKE_PREFIX_PATH for multi-configuration builds - qt

I am using find_package to find Qt and adding "C:\Qt\5.15.0\mingw81_64\lib\cmake" to my CMAKE_PREFIX_PATH environment variable and it has worked fine when just using 64-bit up until now. However, I want the ability to switch between 32-bit and 64-bit builds. I therefore also added the equivalent above path for 32-bit, however this resulted in linking errors (presumably CMake wasn't sure which one to pick and picked the wrong one for one of the configurations).
What is the conventional way to fix this situation? At the moment I'm using a suffix path and searching in that dependent on the compiler architecture, however ideally I'd like to leave that stuff out of the CMake project itself and simply require users of the project to add whatever Qt location themselves, while still being able to have "more than one" Qt location.
Is this solvable? Or is it malpractice to have two Qt paths in your CMAKE_PREFIX_PATH variable?

What is the conventional way to fix this situation?
Only add to your CMAKE_PREFIX_PATH the Qt path corresponding to the architecture you want.
[...] however ideally I'd like to leave that stuff out of the CMake project itself and simply require users of the project to add whatever Qt location themselves, while still being able to have "more than one" Qt location.
You may request the users to pass the Qt path as a parameter (when calling CMake through the command line)
cmake -DQT_PATH={PATH TO QT} ...
Or read an environment variable (which the user would have to set)
if(DEFINED ENV{QT_ENVIRON})
set(QT_PATH $ENV{QT_ENVIRON})
else()
set(QT_PATH ...)
endif()

Related

How to get build environment and configuration parameters of the Qt library

There is a issue that is present with some very specific aspect of applications I build using a Qt library provided in repositories of the system I'm using; this issue isn't present with the same numerical build of Qt that I built myself on this exact system.
I would like to query all information about build environment of Qt, it's configuration flags, etc., anything that could help me determine the difference between two build of Qt library.
I've learned about config.summary file, that is present in mine qtbase sources, but there isn't a counterpart anywhere in the system for pre-built version (I have, besides headers, installed a sources and debug information for the qt library packages).
I also tried looking for some header files that could specify, for example, what features were enabled at the build time, but could't locate anything like that (mostly because I don't know the name or some example contents of such file so that I could search for it or grep it), so if there is indeed such file, please point me to it.
I think the best reply is to quote this answer from Qt mailing list
Unfortunately it isn't that easy to figure out but the data is
available; you just need to know from where to search it :D
Configure options can be found from (qtbase) build log, from qt5.git
integration. E.g for 5.6.3
here:https://testresults.qt.io/coin/integration/qt/qt5/tasks/1505476672
and for 5.9.5 here:
https://testresults.qt.io/coin/integration/qt/qt5/tasks/1523412986
And SW details here: https://wiki.qt.io/Qt_5.6_Tools_and_Versions &
https://wiki.qt.io/Qt_5.9_Tools_and_Versions
You can find the latest builds at https://testresults.qt.io/coin/?project=qt%2Fqt5
If you look inside the "Build" section you have all the system configurations Qt is built for (column "Target") and for each configuration the parameters (column "Configure Arguments").

Setting QTDIR based on generator in use

I am trying to setup a CMake project which consists of multiple static libraries and one main executable which has dependencies on QT. I would like to be able to select either a MinGW or a MSVC build when I run the cmake build.
I recently learned that the QT specific parts of CMake will find the installed library binaries for QT automatically if QTDIR is set as an environment variable and if QTDIR/bin is in the PATH.
Now I am wondering how I can set this information dynamically depending on the compiler that I am using. Since I would need to point cmake to either one of C:\Qt\5.3\mingw482_32 or C:\Qt\5.3\msvc2013_64, or possibly others if I extend the list of targets in the future.
Note that I do not need to build both compiler targets at the same time, I would usually select on target in my IDE and build that one, but I would like to be able to switch between both targets.
The solution should be in such a way, that on Linux the CMake build will still find the libraries which are installed through the package manager automatically.
Can I easily achieve this with CMake?
As a side note, in the future I might also need to select the QT version on demand? So an extensible solution would be nice.

Getting path to compiler executable in Qt

I write applications in C++/Qt, and sometimes I have to compile them in Windows. For that I use MinGW. Unfortunately, that makes the executable dependant on mingwm10.dll and libgcc_s_dw2-1.dll. I prefer to solve such problems by just copying needed DLLs into application folder and distributing it like this. I use QMAKE_POST_LINK in the *.pro file to automate the process.
Unfortunately, for various reasons MinGW ends up in different directories on different systems I use. Is there a way to get the path to the compiler executable in Qt project? MinGW libs lie near its exe, so it would solve the problem.
Thanks.
UPDATE
I'm afraid I didn't put myself clear enough.
I know that 90% of users don't have Qt, and 99% don't have MinGW installed on their Windows desktop. This is why I distribute all needed DLLs along with the executable, so that it can run everywhere without installing anything. I just copy them in the same folder with the *.exe. To automate this copying process, I add a copy command to the QMAKE_POST_LINK, which executes it after the linker finishes linking my program.
The problem is that this copy command still needs to know from where to copy MinGW libraries. Hence my question: how can one know the compiler path in compile time?
$$OUT_PWDin Qt *.pro file expands to the path to the directory where built application is put to. $$PWD expands to the project directory. Is there a similar macro (or maybe a hack) which gives the path to the compiler executable?
You are trying to approach the problem from the wrong angle. In particular, the solution you want will not be robust. It will still break on different systems, for example, the ones that have different version of MinGW toolchain installed and therefore different runtime DLLs, which if loaded by your application (built with another version of MinGW) will most probably cause crashes and undefined behavior during runtime. Furthermore, there might be systems which do not even have MinGW installed. These are the main reasons why applications built with certain version of toolchain should be distributed with the corresponding runtime DLLs included (this is what is called redistributable runtime) which is common practice on Windows, and there is nothing wrong with it.
However, there is much better way to solve your problem. Simply link all the MinGW runtime libraries statically into your application. This is a very good practice for Windows applications (and a very bad one for Unix ones). To do that, add the following to the corresponding *.pro:
QMAKE_LFLAGS_WINDOWS += -static-libgcc -static-libstdc++ -static
NOTE: Qt libraries themselves have to be built with these flags too, i.e. they should be independent of the MinGW runtime too. If not, then you'd still have a transitive dependency to the MinGW runtime because of the Qt libraries your application is linked against.
NOTE: _WINDOWS suffix will ensure that your application gets linked with these flags only for the Windows platform, while on Unix it will still link dynamically with runtimes (such as glibc.so on Linux) for the reasons discussed above.
After that your application will no longer explicitly depend on any MinGW runtime DLLs what will solve both distribution and maintenance headaches.
NOTE: If you ever decide to migrate from QMake to CMake (recommended), then here's how you do the same for CMake.
Update
You could check the QMAKE_CXX variable, but most likely it does not contain an absolute path to g++.exe. Usually it is simply g++, and the directory containing it is searched in PATH then. So in this case you'd have to parse PATH and check each directory in it for existence of g++ in it. This is very nasty logic to write in such a limited build system as QMake. So, as I stated above, you better off with 2 options:
Link runtimes statically into the application, so that you don't have to distribute anything. If you don't want to do it, then I want to know why - please write a comment;
Migrate to more feature-rich and flexible build system - CMake.

Modules of Qt 5.1 and their interdependency?

I am looking for a way to create a minimal static build of Qt 5.1. By minimal, I mean a build with only the basic set of widget classes available (including 2D graphics acceleration through an OpenGL canvas/widget). I am aiming for a static build on Windows 7 32-bit using MinGW-builds GCC 4.8.1 as well as their bundle of MSYS and tools.
I have downloaded the entire source tree, and have met some problems with compiling due to the dependency of packages such as OpenSSL and ICU (the latest OpenSSL did not compile). I wanted to see, if I could avoid dependencies of these packages and, at the same time, achieve a minimal static build of Qt 5.1 so my final executable is not gigantic in size.
I took a look at this list:
http://download.qt-project.org/official_releases/qt/5.1/5.1.0/submodules/.
Q1: Which of these modules, do I need to select to have a basic Qt build without all the fancy stuff?
Q2: Are these modules interdependent on each other in some way (I assume they are all dependent on "qtbase")?
Q3: Do I use the names from that list, (for example: "qtxmlpatterns", "qtx11extras", "qtwebkit", etc.), to deselect them in the configuration of my Qt build?
It would also be nice, with an explanation of the various submodules of Qt 5? If someone could point to any links or docs with illuminating words on this subject, that would also be great.
I shared this same goal. I wanted to "minify" Qt, building only a small subset of the libraries/DLL(s) and omitting the rest.
I did succeed, at least on Mac OS X. I assume that this approach will work on other platforms, too.
I thought that the trick would be to find some kind of exclusion flags for the "configure" script, but that turned out not to be the case.
Here is what I did:
Download the source distribution (in my case, qt-everywhere-opensource-src-5.1.1). of course, extract it all.
Edit the following three "pro" files. these files are in a qt-specific format (but plain text). They are platform-independent project files that Qt (via qmake) uses to generate makefiles.
qtbase/src/src.pro
qtbase/src/plugins/plugins.pro
qtbase/examples/examples.pro
All the changes that I made to the "pro" files were deletions. I deleted references to: dbus, ipc, network, qtconcurrent, sql, xml, sqldrivers, qdbusxml2cpp, qdbuscpp2xml, src_dbus, src_concurrent, src_sql, src_network.
That last part may sound scary. It really wasn't.
The pro files contain a list of module names, plugin names, and directory names. It seemed fairly straightforward how to delete (for example) all SQL-related lines.
Step 3.
The usual configure/make/install. However, note the "module-qtbase" argument passed to make:
./configure -prefix ~/my_test_dir/
make -j2 module-qtbase
make -j2 module-qtbase-install_subtargets
Success. This built and installed only the essentials (QtCore, QtGui, QtOpenGL, QtWidgets) and skipped all the supporting dylibs like QtConcurrent, QtMultimedia, QtSql, and QtWebKit.
ICU can link statically, and you can customize it (see docs) to reduce size. By default the data is also large, I don't know how much data you need. You could include only enough data to run in one language.
Only part of an answer.
There's no need to disable Qt modules. Each application that uses Qt decides what modules it uses and links with. A basic console-only application may use the core module only. That's what you'd use when creating, say, a web service in Qt.

macdeployqt on homebrew installed frameworks

I'm trying to deploy an application using macdeployqt. All Qt frameworks get copied correctly into the application bundle. The problem I encounter is that macdeployqt does not have write permissions on the copied frameworks which originally reside in /usr/local/lib. This is because I have installed qt using homebrew which seems to make install everything read only. My question is whether there is a better way to fix this issue then manually changing all permissions of the qt libraries inside /usr/local/lib so that I can use macdeployqt from within a qt .pro project. (I don't want to use macdeployqt manually with sudo or such)
The reason why I'm asking is because I am using many third party libraries in the project (they get copied ok etc.) which I need to update often through homebrew and thus have to redo the permission changing on them.
Thanks in advance!
Just in case someone finds this old post looking for info about macdeployqt:
Use a script to do macdeployqt in preference to scripting the macdeployqt commands in your .pro file. That will allow you to change the permissions on the files on the fly.
Here is [a snippet of] the script I use for one of my apps:
https://bugreports.qt-project.org/browse/QTBUG-23268
If you're on Windows and don't have bash, you can use perl or python. The script referenced above modifies the files on the fly to work around a bug - you can put anything you want here, including changing the permissions on the files.
Using a script also means that you have the flexibility to add commands later to do code-signing, packaging or whatever else you need.
The Qt .pro "scripting language" actually generates Makefile commands under the hood and can be quite obscure if you want to accomplish deployment tasks that relate to paths and sets of files.
Also you'll need to create an extra target or include it into your build target - either way the build process becomes more complex and more error prone.
Disclaimer: I worked on Qt for 8 years as a Senior Engineer for Nokia/Trolltech, and also have published a commercial cross-platform app using Qt.

Resources