📜 ⬆️ ⬇️

Using CMake with Qt 5

image

CMake is a software build system (more precisely, build control file generation), widely used with Qt. When creating large or complex projects, the choice of CMake would be more preferable than using qmake. KDE was once a turning point in CMake's popularity as such, after which Qt 4 contributed to the “mite”. In Qt 5, CMake support has been significantly improved.

Finding and Attaching Qt 5 Libraries


One of the major changes when using CMake in Qt 5 is the result of increased modularity in Qt itself.

In Qt 4, the search was performed as follows:
find_package (Qt4 COMPONENTS QTCORE QTGUI)

In Qt 5, you can find all the modules you want to use with separate commands:
find_package (Qt5Widgets)
find_package (Qt5Declarative)
In the future, there may be a way to find certain modules in one command, but now, in Qt 5, this type of search will not work:
find_package(Qt5 COMPONENTS Widgets Declarative)

Building Qt 5 Projects


After the successful execution of find_package , Qt 4 users were given the opportunity to use CMake variables: ${QT_INCLUDES} to set additional directories when compiling and ${QT_LIBRARIES} or ${QT_GUI_LIBRARIES} when linking.
It was also possible to use ${QT_USE_FILE} , for the "semi-automatic" inclusion of the necessary directories and the required define.
With the Qt 5 modular system, the variables will now look like this: ${Qt5Widgets_INCLUDE_DIRS}, ${Qt5Widgets_LIBRARIES}, ${Qt5Declarative_INCLUDE_DIRS}, ${Qt5Declarative_LIBRARIES} and so on for each module used.

This causes incompatibility when porting a project from Qt 4 to Qt 5. Fortunately, this is all easily fixable.
Building in Qt 5 is a bit more complicated than in Qt 4. One of the differences is that in Qt 5, the configure -reduce-relocations option is now enabled by default. For this reason, compilation was performed with the -Bsymbolic-functions option, which makes the pointer comparison function ineffective if the -fPIE flag was not added when building executable modules, or -fPIC , when building libraries for position-independent code.
')
Of course, you can configure Qt manually with the -no-reduce-relocations option and avoid this problem, but new problems will arise when you add flags to the compiler for position-independent code that you can avoid using CMake:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
This is a variable for each module available in Qt 5, which will expand to add either -fPIE or an empty string, depending on how Qt was configured. However, the -fPIE flag is for executable programs only and should not be used for libraries.
A global installation of -fPIC , even when building an executable module will not cause failures, but this option should not be first.
set(CMAKE_CXX_FLAGS "-fPIC")

Coupled with new features in CMake, such as an automatic call to moc, a simple CMake build system using Qt 5 will look something like this:
CMakeLists
 cmake_minimum_required(2.8.7) project(hello-world) # Tell CMake to run moc when necessary: set(CMAKE_AUTOMOC ON) # As moc files are generated in the binary dir, tell CMake # to always look for includes there: set(CMAKE_INCLUDE_CURRENT_DIR ON) # Widgets finds its own dependencies (QtGui and QtCore). find_package(Qt5Widgets REQUIRED) # The Qt5Widgets_INCLUDES also includes the include directories for # dependencies QtCore and QtGui include_directories(${Qt5Widgets_INCLUDES}) # We need add -DQT_WIDGETS_LIB when using QtWidgets in Qt 5. add_definitions(${Qt5Widgets_DEFINITIONS}) # Executables fail to build with Qt 5 in the default configuration # without -fPIE. We add that here. set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") add_executable(hello_world main.cpp mainwindow.cpp) # The Qt5Widgets_LIBRARIES variable also includes QtGui and QtCore target_link_libraries(hello_world ${Qt5Widgets_LIBRARIES}) 

Toward a more modern use of CMake


Starting with CMake 2.8.8, we can slightly improve the previous version as follows:
CMakeLists
 cmake_minimum_required(2.8.8) project(hello-world) # Tell CMake to run moc when necessary: set(CMAKE_AUTOMOC ON) # As moc files are generated in the binary dir, tell CMake # to always look for includes there: set(CMAKE_INCLUDE_CURRENT_DIR ON) # Widgets finds its own dependencies. find_package(Qt5Widgets REQUIRED) add_executable(hello_world main.cpp mainwindow.cpp) qt5_use_modules(hello_world Widgets) 


The CMake qt5_use_modules function encapsulates the entire installation necessary to use Qt. It can be used with several arguments at once for brevity, for example:
qt5_use_modules(hello_world Widgets Declarative)
For qmake, this is equivalent to the following:
TARGET = hello_world
QT += widgets declarative

All properties are in the scope of a particular target function in use, rather than being in the scope of CMakeLists. For example, in this snippet:
CMakeList
 add_executable(hello_world main.cpp mainwindow.cpp) add_library(hello_library lib.cpp) add_executable(hello_coretest test.cpp) find_package(Qt5Widgets) qt5_use_package(hello_world Widgets) qt5_use_package(hello_library Core) qt5_use_package(hello_coretest Test) 

because all parameters are within the scope of the target (executable or library) they work with, -fPIE not used when building the hello_library library and -DQT_GUI_LIB not used when building the hello_coretest.
This is a much more rational way to write a build system on CMake.

Implementation details


One of the functions of CMake, with which many developers who use it are familiar, is the Find file. The idea is to write a Find file for each dependency of your project or use an existing Find file. CMake itself provides a large set of Find-files.
One of the Find files provided by CMake is the FindQt4.cmake file. This file takes responsibility for finding Qt in the system so that you can simply call:
find_package(Qt4)

This Find file makes the ${QT_INCLUDES} and ${QT_QTGUI_LIBRARIES} variables available. One of the disadvantages of this file is that it could become outdated. For example, when Qt 4.6 was released in December 2009, it included a new QtMultimedia module. There was no support for this module until CMake 2.8.2, released in June 2010.

The Qt 5 search is somewhat different. In addition to the ability to find dependencies using a Find file, CMake is also able to read files that provide dependencies for locating libraries and header files. Such files are called configuration files, and they are usually generated by CMake itself.

The Qt 5 build will also generate these CMake configuration files, but there will be no dependencies on CMake.
The main advantage of this is that the Qt functions (and modules) that can be used with CMake will not depend on the version of CMake being used. All Qt Essentials and Qt Addons modules will create their own CMake configuration file, and the functions provided by the modules will be immediately accessible via CMake macros and variables.

Original article: www.kdab.com/using-cmake-with-qt-5

Source: https://habr.com/ru/post/181838/


All Articles