How to make CMake use AUTOMOC without find_package? - qt

Currently, I have Qt dlls and include headers as a dependency in my repo. I wanted to make use of CMake's CMAKE_AUTOMOC functionality providing a moc.exe binary along with dlls and include files. CMake allows to set a custom path to binary but it fails to use CMAKE_AUTOMOC functionality.
CMake Warning (dev) in myproj/CMakeLists.txt:
AUTOGEN: No valid Qt version found for target myproj_QT. AUTOMOC
disabled. Consider adding:
find_package(Qt<QTVERSION> COMPONENTS Core)
to your CMakeLists.txt file.
I don't want to use find_package all stuff like that. I want to make dependency management as much straightforward and explicit as it can be. Is there a way to enable automoc/autouic/autorcc features with my approach?

Adding that code helped me. Thanks #Tsyvarev for pointing out
set(PROGRAM_EXTENSION)
if (WIN32)
set(PROGRAM_EXTENSION .exe)
endif()
set(AUTOMOC_EXECUTABLE ${CMAKE_SOURCE_DIR}/3rdparty/qt5/bin/${OS}/moc${PROGRAM_EXTENSION})
add_executable(Qt5::moc IMPORTED)
set_target_properties(Qt5::moc PROPERTIES IMPORTED_LOCATION "${AUTOMOC_EXECUTABLE}")
set(Qt5Core_VERSION_MAJOR 5)
set(Qt5Core_VERSION_MINOR 15)
set(CMAKE_AUTOMOC TRUE)
Qt5CoreMacros.cmake must be included before

Related

Import CMake Project into an existing QT Project .pro

I have a QT Project I am working on, it has a couple of sub-modules, which I list in my project's .pro file as:
if(!include(module/my_module.pri)){
error("module my_module not found")
}
What I tried:
Well, I have found a library which I intend to use, which is a CMake project libcrashreporter-qt. I am just linking the project for completeness - there is nothing wrong with this library (to my knowledge)
Problem:
I figured I will try an include the CMakeLists.txt file as I would a .pri file:
if(!include(libcrashreporter-qt/CMakeLists.txt)){
error("module libcrashreporter-qt not found")
}
where the libcrashreporter-qt folder is in the root of my project
Some Code:
In doing so, I get a horde of compiler errors:
$project_dir/libcrashreporter-qt/CMakeLists.txt:1: 'project' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:2: 'cmake_minimum_required' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:4: Extra characters after test expression.
$project_dir/libcrashreporter-qt/CMakeLists.txt:5: 'cmake_policy' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:6: 'endif' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:10: 'find_package' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:12: Opening parenthesis without prior test name.
$project_dir/libcrashreporter-qt/CMakeLists.txt:16: 'string' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:17: 'string' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:18: 'endif' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:20: 'add_subdirectory' is not a recognized test function.
$project_dir/libcrashreporter-qt/CMakeLists.txt:21: 'add_subdirectory' is not a recognized test function.
CMake file content (note, I changed the file slightly trying to resolve build issues by removing the multi-line if-statement and commented the option line):
project(libcrashreporter-qt)
cmake_minimum_required(VERSION 3.1)
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
#option(ENABLE_GPL_CODE OFF)
find_package(Qt5 COMPONENTS Core Network Widgets)
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_FLAGS) OR (UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
# Breakpad uses GNU compiler extensions like typeof.
# Luckily these features are not used on OSX, so we can build the
# crashreporter there with the normal C++11 standard.
string(REPLACE "-std=c++11" "-std=gnu++11" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REPLACE "-std=c++14" "-std=gnu++14" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
endif()
add_subdirectory(3rdparty)
add_subdirectory(src)
This leads me to believe there is an issue with Qt .pro file compatibility and CMake projects being used within each other.
Question:
How can access the library functions of this CMake project, and compile it with my project (i.e. w/o changing the CMake project itself), or alternatively how best can I convert the CMake project to a compatible .pro project?
AFAIK CMake and QMake cannot be mixed together in one project, they are two different build systems and if you want to use a CMake project in a QMake project you have "two" options:
if you want to use the source files (.cpp and .h) or even modify them in your project you have to import them to your QMake project (you can easily do that in your QtCreator) and compile all of the files of your project
if the CMake library that you are using doesn't need any change (most of the times it's like this when you're using a third party library) and you just want to import it to your project and link it against your executable, you just run and compile the CMake project (separate from your own QMake project) and then use the output dynamic or static library of that project to link against your QMake project
As far as I remember, in Qt you can specify the custom compiler settings for the extra target, so, if you need your CMake project to be rebuilt just before the target Qt application is built, you can try to use this way
A possible solution is here:
https://stackoverflow.com/a/15766946/2333496

Compiling libwebsocket with newest QT

It appears that libwebsocket is the only library that does not come with Qt, so I think I need to compile it and install it in my QT folder so I can use with other things.
I tried to compile libwebsocket and I got this error:
qwebsocket_p.h:65:10: fatal error: private/qobject_p.h: No such file or directory
#include <private/qobject_p.h>
I believe this is because the QT in my system is old. I have a QT installation in my home folder. How should I pass it to websocket?
If it were with cmake I'd have an idea, but I've heard here https://stackoverflow.com/a/49108604/10116440 that you cannot pass qt folder to qmake. Is there a way to pass to make?
I also tried doing this in cmake:
find_package(Qt5WebSockets REQUIRED)
find_package(Qt5 COMPONENTS Core Qml Quick Svg)
this way I can do cmake -DQt5_DIR=/home/lz/Qt5.11.2 . to set the Qt5 variable for everything except Qt5WebSockets, but the project fails to include <QWebSocket> anyway. If someone knows how to solve this, it'd also be good
private/qobject_p.h: No such file or directory
That means that the directory containing qobject_p.h was not added to the Include paths list. Make sure that your .pro has QT += core-private string.
I have a QT installation in my home folder. How should I pass it to websocket?
It should be enough to put the file named qt.confto the directory containing qmake.exe:
qt.conf
[Paths]
Prefix = <qt root>

How to set qt5 path with cmake find_package on Windows?

I am adding QT like this:
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
...
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick ${OpenCV_LIBS})
but cmake finds some python artifacts instead of expected C:\QT...
How can I change this? Tried to find some examples, but didn't find any clear instruction, which subfolder of C:\QT\ I should specify (any where).
find_package search order is following:
Search in cache variables:
CMAKE_PREFIX_PATH, CMAKE_FRAMEWORK_PATH, CMAKE_APPBUNDLE_PATH
Search in environment variables: <package>_DIR, CMAKE_PREFIX_PATH, CMAKE_FRAMEWORK_PATH, CMAKE_APPBUNDLE_PATH.
Search in the HINTS option.
Search the PATH environment variable.
And in some more "desperate" places. More about that here.
With that in mind there are several ways to provide a proper version to QT:
Have an environment variable pointing to the proper version of QT (e.g. QTDIR). And use it in the CMake files:
like set(CMAKE_PREFIX_PATH "$ENV{QTDIR}")
or find_package(Qt5 HINTS "$ENV{QTDIR}" COMPONENTS Core Quick REQUIRED)
Have an environment variable explicitly named Qt5_DIR pointing to the proper version of QT. Then no additional changes to CMake files are required.
Make sure that required version of Qt is the first one to be found in the PATH environment variable, for example, for windows C:\Qt\Qt5.10.1\5.10.1\msvc2017_64
You can set click the Add Entry button in CMake Gui and add a new variable called Qt5_DIR, select its type as PATH and its value to something like C:\Qt\5.11.0\msvc2017_64\lib\cmake\Qt5 where 5.11.0 is the Qt version. This folder must contain Qt5Config.cmake that CMake needs to set things up correctly.
My workaround was to put desired QT to the top of PATH variable. It has to be in PATH if you want CMAKE to find it.

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 can I use CMake's AUTOMOC feature with a custom Qt package?

I'm working on converting an existing project to CMake. I'd like to use CMake's built-in AUTOMOC feature, but since I can't use find_package(Qt4) (due to the custom location of the project's Qt4 binaries/libs/headers/etc.) it's not clear how to enable it. What's the magic sauce?
Here's a portable makefile snippet that triggers automoc:
set(CMAKE_AUTOMOC TRUE)
set(QT_VERSION_MAJOR 4)
find_program(QT_MOC_EXECUTABLE qt_moc48 PATHS ${MY_BINARIES})
add_executable(Qt4::moc IMPORTED)
set_property(TARGET Qt4::moc PROPERTY IMPORTED_LOCATION ${QT_MOC_EXECUTABLE})

Resources