Qt 5 cmake失败,未定义的引用vtable on hello world with inc& src作为subdirs [英] Qt 5 cmake fails with undefined reference to vtable on hello world with inc & src as subdirs

查看:1592
本文介绍了Qt 5 cmake失败,未定义的引用vtable on hello world with inc& src作为subdirs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新2



在解决了一点(以及对生成的Makefile的一些编辑)之后,看起来发生的是moc没有正确处理 MainWindow.h (包含在 main.cpp MainWindow.cpp



Moc在 MainWindow.cpp 上运行,不处理include,因此没有看到Q_OBJECT宏,所以继续产生一个空的输出文件。我不知道moc通常进程包括或者它只是扫描目录,但无论如何,头,需要moction但是在其他目录中没有被处理!



更新



问题似乎与输出相关在第一种情况下(编译的那个), hello-world_automoc.cpp moc_MainWindow.cpp hello-world_automoc.cpp 看起来像

  / *此文件是自动生成的,不要编辑* / 
#includemoc_MainWindow.cpp

在第二种情况下,会生成一个 hello-world_automoc.cpp p>

  / *此文件是自动生成的,不要编辑* / 
enum some_compilers {need_more_than_nothing};

且没有 moc_MainWindow.cpp 所有。如果我在cmake中手动调用moc,而不是在破解的情况下使用automoc,我会得到 moc_MainWindow.cpp ,但它是空的。



原始状态



首先,没有,我没有忘记 set(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

我收到链接错误:

 链接CXX可执行文件hello-world 
CMakeFiles / hello-world.dir / MainWindow.cpp.o:在MainWindow :: MainWindow )':
MainWindow.cpp :(。text + 0x3b):未定义引用`vtable for MainWindow'
MainWindow.cpp :( .text + 0x4d):未定义引用`vtable for MainWindow'
CMakeFiles / hello-world.dir / MainWindow.cpp.o:在MainWindow ::〜MainWindow()函数中:
MainWindow.cpp :(。text + 0xaf):未定义引用`vtable for MainWindow'
MainWindow.cpp :(。text + 0xc1):未定义引用`vtable for MainWindow'
collect2:error:ld返回1退出状态
make [2]:*** [src / hello-world]错误1
make [1]:*** [src / CMakeFiles / hello-world.dir / all]错误2

我真的想在正确的子目录中有我的源代码和头文件,但我不太确定如何解决这个问题。



这实际上是一个更大的项目中错误的最简单的可识别的情况,所以我真的不是所有渴望平铺项目目录只是因为我添加一个Qt GUI。 / p>

解决方案

如上所述,moc不处理您的示例中的 MainWindow.h 。强制这种情况发生的一种方法是直接调用 qt_wrap_cpp()(而不是 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)

例如:

  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,在这种情况下你会手动mocing标头,不管。

  • 您不必在顶层CMakeLists.txt中设置目录变量,但我发现它比执行 qt5_wrap_cpp(hello-world_SRC ../inc/MainWindow.h)

  • 可能有更好的方法。

  • 对于有类似问题的人来说,


Update 2

After messing around a bit (and some editing of the generated Makefiles), it looks like what is happening is that moc is not properly processing MainWindow.h (included by main.cpp and MainWindow.cpp unless it is in the same folder as the source files which included it.

Moc runs on MainWindow.cpp, doesn't process the include and thus doesn't see the Q_OBJECT macro so proceeds to produce an empty output file. I'm not sure whether moc usually processes includes or if it just scans the directory, but either way, headers that need mocing but are in other directories are not being processed!

Update

The problem appears to be related to the output produced by moc. In the first case (the one that compiles), hello-world_automoc.cpp and moc_MainWindow.cpp are generated. hello-world_automoc.cpp looks like

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

In the second case, a hello-world_automoc.cpp is produced that looks like

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

and there is no moc_MainWindow.cpp at all. If I manually call moc in from cmake instead of using automoc in the broken case, I do get moc_MainWindow.cpp but it is empty.

Original Status

Firstly, no, I haven't forgotten to set(CMAKE_AUTOMOC ON). Also note that MainWindow's destructor is declared and implemented.

When my directory structure looks like:

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

compiling works just fine.

However, when it looks like:

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

I get linking errors:

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

I'd really like to have my sources and headers in proper subdirectories, but I'm not quite sure how to fix this.

This is actually the simplest identifiable case of an error from a much larger project, so I'm really not all that keen to flatten the project directories just because I'm adding a Qt GUI to it.

解决方案

As noted, moc is not processing MainWindow.h in your example. One way to force this to happen is to call qt_wrap_cpp() on it directly (instead of on MainWindow.cpp) and then include the resulting file in the call to add_executable().

Your top level CMakeLists.txt might look like:

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)

and your src level one like:

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)

Addendum:

  • This works in your example with and without AUTOMOC enabled. I don't know for sure if having it on will cause issues in the future. If you don't enable it you'll have to manually moc any other stuff... although it might all behave like MainWindow in which case you'll be manually mocing the headers regardless.
  • You don't have to set the directory variables in the top level CMakeLists.txt but I find it cleaner than doing qt5_wrap_cpp(hello-world_SRC ../inc/MainWindow.h)
  • There might be a better way of doing this.
  • For anybody else with similar issues, so far this solution has held up in the larger project that I initially encountered this in. I will update accordingly if it fails.

这篇关于Qt 5 cmake失败,未定义的引用vtable on hello world with inc& src作为subdirs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