How to list all CMake components of Qt5? - qt

I know that in CMake I can find and require the Qt5 libraries I need with code like this:
find_package(Qt5 5.12.0 REQUIRED
COMPONENTS Gui Qml QuickControls2 Svg
)
But how do I know the exact names I can list after COMPONENTS?

Component names are interpreted by the package (here: Qt5), not CMake itself (see). So their naming scheme is package specific. In the case of Qt5, ${QT5_DIR}/lib/cmake/Qt5/Qt5Config.cmake shows that their names are the same as the CMake module names when omitting the Qt5 prefix:
foreach(module ${Qt5_FIND_COMPONENTS})
find_package(Qt5${module} ... )
...
endforeach()
So to list all component names, just list the CMake modules (as derived from the corresponding ModuleNameConfig.cmake filenames) and omit the Qt5 prefix. Under Linux, this does the job and also sorts the output into columns:
find /path/to/your/qt5/ -name "*Config.cmake" |
sed 's/^.*\/Qt5//; s/Config.cmake$//; /^\s*$/d' |
sort | pr -t -3
As of Qt 5.12, this lists the COMPONENT names as follows:
3DAnimation Help QuickWidgets
3DCore LinguistTools RemoteObjects
3DExtras Location RepParser
3DInput Multimedia Scxml
3DLogic MultimediaWidgets Sensors
3DQuick Network SerialPort
3DQuickAnimation Nfc Sql
3DQuickExtras OpenGL Svg
3DQuickInput OpenGLExtensions Test
3DQuickRender Positioning TextToSpeech
3DQuickScene2D PositioningQuick UiPlugin
3DRender PrintSupport UiTools
AndroidExtras Qml WebChannel
Bluetooth Quick WebSockets
Concurrent QuickCompiler WebView
Core QuickControls2 Widgets
Gamepad QuickTemplates2 Xml
Gui QuickTest XmlPatterns

Related

How do you build depended-upon libs before the main project with CMake in Qt?

