Setting QTDIR based on generator in use - qt

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.

Related

Build application and Qt from source using cmake

I'm trying to set up building an application that uses qt5.6 in a way that both qt and the application are build from source (using the ninja generator, with visual studio compiler on windows and clang on mac).
I'm stuck at find_package(Qt5Core ..) : when Qt is not build yet, it will not be found. And because it's not found, the generate cmake file is not complete.
I think I need a setup where it generates a ninja files that, when build, builds Qt and then regenerates the ninja file (and at this point it would find qt) before continuing the build.
Or any other way in which I can build Qt+application from source, so that if I change something in Qt, it is automatically rebuild.
How should I set up my cmake file(s) to do that?
You could use CMake's ExternalProject command to invoke CMake from within CMake. You can specify dependencies there, so that your application will only be built after Qt has been built.
I happend to have a small example here that uses ExternalProject_Add to build a library followed by an application. In that example, CMake for the library and the application is invokved at make time.
cmake_minimum_required(VERSION 3.0)
include(ExternalProject)
ExternalProject_Add(cmake_lib
URL ../cmake_lib
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)
ExternalProject_Add(cmake_app
DEPENDS cmake_lib
URL ../cmake_app
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
)
The problem with Qt 5 is that it doesn't use cmake to get built, and thus your ninja build process won't know anything about the internals of Qt unless you tell it everything. E.g. if you change any dependencies of Qt, or if Qt gets partially built, you'd have to add a lot of knowledge to your project's build system to determine whether the Qt build needs to be invoked again. This can be certainly made to work in a "fire and forget" style of build, where the build always starts from scratch, like in a CI system. One quickly runs into serious trouble if the intent is to change Qt itself and re-run the build. Even Qt's own build system has serious trouble with full dependency tracking due to fundamental architectural decisions in qmake.
Qmake-based developer re-builds of Qt suck - and they do to such an extent that I didn't bother contributing to the project since it felt like a penance, where the simplest of changes to one source file would take a minute or more to rebuild on, and any changes to qmake project files would sometimes ballon into multi-minute affairs.
The only solution that I have found that actually works and doesn't make you hate life, the universe and everything, was to reimplement Qt's build and configuration system using cmake, so that qmake becomes unnecessary. As a result, a statically linked unity debug build of qtbase takes a couple of minutes with all features enabled - it's pretty zippy and is much faster than the fastest option provided by Qt 5 on Windows for MSVC builds: qmake+jom.
The Qt project endeavored to do this during Qt 6 development, and I believe that they were successful :)

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.

Maintaining CMake on Qt Creator

I wonder, how do people maintain CMake projects on Qt creator? When you open the project you run CMake generator and after that you can't change much. In order to add another class to the project you have to create class files by hand, add them to CMakeLists.txt and rerun CMake again. Moreover, changing the class name is a nightmare.
I do actually like CMake (except its syntax), since it has some nice features. However, maintaining a project is a nightmare. Am I missing or doing something wrong?
No, you did not, that is how cmake works: You maintain the build system by hand and generate files for your preferred build system.
That approach makes it pretty easy to support several IDEs/buildsystems using cmake. Unfortunately it also makes it impossible to have an Integrated Development Environment for cmake projects. The rather complex syntax which makes it basically impossible for a machine to modify cmake projects does not help there either.

How to install two versions of Qt and tell the application which to use?

I am developing an application in Qt, but using D language (with QtD binding). I've noticed that my app crashes with Qt 4.7.x, so I need to use Qt 4.6.2 instead. However in my system Qt 4.7.2 is installed. Unfortunately I neither make QtD work with the latest Qt versions nor (I'm afraid) count on QtD developers...
The only thing I need to make my application install in system Qt 4.6.2 libs and use it, but let all the other applications still use Qt 4.7.2. Is it possible? If it is, how to do it then?
The answer to your question is the version of Qt is determined by the qmake you use to generate your Makefile.
/opt/QtSDK/Qt-4.6.2/bin/qmake
/opt/QtSDK/Qt-4.7.3/bin/qmake
Each will use the library in the directory.
It is possible to install several versions of the library into one system, and all package managers (rpm, deb) support this out of the box.
These libraries will be just differently named. For example, if id do
ls /usr/lib/ | grep libcurl
on my system, I'll get:
libcurl-gnutls.so.3
libcurl-gnutls.so.4
libcurl-gnutls.so.4.2.0
libcurl.so.3
libcurl.so.4
libcurl.so.4.2.0
, so, different version of the same library happily live together.
All you need to do is to link against the desired version of QT library. You need to sepcify it in linker options (don't remember the exact option).

Qt create executable

Is there a quick, straightforward way to make a Qt application into an executable? I attempted to follow the instructions at http://doc.qt.digia.com/4.1/deployment-windows.html but have been unsuccesfull thus far; I'm unable to Any help would be much appreciated. Thanks!
I always use CMake to build Qt projects, it's easy, free and cross platform. Guide : Compiling Qt4 apps with CMake. CMake also come with CPack to easly make installer for Windows, Mac and Linux.
I agree with chmod700 about the Qt Creator suggestion, it's not my favorite IDE but it's still really nice and easy.
Do you mean an installer package? I assume you are able to compile, link, and run your app and you mean how do you package it up for others.
http://installbuilder.bitrock.com/ <-- special handling of Qt based projects but costs $
http://www.jrsoftware.org/isinfo.php <-- my personal favorite and it's free (can be rough to learn advanced features though)
Though if you mean how do you build your app, you may want to try the new Qt Creator (http://www.qtsoftware.com/products/appdev/developer-tools/developer-tools#qt-tools-at-a) which will setup build targets for you and really makes desktop Qt dev a snap. Also if you're still using 4.1, you can now use 4.5 under the LGPL on all platforms making it almost a no-brainer to upgrade.
I'm not sure if I understand your problem. Assuming you're using MinGW, it's really easy and quite straightforward:
get the Qt sources and unpack them to some folder (f.e. c:\Qt\4.5.0-static)
install MinGW. Make sure the MinGW executable folder is in the %PATH% variable.
open a cmd windows, go to the Qt sources and run configure -static. You can add other config options if you like to, but usually you don't need that.
when building Qt finished, go to your application sources, open a cmd window and run the qmake of your built Qt installation -- i.e. c:\Qt\4.5.0-static\bin\qmake in the example given above.
run make
you get a statically linked binary in the end (you might want to check it with Dependency Walker).
Doing the same using Visual Studio is pretty similar.
Or do you want to build dynamically and create an installer package?

Resources