由于QtRemoteObjects副本定义中未解析的符号,导致链接器错误

问题描述

我正在研究使用Qt Remote Objects的项目,我想使用自动生成ReplicaDefSimpleSource类测试我的组件之一(有关详细信息,请参见下面的示例)。但是,当我尝试将测试可执行文件与我的库链接时,出现以下链接错误

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

我通过DependencyWalker检查了我的MyLib.dll,其中存在必需的符号:

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:是的,我知道这不是您应该测试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
)

所提供的示例当然可以在任何普通系统上编译和运行,我只是在Windows上遇到了这个问题,我不得不使用它(很抱歉询问有关该平台的问题)。

我应该怎么做才能使用自动生成的副本类来测试我的系统,而无需多次编译源代码

作为附带的问题:如果我在主可执行文件中包含副本源,为什么链接程序不会抱怨多个定义?

===编辑===

为了确保当我用手写代码编译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
)

但是问题仍然存在。如果我没有在每个目标中明确包含自动生成的源,则会缺少符号。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)