Qt 5 cmake завершается неудачно с неопределенной ссылкой на vtable в hello world с inc & amp; src as subdirs

Обновление 2

После небольшой работы (и некоторого редактирования сгенерированных Make-файлов), похоже, что происходит то, что moc не обрабатывает должным образом MainWindow.h (включено main.cpp а также MainWindow.cpp если он не находится в той же папке, что и исходные файлы, в которые он был включен.

Мок работает на MainWindow.cpp, не обрабатывает включение и, следовательно, не видит макрос Q_OBJECT, поэтому переходит к созданию пустого выходного файла. Я не уверен, включает ли moc обычно процессы или просто просматривает каталог, но в любом случае заголовки, которые требуют перемещения, но находятся в других каталогах, не обрабатываются!

Обновить

Проблема, по-видимому, связана с продукцией, производимой 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 совсем. Если я вручную вызываю moc из cmake вместо использования automoc в неработающем случае, я получаю moc_MainWindow.cpp но пусто

Исходный статус

Во-первых, нет, я не забыл set(CMAKE_AUTOMOC ON). Также обратите внимание, что MainWindow«s деструктор объявлен и реализован.

Когда моя структура каталогов выглядит так:

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

компиляция работает просто отлично.

Тем не менее, когда это выглядит так:

Привет, мир/
| __ 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.

10

Решение

Как уже отмечалось, МОК не обрабатывает 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)

и ваш уровень 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. Я не знаю наверняка, если это будет вызывать проблемы в будущем. Если вы не включите его, вам придется вручную перемещать любой другой материал … хотя все это может вести себя как MainWindow, в этом случае вы будете вручную перемещать заголовки независимо от этого.
  • Вам не нужно устанавливать переменные каталога в верхнем уровне CMakeLists.txt, но я считаю, что это чище, чем делать qt5_wrap_cpp(hello-world_SRC ../inc/MainWindow.h)
  • Там может быть лучший способ сделать это.
  • Для всех, кто сталкивался с подобными проблемами, до сих пор это решение задерживалось в более крупном проекте, с которым я изначально сталкивался. Я обновлю соответствующим образом, если он потерпит неудачу.
10

Другие решения

Хорошо, может быть 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 после изменения структуры каталогов.

3

По вопросам рекламы [email protected]