Unresolved external symbol while building Installer Framework
Hi!
Currently I'm trying to build sources of IF with dynamically linked QT.
OS: win 10
QT - branches ifw-5.15.2, 5.15.6-lts-lgpl,... (tried different)
IF - branch 4.3
compiler: msvc, tried compilers from different Visual Studios: 2015, 2017, 2019
That's how I build dynamic QT
Code:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 10.0.17763.0
SET _ROOT=D:\tfgit\qt\qt_test3\qt5
SET PATH=%_ROOT%\qtbase\bin;%_ROOT%\gnuwin32\bin;%PATH%
SET PATH=%_ROOT%\qtrepotools\bin;%PATH%
SET _ROOT=
call ..\configure -prefix %CD%\qtbase -opensource -confirm-license -platform win32-msvc2017 -release ^
-nomake examples -nomake tests -skip qtwebengine -no-openssl -opengl desktop && -developer-build ^
call nmake module-qtbase module-qtdeclarative module-qttools module-qttranslations module-qtwinextras && ^
call nmake install
This build finishes successfully all the times.
This is how I'm trying to build IF:
Code:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 10.0.17763.0
SET QTDIR=D:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase
SET QTDIR_LIB=%QTDIR%\lib
SET PATH=%QTDIR%\bin;%QTDIR%\..\..\gnuwin32\bin;%QTDIR_LIB%;D:\tfgit\qt\qt_test2\installer-framework\lib;%PATH%
call qmake.exe "LIBS+= -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\lib -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\bin -LD:\tfgit\qt\qt_test2\installer-framework\lib" && ^
call nmake && ^
call nmake install
Example for VS 2015. Same tried for other studios.
Code:
call qmake.exe "LIBS+= -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\lib -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\bin -LD:\tfgit\qt\qt_test2\installer-framework\lib" && ^
This line also tried different options. This is last try, thats why it looks like this.
Errors I'm getting are:
Linker errors when building the installer:
1. Unresolved RunOnceChecker symbols:
- RunOnceChecker constructor and destructor
- RunOnceChecker::isRunning()
2. Missing QInstaller symbols:
- QInstaller::init()
- GenericFactory<QInstaller::PackageManagerPage>
- QInstaller::PackageManagerPageFactory::instance()
3. Missing QWinTaskbarButton and QWinTaskbarProgress symbols:
- Constructors, destructors, and methods
4. Missing Windows API functions:
- SHGetFolderPathW
- Security functions (AllocateAndInitializeSid, etc.)
- COM functions (CoInitialize, CoUninitialize)
- Shell functions (ShellExecuteExW)
- Privilege functions (AdjustTokenPrivileges, etc.)
- Other Windows APIs (SysAllocString, VariantClear, etc.)
Total: 38 unresolved external symbols
Ex:
Code:
error LNK2001: unresolved external symbol "RunOnceChecker::RunOnceChecker(const QString&)" (__imp_...)
error LNK2001: unresolved external symbol "RunOnceChecker::~RunOnceChecker(void)" (__imp_...)
error LNK2019/LNK2001: unresolved external symbol "bool RunOnceChecker::isRunning(QFlags<RunOnceChecker::ConditionFlag>)" (__imp_...)
main.obj:
error LNK2019: unresolved external symbol "RunOnceChecker::~RunOnceChecker(void)" (__imp_...) referenced in SDKApp destructor
[QWinTaskbarButton & QWinTaskbarProgress]
installer.lib (packagemanagergui.obj, performinstallationform.obj):
error LNK2001/LNK2019: unresolved external symbol "QWinTaskbarButton::QWinTaskbarButton(QObject*)" (__imp_...)
error LNK2001/LNK2019: unresolved external symbol "virtual QWinTaskbarButton::~QWinTaskbarButton(void)" (__imp_...)
error LNK2019: unresolved external symbol "void QWinTaskbarButton::setWindow(QWindow*)" (__imp_...)
error LNK2001/LNK2019: unresolved external symbol "QWindow* QWinTaskbarButton::window(void)const" (__imp_...)
error LNK2001/LNK2019: unresolved external symbol "QWinTaskbarProgress* QWinTaskbarButton::progress(void)const" (__imp_...)
error LNK2001/LNK2019: unresolved external symbol "void QWinTaskbarProgress::setValue(int)" (__imp_...)
error LNK2019: unresolved external symbol "void QWinTaskbarProgress::reset(void)" (__imp_...)
error LNK2019: unresolved external symbol "void QWinTaskbarProgress::setVisible(bool)" (__imp_...)
error LNK2019: unresolved external symbol "void QWinTaskbarProgress::resume(void)" (__imp_...)
error LNK2019: unresolved external symbol "void QWinTaskbarProgress::stop(void)" (__imp_...)
error LNK2001: unresolved external symbol virtual ?????? QWinTaskbarButton (eventFilter, metaObject, qt_metacall, qt_metacast)
[Windows API ? COM]
installer.lib (packagemanagercoredata.obj):
error LNK2019: unresolved external symbol "SHGetFolderPathW" (__imp_SHGetFolderPathW)
installer.lib (adminauthorization_win.obj):
error LNK2019: unresolved external symbols "AllocateAndInitializeSid", "CheckTokenMembership", "FreeSid", "ShellExecuteExW", "CoInitialize", "CoUninitialize" (__imp_...)
installer.lib (utils.obj):
error LNK2019: unresolved external symbols "OpenProcessToken", "AdjustTokenPrivileges", "PrivilegeCheck", "LookupPrivilegeValueW" (__imp_...)
7z.lib (ArchiveExtractCallback.obj, PropVariant.obj, EnumDirItems.obj, 7zHandlerOut.obj):
error LNK2001/LNK2019: unresolved external symbols "OpenProcessToken", "AdjustTokenPrivileges", "SysAllocString", "SysAllocStringLen", "VariantClear", "VariantCopy", "SysFreeString", "GetFileSecurityW", "SetFileSecurityW" (__imp_...)
..\..\bin\installerbase.exe : fatal error LNK1120: 38 unresolved externals
Re: Unresolved external symbol while building Installer Framework
Are you running your scripts from within a Visual Studio Developer Command Prompt terminal window, or from an ordinary DOS Command Prompt window? The VS window sets up the environment for code building, whereas the ordinary prompt simply uses your existing environment. You can find the Developer Command Prompt on the Windows Start menu, under Visual Studio 20xx-> Visual Studio Tools.
Re: Unresolved external symbol while building Installer Framework
Hi! Thank you for you reply!
I'm calling
Code:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 10.0.17763.0
On every build. It's script which setups env variables
Re: Unresolved external symbol while building Installer Framework
Are the environment variables set using the "call" command preserved after the call returns? I usually run build scripts from inside a developer command prompt. This guarantees that anything executed within that prompt inherits the build environment. Try commenting out your "call" statement and then executing your script inside the developer command window.
Re: Unresolved external symbol while building Installer Framework
I made this a single script file:
Code:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 10.0.17763.0
SET QTDIR=D:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase
SET QTDIR_LIB=%QTDIR%\lib
SET PATH=%QTDIR%\bin;%QTDIR%\..\..\gnuwin32\bin;%QTDIR_LIB%;D:\tfgit\qt\qt_test2\installer-framework\lib;%PATH%
call qmake.exe "LIBS+= -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\lib -LD:\tfgit\qt\qt_test2\qt_test\qt5\qt5_build\qtbase\bin -LD:\tfgit\qt\qt_test2\installer-framework\lib" && ^
call nmake && ^
call nmake install
So after call vcvarsall.bat is executed all variables are definitely set during build-script execution. Otherwise nmake command wouldn't have been be found.
I tried simply running it from developer command prompt(vs 2017): same result, no changes: 38 unresolved external symbols.
Re: Unresolved external symbol while building Installer Framework
Well, sorry. Are you sure that you are linking to the correct libraries? In Windows, you cannot mix Release and Debug or 32- and 64-bit libraries. A 64-bit Debug build must be linked with 64-bit Debug libraries, likewise for Release and 32-bit builds. Turn on a verbose build and have it write a log file so you can see all the details.
Otherwise, I do not know what else to suggest.
Re: Unresolved external symbol while building Installer Framework
Well, both builds for qt and IF are always both x86 or both x64. Also I checked generated files and they are all release versions. Also during build I managed to lower amount of errors to only this:
Code:
main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::RunOnceChecker(class QString const &)" (__imp_??0RunOnceChecker@@QEAA@AEBVQString@@@Z) referenced in function "public: __cdecl SDKApp<class QCoreApplication>::SDKApp<class QCoreApplication>(int &,char * *)" (??0?$SDKApp@VQCoreApplication@@@@QEAA@AEAHPEAPEAD@Z)
installerbase.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::RunOnceChecker(class QString const &)" (__imp_??0RunOnceChecker@@QEAA@AEBVQString@@@Z)
commandlineinterface.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::RunOnceChecker(class QString const &)" (__imp_??0RunOnceChecker@@QEAA@AEBVQString@@@Z)
main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::~RunOnceChecker(void)" (__imp_??1RunOnceChecker@@QEAA@XZ) referenced in function "int `public: __cdecl SDKApp<class QCoreApplication>::SDKApp<class QCoreApplication>(int &,char * *)'::`1'::dtor$5" (?dtor$5@?0???0?$SDKApp@VQCoreApplication@@@@QEAA@AEAHPEAPEAD@Z@4HA)
installerbase.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::~RunOnceChecker(void)" (__imp_??1RunOnceChecker@@QEAA@XZ)
commandlineinterface.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl RunOnceChecker::~RunOnceChecker(void)" (__imp_??1RunOnceChecker@@QEAA@XZ)
installerbase.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: bool __cdecl RunOnceChecker::isRunning(class QFlags<enum RunOnceChecker::ConditionFlag>)" (__imp_?isRunning@RunOnceChecker@@QEAA_NV?$QFlags@W4ConditionFlag@RunOnceChecker@@@@@Z) referenced in function "public: bool __cdecl SDKApp<class QApplication>::init(class QString &)" (?init@?$SDKApp@VQApplication@@@@QEAA_NAEAVQString@@@Z)
commandlineinterface.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: bool __cdecl RunOnceChecker::isRunning(class QFlags<enum
RunOnceChecker::ConditionFlag>)" (__imp_?isRunning@RunOnceChecker@@QEAA_NV?$QFlags@W4ConditionFlag@RunOnceChecker@@@@@Z)
installerbase.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl QInstaller::init(void)" (__imp_?init@QInstaller@@YAXXZ) referenced in function "public: __cdecl InstallerBase::InstallerBase(int &,char * * const)" (??0InstallerBase@@QEAA@AEAHQEAPEAD@Z)
commandlineinterface.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) void __cdecl QInstaller::init(void)" (__imp_?init@QInstaller@@YAXXZ)
installerbasecommons.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class QInstaller::PackageManagerPage * __cdecl GenericFactory<class QInstaller::PackageManagerPage,int,class QInstaller::PackageManagerCore *>::create(int const &,class QInstaller::PackageManagerCore *)const " (__it &,class QInstaller::PackageManagerCore *)const " (__iler@@HPEAVPackageManagerCore@2@@@QEBAPEAVPackageManagerPage@QInstaller@@AEBHPEAVPackageManagerCore@3@@mp_?create@?$GenericFactory@VPackageManagerPage@QInstaller@@HPEAVPackageManagerCore@2@@@QEBAPEAVPackagCore *)" (??0InstallerGui@@QEAA@PEAVPackageManagerCore@eManagerPage@QInstaller@@AEBHPEAVPackageManagerCore@3@@
Z) referenced in function "public: __cdecl InstallerGui::InstallerGui(class QInstaller::PackageManageratic class QInstaller::PackageManagerPageFactory & __cdCore *)" (??0InstallerGui@@QEAA@PEAVPackageManagerCore@d)" (__imp_?instance@PackageManagerPageFactory@QInstaller@@SAAEAV12@XZ) referenced in function "publicQInstaller@@@Z) EAVPackageManagerCore@QInstaller@@@Z)
installerbasecommons.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: sttory<class QInstaller::PackageManagerPage,int,class QInstaller::PackageManagerCore *>::create(int const &,class QInstaller::PackageManagerCore *)const " (__imp_?create@?$GenericFactory@VPackageManagerPage@QInstaller@@HPEAVPackageManagerCore@2@@@QEBAPEAVPackageManagerPage@QInstaller@@AEBHPEAVPackageManagerCore@3@@Z) referenced in function "public: __cdecl InstallerGui::InstallerGui(class QInstaller::PackageManagerCore *)" (??0InstallerGui@@QEAA@PEAVPackageManagerCore@QInstaller@@@Z)
installerbasecommons.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static class QInstaller::PackageManagerPageFactory & __cdecl QInstaller::PackageManagerPageFactory::instance(void)" (__imp_?instance@PackageManagerPageFactory@QInstaller@@SAAEAV12@XZ) referenced in function "public: __cdecl InstallerGui::InstallerGui(class QInstaller::PackageManagerCore *)" (??0InstallerGui@@QEAA@PEAVPackageManagerCore@QInstaller@@@Z)
..\..\bin\installerbase.exe : fatal error LNK1120: 6 unresolved externals
But I never ever saw installer.dll anywhere. So I don't know how to build this one.
Have you ever tried dynamic build for IF?
PS.
in installer-framework\src\libs\installer\installer.pro there is a line
Code:
CONFIG += staticlib
which makes me think that dynamic build for IF is impossible.
Added after 1 33 minutes:
Seems like due to this bugs discussions(specifically messages from Katja Marttila)
https://bugreports.qt.io/browse/QTIFW-3180
https://bugreports.qt.io/browse/QTIFW-2611
It's required to build QT statically for installer.
Re: Unresolved external symbol while building Installer Framework
Quote:
It's required to build QT statically for installer.
Well, I guess that makes sense. If you are building an installer that is based on Qt, there is no guarantee that the required Qt DLLs are already on the PC, so all of the necessary Qt components must be a static part of the installer program. (The application being installed by the installer can be dynamically linked, so the installer must also install the Qt DLLs, but the installer program itself must be statically linked).
I have not used the IF. However, I am pretty sure you do not need to build ALL of Qt, probably only the qtbase component. Looking at your qmake command, that seems to be the only component you are linking. Your linker errors are because you are trying to link a static IF build to dynamic Qt libraries.
Re: Unresolved external symbol while building Installer Framework
Quote:
Your linker errors are because you are trying to link a static IF build to dynamic Qt libraries.
Yes BUT: IF gets CONFIG setting from QT build. So if QT was build static CONFIG contains static, in case of shared, CONFIG contains shared. And this CONFIG applies to IF build. I checked sources deeply and you can build IF dynamic, but you need to change source code to make symbols exported correctly. More specifically, there is flag staticlib added to installer_lib(installer.pro) project 7 years ago, which is impossible to overwrite, also CommandLineParser class need to be exported to make everything link correctly.
Quote:
If you are building an installer that is based on Qt, there is no guarantee that the required Qt DLLs are already on the PC
I can create self extracting archive with possibility for end user to replace my qt libs with his own so It will comply with opensource license and user will get 1-file-installer.
Re: Unresolved external symbol while building Installer Framework
Quote:
I can create self extracting archive with possibility for end user to replace my qt libs with his own so It will comply with opensource license and user will get 1-file-installer.
No, that's not what I meant. If the installer program has a Qt-based GUI (like an install wizard to guide the user through different installation options), then the installer program cannot be sure that the Qt DLLs it needs to run itself are already on the PC. It has to assume that nothing is there, so it needs to provide all of the Qt resources itself. The easiest way to do that is if it is linked statically with Qt so that it carries with it everything it needs to run.
Re: Unresolved external symbol while building Installer Framework
Exactly, this installer exe with dlls can be placed in SFX.
SO sfx is your main installer, which uses exe, which was build with qt. in this case you won't need qt installed in system, because they will be in that sfx.