I am working on the project which uses Qt Remote Objects and I wanted to test one of my components using auto-generated ReplicaDefSimpleSource
class (see the example below for the details). However, when I tried to link test executable with my library, I got the following linker error:
main.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const ReplicaDefSimpleSource::staticMetaObject" (?staticMetaObject@ReplicaDefSimpleSource@@2UQMetaObject@@B)
I checked my MyLib.dll
with DependencyWalker, the required symbol is there:
79 (0x004f), 78 (0x0000004e), public: static struct QMetaObject const ReplicaDefSimpleSource::staticMetaObject, 0x00018370, Microsoft
I also checked dumpbin /EXPORTS Debug/MyLib.lib | grep "static struct QMetaObject"
, and again the required symbol is there:
?staticMetaObject@ReplicaDefSimpleSource@@2UQMetaObject@@B (public: static struct QMetaObject const ReplicaDefSimpleSource::staticMetaObject)
To build the project I used CMake:
cmake -G "Visual Studio 15 2017 Win64" ../
cmake --build . --config Debug
To reproduce the problem you need the following files:
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, I know it is not how you are supposed to test Qt code, I just use it as minimal example (e.g. it doesn't have 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
: it actually can be anything, I just put there some dummy function to show that the symbols from a.cpp
are visible#include <iostream>
void foo() { std::cout << "foo" << std::endl; }
As a workaround I can just explicitly include auto-generated sources in my test, but this is not acceptable solution.
add_executable(main main.cpp
moc_rep_ReplicaDef_source.cpp
)
The provided example of course compiles and works on any normal system, I just have the problem on windows, which I am forced to use (sorry for asking a question about this platform).
What should I do to test my system using auto-generated replica classes and without compiling their sources multiple times?
As a side question: why the linker does not complain about multiple definitions if I include the replica sources in main executable?
=== EDIT ===
Just to make sure that nothing weird happens when I compile Qt autogenerated code with my hand-written code, I tried to put replica sources in a separate library:
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
)
but the problem remains the same. Missing symbols if I do not include autogenerated sources explicitly in each target.
User contributions licensed under CC BY-SA 3.0