После небольшой работы (и некоторого редактирования сгенерированных 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.
Как уже отмечалось, МОК не обрабатывает 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)
Приложение:
qt5_wrap_cpp(hello-world_SRC ../inc/MainWindow.h)
Хорошо, может быть 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 после изменения структуры каталогов.