10

Qt Creator で作成された ui ファイルをロードする Qt ウィジェット C++ クラスがあります。クラスのヘッダーとソース ファイルは、2 つの別個のディレクトリにあります。クラスのヘッダーを見つけるように cmake/automoc に指示するのに問題があります。cmake は、C++ ファイルをモックする必要があることを認識しますが、類似のヘッダーを見つけることができません。

cmakeがファイルを見つけるのを助けるためにできることはありますか?

cpp とヘッダー ファイルの両方が同じディレクトリにあれば、すべて正常に動作します。これは、ヘッダーが他の場所にある場合にのみ発生します。

私のディレクトリ構造は

project
    src
        include
            Foo
                Bar.h
    lib
        Foo
            Bar.cpp
            forms
                Bar.ui           

src/include/Foo/Bar.h には次のものがあります。

// Bar.h
#include <QtWidgets/QWidget>

namespace Ui { class Bar; }

class Bar : public QWidget {
    Q_OBJECT
    ...
}

src/Foo/Bar.cpp ファイル:

#include "Foo/Bar.h"
#include "moc_Bar.cpp"
#include "ui_Bar.h"

src/lib/Foo の CMakeLists.txt は次のように設定されています。

# there is a project() call at the root that defines PROJECT_SOURCE_DIR
set(PUBLIC_HEADERS_DIR ${PROJECT_SOURCE_DIR}/src/include)

# Pick up public library headers
include_directories(${PUBLIC_HEADERS_DIR})

# Pick up private headers in library dir    
include_directories(${CMAKE_CURRENT_SOURCE_DIR})

# Set up Qt
set(CMAKE_AUTOMOC ON)                    
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED) 
include_directories(${Qt5Core_INCLUDE_DIRS})
include_directories(${Qt5Gui_INCLUDE_DIRS})
include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_definitions(${Qt5Widgets_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")

# Set up Qt forms/resources
qt5_wrap_ui(UI_OUT_FILES forms/Bar.ui)
qt5_add_resources(RESOURCE_FILE resources.qrc)

# Library cpp and header files
set(CORE_CPP_FILES Bar.cpp)
set(LIB_CPP_FILES ${LIB_CPP_FILES} ${CORE_CPP_FILES} ${UI_OUT_FILES} ${RESOURCE_FILE}) 
set(LIB_HEADER_FILES ${PUBLIC_HEADERS_DIR}/Foo/Bar.h)

# Build library
add_library(Foo SHARED ${LIB_CPP_FILES} ${LIB_HEADER_FILES})
target_link_libraries(Foo ${Qt5Widgets_LIBRARIES})

cmake を実行すると、次のエラーが表示されます。

AUTOGEN: エラー: /automoc/src/lib/Foo/Bar.cpp ファイルには moc ファイル "moc_Bar.cpp" が含まれていますが、ヘッダー "Bar{.h,.hh,.h++,.hm,.hpp" が見つかりませんでした,.hxx,.in,.txx}" /automoc/src/lib/Foo/

4

2 に答える 2

3

ヘッダー ファイルを手動でラップする必要があります。それを CMakeLists.txt に入れます。

file(GLOB HEADERS_TO_MOC src/include/Foo/ *.h)

qt5_wrap_cpp(PROCESSED_MOCS                                                                                                                                                                                                                                                                    
             ${HEADERS_TO_MOC}                                                   
             TARGET Foo
             OPTIONS --no-notes) # Don't display a note for the headers which don't produce a moc_*.cpp

target_sources(Foo PRIVATE ${PROCESSED_MOCS}) # This adds generated moc cpps to target

このアプローチの実際の例 https://github.com/paceholder/nodeeditor/blob/master/CMakeLists.txt#L133

于 2016-04-21T13:10:35.960 に答える
0

AUTOMOCこれの回避策は、独自のデバイスに任せるだけで簡単にできることがわかりました。これが私がしていることです(現在、サポートされているすべてのCMakeバージョンで機能します3.2...3.17):

  1. ファイルから行を削除#include "moc_Bar.cpp"ますBar.cpp
  2. 外部 (現在のディレクトリ) ヘッダー ファイルをPRIVATEターゲットのソースとして追加します。
set(CMAKE_AUTOMOC True)
target_sources(Foo PRIVATE
  ${CMAKE_SOURCE_DIR}/src/include/Foo/Bar.h
  ${CMAKE_SOURCE_DIR}/src/include/Foo/Baz.h)

AUTOMOCFoo_autogen問題のファイルをMOCすると、出力ディレクトリが作成されます。ランダムな名前のサブディレクトリに作成され、次のような内容のmoc_Bar.cppファイルが作成されます。moc_Baz.cppABDEADBEEFmocs_compilation.cpp

// This file is autogenerated. Changes will be overwritten.
#include "ABDEADBEEF/moc_Bar.cpp"
#include "ABDEADBEEF/moc_Baz.cpp"

そのファイルはコンパイルされ、ターゲットの最終出力にリンクされます。

CMAKE_AUTOMOCglobal setを使用Trueすると、各ターゲットも独自のtarget_autogenディレクトリを受け取りますが、MOC 可能なクラスを持たないターゲットでは何も生成されません。AUTOMOCそれでも、それを必要とするターゲットにのみ target プロパティを設定する方が良いかもしれません:

set_property(TARGET Foo PROPERTY AUTOMOC ON)
于 2020-02-25T18:19:17.810 に答える