Home > Software engineering >  cmake qt6: unresolved external symbol “public: virtual struct QMetaObject”
cmake qt6: unresolved external symbol “public: virtual struct QMetaObject”

Time:07-01

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

    #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:

 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.

In addition, I have add set(CMAKE_AUTOMOC 1), and it do not work.

I have upload the code in github (https://github.com/zhang-qiang-github/cmake_qt).

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


Update: sorry for uploading code to github.

  1. First, I define my GLOBAL_EXPORTS in a Global.h file:
#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

  1. Then I define my custom widget as:
#ifndef swidget_header_h
#define swidget_header_h

#include "Global.h"

#include <qwidget.h>
#include "qpushbutton.h"

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

#endif // !swidget_header_h

CodePudding user response:

As @Tsyvarev has pointed out, your handling of the GLOBAL_EXPORTS definition is wrong.

You should export the symbols if the GLOBAL_EXPORTS definition is set, therefore it should read (note: I changed #ifndef to #ifdef):

#ifdef GLOBAL_EXPORTS
    #define GLOBAL_EXPORT __declspec(dllexport)
#else
    #define GLOBAL_EXPORT __declspec(dllimport)
#endif // !GLOBAL_EXPORTS

Then in your CMakeLists.txt of the export_dll project you should add a line defining GLOBAL_EXPORTS:

set(CMAKE_AUTOMOC 1)
add_library(export_dll SHARED ${SOURCES} ${HEADERS})
set_target_properties(export_dll PROPERTIES COMPILE_DEFINITIONS GLOBAL_EXPORTS)
find_package(Qt6 REQUIRED COMPONENTS Widgets Core Gui)
target_link_libraries(export_dll PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui)

By doing this __declspec(dllexport) will be added to the symbols when creating the DLL and every consumer of the DLL will automatically get the symbols with a proper __declspec(dllimport) set.

  • Related