I've looked at similar questions but haven't found one for this basic scenario. I'm relatively new to CMake. I have a CMake-based Qt 5 project. It's a simple test application; during its build I want to build and statically link the open-source Paho MQTT C lib and the C++ wrapper for it. Those are two separate projects with their own CMakeLists.txt files.
Per Qt's default, it builds into a directory outside the source tree.
I've copied the source trees for these open-source libs under the parent directory of my project, and edited the top-level CMakeLists.txt file to add_subdirectory them.
I also added target_link_libraries. I can get the C lib by itself to build and link into the parent project, but if I add the C++ wrapper, the processing for the C++ wrapper complains that it can't find the C lib... which is true because it hasn't been built yet. A similar complaint for the C lib was solved by simply using Qt's "build all projects" menu item, but that doesn't work when the C++ wrapper lib is added. The wrapper's CMakeLists.txt files issues this:
CMake Error at paho.mqtt.cpp/src/CMakeLists.txt:150 (message):
Could not find Paho MQTT C library
And sure enough it doesn't exist because it has not been built when this preprocessing is done.
UPDATED: Here's my top-level CMakeLists.txt file, revised per Corristo's suggestion, which was successful in getting CMake to parse the entire hierarchy. The project now builds. I'm perplexed that the last two lines here result in an empty string, though. So does a similar attempt for the link directories.
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
task.h
task.cpp
task.ui
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(MQTTTest
${PROJECT_SOURCES}
)
else()
if(ANDROID)
add_library(MQTTTest SHARED
${PROJECT_SOURCES}
)
else()
add_executable(MQTTTest
${PROJECT_SOURCES}
)
endif()
endif()
add_subdirectory(paho.mqtt.c)
set(PAHO_MQTT_C_LIB paho-mqtt3a)
set(PAHO_MQTT_C_PATH "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c")
add_subdirectory(paho.mqtt.cpp)
target_link_libraries(MQTTTest PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
target_link_directories(MQTTTest PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/build/paho.mqtt.c/src"
"${CMAKE_CURRENT_LIST_DIR}/build/paho.mqtt.cpp/src")
target_link_libraries(MQTTTest PUBLIC paho-mqtt3a)
target_link_libraries(MQTTTest PUBLIC paho-mqttpp3)
target_include_directories(MQTTTest PUBLIC
"${PROJECT_BINARY_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c/src"
"${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.cpp/src")
get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("Top-level include dirs = ${inc_dirs}")
It is a bit of a hack, but you can use the fact that the CMake find_* commands don't perform a search if the result variable is already set.
From the paho.mqtt.cpp/src/CMakeLists.txt file we find that the output variable for find_library is called PAHO_MQTT_C_LIB and the include directory is expected to be in PAHO_MQTT_C_INC_DIR, which in the original CMakeLists.txt from version 1.0.0 (which seems to be the version you're using) is itself computed from PAHO_MQTT_C_PATH.
Setting these two variables between the two add_subdirectory calls should then make this work:
add_subdirectory(paho.mqtt.c)
set(PAHO_MQTT_C_LIB paho-mqtt3a)
set(PAHO_MQTT_C_PATH "${CMAKE_CURRENT_LIST_DIR}/paho.mqtt.c")
add_subdirectory(paho.mqtt.cpp)
This makes use of the fact that target_link_libraries can be called both with library files (which is what the original paho.mqtt.cpp project expected) and with existing CMake targets (which is what we replaced it with). Linking to a CMake target also automatically introduces a build-order dependency, so this simultaneously ensures that the c library is built before the cpp library.
However, since this relies on the names of the variables used in the paho.mqtt.cpp project as well as the target name of the library target in the paho.mqtt.c project this can break any time you update one of these libraries to a newer version.

Building a Qt module from source and use it

I've downloaded Qt from sources and thus I have the qt-everywhere-opensource-src folder containing all the Qt modules.
I needed to edit the bluetooth module, so I customized the QtConnectivity module (which contains Bluetooth and NFC APIs), and when building it, I'm getting .so and .a files.
Now my question is, how to use this new bluetooth library in a Qt project ?
1. Replace Qt files in Qt installation folder - Working
I've tried to put my generated libraries directly in my Qt sources, so I replaced original Qt files in C:\Qt\5.9.6\android_armv7\lib with my .so files for Android, and it is working great.
In my .pro, just with QT += bluetooth, everythings builds correctly, and in my application, I can access to my new functions.
2. Import library as standalone library - Not working
I've tried many ways to add bluetooth from my new sources, but none of them worked, here are some QMake variables I tried to set :
ANDROID_BUNDLED_JAR_DEPENDENCIES += \
$$PWD/mylib/src/bluetooth/jar/QtAndroidBluetooth-bundled.jar
ANDROID_JAR_DEPENDENCIES += \
$$PWD/mylib/src/bluetooth/jar/QtAndroidBluetooth.jar
ANDROID_LIB_DEPENDENCIES += \
$$PWD/mylib/lib/android/libMyLib.so
ANDROID_PERMISSIONS += \
android.permission.BLUETOOTH \
android.permission.BLUETOOTH_ADMIN
LIBS += -L$$PWD/mylib/lib/ -lMyLib

How can I model OTHER_FILES from qmake with CMake?

In qmake based projects, it's possible to include OTHER_FILES to use them in QtCreator, e.g.
QT += core gui widgets
TARGET = example-program
TEMPLATE = app
HEADERS = mainwindow.h
SOURCES = main.cpp mainwindow.cpp
OTHER_FILES = README.md LICENCE examples/network/server.c
That way one can access README.md within QtCreator easily. A CMake file with the same target looks like
cmake_minimum_required(VERSION 3.5)
project(example CXX)
set(CMAKE_AUTOMOC ON)
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
set(HEADERS mainwindow.h)
set(SOURCES main.cpp mainwindow.cpp)
set(OTHER_FILES README.md LICENCE examples/network/server.c)
add_executable(example-program ${SOURCES} ${HEADERS})
target_link_libraries(example-program Qt5::Core Qt5::Gui Qt5::Widgets)
However, the OTHER_FILES aren't shown in QtCreator and I have to access them via "File > Open" instead of the project browser. Is there a workaround?
You can use a custom target that depends on the given files:
add_custom_target(project-related-files SOURCES ${OTHER_FILES})
Since the COMMAND is missing, an empty target will be generated, but it will still depend on the SOURCES. This is also the official way to include other files into an IDE:
SOURCES
Specify additional source files to be included in the custom target. Specified source files will be added to IDE project files for convenience in editing even if they have no build rules.
There's no problem with adding non-compiled files as the sources of a CMake target; CMake will simply ignore them if it doesn't recognise their extension. So you can easily do this:
add_executable(example-program ${SOURCES} ${HEADERS} ${OTHER_FILES})
With files which could be confused for actual sources (based on their extension), there's always the option of setting their HEADER_FILE_ONLY property to true:
set_source_files_properties(
${OTHER_FILES}
PROPERTIES
HEADER_FILE_ONLY TRUE
)
I'll comment that I think both answers are correct, which to use depends on the particulars of the project.
Angew's answer adds the files to a single project, within the project.
In my case, Zeta's answer worked better, as I had files at the top-level of a project with subprojects, and having a new folder (with a name I could customize) in QtCreator better fit my needs.
Adding an additional answer, as I didn't see the differences between the two approaches mentioned.

How to use moc in a qmake project that doesn't use Qt modules?

I have a qmake project that includes the needed Qt source files directly, thus I don't need to link with any Qt libraries:
TEMPLATE = app
CONFIG -= qt
Yet the removal of Qt support also forces qmake not to process any headers with moc. Is there a workaround?
Yes:
CONFIG += moc
This causes the mkspecs/features/moc.prf to be included by qmake, adding moc to its repertoire.

Error: undefined reference to QQuickRectangle::QQuickRectangle(QQuickItem*)

I want to use Qt Quick 2 directly from C++ without those qml/javascript stuffs that could slows down the app, but i got compilation error when using QQuickRectangle (Rectangle when used from qml).
In .pro file i have: QT += quick quick-private core-private gui-private declarative-private qml-private
and in .cpp file - #include <private/qquickrectangle_p.h>
I compiled the Qt 5.5 from sources and the command nm -D /usr/local/Qt-5.5.0/lib/libQt5Quick.so.5 | grep "Rectangle"
doesn't print anything related to QQuickRectangle, so it looks that it is not included in the shared library, but i don't know why, because the qquickrectangle.cpp exists in qt sources, so it should be included in the shared library after compilation.

Resources