Undefined reference to QT::RemoteObjects autogenerated const static class member field (windows only)

Viewed 43

I have the problem with reusing my shared libraries on windows, because of microsoft declspec "feature". In the shared library I have the class using QT::RemoteObjects autogenerated SOURCE or REPLICA classes, and I am not able to use signal-slot features anywhere outside my library code. Consider this small example:

CMakeLists.txt

cmake_minimum_required(VERSION 3.11.0)
project(QtSymbolsProblem CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)

set (CMAKE_CXX_STANDARD 17)
find_package(Qt5 COMPONENTS RemoteObjects Core REQUIRED)

qt5_generate_repc(GENERATED PanelInterface.rep SOURCE)
set_source_files_properties(${GENERATED} PROPERTIES GENERATED TRUE SKIP_AUTOMOC TRUE)
message(STATUS "generated sources: ${GENERATED}")
add_library(SampleProcedure SHARED
    Procedure.cpp
    ${GENERATED}
)
set_target_properties(SampleProcedure PROPERTIES
    WINDOWS_EXPORT_ALL_SYMBOLS ON
)
target_link_libraries(SampleProcedure
  Qt5::RemoteObjects
  Qt5::Core
)
add_executable(main main.cpp)
target_link_libraries(main PUBLIC SampleProcedure)

Replica definition PanelInterface.rep:

#include <QtCore>
#include <QString>

class PanelInterface
{
    PROP(QString foo);
};

Library code:

//// Procedure.hpp
#pragma once

#include <SampleProcedure_export.h>
#include <QObject>
#include <memory>

class PanelInterfaceSimpleSource;

class Procedure {
public:
  Procedure();
  ~Procedure();
  PanelInterfaceSimpleSource *panelInterface();

private:
  std::unique_ptr<PanelInterfaceSimpleSource> _panel;
};

//// Procedure.cpp
#include "Procedure.hpp"
#include "rep_PanelInterface_source.h"
#include <QObject>

Procedure::Procedure()
    : _panel(std::make_unique<PanelInterfaceSimpleSource>()) {}

Procedure::~Procedure() = default;

PanelInterfaceSimpleSource *Procedure::panelInterface() { return _panel.get(); }

Main executable:

#include "Procedure.hpp"
#include "rep_PanelInterface_source.h"
#include <QObject>

#include <iostream>

class Foo : public QObject {
  Q_OBJECT
public:
  Foo(Procedure &proc) {
    QObject::connect(  // this is impossible because of missing symbol
        proc.panelInterface(), &PanelInterfaceSimpleSource::fooChanged, this,
        [](QString str) { std::cout << str.toStdString() << std::endl; });
  }
};

int main() {
  Procedure proc;
  Foo foo(proc);
  return 0;
}

#include "main.moc"

In this example PanelInterfaceSimpleSource is a class autogenerated by QT. When I try to connect to one of its signals, linker gives me the error:

main.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const PanelInterfaceSimpleSource::staticMetaObject" (?staticMetaObject@PanelInterfaceSimpleSource@@2UQMetaObject@@B)

In the CMake docs it is mentioned that

For global data symbols, __declspec(dllimport) must still be used when compiling against the code in the .dll.

and I even found some other topics that mention the use of CMake autogenerated export header

include(GenerateExportHeader)
generate_export_header(SampleProcedure)

but this solution will only work with the code that I am allowed to modify.

How should I solve the problem with missing symbol to the class static variable, in the code that was autogenerated by QT?

0 Answers
Related