我有一个Qt小部件C ++类,它加载在Qt Creator中创建的ui文件。该类的头文件和源文件位于两个单独的目录中。我无法指示cmake / automoc找到该类的标头。 cmake认识到它需要moc 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}“in / automoc / src / lib / Foo /
答案 0 :(得分:1)
尝试以下技巧:
1)将原始.h和.cpp放入库源文件夹:
lib
Foo
Bar.h
Bar.cpp
forms
Bar.ui
2)在public include目录下创建另一个Bar.h:
src
include
Foo
Bar.h
内容:
#include "../../../lib/Foo/Bar.h"
这种方法的真实例子 https://github.com/paceholder/nodeeditor/tree/master/include/nodes
答案 1 :(得分:0)
我发现只需将AUTOMOC
留在其自己的设备上,即可简化此解决方法。这是我的工作(适用于我们所有受支持的CMake版本,当前为3.2...3.17
):
#include "moc_Bar.cpp"
中删除行Bar.cpp
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)
AUTOMOC
在将相关文件MOC时将创建一个Foo_autogen
输出目录。 moc_Bar.cpp
和moc_Baz.cpp
将在随机命名的ABDEADBEEF
子目录中创建,并且将创建一个mocs_compilation.cpp
文件,其内容如下:
// This file is autogenerated. Changes will be overwritten.
#include "ABDEADBEEF/moc_Bar.cpp"
#include "ABDEADBEEF/moc_Baz.cpp"
该文件被编译并链接到目标的最终输出。
在CMAKE_AUTOMOC
全局设置为True
的情况下,每个目标也将收到其自己的target_autogen
目录,尽管在没有任何MOC'able类的目标中将不生成任何目录。不过,最好仅在需要它的目标上设置AUTOMOC
目标属性:
set_property(TARGET Foo PROPERTY AUTOMOC ON)