Statically Link 3rd Party Library Built with CMake into Qt 5.12.11 Project Built with QMake in Qt Creator
-
I found the issue, there's a glitch in the src
CMakeLists.txt
, they have hard coded the library build as shared. Just removed that from theadd_library
line, configure the build to be static and you will have a static build of it.@SGaist Thanks, SGaist, I found the same issue, see three posts ago. I just now tried leaving both STATIC and SHARED out of add_library and get the same compile errors/warnings as using STATIC with add_library.
I have the same question as before... Does this mean the developer designed the library to be shared only? Would it take a herculean effort to convert it to static? Thanks again!
-
@SGaist Thanks, SGaist, I found the same issue, see three posts ago. I just now tried leaving both STATIC and SHARED out of add_library and get the same compile errors/warnings as using STATIC with add_library.
I have the same question as before... Does this mean the developer designed the library to be shared only? Would it take a herculean effort to convert it to static? Thanks again!
Do you mean you can't get a static build of the library ?
-
@SGaist These are the errors/warnings I get when I try to build the library without the SHARED option passed to add_library:
With
BUILD_SHARED_LIBS
set to OFF ? -
@SGaist I might have just gotten it to work... will confirm tomorrow but it looks pretty convincing. I added add_compile_definitions(SimpleMail2Qt5_EXPORTS) to both CMakeLists.txt's. Forgot how I arrived at this necessity I'll try to remember tomorrrow :) Thanks for the help!
-
@SGaist I might have just gotten it to work... will confirm tomorrow but it looks pretty convincing. I added add_compile_definitions(SimpleMail2Qt5_EXPORTS) to both CMakeLists.txt's. Forgot how I arrived at this necessity I'll try to remember tomorrrow :) Thanks for the help!
@SGaist I finally got the library to compile statically. I had to remove SHARED from add_library, set BUILD_SHARED_LIBS to off, and add add_compile_definitions(SimpleMail2Qt5_EXPORTS) to CMakeLists.txt.
In the SimpleMail project we have src/smtpexports.h with:
#if defined(SimpleMail2Qt5_EXPORTS) || defined(SimpleMail2Qt6_EXPORTS) #define SMTP_EXPORT Q_DECL_EXPORT #else #define SMTP_EXPORT Q_DECL_IMPORT #endif
The Q_DECL_EXPORT seems to be essential.
Now I get another error! Bloody hell.
Running NMake trying to build my project that uses SimpleMail I get some of these:
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
and a lot of these:
SimpleMail2Qt5.lib(mimemessage.cpp.obj) : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl QByteArray::QByteArray(class QByteArray const &)" (__imp_??0QByteArray@@QEAA@AEBV0@@Z) referenced in function "public: __cdecl QStringBuilder<class QByteArray,class QByteArray>::operator class QByteArray(void)const " (??B?$QStringBuilder@VQByteArray@@V1@@@QEBA?AVQByteArray@@XZ)
and these:
SimpleMail2Qt5.lib(mimepart.cpp.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl QByteArray::QByteArray(class QByteArray const &)" (__imp_??0QByteArray@@QEAA@AEBV0@@Z)
I'll google these guys... do you know off the top of your head what's going on?
Thanks -
@SGaist I finally got the library to compile statically. I had to remove SHARED from add_library, set BUILD_SHARED_LIBS to off, and add add_compile_definitions(SimpleMail2Qt5_EXPORTS) to CMakeLists.txt.
In the SimpleMail project we have src/smtpexports.h with:
#if defined(SimpleMail2Qt5_EXPORTS) || defined(SimpleMail2Qt6_EXPORTS) #define SMTP_EXPORT Q_DECL_EXPORT #else #define SMTP_EXPORT Q_DECL_IMPORT #endif
The Q_DECL_EXPORT seems to be essential.
Now I get another error! Bloody hell.
Running NMake trying to build my project that uses SimpleMail I get some of these:
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
and a lot of these:
SimpleMail2Qt5.lib(mimemessage.cpp.obj) : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl QByteArray::QByteArray(class QByteArray const &)" (__imp_??0QByteArray@@QEAA@AEBV0@@Z) referenced in function "public: __cdecl QStringBuilder<class QByteArray,class QByteArray>::operator class QByteArray(void)const " (??B?$QStringBuilder@VQByteArray@@V1@@@QEBA?AVQByteArray@@XZ)
and these:
SimpleMail2Qt5.lib(mimepart.cpp.obj) : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl QByteArray::QByteArray(class QByteArray const &)" (__imp_??0QByteArray@@QEAA@AEBV0@@Z)
I'll google these guys... do you know off the top of your head what's going on?
Thanks@SGaist ( or anybody ) Making progress on this, it looks like error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' is due to symbol mismatch detected by the linker. So one part of the program uses the DLL version of the run time library and another uses static version of the run time library. See here and here.
For those who aren't following this thread I am getting this error (and many others probably related to this) when trying to compile my project using a static build of the SimpleMail plugin:
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
The fix should be easy, just make the library use the static run time library. I tried to do this in CMakeLists.txt using both:
set_property(TARGET SimpleMail2Qt${QT_VERSION_MAJOR} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") //used at the end of the CMakeLists.txt in src directory of SimpleMail project directory
and
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") //used at the beginning of both CMakeLists.txt files (the one in the SimpleMail root and src subdirectory of SimpleMail project)
but still get the linker error. See here and here and for these CMake variables. Any idea what might be wrong? Is there another way to specify whether to use the static or dll run time library when building a project using CMake and Qt Creator?
-
@SGaist ( or anybody ) Making progress on this, it looks like error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' is due to symbol mismatch detected by the linker. So one part of the program uses the DLL version of the run time library and another uses static version of the run time library. See here and here.
For those who aren't following this thread I am getting this error (and many others probably related to this) when trying to compile my project using a static build of the SimpleMail plugin:
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
The fix should be easy, just make the library use the static run time library. I tried to do this in CMakeLists.txt using both:
set_property(TARGET SimpleMail2Qt${QT_VERSION_MAJOR} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") //used at the end of the CMakeLists.txt in src directory of SimpleMail project directory
and
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") //used at the beginning of both CMakeLists.txt files (the one in the SimpleMail root and src subdirectory of SimpleMail project)
but still get the linker error. See here and here and for these CMake variables. Any idea what might be wrong? Is there another way to specify whether to use the static or dll run time library when building a project using CMake and Qt Creator?
-
@SGaist Hi SGaist, any idea what's causing the LNK2038 error previously mentioned? Is it not using the static run-time library for building the SimpleMail library? Shouldn't CMake set variable commands shown remedy the situation? Thanks!
Might be a silly question but are you sure you are using the same version of Qt to build the library and your project ?
-
Might be a silly question but are you sure you are using the same version of Qt to build the library and your project ?
-
And that is a dynamic build of Qt ?
-
@SGaist The program is built statically but the library is built using Qt Creator so dynamic right? I tried building the library static as well but bot a bunch of errors, could try again...
No need to build Qt statically, I am just trying to asses the situation as I currently can't figure out why the two run times are being used. The fact that the library is static does not mean that it shall use the static runtime. All the more when using a shared build of Qt.
-
No need to build Qt statically, I am just trying to asses the situation as I currently can't figure out why the two run times are being used. The fact that the library is static does not mean that it shall use the static runtime. All the more when using a shared build of Qt.
-
@SGaist Sorry I meant I tried building the library using my static build of Qt, not just building the library statically (the whole point of this thread).
Then here lies the issue: your static build of Qt uses the static runtime and you are trying to build your application with a dynamic build of Qt.
Rebuild that library with the same version of Qt as the original application.
-
Then here lies the issue: your static build of Qt uses the static runtime and you are trying to build your application with a dynamic build of Qt.
Rebuild that library with the same version of Qt as the original application.
@SGaist I got a little further compiling the library with Qt static. Had to turn off SimpleMail demos but who cares... Now I still get the below guys. Do these mean SimpleMail or QtSingleApplication is MD_DynamicRelease? If it's SimpleMail the author might have hard coded dynamic somewhere else in the library and I will ask him for help.
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimemessage.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(sender.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimepart.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimecontentformatter.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimemultipart.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(quotedprintable.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
and a bunch of these guys:
LINK : warning LNK4217: symbol '??0Sender@SimpleMail@@QEAA@AEBVQString@@HW4ConnectionType@01@PEAVQObject@@@Z (public: __cdecl SimpleMail::Sender::Sender(class QString const &,int,enum SimpleMail::Sender::ConnectionType,class QObject *))' defined in 'SimpleMail2Qt5.lib(sender.cpp.obj)' is imported by 'worker.obj' in function '"private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z)'
and these guys:
worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl SimpleMail::MimeText::MimeText(class QString const &)" (__imp_??0MimeText@SimpleMail@@QEAA@AEBVQString@@@Z) referenced in function "private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z) worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl SimpleMail::MimeText::~MimeText(void)" (__imp_??1MimeText@SimpleMail@@UEAA@XZ) referenced in function "public: virtual void * __cdecl SimpleMail::MimeText::`scalar deleting destructor'(unsigned int)" (??_GMimeText@SimpleMail@@UEAAPEAXI@Z) worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl SimpleMail::MimeText::setText(class QString const &)" (__imp_?setText@MimeText@SimpleMail@@QEAAXAEBVQString@@@Z) referenced in function "private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z)
-
@SGaist I got a little further compiling the library with Qt static. Had to turn off SimpleMail demos but who cares... Now I still get the below guys. Do these mean SimpleMail or QtSingleApplication is MD_DynamicRelease? If it's SimpleMail the author might have hard coded dynamic somewhere else in the library and I will ask him for help.
SimpleMail2Qt5.lib(emailaddress.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimemessage.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(sender.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimepart.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimecontentformatter.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(mimemultipart.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj SimpleMail2Qt5.lib(quotedprintable.cpp.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MD_DynamicRelease' doesn't match value 'MT_StaticRelease' in qtsingleapplication.obj
and a bunch of these guys:
LINK : warning LNK4217: symbol '??0Sender@SimpleMail@@QEAA@AEBVQString@@HW4ConnectionType@01@PEAVQObject@@@Z (public: __cdecl SimpleMail::Sender::Sender(class QString const &,int,enum SimpleMail::Sender::ConnectionType,class QObject *))' defined in 'SimpleMail2Qt5.lib(sender.cpp.obj)' is imported by 'worker.obj' in function '"private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z)'
and these guys:
worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl SimpleMail::MimeText::MimeText(class QString const &)" (__imp_??0MimeText@SimpleMail@@QEAA@AEBVQString@@@Z) referenced in function "private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z) worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual __cdecl SimpleMail::MimeText::~MimeText(void)" (__imp_??1MimeText@SimpleMail@@UEAA@XZ) referenced in function "public: virtual void * __cdecl SimpleMail::MimeText::`scalar deleting destructor'(unsigned int)" (??_GMimeText@SimpleMail@@UEAAPEAXI@Z) worker.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl SimpleMail::MimeText::setText(class QString const &)" (__imp_?setText@MimeText@SimpleMail@@QEAAXAEBVQString@@@Z) referenced in function "private: void __cdecl Worker::sendEmails(class QList<class Job> &,class QList<class Job> &)" (?sendEmails@Worker@@AEAAXAEAV?$QList@VJob@@@@0@Z)
-
@SGaist Also I got this as well but using QMAKE_LFLAGS += /NODEFAULTLIB:MSVCRT fixed it but nothing else. Thanks!
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
@SGaist Hi Sgaist, I made a little progress, I fixed the LNK2038 errors by adding some compiler flags to change the runtime library to static. I think the MSVC_RUNTIME_LIBRARY and CMAKE_MSVC_RUNTIME_LIBRARY variables to change compiler flags to /MT and /MTd (static flags) are for executables only. And also they require cmake_minimum_required(VERSION 3.15) and cmake_policy(SET CMP0091 NEW). So I used set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") and set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") instead at the very end of the CMakeLists.txt so they override any previous setting of the compiler flags being set to something other than /MT and /MTd. These flags set the runtime library to be static.
However I have been unable to fix the LNK4217 and LNK2019 guys. It looks like for a static library I need to remove the __declspec(dllimport) and __declspec(dllexport) macros and replace with nothing. So in the case of SimpleMail it uses the following code in the smtpexports.h file, Q_DECL_EXPORT and Q_DECL_IMPORT being the Qt equivalent of the __declspec guys.
#if defined(SimpleMail2Qt5_EXPORTS) #define SMTP_EXPORT Q_DECL_EXPORT #else #define SMTP_EXPORT Q_DECL_IMPORT #endif
I simply replaced it with this code for brevity just to test things out:
#if defined(SimpleMail2Qt5_EXPORTS) #define SMTP_EXPORT #else #define SMTP_EXPORT #endif
The library ended up being a different size but still gave the LNK4217 and LNK2019 errors.
Any idea why it's not working?
Thanks