如何指示cmake / automoc查找外部标头

时间:2015-02-13 04:17:57

标签: qt cmake qt5 moc

我有一个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 /

2 个答案:

答案 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):

  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)

AUTOMOC在将相关文件MOC时将创建一个Foo_autogen输出目录。 moc_Bar.cppmoc_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)