c++qtcmakemoc

CMake AUTOMOC with files on different folders


I have a simple CMake project:

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)
{
}

and everything compiles great. Next, I tried to move the header file and the source file into different folder as so:

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

And tried different configurations of the following calls:

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

set( proj_SOURCE
    src/a.cpp
)

Dosen't matter what I do the compilation fails with variations of

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]

I don't know if I need to set something extra for CMake to work or what the problem is. This answer says that CMake does not work well on this configuration (files on different folders), but maybe there is a way?


Solution

  • From the CMake users list: It seems like on this specific configuration one needs to add the header files to the target. I still dont know exactly why, but code below answers the above question.

    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})