Is there any way to building static Qt with static OpenSSL?

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:


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.