OpenSSL 1.0.0.1 собираем статически c Qt 4.8.1

OpenSSL может понадобиться к примеру в HTTP клиенте, чтобы установить защищенное соединение.

OpenSSL это открытая свободная библиотека на C, которая не является частью Qt библиотек.

Примечание: тут описывается старая версия openssl 1.0.0.1 с TLS1.0. Подключение TLSv1.2 смотрите здесь openssl 1.0.2 под Qt Creator 2.4.1.

То есть хотя в исходниках QtSources и есть подкаталог с некоторыми исходниками для openssl , но они ссылаются на другие файлы , которых в поставке исходников QtSources нет. Например :

d:\qtsdk1.2.1\qtsources\4.8.1\src\network\ssl\qsslsocket_openssl_p.h:66: error: C1083: Cannot open include file: 'openssl/asn1.h': No such file or directory.

asn1.h например находится в исходниках свободного проекта OpenSSL.

Наша задача скачать OpenSSL, собрать статически библиотеки под тулчейном msvc2010 и подключить их к QT.

Нам понадобится NASM , Perl и MSVC2010.

NASM (Netwide Assembler) — свободный (LGPL и лицензия BSD) ассемблер для архитектуры Intel x86.
Perl вариант Strawberry подошел нормально.

Исходники openSSL те, что openssl-1.0.0d .

Далее запускаем самописный cmd файл для создания makefile:

@set path=D:\PROG\NASM;%PATH%
cd D:\OpenSSL\openssl-1.0.0d
perl Configure VC-WIN32 --prefix=D:\OpenSSL\1_0_0_1
pause
ms\do_ms
pause

И если первый этап без ошибок прошел потом запускаем второй cmd файл:


@set path=D:\PROG\NASM;%PATH%
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86

cd D:\OpenSSL\openssl-1.0.0d
nmake -f ms\ntdll.mak
nmake -f ms\ntdll.mak install
pause

ntdll.mak - это Makefile с вариантом динамики
nt.mak - это Makefile с вариантом статики
Важно чтобы в nt.mak и ntdll.mak были указаны разные каталоги сборки, иначе последняя сборка затрет предыдущую.

Например для ntdll.mak:

INSTALLTOP=d:\OpenSSL\1_0_0_1dll
OPENSSLDIR=d:\OpenSSL\1_0_0_1dll\ssl

Например для nt.mak:

INSTALLTOP=d:\OpenSSL\1_0_0_1_static
OPENSSLDIR=d:\OpenSSL\1_0_0_1d_static\ssl

Если все прошло правильно в D:\OpenSSL\1_0_0_1\lib у нас появятся две lib библиотеки libeay32.lib и ssleay32.lib . Заголовочные файлы к ним будут в каталоге D:\OpenSSL\1_0_0_1_static\include.

В результате выполнения ntdll.mak в D:\OpenSSL\1_0_0_1dll\bin у нас появятся две dll библиотеки libeay32.dll и ssleay32.dll . Заголовочные файлы к ним будут в каталоге D:\OpenSSL\1_0_0_1dll\include . И еще в каталоге D:\OpenSSL\1_0_0_1dll\lib появятся файлы libeay32.lib , ssleay32.lib - это lib-ы в дополнение к динамическим dll.

Примечание: после выполнения ms\do_ms создаются Makefile-ы :
nt.mak - это с ключом комиляции -MT (static)
ntdll.mak - это с ключом комиляции -MD (dll)

Переходим к нашему Qt проекту

Далее вызываем config.exe для qt исходников:


call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
configure.exe -opensource -release -mp -platform win32-msvc2010 -nomake examples -nomake demos -no-qt3support -no-scripttools -no-opengl -no-phonon -no-style-motif -no-style-cde -no-style-cleanlooks -no-style-plastique -no-sql-sqlite -qt-libjpeg -qt-zlib -qt-libpng -fast -static -openssl -openssl-linked OPENSSL_LIBS="-lcrypto -lssl" -I D:\OpenSSL\1_0_0_1\include -L D:\OpenSSL\1_0_0_1\lib

Примечание: В последних версиях openSSL файлы библиотек имеют другие названия libcrypto.lib и libssl.lib .

Обратите внимание на нашу ошибку OPENSSL_LIBS="-lcrypto -lssl" . При этом исходники самого Qt (каталог src) собираются нормально, так как им надо только -I D:\OpenSSL\1_0_0_1_static\include -L D:\OpenSSL\1_0_0_1_static\lib. А вот вашему проекту вложенному в src придется при линковке получить ошибку cannot open input file 'ssl.lib'. Хотя упоминания в вашем проекте о ssl.lib нигде нет...

Примечание: глобальная переменная OPENSSL_LIBS используется в исходниках Qt 4.8.1 только в файле ssl.pri :
LIBS_PRIVATE = $$OPENSSL_LIBS

