fail to use Q_OBJECT Macro in CMake Project
-
I am having trouble with the meta Object Compiler of Qt in my CMake Project. A shared lib I am building contains the following code and employs the pimpl idiom. After invoking CMake and upon compilation I get
AUTOGEN: error: ~/tools/Project/gui/src/mainWindow.cpp: The file contains a Q_OBJECT macro, but does not include "mainWindow.moc" ! gui/CMakeFiles/gui_automoc.dir/build.make:57: recipe for target 'gui/CMakeFiles/gui_automoc' failed make[2]: *** [gui/CMakeFiles/gui_automoc] Error 1 CMakeFiles/Makefile2:234: recipe for target 'gui/CMakeFiles/gui_automoc.dir/all' failed
I dont get what I am doing wrong or whats the correct way to incorporate src files with the Q_OBJECT Macro in my project.
Please help =/
gui/src/mainWindow.hpp
#include <QMainWindow> #include <string> class MainWindow : public QMainWindow { class MainWindowImpl; public: MainWindow(QWidget* parent = nullptr); private: MainWindowImpl* pimpl_; }; gui/include/gui/mainWindow.cpp #include "gui/mainWindow.hpp" class MainWindow::MainWindowImpl : public QWidget{ Q_OBJECT public: explicit MainWindowImpl(MainWindow *parent); private: MainWindow &parent_; }; MainWindow::MainWindowImpl::MainWindowImpl(MainWindow *parent) : QWidget{parent}, parent_(*parent) {} MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent} { pimpl_ = new MainWindowImpl{this}; setCentralWidget(pimpl_); }
I compile the library like so:
cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR) project(gui) add_library(${PROJECT_NAME} SHARED src/mainWindow.cpp ) add_library(gui::gui ALIAS ${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include ) set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE) target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets Qt5::Core Qt5::Xml Qt5::OpenGL Qt5::Gui ) install(TARGETS ${PROJECT_NAME} DESTINATION lib)
Now I want to link this lib against my executable
apps/main.cpp #include <QApplication> #include "gui/mainWindow.hpp" int main(int argc, char *argv[]) { QApplication app{argc, argv}; MainWindow gui{}; gui.show(); return app.exec(); }
with the following CMakelists.txt where I link against the gui lib
cmake_minimum_required (VERSION 3.5.1 FATAL_ERROR) project (app) add_executable(${PROJECT_NAME} main.cpp ) target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR} ) target_link_libraries(${PROJECT_NAME} PRIVATE gui::gui Qt5::Widgets Qt5::Core Qt5::Xml Qt5::OpenGL Qt5::Gui ) install(TARGETS ${PROJECT_NAME} DESTINATION bin)
my top-level CMakeLists of the project looks like the following
cmake_minimum_required (VERSION 3.5.1 FATAL_ERROR) project(project) set(CMAKE_INSTALL_DIR ${PROJECT_SOURCE_DIR}/obj) set(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_DIR}) # add our local path to the runtime path SET(CMAKE_INSTALL_RPATH "$ORIGIN:${CMAKE_INSTALL_PREFIX}/lib") # also add the link paths to the runtime paths SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) find_package(Qt5 COMPONENTS Core Widgets Xml OpenGL Gui REQUIRED) ## --> Build libraries and applications <-- add_subdirectory(gui) add_subdirectory(apps)
-
@Sewing said in fail to use Q_OBJECT Macro in CMake Project:
Anyone?
It's only 2 hours since your initial post. Please show a little more patience, like 24 hours. It's always nighttime for half of the community. And it's friday.
-
Hi,
Did you already took a look at the CMake Manual from Qt's documentation ?
-
The problem is not CMake:
@Sewing said in fail to use Q_OBJECT Macro in CMake Project:
mainWindow.cpp: The file contains a Q_OBJECT macro
from http://doc.qt.io/qt-5/moc.html
The moc tool reads a C++ header file.
Did you declare a class with
Q_OBJECT
in a .cpp file? if so either yo do as the compiler tells you and#include "mainWindow.moc"
(this file name might change depending on how moc gets invoked) at the end of the file or, as I would recommend, move it into a header -
Then move the private declaration part in its own header that you only include in the implementation part.
Note that your MainWindow implementation looks a bit convoluted, you might be over-engineering some things.
-
@Sewing said in fail to use Q_OBJECT Macro in CMake Project:
pimpl idiom in which the nested implementation class in defined entirely within the source file
You can move it into a header file, Qt does it all the time, they use
_p.h
suffix to mark private headers. For example: QDateTimePrivate -
so if I understood correctly, the reason of having to do this is that the Q_OBJECT Macro has to be defined in the header file instead of the source file?
and after doing so, is the line
set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE)
sufficient for invoking the MOC in my CMakeLists file?
-
@SGaist said in fail to use Q_OBJECT Macro in CMake Project:
Did you already took a look at the CMake Manual from Qt's documentation ?
@Sewing said in fail to use Q_OBJECT Macro in CMake Project:
I did
from http://doc.qt.io/qt-5/cmake-manual.html:
# Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON)