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

10,592

Solution 1

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.

Solution 2

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.

Solution 3

This is how I build Qt 5.7.1 with SSL support on Windows using MSVC 2013:

Make sure Perl, Python and Ruby can be found in the PATH environment variable.

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:

Share:
10,592
cen
Author by

cen

Updated on July 05, 2022

Comments

  • cen
    cen almost 2 years

    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"
    
  • László Papp
    László Papp over 10 years
    -l and -L are fine actually if there is no clash, and that should be the recommendation as well IMO since that is more portable as opposed to specifying a full path, which is OS specific at large.
  • jww
    jww over 10 years
    Laszlo - I kind of agree, but I can tell you for certain that the linker and scripts don't do what you want at times. That never happens when you abandon -L, -l and -Bstatic in favor of fully specifying libraries and archives like object files. I cited examples of problems with both (and cen is having a similar problem). Its the difference between theory and practice.
  • László Papp
    László Papp over 10 years
    IMO, it is your practice, but it is not like that when people use it correctly. Writing platform dependent buildsystem in a Qt Project looks out of place.
  • jww
    jww over 10 years
    Lazlo - OK, whatever. You're right. Have you tried testing that "it is not like that when people use it correctly" theory on Apple platforms? Or when using OpenSSL in an alternate location for the FIPS library?
  • László Papp
    László Papp over 10 years
    Yes, also, the OP is asking about Windows AFAICT, not Apple.