# cmake qt6: unresolved external symbol "public: virtual struct QMetaObject"

**URL:** https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954
**Category:** Usage
**Created:** [June 28, 2022, 7:53am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954 "2022-06-28T07:53:46Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [June 28, 2022, 7:53am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/1 "2022-06-28T07:53:46Z")

</div>

I am building qt6 project with cmake. I want to generate a library with QWidget, and the code is:

```auto
	#ifndef GLOBAL_EXPORTS
		#define GLOBAL_EXPORT __declspec(dllexport)
	#else
		#define GLOBAL_EXPORT __declspec(dllimport)
	#endif // !GLOBAL_EXPORTS

class GLOBAL_EXPORT SWidgets : public QWidget
{
	Q_OBJECT
public:
	SWidgets();
};

```

In compiling, the vs reports:

```auto
 unresolved external symbol "public: virtual struct QMetaObject const SWidgets::staticMetaObject"

```

The bug can be solved by copy moc file. But, it is inconvenient because I have many qt relative library.

How to solve this bug by cmake? Any suggestion is appreciated~~~

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [June 28, 2022, 11:21am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/2 "2022-06-28T11:21:07Z")

</div>

You can tell CMake to enable `moc` support on the target by either:

```cmake
set(CMAKE_AUTOMOC 1) # setting this variable

add_library(mylib) # before this call

# or by setting the property
set_property(TARGET mylib PROPERTY AUTOMOC 1)

# or by using the Qt API
qt5_wrap_cpp(moc_files swidgets.cpp TARGET mylib)
target_sources(mylib PRIVATE ${moc_files})

```

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [June 28, 2022, 2:52pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/3 "2022-06-28T14:52:58Z")

</div>

I have tried `set(CMAKE_AUTOMOC 1)`, but it do not work.

I have upload the code in github ([GitHub - zhang-qiang-github/cmake\_qt: a test](https://github.com/zhang-qiang-github/cmake_qt)).

The `set(CMAKE_AUTOMOC 1)` has been added in `export_dll/CMakeLists.txt (line 9)`.

Could you please have a look at my code?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [June 28, 2022, 4:55pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/4 "2022-06-28T16:55:53Z")

</div>

It looks OK to me. Some more debugging would be necessary to see why moc isn’t being run here.

@craig.scott ?

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [June 29, 2022, 12:55am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/5 "2022-06-29T00:55:35Z")

</div>

My environment is:

```auto
win10
vs 2022
Qt 6.3.1
cmake 3.22.1

```

Would this environment provide the bug `unresolved external symbol`?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [June 30, 2022, 11:35am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/6 "2022-06-30T11:35:02Z")

</div>

What is supposed to be defining your `GLOBAL_EXPORTS` symbol? It looks like your code is expecting that to be defined when building the `export_dll` library, but nothing seems to be.

Rather than providing your own hand-written `Global.h`, consider taking a look at CMake’s [GenerateExportHeader](https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html) module. The docs for that module are worth a read.

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [July 1, 2022, 1:28am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/7 "2022-07-01T01:28:14Z")

</div>

The `GLOBAL_EXPORTS ` is used to declare that `SWidgets` would export a dll.

After several experiments, I find:

1. If I remove `Q_OBJECT`, the code works and the exported dll can be imported by others.
2. If I just import Qt rather than export a dll, the code also works.

So, how can I export the `SWidgets` with `Q_OBJECT` as a dll.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [July 1, 2022, 6:48am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/8 "2022-07-01T06:48:02Z")

</div>

You didn’t answer my question. What is defining/setting `GLOBAL_EXPORTS`?

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [July 1, 2022, 9:39am UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/9 "2022-07-01T09:39:21Z")

</div>

It has been defined as:

```auto
#ifndef GLOBAL_EXPORTS_H
#define GLOBAL_EXPORTS_H

#if (WIN32)
	#ifndef GLOBAL_EXPORTS
		#define GLOBAL_EXPORT __declspec(dllexport)
	#else
		#define GLOBAL_EXPORT __declspec(dllimport)
	#endif // !GLOBAL_EXPORTS

#else
	#define GLOBAL_EXPORT 
#endif

#endif

```

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [July 1, 2022, 1:33pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/10 "2022-07-01T13:33:05Z")

</div>

Nothing there is _defining_ `GLOBAL_EXPORTS`. That code is only _checking_ if it is defined. I also think you might have the sense of the block that checks it reversed. Compare your hand-written file with the one that `GenerateExportHeader` creates.

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [July 1, 2022, 2:34pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/11 "2022-07-01T14:34:31Z")

</div>

I have tried `GenerateExportHeader `, and it can solve my problem. But I still feel confuzed.

If the bug is caused by `GLOBAL_EXPORTS`, why I can correctly generate the dll if I remove `Q_OBJECT`? If I remove `Q_OBJECT`, I can correctly generate dll, and import the generated dll in other project.

---

<div class="post-metadata">

### Author: ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)
#### Post date: [July 1, 2022, 2:54pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/12 "2022-07-01T14:54:08Z")

</div>

`Q_OBJECT` expands to a whole bunch of stuff. It defines and calls methods, and adds some static members.  
If you have your defines backwards, like you had, you’re not exporting the things correctly, and the linker cannot find the definitions.  
If you remove the macro, no “special souse” will be added, so you won’t see the problem (at least not right away - it will eventually appear again).

---

<div class="post-metadata">

### Author: ![zhang-qiang-github](https://discourse.cmake.org/user_avatar/discourse.cmake.org/zhang-qiang-github/32/1913_2.png) [@zhang-qiang-github](https://discourse.cmake.org/u/zhang-qiang-github)
#### Post date: [July 1, 2022, 3:36pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/13 "2022-07-01T15:36:47Z")

</div>

> [@fenrir](#):
>
> If you remove the macro, no “special souse” will be added, so you won’t see the problem (at least not right away - it will eventually appear again).

When and how it will appear?

---

<div class="post-metadata">

### Author: ![fenrir](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fenrir/32/734_2.png) [@fenrir](https://discourse.cmake.org/u/fenrir)
#### Post date: [July 1, 2022, 5:37pm UTC](https://discourse.cmake.org/t/cmake-qt6-unresolved-external-symbol-public-virtual-struct-qmetaobject/5954/14 "2022-07-01T17:37:10Z")

</div>

As you extend your class, it’s almost guaranteed that at some point you’ll call some unexported method or something like that.  
In any case this has already nothing to do with CMake and everything to do with C/C++, shared objects, and symbol visibility. If you want to know more, google something along those terms.
