簡體   English   中英

無法在CMake項目中使用Q_OBJECT宏

[英]fail to use Q_OBJECT Macro in CMake Project

我在我的CMake項目中使用Qt的元對象編譯器時遇到了問題。 我正在構建的共享庫包含以下代碼並使用了pimpl習慣用法。 在調用CMake並編譯后,我得到了

AUTOGEN:錯誤:〜/ tools / Project / gui / src / mainWindow.cpp:該文件包含一個Q_OBJECT宏,但不包含“mainWindow.moc”! gui / CMakeFiles / gui_automoc.dir / build.make:57:目標'gui / CMakeFiles / gui_automoc'的配方失敗make [2]:*** [gui / CMakeFiles / gui_automoc]錯誤1 CMakeFiles / Makefile2:234:食譜目標'gui / CMakeFiles / gui_automoc.dir / all'失敗

我不知道我做錯了什么,或者在我的項目中使用Q_OBJECT宏合並src文件的正確方法是什么。 請幫忙= /

GUI /包括/ GUI / mainWindow.hpp

#include <QMainWindow>
#include <string>


class MainWindow : public QMainWindow {
  class MainWindowImpl;

 public:
  MainWindow(QWidget* parent = nullptr);

 private:
  MainWindowImpl* pimpl_;
};

GUI / SRC / 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_);
}

我像這樣編譯libray:

cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(gui)

QT5_WRAP_CPP(MOC_Files
include/gui/mainWindow.hpp
)

add_library(${PROJECT_NAME}
  SHARED
   src/mainWindow.cpp
   ${MOC_Files}
)
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)

現在我想將此lib鏈接到我的可執行文件

應用程序/ 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();
}

使用以下CMakelists.txt,我鏈接到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)

我的項目的頂級CMakeLists如下所示

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)

關於使用CMake編譯Qt應用程序的典型困惑。 基本上有兩種方法可以使用CMake運行moc預處理器:

1. CMake使用AUTOMOC屬性的方法。

它非常易於使用,但有一些文檔中提到的要求。

  • 確保為目標啟用了屬性AUTOMOC

     set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE) 
  • 如果.cpp文件包含Q_OBJECT宏,則需要在最后一個qobject類之后包含生成的.moc文件(在文件末尾更好)。 對於此步驟,您還需要啟用CMAKE_INCLUDE_CURRENT_DIR但它是任何CMake + Qt構建的一般建議。

  • 如果您的頭文件包含Q_OBJECT確保CMake知道它。 最簡單的方法是傳遞源文件:

     add_library(${PROJECT_NAME} SHARED include/mainWindow.hpp src/mainWindow.cpp ) 
  • 最后鏈接所有必需的Qt庫。

     target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets Qt5::Core ) 

所以以CMake的方式修復你的代碼:

GUI / src目錄/ 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_);
}

#include "mainWindow.moc"

GUI /的CMakeLists.txt:

project(gui)

set(CMAKE_INCLUDE_CURRENT_DIR YES)

add_library(${PROJECT_NAME}
  SHARED
  include/gui/mainWindow.hpp
  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
)

2. Qt方法與QT5_WRAP_CPP

在這里,您只需要“包裝”所有包含Q_OBJECT頭文件,並將結果添加到源文件列表中。

或者如果你在cpp文件中有一個類,它會變得棘手。 Q_OBJECT宏將成員函數添加到類中。 在類體外部的任何類成員函數的實現需要知道類聲明。 這些實現位於生成的.moc文件中,但是它們無法看到類的聲明。 解決它的最簡單方法是將.cpp文件拆分為兩個:

GUI / src目錄/ mainWindowImpl.hpp:

#pragma once
#include "gui/mainWindow.hpp"

class MainWindow::MainWindowImpl : public QWidget{
 Q_OBJECT
  public:
   explicit MainWindowImpl(MainWindow *parent);

  private:
   MainWindow &parent_;
};

GUI / src目錄/ mainWindow.cpp:

#include "gui/mainWindow.hpp"
#include "mainWindowImpl.hpp"

MainWindow::MainWindowImpl::MainWindowImpl(MainWindow *parent)
    : QWidget{parent}, parent_(*parent) {}

MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent} {
    pimpl_ = new MainWindowImpl{this};
    setCentralWidget(pimpl_);
}

並在QT5_WRAP_CPP添加其他標頭:

GUI /的CMakeLists.txt:

project(gui)

QT5_WRAP_CPP(MOC_Files
  include/mainWindow.hpp
  src/mainWindowImpl.hpp
)

add_library(${PROJECT_NAME}
  SHARED
   src/mainWindow.cpp
   ${MOC_Files}
)
add_library(gui::gui ALIAS ${PROJECT_NAME})

target_include_directories(${PROJECT_NAME} 
  PUBLIC 
   ${PROJECT_SOURCE_DIR}/include
)

target_link_libraries(${PROJECT_NAME}
  PUBLIC
   Qt5::Widgets
   Qt5::Core
)

注意! 由於存在限制 ,請注意使用復雜語法的moc和類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM