How do I use Qt headers in a CMake sub-project?
-
I'm using Windows. I have a CMake project that uses Qt and I wish to divide it into subprojects for clarity.
However, if I compile a class outside of the root folder, I get an error that CMake cannot find the Qt headers.
For example, let's say I have the following project tree :
root/ -->gui/ -->CMakeLists.txt -->mainwindow.cpp -->mainwindow.h -->CMakeLists.txt -->main.cpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5) project(testcmake VERSION 0.1 LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED) add_subdirectory(gui) set(PROJECT_SOURCES main.cpp) add_executable(testcmake ${PROJECT_SOURCES}) target_link_libraries(testcmake PRIVATE gui Qt${QT_VERSION_MAJOR}::Widgets)
main.cpp:
#include "gui/mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
gui/CMakeLists.txt:
set(GUI_SRC mainwindow.cpp mainwindow.h) add_library(gui ${GUI_SRC})
gui/mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class QPushButton; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: QPushButton *m_button; }; #endif // MAINWINDOW_H
gui/mainwindow.cpp:
#include "mainwindow.h" #include <QPushButton> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { m_button = new QPushButton("Hello CMake!", this); m_button->resize(150, 50); } MainWindow::~MainWindow() { }
In this example, if I put class MainWindow in the root folder, the project compiles. But MainWindow class is in a subfolder, I get this error:
[build] ...\build\gui\gui_autogen\include_debug\ewiega46ww\../../../../../gui/mainwindow.h(4): fatal error C1083: Impossible d'ouvrir le fichier include : 'QMainWindow' : No such file or directory [...\build\gui\gui.vcxproj] [build] mainwindow.cpp [build] ...\gui\mainwindow.h(4): fatal error C1083: Impossible d'ouvrir le fichier include : 'QMainWindow' : No such file or directory [...\build\gui\gui.vcxproj]
Which means, at the preprocessing step, the compiler cannot find any Qt header file, because the source file is in a sub-folder.
How do I let CMake use the Qt headers, which are retrieved from thefind_package
command in the root folder? -
I've been bitten by this before; forgetting to add a library to a target_link_libraries() statement and getting 'include' errors during compilation. Then, not checking the target_link_libraries() statements; wrongly think they would only come into play during linking.
-
If you want to use a library you have to link against this library with target_link_libraries()
-
I've been bitten by this before; forgetting to add a library to a target_link_libraries() statement and getting 'include' errors during compilation. Then, not checking the target_link_libraries() statements; wrongly think they would only come into play during linking.
-
OK, I think I have a solution, or maybe a workaround. I added linking to the Qt libraries at the end of gui/CMakeLists.txt:
set(GUI_SRC mainwindow.cpp mainwindow.h) add_library(gui ${GUI_SRC}) target_link_libraries(gui PUBLIC Qt${QT_VERSION_MAJOR}::Widgets)
and then it compiles.
Even though it's just a library, I guess I still need to link the Qt libraries so my code can use the header files. -
@tuzepoito said in How do I use Qt headers in a CMake sub-project?:
I think I have a solution, or maybe a workaround.
Why workaround? If you want to use a library, you have to link against it what you're doing now - how should this be a workaround?