Примечание: openssl-linked это похоже для подключения в качестве dll . То есть его не используем.

В результате выполнения config.exe в конце запускается некая утилита syncqt. Интересно что она делает ? Running syncqt....

При отсутствии ключа -dont-process (у config.exe) syncqt проходится по вложенным каталогам  и изменяет содержание Makefile на примерно такое , лучше бы он этого не делал. Он создаёт  Makefile-ы для каждого каталога с pro файлом. В результате исходники Qt придется пересобирать заново:

Тут написано как работать с configure.exe , практическое использование.

all:
	D:\QtSDK1.2.1\QtSources\4.8.1\bin\qmake D:/QtSDK1.2.1/QtSources/4.8.1/src\_MY_\http\http.pro  -o Makefile -spec win32-msvc2010
	"$(MAKE)" -$(MAKEFLAGS) -f Makefile
first: all
qmake:
	D:\QtSDK1.2.1\QtSources\4.8.1\bin\qmake D:/QtSDK1.2.1/QtSources/4.8.1/src\_MY_\http\http.pro  -o Makefile -spec win32-msvc2010

Примечание: config.exe как результат своей работы создает две специальных файла .qmake.cache и configure.cache, Qt Creator будет их искать выше каталога своего текущего собираемого проекта. Просто отметим это , так как в конце эти два файла нам пригодятся для решения одной проблемы.

Далее когда вы зайдете в Qt Creator и сделаете run qmake , то Makefile опять будет изменен уже в соответствии с идеалогией Qt Creator. Это не надо забывать.

После того как Creator заново создаст Makefile при run qmake , примечательно что в результирующей папки для собираемых библиотек qt появятся файлы *.prl . Вот содержание одного из них :

QMAKE_PRL_BUILD_DIR = D:/QtSDK1.2.1/QtSources/4.8.1/src/network
QMAKE_PRO_INPUT = network.pro
QMAKE_PRL_TARGET = QtNetwork
QMAKE_PRL_DEFINES = QT_THREAD_SUPPORT
QMAKE_PRL_CONFIG = include_source_dir lex yacc warn_on uic resources incremental_off windows release ReleaseBuild Release build_pass qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe release static msvc_mp stl exceptions rtti mmx 3dnow sse sse2 minimal-config small-config medium-config large-config full-config release incremental msvc_mp create_prl link_prl depend_includepath QTDIR_build release release ReleaseBuild Release build_pass openssl qt_install_headers qt warn_on depend_includepath qmake_cache target_qt debug_and_release static release ReleaseBuild Release build_pass no_autoqmake staticlib static moc thread
QMAKE_PRL_VERSION = 4
QMAKE_PRL_LIBS = ws2_32.lib /LIBPATH:D:\\OpenSSL\\1_0_0_1\\lib d:\\QtSDK1.2.1\\QtSources\\4.8.1\\lib\\QtCore.lib kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib libeay32.lib ssleay32.lib

Тут примечательно содержание QMAKE_PRL_LIBS . Похоже здесь находится расширенная информация о собранной библиотеке.

Похоже , что если вы будете использовать далее эту библиотеку (на этом же ПК), то Qt creator будет знать где лежат зависимые библиотеки (например наши openssl ), смотрите :
/LIBPATH:D:\\OpenSSL\\1_0_0_1_static\\lib
libeay32.lib ssleay32.lib

Теперь если мы создаем свою программу в дереве src , то есть внутри srс каталога, то нам в общем-то и не надо подключать библиотек libeay32.lib ssleay32.lib к своему проекту. То есть они будет подключены по результату работы config.exe , а потом по результату создания Makefile утилитой qmake. А именно в Makefile появятся примерно такие записи :


d:\QtSDK1.2.1\QtSources\4.8.1\lib\QtGui.prl \
d:\QtSDK1.2.1\QtSources\4.8.1\lib\QtNetwork.prl \
d:\QtSDK1.2.1\QtSources\4.8.1\lib\QtCore.prl

Теперь если взять ваш проект и вынести из дерева src, например перенести на другой диск, то результат работы qmake в Qt Creator будет другой, а именно выше приведенных строчек с prl не будет и вы нормально соберете проект, но есть нюанс: останется зависимость от Qt*****.dll , то есть проект похоже соберётся не статически. При запуске программы не найдена будет QtGui4.dll и т.д.

Если попытаться запустить config.exe с таким же параметрами в новом месте размещения вашего проекта, то это выдаст ошибку:
Invalid option "win32-msvc2010" for -platform.

Может показаться ,что ситуацию исправит добавление в pro файл вашего проекта этого, но это не влияет:

INCLUDEPATH  = d:\OpenSSL\1_0_0_1_static\include\openssl
LIBS  = -LD:\OpenSSL\1_0_0_1_static\lib -llibeay32 -lssleay32

