Original question was slightly different but part of a more major question.
I am trying to build Qt 5.2 as static with static OpenSSL on Windows.
My final goal is to ship a single binary without the need to provide libeay32.dll and ssleay32.dll with it. However, it seems to me that this is impossible. I built static Qt with static openssl libs but it seems like Qt is outright ignoring the libs provided and always searches for DLLs.
This answer also suggests that QtNetwork always searches for DLLs and ignores everything else but it also states that "two options are to compile OpenSSL into Qt..." but this does not seem to be the case.
Can someone provide a definitive answer?
This is my Qt configure (line breaks added for readability):
configure -static -qmake -opensource -nomake examples -opengl desktop
-platform win32-msvc2010 -openssl -I C:\git\openssl\build\include
-L C:\git\openssl\build\lib OPENSSL_LIBS="-llibeay32 -lssleay32 -lgdi32"
Is there any way to building static Qt with static OpenSSL?
Sure, you need to use the following option when configuring Qt:
-openssl-linked
The reason is that QtNetwork uses the QLibrary
class by default for dynamically opening the library to get the necessary symbols.
This is the option to tell Qt not to do so, and respect the the normal linkage rules.
That being said, it is not recommended to use static linkage for openssl if security updates need to be available for the end user without your involvement. Consider that for a moment what happens if you are gone, not working on this project anymore, etc.
Also, this setup is not tested frequently, so you may actually encounter some issues that should be fixed upstream, but this is solution design for the use case in question.
Disclaimer: since SO is about programming, I am ignoring the licensing consequences for static linking againt Qt, so I would just like to quickly remind that you that be aware of the proper usage not to get into legal troubles.
OPENSSL_LIBS="-llibeay32 -lssleay32"...
Avoid -l
altogether (and -L
, and -Wl,-Bstatic
). The linker sometimes ignores the request for static linking (Apple), and sometimes a script modifies it (I can't tell you how many custom build scripts have bitten me).
Instead, use a fully specified archive just like you would use an object file. In your LDLIBS
add the following so there's no chance for a script to screw things up or the linker to ignore your request:
/usr/local/ssl/lib/libssl.a /usr/local/ssl/lib/libcrypto.a
Obviously, you should change the path of libssl.a
and libcrypto.a
to match your installation.
If you don't have an LDLIBS
, then add it to LDFLAGS
(or "other linker flags" in the IDE).
In Qt, it looks like that would be QMAKE_LFLAGS
or LIBS
. Or you could try this post: How to add "Additional Dependencies" (Linker settings).
The same trick applies to shared objects, too (but linkers favor shared objects, so it usually does not become an issue). That is, you can specify:
/usr/local/ssl/lib/libssl.so /usr/local/ssl/lib/libcrypto.so
The thing to remember when specifying a shared object like above is that you have to specify an rpath
to ensure the runtime linker gets the message. That is, you should add the following to LDFLAGS
or "other linker options":
-Wl,-rpath=/usr/local/ssl/lib
I've been bitten a few when specifying shared objects when using the OpenSSL FIPS Capable Library that resides in /usr/local/ssl/lib
because the runtime linker uses the distribution's OpenSSL in /usr/lib
or /usr/lib64
. The OpenSSL FIPS Capable Library is the one you call FIPS_mode_set
on.
You can also remove (or rename) the shared object from the location, leaving only the static archive. I've had to use this technique in the past when building under Xcode for iPhone. Xcode refused to use the static archive, even with a properly placed -Bstatic
. (Cross-compilers and modified toolchains are some of the worst to use at times). I don't think you should have to modify install directories, so I generally don't use it technique.
To summarize, leave nothing to chance and avoid -l
, -L
, and -Wl,-Bstatic
. Fully specify what you want and use the fully qualified library path name, and use them like object files. Use an rpath
if you are specifying a shared object.
This is how I build Qt 5.7.1 with SSL support on Windows using MSVC 2013:
- Download and install: Perl version 5.12 or later
- Download and install: Python version 2.7 or later
- Download and install: Ruby version 1.9.3 or later
Make sure Perl, Python and Ruby can be found in the PATH environment variable.
- Download and install: Win32 OpenSSL v1.0.2L
Download Qt from the github repository:
cd C:\Qt
git clone https://github.com/qt/qt5.git
cd C:\Qt\qt5
git checkout 5.7
Make sure to checkout commit 36e7cff94fbb4af5d8de6739e66164c6e6873586. At this time, checking out 5.7 does exactly that.
Place the contents below in qt5vars.bat located at C:\Qt\qt5
. Make adjustments if you need to:
@echo off
REM Set up \Microsoft Visual Studio 2015, where <arch> is \c amd64, \c x86, etc.
CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
REM Edit this location to point to the source code of Qt
SET _ROOT=C:\Qt\qt5
SET PATH=%_ROOT%\qtbase\bin;%_ROOT%\gnuwin32\bin;%PATH%
REM Uncomment the below line when using a git checkout of the source repository
SET PATH=%_ROOT%\qtrepotools\bin;%PATH%
REM Uncomment the below line when building with OpenSSL enabled. If so, make sure the directory points
REM to the correct location (binaries for OpenSSL).
SET PATH=C:\OpenSSL-Win32\bin;%PATH%
REM When compiling with ICU, uncomment the lines below and change <icupath> appropriately:
REM SET INCLUDE=<icupath>\include;%INCLUDE%
REM SET LIB=<icupath>\lib;%LIB%
REM SET PATH=<icupath>\lib;%PATH%
REM Contrary to earlier recommendations, do NOT set QMAKESPEC.
SET _ROOT=
REM Keeps the command line open when this script is run.
cmd /k
After that, execute this file and properly initiate the repository:
qt5vars.bat
perl init-repository
Finally, to configure and compile the library successfully (with debug and release versions), make sure the paths referenced by configure
are also valid on your system:
configure -static -static-runtime -debug-and-release -ssl -openssl -openssl-linked -opengl dynamic -platform win32-msvc2013 -prefix C:\Qt\qt5.7-msvc2013-static -nomake tests -nomake examples -I "C:\OpenSSL-Win32\include" -L "C:\OpenSSL-Win32\lib\VC\static" OPENSSL_LIBS="-lUser32 -lAdvapi32 -lGdi32 -lCrypt32" OPENSSL_LIBS_DEBUG="-lssleay32MTd -llibeay32MTd" OPENSSL_LIBS_RELEASE="-lssleay32MT -llibeay32MT"
nmake
nmake install
Everything so far should have run smoothly and beautifully. Now it's a matter of configuring Qt Creator to detect this new Qt Version and create a new Kit use on your projects: