Right off the bat, sorry about the length of the question, but it is due to all the additional details I am providing which I hope could help trouble shoot the issue faster
What am I trying to achieve?
I need to create a portable (all-in-one) application, with SSL support.
What is the problem?
So the core problem I am facing is getting SSL support included into my binary/portable app.
A MCVE of the app is simple:
Project .pro
file
QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle
SOURCES += \
main.cpp
INSTALLS += target
Project main.cpp
#include <QCoreApplication>
#include <QSslSocket>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Is SSL Enabled? " << QSslSocket::supportsSsl();
qDebug() << "SSL Library Build Version (Qt compiled against): " << QSslSocket::sslLibraryBuildVersionString();
qDebug() << "SSL Library Version String (available locally): " << QSslSocket::sslLibraryVersionString();
return a.exec();
}
Is SSL Enabled? true
SSL Library Build Version (Qt compiled against): "OpenSSL 1.1.1d 10 Sep 2019"
SSL Library Version String (available locally): "OpenSSL 1.1.1d 10 Sep 2019"
Info of Dev Machine
C:\Users\cybex>echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin
C:\Users\cybex>openssl
WARNING: can't open config file: /z/extlib/_openssl_/ssl/openssl.cnf
OpenSSL> version
OpenSSL 1.0.2g 1 Mar 2016
Is SSL Enabled? false
SSL Library Build Version (Qt compiled against): "OpenSSL 1.1.1d 10 Sep 2019"
SSL Library Version String (available locally): ""
Info of Test Machine (Completely fresh install - Windows 10 x86)
C:\Users\cybex>echo %PATH%
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
C:\Users\cybex>openssl
'openssl' is not recognized as an internal or external command,
operable program or batch file.
Is SSL Enabled? false
SSL Library Build Version (Qt compiled against): "OpenSSL 1.1.1d 10 Sep 2019"
SSL Library Version String (available locally): ""
Info of Test Machine (Windows 7 x64 laptop with drivers installed)
C:\Users\Home>echo %PATH%
C:\Program Files (x86)\OpenSSL\libs;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\OpenSSL\libs;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\
C:\Users\Home>openssl
'openssl' is not recognized as an internal or external command, operable program or batch file.
By look at the above results, I conclude that installing OpenSSL solves the problem. Good, but I want need to have it included in my portable app.
In achieving this, I am required to
I have done this with the help of this script adapted from ps1
powershell script found here on Qt's wiki. I made additions for:
OpenSSL home $OPENSSL_HOME
number of threads $threads
, and
architecture type $arch
to be used.
Qt Compiling Details & OpenSSL info
Compiler: mingw32
located in C:\Qt\Qt5.13.1\Tools\mingw730_32\bin
mkspec: win32-g++
(if that makes any difference).
OpenSSL version (32 bit): 1.1.1d
The configuration is as follows:
cmd /C "configure.bat -static -debug-and-release -platform win32-g++ -prefix $QtDir `
-qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -sql-sqlite -ssl -openssl -I $($OPENSSL_HOME)\include -L$($OPENSSL_HOME)\lib\MinGW`
-opensource -confirm-license `
-make libs -nomake tools -nomake examples -nomake tests -v"
cmd /C "mingw32-make -k -j$($threads)"
Note 1:
I am using -openssl
and not -openssl-linked
. I have tried several variations of builing Qt with both -openssl
and -openssl-linked
. -openssl-linked
could never successfully build, see this post I made as to the reason why.
Note 2:
The only successful static Qt compilation I had working was with -ssl -openssl
configuration flags enabled
OpenSSL installation (on DEV machine only) is at
`$OPENSSL_HOME = "C:\OpenSSL-Win32"`
where I am using the statically compiled MinGW
libraries for OpenSSL, found in
`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`
The file contents of C:\OpenSSL-Win32\lib\MinGW
is:
Directory: C:\OpenSSL-Win32\lib\MinGW
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2019/09/11 18:11 3347286 libcrypto.a
-a---- 2019/09/11 18:10 109020 libcrypto.def
-a---- 2019/09/11 18:11 385126 libssl.a
-a---- 2019/09/11 18:10 14033 libssl.def
I added the OpenSSL libraries to the .pro
file using 2 methods(libraries are the statically compiled MinGW OpenSSL libraries found at C:\OpenSSL-Win32\lib\MinGW
)
QT -= gui
QT += network
# OpenSSL static .a libraries
INCLUDEPATH += "C:\OpenSSL-Win32\include"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libssl.a"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libcrypto.a"
CONFIG += c++11 console
CONFIG -= app_bundle
SOURCES += \
main.cpp
INSTALLS += target
Note 3
The binary size with and without the linked libraries above remains the same size
The LDD output of the binary (on my dev machine) with libraries added above is:
Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module
Size(K) ModuleName FileName
------- ---------- --------
6280 SSL-Test.exe C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
1512 ntdll.dll C:\Windows\SYSTEM32\ntdll.dll
596 KERNEL32.DLL C:\Windows\system32\KERNEL32.DLL
1500 KERNELBASE.dll C:\Windows\system32\KERNELBASE.dll
The LDD output of the binary (on my Windows 10 x86 test machine) with libraries added above is:
Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module
Size(K) ModuleName FileName
------- ---------- --------
6280 SSL-Test.exe C:\Users\cybex\Desktop\SSL-Test.exe
1512 ntdll.dll C:\Windows\SYSTEM32\ntdll.dll
596 KERNEL32.DLL C:\Windows\system32\KERNEL32.DLL
1500 KERNELBASE.dll C:\Windows\system32\KERNELBASE.dll
Import using (External Library
> Import .a
file> Static
& Windows
only options with no debug
suffix)
QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle
SOURCES += \
main.cpp
INSTALLS += target
win32: LIBS += -L$$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ -lssl
INCLUDEPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
DEPENDPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ssl.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/libssl.a
win32: LIBS += -L$$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/ -lcrypto
INCLUDEPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
DEPENDPATH += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW
win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/crypto.lib
else:win32-g++: PRE_TARGETDEPS += $$PWD/../../../../OpenSSL/OpenSSL-Win32/lib/MinGW/libcrypto.a
Using the automatic binary import, the LDD output of the binary (on my dev machine) with libraries added above is:
Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module
Size(K) ModuleName FileName
------- ---------- --------
6280 SSL-Test.exe C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
1512 ntdll.dll C:\Windows\SYSTEM32\ntdll.dll
596 KERNEL32.DLL C:\Windows\system32\KERNEL32.DLL
1500 KERNELBASE.dll C:\Windows\system32\KERNELBASE.dll
And using the automatic library import, the LDD output of the binary (on my Windows 10 x86 test machine) with libraries added above is:
Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module
Size(K) ModuleName FileName
------- ---------- --------
6280 SSL-Test.exe C:\Users\cybex\Desktop\SSL-Test.exe
1512 ntdll.dll C:\Windows\SYSTEM32\ntdll.dll
596 KERNEL32.DLL C:\Windows\system32\KERNEL32.DLL
1500 KERNELBASE.dll C:\Windows\system32\KERNELBASE.dll
The application output for the dev machine is SSL enabled
as mentioned previously in my post (for both manual and automatic library entry):
Is SSL Enabled? true
SSL Library Build Version (Qt compiled against): "OpenSSL 1.1.1d 10 Sep 2019"
SSL Library Version String (available locally): "OpenSSL 1.1.1d 10 Sep 2019"
The application output for the test machines (w/o OpenSSL installed) is the same as previously too (for both manual and automatic library entry):
Is SSL Enabled? false
SSL Library Build Version (Qt compiled against): "OpenSSL 1.1.1d 10 Sep 2019"
SSL Library Version String (available locally): ""
So with OpenSSL library not being present, it causes the below error when requesting a SSL connection on Non-Dev (fresh / client) machines:
QSslSocket::connectToHostEncrypted: TLS initialization failed
which is the result of the OpenSSL libary not being included in the binary as a dependency. So basically, adding a static OpenSSL library to the project file does not work or I am doing something incorrectly somewhere down the line.
Note 4: Why isn't the question titled: How to Import a static library into Qt?
Importing a static library is straight forward and not complicated. I am assuming I have made a mistake somewhere in the static compilation of Qt with SSL support enabled.
Advice on solving this problem would be greatly appreciated.
I have resolved the problem with -openssl-linked
. The cause (or fix rather) is to not install OpenSSL to your machine. Rather, extract the .a
& include
directries into a seperate directory. So everything is the same with exception of you having the lib
s & include
without installing.
Then use the standard configureation (mentioned above), replacing -openssl
with -openssl-linked
and you should have a successful compile.
Updated Problem
When building & running my application with the new Linked OpenSSL Qt kit, I get a message saying:
The code execution cannot proceed because libcrypto.dll was not found. Reinstalling the program may fix this problem.
Followed by another dialog
The code execution cannot proceed because libssl.dll was not found. Reinstalling the program may fix this problem
LDD requirments:
Start-Process -PassThru .\MyAwesomeApp.exe | Get-Process -Module
Size(K) ModuleName FileName
------- ---------- --------
22708 MyAwesomeApp.exe C:\Users\CybeX\QtProjects\build-MyAwesomeApp-Desktop_Qt_OpenSSL_Linked_5_13_1_MinGW_32bit-Release\release\MyAwesomeApp.exe
1924 ntdll.dll C:\WINDOWS\SYSTEM32\ntdll.dll
328 wow64.dll C:\WINDOWS\System32\wow64.dll
480 wow64win.dll C:\WINDOWS\System32\wow64win.dll
40 wow64cpu.dll C:\WINDOWS\System32\wow64cpu.dll
Have tested this with and without the .pro LIBS
& INCLUDEPATH
. Both result in the missing dll
's required.
The -openssl
configuration option configures Qt to load libopenssl dynamically using LoadLibrary
or another platform equivalent function. Therefore from this point on all your efforts are futile. You need to go back and solve the -openssl-linked problem.
If you have built Qt correctly, linking to ssl as static, you no longer need to link the ssl to the application explicitly, just link Qt.
The correct form for gcc is -Lrelative-or-absolute/path
(I'm using *nix paths), -L
to specify the path where the libraries are located and -lxyz
where xyz is the name of the library to link, ssl
(without the prefix lib
and without the suffix .a
)
But in the end an .a
file is a collection of .o
files, and can be added at linking stage like this: gcc -o target file.o libssl.a
(consequently on some occasion simply LIBS += /path/libssl.a
could work)
According to the Qt documentation it is not necessary to uninstall system ssl, just pass (export) an OPENSSL_LIBS
environment variable to the Qt configure script (OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto'
)
If both files (.a
, .dll
) are present gcc could still prefer the dynamic version, to be sure that you link the static version you can delete the .dll
files.
The Qt documentation is not clear (IMHO) on the fact that supports ssl linked statically, I assume that it is so but should be checked
By default, an SSL-enabled Qt library dynamically loads any installed OpenSSL library at run-time. However, it is possible to link to the library at compile-time by configuring Qt with the -openssl-linked option.
Should I do the build for me, I would enable a verbose output, and I would verify in the log that it is actually linked statically, I would verify that it is taken from the right directory, and that the final target Qt contains the ssl symbols.
I' using VS2019 as native win32 compiler, not mingw:
Bukd openSSL as static lib
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
SET CL=/MP
perl Configure VC-WIN64A no-shared --prefix=C:\Build-OpenSSL-VC-64-STATIC
nmake
nmake install
build Qt with static SSL:
..\configure -static -I C:\Build-OpenSSL-VC-64-STATIC\include -L C:\Build-OpenSSL-VC-64-STATIC\lib OPENSSL_LIBS="-llibcrypto -llibssl -lgdi32 -lWs2_32 -lwsock32 -ladvapi32 -luser32 -lCRYPT32" -openssl-linked -static-runtime ... etc
The same for 32 bits
perl Configure VC-WIN32 no-shared --prefix=C:\Build-OpenSSL-VC-32-STATIC
etc
I have applications with SSL support in a single .exe with no DLLs. --static-runtime is fo no VC_redistributable dependencies.
Then you need to allow relinking of the closed source app to make it compatible with LGPL V3
for example, using this app template:
Just ship the 4 DLL files from OpenSSL with your application (i.e. copy libcrypto-1_1-x64.dll, libssl-1_1-x64.dll, libcrypto-1_1.dll and libssl-1_1.dll to the installation of your application).
Builiding all libraries statically may violate LGPL license if you are using a free version of Qt.