16

更新 2

少しいじった後 (および生成された Makefile を編集した後)、moc が適切に処理されていないように見えますMainWindow.h(インクルードされたソース ファイルと同じフォルダーにない限りmain.cpp、 moc によってインクルードされます)。MainWindow.cpp

Moc は で実行されMainWindow.cpp、インクルードを処理しないため、Q_OBJECT マクロが表示されないため、空の出力ファイルの生成に進みます。moc が通常インクルードを処理するのか、ディレクトリをスキャンするだけなのかはわかりませんが、いずれにせよ、mocing が必要であるが他のディレクトリにあるヘッダーは処理されていません!

アップデート

この問題は、moc によって生成される出力に関連しているようです。最初のケース (コンパイルされたもの) ではhello-world_automoc.cppmoc_MainWindow.cpp生成されます。hello-world_automoc.cppのように見える

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

2 番目のケースでhello-world_automoc.cppは、次のような a が生成されます。

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

そして、まったくありませんmoc_MainWindow.cpp。壊れた場合にautomocを使用する代わりにcmakeからmocを手動で呼び出すと、取得できますmoc_MainWindow.cppが空です。

元のステータス

まず、いいえ、忘れていませんset(CMAKE_AUTOMOC ON)また、デストラクタが宣言され、実装されMainWindowていることにも注意してください。

ディレクトリ構造が次のようになっている場合:

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

コンパイルは問題なく動作します。

ただし、次のように見える場合:

こんにちは世界/
|__ CMakeLists.txt
|__ src/
| | |__ CMakeLists.txt
| | |__ main.cpp
| | |__ MainWindow.cpp
| |
|__ inc/
| | |__ MainWindow.h
| |
|__グイ/
    |__ 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 を追加するという理由だけで、プロジェクト ディレクトリをフラット化することにそれほど熱心ではありません。

4

3 に答える 3

16

前述のように、MainWindow.hあなたの例では moc は処理されていません。これを強制的に実行する 1 つの方法は、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)
  • これを行うためのより良い方法があるかもしれません。
  • 同様の問題を抱えている他の人にとって、これまでのところ、このソリューションは、最初にこれに遭遇したより大きなプロジェクトで保持されています。失敗した場合は、それに応じて更新します。
于 2013-11-07T23:19:48.123 に答える
13

私は同じ問題を抱えていて、解決策を見つけました。Eric Lemanissierが GitHub の問題でコメントしたように:

このエラーはコナンとは関係ありません: ヘッダー ファイルを add_executable に追加する必要があります。そうしないと、moc はそれらを解析しません。

add_executableoradd_libraryステートメントを使用して、ヘッダー ファイルをプロジェクトに追加する必要があります。これを行わないと、automoc はファイルを解析しません。

于 2019-03-26T17:41:16.323 に答える
3

CMakeautomocが対応するファイルを見つけられないためだと思います。ここのドキュメントを確認してください: 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です。

これは推測に過ぎませんが、エラーの原因の可能性を排除するために、最初に automagic を使用せずに試してください。

また、ディレクトリ構造を変更した後、CMake キャッシュを完全に削除したことを確認してください。

于 2013-11-04T05:06:07.873 に答える