Но оказывается есть способ сделать второй вариант вашего проекта статическим. Поскольку config.exe мы здесь не можем выполнить , но вот перенести .qmake.cache и configure.cache нам никто не запрещает?...

Смотрим и изучаем какие строчки файла .qmake.cache влияют на сборку статически:


LIBS            = -LD:\\OpenSSL\\1_0_0_1_static\\lib
OBJECTS_DIR     = tmp\\obj\\release_static
MOC_DIR         = tmp\\moc\\release_static
RCC_DIR         = tmp\\rcc\\release_static
INCLUDEPATH     = D:\\OpenSSL\\1_0_0_1_static\\include
OPENSSL_LIBS=-llibeay32 -lssleay32
styles          = windows windowsxp windowsvista
CONFIG          = minimal-config small-config medium-config large-config full-config release incremental msvc_mp create_prl link_prl depend_includepath QTDIR_build
QT_BUILD_PARTS  = libs tools docs translations
QMAKESPEC       = D:\\QtSDK1.2.1\\QtSources\\4.8.1\\mkspecs\\win32-msvc2010
ARCH            = windows
QT_BUILD_TREE   = D:\\QtSDK1.2.1\\QtSources\\4.8.1
QT_SOURCE_TREE  = D:\\QtSDK1.2.1\\QtSources\\4.8.1
QMAKE_MOC       = $$QT_BUILD_TREE\\bin\\moc.exe
QMAKE_UIC       = $$QT_BUILD_TREE\\bin\\uic.exe
QMAKE_UIC3      = $$QT_BUILD_TREE\\bin\\uic3.exe
QMAKE_RCC       = $$QT_BUILD_TREE\\bin\\rcc.exe
QMAKE_DUMPCPP   = $$QT_BUILD_TREE\\bin\\dumpcpp.exe
QMAKE_INCDIR_QT = $$QT_BUILD_TREE\\include
QMAKE_LIBDIR_QT = $$QT_BUILD_TREE\\lib

Оказывается влияют только две ниже приведенные строчки файла .qmake.cache:

QT_BUILD_TREE   = D:\\QtSDK1.2.1\\QtSources\\4.8.1
QMAKE_INCDIR_QT = $$QT_BUILD_TREE\\include

configure.cache в данном вопросе не влияет.

Ну и наконец в чем отличие сборок получается : отличите в линковке в самом конце . Какой вариант собирает статику думаю очевиден :

link /LIBPATH:"d:\QtSDK1.2.1\Desktop\Qt\4.8.1\msvc2010\lib" ......
link /LIBPATH:"d:\QtSDK1.2.1\QtSources\4.8.1\lib" ......

Просто тупо используется разные пути к библиотекам , их как видно как минимум два варианта. Причем в *.lib варианте библиотек для
d:\QtSDK1.2.1\Desktop\Qt\4.8.1\msvc2010\lib число 4 на конце : QtCore4.lib
А в статике почему-то вариант QtCore.lib (без 4 на конце)? Может в этом есть какой-то сокральный смысл?...

Остается интересный вопрос как в среде Qt Creator где-то иметь возможность установить нужный QMAKE_INCDIR_QT и т.д.

Оказывается , что в pro файле где-то в начале можно прописать инструкции из файла .qmake.cache и все соберется статически :

.....
QT_BUILD_TREE   = D:\\QtSDK1.2.1\\QtSources\\4.8.1
QMAKE_MOC       = $$QT_BUILD_TREE\\bin\\moc.exe
QMAKE_UIC       = $$QT_BUILD_TREE\\bin\\uic.exe
QMAKE_UIC3      = $$QT_BUILD_TREE\\bin\\uic3.exe
QMAKE_RCC       = $$QT_BUILD_TREE\\bin\\rcc.exe
QMAKE_DUMPCPP   = $$QT_BUILD_TREE\\bin\\dumpcpp.exe
QMAKE_INCDIR_QT = $$QT_BUILD_TREE\\include
QMAKE_LIBDIR_QT = $$QT_BUILD_TREE\\lib
......

Выводы : наконец-то становится понятно примерно где искать проблемы при статической сборке.

Примечание: на самом деле libeay32.dll и ssleay32.dll могут лежать не одном , а даже в нескольких общедоступных папках. Вы будете думать , что собрали статически, а на самом деле ваша программа будет находить libeay32.dll, ssleay32.dll , грузить в память и использовать.

У нас на ПК например эти библиотеки найдены примерно в таких папках:
C:\Windows\SysWOW64 - общая
C:\QtSDK1.2.1 look disk D\Desktop\Qt\4.8.1\mingw\bin
C:\QtSDK1.2.1 look disk D\QtCreator\bin
.....

openssl 1.0.2 под Qt 4.8.1.