8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Qt 5 cmake 失败,在 hello world 中对 vtable 的引用未定义,其中 inc 和 src 为子目录

fantazea 1月前

44 0

更新 2经过一番折腾(以及对生成的 Makefile 进行了一些编辑),看起来发生的原因是 moc 没有正确处理 MainWindow.h(包含在 main.cpp 和

更新 2

经过一番捣鼓(以及对生成的 Makefile 进行一些编辑)之后,看起来发生的事情是 moc 没有被正确处理 MainWindow.h (包含在内 main.cpp MainWindow.cpp 除非它与包含它的源文件位于同一文件夹中)。

Moc 在 上运行 MainWindow.cpp ,不处理包含,因此看不到 Q_OBJECT 宏,因此继续生成一个空的输出文件。我不确定 moc 是否通常处理包含,或者它是否只扫描目录,但无论哪种方式,需要 mocing 但位于其他目录中的标头都不会被处理!

更新

问题似乎与 moc 生成的输出有关。在第一种情况下(编译的那种), hello-world_automoc.cpp 生成了 。 moc_MainWindow.cpp 看起来 hello-world_automoc.cpp

/* This file is autogenerated, do not edit*/
#include "moc_MainWindow.cpp"

在第二种情况下, hello-world_automoc.cpp 产生的结果是

/* This file is autogenerated, do not edit*/
enum some_compilers { need_more_than_nothing };

根本没有 moc_MainWindow.cpp 。如果我手动从 cmake 调用 moc,而不是在损坏的情况下使用 automoc,我会得到结果, moc_MainWindow.cpp 但它是空的。

原始状态

首先,我没有忘记 设置(CMAKE_AUTOMOC ON) 。还要注意, MainWindow 析构函数已声明并实现 .

当我的目录结构如下所示时:

CMakeLists.txt
|__ main.cpp
|__ MainWindow.cpp
|__ MainWindow.h
|__ MainWindow.ui

编译工作正常。

然而,当它看起来像:

helloworld/
|__ CMakeLists.txt
|__ src/
|   |__ CMakeLists.txt
|   |__ main.cpp
|   |__ MainWindow.cpp
|
|__ inc/
|   |__ MainWindow.h
|
|__ gui/
    |__ MainWindow.ui

我收到链接错误:

Linking CXX executable hello-world
CMakeFiles/hello-world.dir/MainWindow.cpp.o: In function `MainWindow::MainWindow()':
MainWindow.cpp:(.text+0x3b): undefined reference to `vtable for MainWindow'
MainWindow.cpp:(.text+0x4d): undefined reference to `vtable for MainWindow'
CMakeFiles/hello-world.dir/MainWindow.cpp.o: In function `MainWindow::~MainWindow()':
MainWindow.cpp:(.text+0xaf): undefined reference to `vtable for MainWindow'
MainWindow.cpp:(.text+0xc1): undefined reference to `vtable for MainWindow'
collect2: error: ld returned 1 exit status
make[2]: *** [src/hello-world] Error 1
make[1]: *** [src/CMakeFiles/hello-world.dir/all] Error 2

我真的很想将我的源和标题放在适当的子目录中,但我不太确定如何解决这个问题。

这实际上是大型项目中最简单的可识别错误情况,因此我并不热衷于扁平化项目目录,只是因为我要向其中添加 Qt GUI。

帖子版权声明 1、本帖标题:Qt 5 cmake 失败,在 hello world 中对 vtable 的引用未定义,其中 inc 和 src 为子目录
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由fantazea在本站《qt》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 如上所述,您的示例中没有处理 moc MainWindow.h 。强制执行此操作的一种方法是 qt_wrap_cpp() 直接调用它(而不是 on MainWindow.cpp ),然后将结果文件包含在对 add_executable() .

    您的顶级 CMakeLists.txt 可能看起来像:

    cmake_minimum_required(VERSION 2.8.9)
    
    #set(CMAKE_AUTOMOC ON)
    
    set(CMAKE_PREFIX_PATH "/opt/Qt/5.1.1/gcc_64")
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    
    project(hello-world)
    
    find_package(Qt5Widgets REQUIRED)
    
    set(HW_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/inc)
    set(HW_GUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/gui)
    
    include_directories(${HW_HEADER_DIR})
    
    subdirs(src)
    

    并且你的 src 级别一如下:

    qt5_wrap_cpp(hello-world_SRC ${HW_HEADER_DIR}/MainWindow.h)
    qt5_wrap_ui(hello-world_UI ${HW_GUI_DIR}/MainWindow.ui)
    
    add_executable(hello-world MainWindow.cpp main.cpp
                   ${hello-world_UI} ${hello-world_SRC})
    qt5_use_modules(hello-world Widgets)
    

    附录:

    • 在您的示例中,无论是否启用 AUTOMOC,此方法均有效。我不确定启用它是否会在将来导致问题。如果您不启用它,则必须手动 moc 任何其他内容……尽管它可能都像 MainWindow 一样运行,在这种情况下,无论如何您都需要手动 moc 标题。
    • 您不必在顶层 CMakeLists.txt 中设置目录变量,但我发现它比这样做更干净 qt5_wrap_cpp(hello-world_SRC ../inc/MainWindow.h)
    • 可能有更好的方法来做到这一点。
    • 对于有类似问题的任何人来说,到目前为止,这个解决方案已经在我最初遇到这个问题的较大项目中得到了证实。如果失败,我会进行相应的更新。
  • Eric Lemanissier 上评论道 — 使用 Q_OBJECT 在编译时给出 \'对 plop 的 vtable 的未定义引用\' :

    此错误与 conan 无关:您需要在 add_executable 中添加头文件,否则 moc 将无法解析它们

    add_executable 将头文件添加到项目中 add_library 。如果不这样做,automoc 将不会解析这些文件。

  • 好吧,也许 automoc 对你不起作用,我猜是因为 CMake 没有找到相应的文件。查看此处的文档: http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_tgt:AUTOMOC

    在这种情况下,你始终可以在你的文件中手动调用 moc 命令 CMakeLists.txt

    qt5_wrap_cpp(moc_sources src/MainWindow.cpp)
    qt5_wrap_ui(uic_sources src/MainWindow.cpp)
    
    list(APPEND library_sources ${moc_sources} ${uic_sources})
    

    注意:您必须确保自己正确使用 list 命令。此代码示例来自我的项目,其中我使用特定的源列表 ( library_sources )。

    这只是一个猜测,但您应该先尝试不使用自动化方法来排除一个可能的错误来源。

    另外,请确保在更改目录结构后完全删除了 CMake 缓存。

  • 1) 我确实完全删除了 CMake 缓存。2) 如果 automoc 对我来说不起作用,那么这两个版本肯定都无法编译?我还相当确定我可以在 Make 输出中看到 automoc 正在运行,并且构建树包含生成的文件。不过,我会尝试手动运行 moc,然后再回复您。

  • 更清楚一点,仅当使用子目录结构时手动调用 moc 时才会遇到同样的错误 - 在平面目录情况下手动调用 moc 可以正常工作,其中 automoc 也可以正常工作。

  • 这很奇怪。我也使用子目录,但在我的例子中,标题总是在同一个位置。我会向 Qt 项目提交错误报告。也许先用 qmake 尝试这个简单的例子,看看这是否与 CMake 有关。

  • 我有消息。我迟迟才想到要查看生成的 moc 文件。如果出现问题并且我使用 automoc,hello-world_automoc.cpp 仅包含枚举 (enum some_compilers { need_more_than_nothing };),没有其他内容,并且不会生成 moc_MainWindow.cpp。当我手动运行 moc 时,我得到一个空的 moc_MainWindow.cpp。如果确实有效,hello-world_automoc.cpp 包含 #include \'moc_MainWindow.cpp\',并且 moc_MainWindow.cpp 包含正确的生成方法。

返回
作者最近主题: