Build application and Qt from source using cmake - qt

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 :)

Related

What are CMake vs qmake pros and cons?

I would like to know reasons for use CMake for particular project over qmake and vice versa.
Simply what are the pros and cons of both build systems?
Both are build systems, but they're not very similar at all. If your project uses Qt, you're probably best off using qmake. CMake is more generic, and fits pretty much any type of project.
Both qmake and CMake generate a Makefile, which is read by make to build the project. Not all build systems generate a Makefile, but many do. Even a Makefile is a type of build system; it tells the compiler and linker what to do, in order to create an executable (or a dynamic or static library).
If your project uses Qt, but you don't want to use qmake, you'll have to do a few more things yourself:
running the Meta Object Compiler (MOC)
include paths (tell the compiler where to look for Qt headers)
linking (tell the linker where to look for Qt libraries)
So, you'll have to do a bit more work to build a Qt project without qmake, but it is possible and it will teach you a lot about how Qt and qmake do things.
On a personal note (take this only as a recommendation, do further research yourself): I'm not a big fan of qmake. It helps you with the Qt stuff, but apart from that, I've found it to be pretty limited.
In any case, I would recommend learning to build a small project (~10 source files) without using any type of build system. Not using CMake, not with a Makefile, just using the compiler and linker directly. You shouldn't actually build any real project in this way, but you should learn how to do it, just to learn what build systems actually do. Knowing what they do will make them a lot easier to use.
A few months ago, we switched a project from qmake to Premake, which is also worth a look. It's highly scriptable (with Lua), which is great when you need to customize your build process.
That said, it is a bit more "manual", so prepare yourself to learn how compiling and linking works at a more basic level, without the use of a build system. It's also in beta (Premake 5), so there are some bits and pieces still missing.
You can also take a look at qbs, which is supposed to be a better qmake. It's still in a beta stage, so I'd wait while it matures and becomes easier to use.
CMake is by far the more powerful build system. The syntax is "not so nice" to put it mildly. But then, for any complex project, what one has to do with QMake (or any buildsystem I know of) to achieve things isn't nice either. For simple projects, QMake is nicer to look at though.
If you need configure checks for third-party dependencies other than Qt, CMake is what you want, support for configure checks in QMake is minimal to non-existent.
QMake on the other hand works great with Qt Creator (CMake support in there is lacking, although it's doable to use CMake with Creator).
If you want to build and deploy for iOS and Android from within Qt Creator, I strongly suggest QMake. (Not sure if it's even possible these days with CMake - it will be certainly cause a lot more headache).
I use CMake for my Qt projects and am very happy with it. Specifically, I have the following in my CMakeLists.txt:
set(QT_VERSION_REQ "5.2")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt5Core ${QT_VERSION_REQ} REQUIRED)
find_package(Qt5Quick ${QT_VERSION_REQ} REQUIRED)
find_package(Qt5Widgets ${QT_VERSION_REQ} REQUIRED)
find_package(Qt5Gui ${QT_VERSION_REQ} REQUIRED)
set(CMAKE_AUTOMOC ON)
QT5_WRAP_UI( UI_HDRS ${UI_FILES} )
ADD_EXECUTABLE(${MOC_HEADERS})
target_link_libraries(${PROJECT_NAME}
Qt5::Core
Qt5::Quick
Qt5::Widgets
Qt5::Gui
)
I hope this helps if you do decide to go with CMake.
CMake will help you generating configuration files for many build systems (a "build system" is called Generators in CMake). See What is a CMake generator?.
It means that if you have a set of C/C++ sources and a well written CMakeLists.txt, you can use CMake to create projects for different build system (IDE based on command-line based) like Visual Studio, CodeBlocks, g++...
With CMake, you can choose the IDE and compiler you will use in the end and 'easily' switch between supported ones.
qmake, as far as I know, will only support QtCreator as an IDE (itleft using 3rd party compiler in the background: nmake from Visual Studio, g++, MinGW...). But you won't generate a Visual Studio solution (sln file) using qmake. That's the main limitation I see in qmake (because I hate QtCreator...Visual Studio is way more powerful and intuitive...but that's just my opinion).
It's true qmake makes it easier to compile Qt-based applications (because MOC, .ui and liking to Qt is natively supported) than CMake. But it's doable anyway using CMake (there's built-in functions for Qt integration). Only your CMakeLists.txt may have to be reworked a bit when moving to new releases of Qt (I had a hard time when moving from Qt4 to Qt5, I guess that using qmake makes this easier).
Personnaly, I use CMake for my build environment and, when I need to use QtCreator (for Android deployment mainly), I make my CMake scripts generate a .pro file for qmake/QtCreator. It works well because qmake .pro file syntax is really simple. Then I'm not locked to a specific IDE.
qmake
Has focus on projects using Qt
Project file is easily generated by QtCreator (good for beginners)
Supported by QtCreator
CMake
Is used in a wide range of projects
Supports a lot of platforms and languages
Supported by multiple IDE's: e.g. QtCreator, Visual Studio
Generates project description for multiple IDE's
Contains commands to make usage of Qt easy (Most important: automoc)
My recommendation: Use qmake in case QtCreator is your IDE and you starts with Qt or C++. Use cmake in case you want to do any complex stuff in your build.
Both qmake and CMake work similary. See http://www.th-thielemann.de/development/cmake/cmake_qmake_to_cmake.html for a tutorial to migrate from qmake to CMake.

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.

Does Qt creator by default statically or dynamically link it's libraries?

I'm developing a closed source application and to do so in accordance with the LGPL I have to dynamically link Qt's libraries to my application. Does Qt do this by default or do I have to take steps to do so? If that's the case how would I go about doing it?
Qt uses dynamic linking by default.
You'll notice this immediately during deployment to a non-developer machine, because your code will not run without the Qt libraries.
If your concern is the LGPL, just be careful when compiling Qt itself. Most LGPL violations with Qt are not because of static linking (since dynamic is the default), but for compiling Qt with non-default parameters.
LGPL is not just that the library must be provided along your binaries, but also that you specify how your users can build themselves the LGPL part. If you compile Qt yourself and do not use the pre-compiled binaries from the website, you must document that part of your build configuration in your release!
As soon as you get something running on your program, start preparing a release version for a non-developer environment without Qt installed. Your program should fail as soon as you delete the DLLs that you must copy along your program (or whatever format your OS uses).
It does it by default, statically linking seems to be quite involved judging by the many questions on the site regarding it.

Deploying QT app on OS X and linux

Whats the best way to deploy a QT app? I've read the documentation hosted at trolltech but is it better to link with a static library or the dynamic libraries and have the user install the framework? I don't really want anyone using my app to have to download a 160mb framework just to run a simple gui frontend.
On OS X it's a good way to do a dynamic build and post-process the resulting ".app" with the macdeployqt tool which comes with Qt starting with 4.5.
This will copy the Qt frameworks used by your application into the application bundle, which results in a larger package than building a static version of your application.
Here is what you can do to make sure you get the smallest file size possibly in a dynamic build:
First off, make sure you only include the stuff you need (in the project.pro file's QT += core gui network xml lines).
Open the application bundle and remove any unneeded "Qt Plugins" from the bundle. macdeployqt automatically compies all the Qt plugins in there, which can be kind of bulky.
Make sure you are building your application in release mode. Otherwise your application might be linked against the debug libraries of the Qt4 framework, and they are really big (for instance, well over 90 MB for the debug library vs. 16 MB of a release variant without debugging symbols). This might be what happened in your case.
If you have a large application binary, you can use UPX to compress your executable file by 40-50%.
Other than that, you should use compressed disk images to deploy your application.
One of my projects uses QtGui, QtNetwork, QtCore and QtXml and the resulting bundle is about 16 MB in size.
Hope that helps.
Unfortunately you will have to include the Qt libraries you need into your own bundle, as you cannot expect your users to have Qt installed on Mac (whereas on Linux packaging systems allow you to require at least a given version of Qt.
There is a nice tool to help you with that, which is called macdeployqt. You just need to invoke it on your bundle application and it will pack the required libraries, changing the linkage of your binary to refer to them. Without it, making bundles for Mac is a real pain (it still is, but considerably less though).
http://doc.trolltech.com/4.6/deployment-mac.html#the-mac-deployment-tool
Afterwards, you can make a .dmg image as you would do with any other app. There is an option in macdeployqt that builds a basic one.
On Linux, it's better to rely on the OS's copy of Qt, as it's almost certainly installed - for OS X, almost all apps use a statically compiled library.

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