qt - 使用 CMake 将带有 .pro 文件的 Qt 项目转换为项目 - moc 问题

标签 qt cmake moc

我有一个项目,当我使用 QtCreator 使用 .pro 文件构建它时,它编译得很好。我正在尝试将其转换为 cmake,但遇到了问题。

使用最小的可重现示例进行编辑:

项目文件夹结构:

src/foo.cpp   --> #include "ui_foo.h"
src/bar.cpp   --> #include "bar.moc"
inc/foo.h   
ui/foo.ui    

预期的编译流程(使用qmake时观察到的流程):

(1)  moc  inc/foo.h              -o moc_foo.cpp
(2)  moc  src/bar.cpp            -o bar.moc
(3)  uic  ui/foo.ui              -o ui_foo.h
(4)  gcc  src/foo.cpp            -o foo.o
(5)  gcc  src/bar.cpp            -o bar.o
(6)  gcc  moc_foo.cpp            -o moc_foo.o
(7)  ld   foo.o bar.o moc_foo.o  -o foobar

CMakeLists.txt(1):

set(CMAKE_INCLUDE_CURRENT_DIR ON )
set(CMAKE_AUTOMOC ON )
set(CMAKE_AUTOUIC ON )
add_executable(foobar src/foo.cpp src/bar.cpp)

moc_foo.cpp 未创建(缺少第 1 步和第 6 步)并且未在第 7 步中添加到 add_executable 中。未定义的 vtable 引用发生是因为丢失的对象。我认为这是因为 foo.cpp 和 foo.h 在不同的文件夹中。

CMakeLists.txt(2):

set(CMAKE_INCLUDE_CURRENT_DIR ON )
qt5_wrap_cpp(foobar_moc inc/foo.h src/bar.cpp)
qt5_wrap_ui (foobar_ui  ui/foo.ui)
add_executable(foobar src/foo.cpp src/bar.cpp ${foobar_moc} ${foobar_ui})

moc_bar.cpp 在步骤 2 中生成而不是 bar.moc。我收到编译器错误,因为找不到 bar.moc在第 5 步中。

最佳答案

你试图通过 moc .cpp 文件来让你自己的生活变得不必要。

尽管名称 qt5_wrap_cpp 实际上将头文件 作为其参数并调用 moc 以生成匹配的 cpp 文件:

qt5_wrap_cpp(foobar_moc inc/foo.h)

# ${foobar_moc} will contain the name 
# of the .cpp file created for foo.h
# which we pass to add_executable()

请注意,通常您还会在某处放置一个 foo.cpp 源文件,它与由 moc 生成的 .cpp 一起提供完整的实现foo.h 中定义的类。

现在,如果您真的想在 .cpp 文件上调用 moc,过程会略有不同。在这里,由于类定义不再在头文件中,因此 moc 生成的源文件无法访问它引用的类定义。结果,生成的源文件不能再自行编译。相反,您需要使用 #include 在类定义之后将其拉入原始源文件,这不是很好。

更糟糕的是,对于 CMake 调用 moc 命令,生成的源文件仍然需要在某处成为依赖链的一部分,这使得一切变得非常丑陋。

我们将使用 qt5_generate_mocbar.cpp 上调用 moc 的命令(因为 qt5_wrap_cpp 还会将生成的源添加到构建中,这会中断):

qt5_generate_moc(src/bar.cpp ${CMAKE_BINARY_DIR}/bar.moc)

请注意,我们将生成的文件放在二叉树中,以免生成的文件污染源树。如果你设置了 AUTOGEN_BUILD_DIR ,您可能希望将生成的文件放在那里。为了让 #include 找到生成的文件,我们将二叉树添加到项目的 include 目录中:

target_include_directories(foobar PUBLIC ${CMAKE_BINARY_DIR})

最后,我们需要一个构建步骤依赖项的自定义目标。否则,moc 命令将永远不会真正被调用:

add_custom_target(moc_dummy DEPENDS ${CMAKE_BINARY_DIR}/bar.moc)
add_dependencies(foobar moc_dummy)

底线:只需将所有类定义移动到头文件,然后移动它们。没有缺点,您会为自己省去很多难看的样板文件。

关于qt - 使用 CMake 将带有 .pro 文件的 Qt 项目转换为项目 - moc 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46097066/

相关文章:

qt - 不同的 QMessageBox.Roles 是什么意思?

c++ - 超时时暂停线程

c++ - 如何处理来自不同开发环境的提交?

c++ - 在 LGPL 下的商业产品中使用 Qt 时如何允许私有(private)修改

c++ - 什么//! [0] 在 Qt C++ 示例代码中是什么意思?

cmake - Cmake 是否正确处理递归构建

android - 可以在 gradle 中为每个 ABI 设置 cmake 参数吗?

qt - 如何在Qmake项目中向MOC添加特定标志?

visual-studio - cmake + qt + Visual Studio : moc objects on build