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?
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.