Ошибка компоновщика из-за неразрешенных символов из определений реплик QtRemoteObjects

Я работаю над проектом, который использует удаленные объекты Qt, и я хотел протестировать один из моих компонентов, используя автоматически сгенерированный ReplicaDefSimpleSourceclass (подробности см. в примере ниже). Однако, когда я попытался связать тестовый исполняемый файл с моей библиотекой, я получил следующую ошибку компоновщика:

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

Я проверил свой MyLib.dll с DependencyWalker требуемый символ присутствует:

79 (0x004f), 78 (0x0000004e), public: static struct QMetaObject const ReplicaDefSimpleSource::staticMetaObject, 0x00018370, Microsoft

Я также проверил dumpbin /EXPORTS Debug/MyLib.lib | grep "static struct QMetaObject", и снова там есть нужный символ:

?staticMetaObject@ReplicaDefSimpleSource@@2UQMetaObject@@B (public: static struct QMetaObject const ReplicaDefSimpleSource::staticMetaObject)

Для сборки проекта я использовал CMake:

cmake -G "Visual Studio 15 2017 Win64" ../
cmake --build . --config Debug

Для воспроизведения проблемы вам потребуются следующие файлы:

  • CMakeLists.txt:
cmake_minimum_required(VERSION 3.11)
project(test_project)

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

set (CMAKE_CXX_STANDARD 17)

find_package(Qt5 COMPONENTS
    Core REQUIRED
    RemoteObjects REQUIRED
    Test REQUIRED
)

qt5_generate_repc(GENERATED ReplicaDef.rep SOURCE)
qt5_generate_repc(GENERATED ReplicaDef.rep REPLICA)
set_source_files_properties(${GENERATED} PROPERTIES GENERATED TRUE SKIP_AUTOMOC TRUE)

add_library(MyLib SHARED a.cpp ${GENERATED})
set_target_properties(MyLib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)

target_link_libraries(MyLib
    Qt5::Core
    Qt5::RemoteObjects
)

add_executable(main main.cpp
    # moc_rep_ReplicaDef_source.cpp
)
target_link_libraries(main MyLib Qt5::Test)

  • main.cpp: yep, я знаю, что это не то, как вы должны тестировать код Qt, я просто использую его как минимальный пример (например, в нем нет QApplication)
#include "rep_ReplicaDef_source.h"
#include <QTest>
#include <QSignalSpy>
#include <QUrl>
#include <memory>
void foo();
int main()
{
    foo();  // here no problem with linker
    ReplicaDefSimpleSource source;
    QRemoteObjectHost host;
    host.setHostUrl(QUrl{ "local:main" });
    host.enableRemoting(&source);
    // QSignalSpy is using staticMetaObject that linker complains about
    QSignalSpy spy(&source, &ReplicaDefSimpleSource::settingsChanged);
    spy.wait(1000);
    return 0;
}
  • ReplicaDef.rep:
#include <QtCore>
#include <QString>
class ReplicaDef
{
    PROP(QString settings);
};
  • a.cpp: на самом деле это может быть что угодно, я просто добавил фиктивную функцию, чтобы показать, что символы из a.cpp видны
#include <iostream>
void foo() { std::cout << "foo" << std::endl; }

В качестве обходного пути я могу просто явно включить в свой тест автоматически сгенерированные источники, но это неприемлемое решение.

add_executable(main main.cpp
    moc_rep_ReplicaDef_source.cpp
)

Приведенный пример, конечно, компилируется и работает в любой нормальной системе, у меня просто проблема с окнами, которые я вынужден использовать (извините за вопрос об этой платформе).

Что мне делать, чтобы протестировать свою систему с использованием автоматически сгенерированных классов реплик и без многократной компиляции их источников?

В качестве побочного вопроса: почему компоновщик не жалуется на несколько определений, если я включаю источники реплик в основной исполняемый файл?

=== РЕДАКТИРОВАТЬ ===

Чтобы убедиться, что ничего странного не произойдет, когда я компилирую автоматически сгенерированный код Qt с моим рукописным кодом, я попытался поместить источники реплик в отдельную библиотеку:

qt5_generate_repc(GENERATED ReplicaDef.rep SOURCE)
qt5_generate_repc(GENERATED ReplicaDef.rep REPLICA)
set_source_files_properties(${GENERATED} PROPERTIES GENERATED TRUE SKIP_AUTOMOC TRUE)

add_library(MyLib-replica SHARED ${GENERATED})
target_link_libraries(MyLib-replica
    Qt5::Core
    Qt5::RemoteObjects
)
set_target_properties(MyLib-replica PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(MyLib SHARED a.cpp)
set_target_properties(MyLib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)

target_link_libraries(MyLib
    MyLib-replica
)

но проблема осталась прежней. Отсутствуют символы, если я не включаю автоматически сгенерированные источники явно в каждую цель.

0 ответов

Другие вопросы по тегам