CMake AUTOMOC,文件位于不同文件夹中

问题描述 投票:0回答:2

我有一个简单的 CMake 项目:

proj (project folder)
├── a.h
├── a.cpp
└── CMakeLists.txt

CMakeLists.txt:

cmake_minimum_required(VERSION 3.2)

set(CMAKE_VERBOSE_MAKEFILE ON)

set(CMAKE_AUTOMOC ON)

project(proj)

set( proj_SOURCE
    a.cpp
)

find_package(Qt5Core)

set( proj_LIBRARIES
    Qt5::Core
)

add_library(proj SHARED ${proj_SOURCE})
target_link_libraries(proj ${proj_LIBRARIES})

a.h:

#pragma once

#include <QObject>

class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObject *parent = 0);
};

a.cpp:

#include "a.h"

A::A(QObject *parent) : QObject(parent)
{
}

一切都编译得很好。接下来,我尝试将头文件和源文件移动到不同的文件夹中,如下所示:

proj (project folder)
├── include
│   └── a.h
├── src
│   └── a.cpp
└── CMakeLists.txt

并尝试了以下调用的不同配置:

include_directories("include")
include_directories("src")

set( proj_SOURCE
    src/a.cpp
)

不管我做什么,编译都会失败,并出现以下变化:

a.obj : error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __cdecl A::metaObject(void)const
" (?metaObject@A@@UEBAPEBUQMetaObject@@XZ) [C:\Users\me\AppData\Local\Temp\subclass\build\proj.vcxproj]
a.obj : error LNK2001: unresolved external symbol "public: virtual void * __cdecl A::qt_metacast(char const *)" (?qt_metacast@A
@@UEAAPEAXPEBD@Z) [C:\Users\me\AppData\Local\Temp\subclass\build\proj.vcxproj]
a.obj : error LNK2001: unresolved external symbol "public: virtual int __cdecl A::qt_metacall(enum QMetaObject::Call,int,void *
 *)" (?qt_metacall@A@@UEAAHW4Call@QMetaObject@@HPEAPEAX@Z) [C:\Users\me\AppData\Local\Temp\subclass\build\proj.vcxproj]
C:\Users\me\AppData\Local\Temp\subclass\build\Debug\proj.exe : fatal error LNK1120: 3 unresolved externals [C:\Users\me\Ap
pData\Local\Temp\subclass\build\proj.vcxproj]

我不知道我是否需要设置一些额外的东西才能让 CMake 工作或者问题是什么。 This答案说CMake在此配置(不同文件夹中的文件)上运行不佳,但也许有办法?

c++ qt cmake moc
2个回答
7
投票

来自 CMake 用户列表:似乎在此特定配置上需要将头文件添加到目标。我仍然不知道到底为什么,但下面的代码回答了上述问题。

cmake_minimum_required(VERSION 3.2)

set(CMAKE_VERBOSE_MAKEFILE ON)

set(CMAKE_AUTOMOC ON)

project(proj)

set( proj_SOURCE
    a.cpp
)

# add this
set( proj_HEADER
    include/a.h
)

find_package(Qt5Core)

set( proj_LIBRARIES
    Qt5::Core
)

# modify this
add_library(proj SHARED ${proj_SOURCE} ${proj_HEADER})
target_link_libraries(proj ${proj_LIBRARIES})

0
投票

AUTOMOC 由于 AUTO 这个词而导致误解。

文档中描述了 CMake 如何自动(通过 AUTOMOC 选项)查找标头:

在配置时,应由 AUTOMOC 扫描的头文件列表是根据目标源计算的。

  • 目标源中的所有头文件都将添加到扫描列表中。
  • 对于目标源中的所有 C++ 源文件 ,CMake 会搜索
    • 具有相同基本名称 (.) 和
    • 的常规标头
    • 具有相同基本名称和 _p 后缀的私有标头 (_p.)

并将它们添加到扫描列表中。

换句话说,您有两个不同的扫描:

  • 手动扫描
    All header files in the target's sources are added to the scan list.
  • 自动扫描
     CMake searches for a regular header with the same base name

由于您的头文件

a.h
位于源目录之外,因此您必须使用手动扫描。事实上,CMake 无法弄清楚头文件在其他地方。这就是为什么您必须手动将头文件添加到 CMake 文件中目标源的原因。

set( proj_HEADER
    include/a.h
)

通过这样做,您可以将标题添加到 moc 的列表中。然后,当

AUTOMOC
为 ON 时,所有头文件将在构建时 自动“moc 编译”

© www.soinside.com 2019 - 2024. All rights reserved.