CD8*_*D86 3 c++ qt cmake qobject qmetaobject
我在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'的配方制作失败[2]:*** [gui / CMakeFiles / gui_automoc]错误1 CMakeFiles / Makefile2:234:配方目标'gui / CMakeFiles / gui_automoc.dir / all'失败
我没有弄错我的意思,或者是将src文件与Q_OBJECT宏合并到我的项目中的正确方法是什么。请帮助= /
gui / include / gui / mainWindow.hpp
#include <QMainWindow>
#include <string>
class MainWindow : public QMainWindow {
class MainWindowImpl;
public:
MainWindow(QWidget* parent = nullptr);
private:
MainWindowImpl* pimpl_;
};
Run Code Online (Sandbox Code Playgroud)
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_);
}
Run Code Online (Sandbox Code Playgroud)
我这样编译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)
Run Code Online (Sandbox Code Playgroud)
现在我想将此lib链接到我的可执行文件
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();
}
Run Code Online (Sandbox Code Playgroud)
与以下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)
Run Code Online (Sandbox Code Playgroud)
我的项目的顶级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)
Run Code Online (Sandbox Code Playgroud)
关于使用CMake编译Qt应用程序的典型困惑。基本上,有两种方法可以moc使用CMake 运行预处理器:
AUTOMOC财产的态度。它非常易于使用,但是有一些要求,在文档中已经提到。
确保AUTOMOC为目标启用了属性。
set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE)
Run Code Online (Sandbox Code Playgroud)如果您的.cpp文件包含Q_OBJECT宏,则需要.moc在最后一个qobject类之后(最好在文件末尾)包括生成的文件。对于此步骤,您还需要启用,CMAKE_INCLUDE_CURRENT_DIR但这是任何CMake + Qt构建的一般建议。
如果头文件包含,请Q_OBJECT确保CMake知道它。最简单的方法是与源文件一起传递:
add_library(${PROJECT_NAME}
SHARED
include/mainWindow.hpp
src/mainWindow.cpp
)
Run Code Online (Sandbox Code Playgroud)最后链接所有必需的Qt库。
target_link_libraries(${PROJECT_NAME}
PUBLIC
Qt5::Widgets
Qt5::Core
)
Run Code Online (Sandbox Code Playgroud)因此,以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"
Run Code Online (Sandbox Code Playgroud)
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
)
Run Code Online (Sandbox Code Playgroud)
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_;
};
Run Code Online (Sandbox Code Playgroud)
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_);
}
Run Code Online (Sandbox Code Playgroud)
并在中添加其他标题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
)
Run Code Online (Sandbox Code Playgroud)
注意!小心moc使用复杂语法的类,因为存在局限性。
| 归档时间: |
|
| 查看次数: |
1934 次 |
| 最近记录: |