Статические библиотеки OpenSSL * .a не связаны целевым двоичным файлом (используя статически скомпилированный Qt с SSL) - PullRequest
3 голосов
/ 16 октября 2019

Сразу же, извините за длину вопроса, но это связано со всеми дополнительными деталями, которые я предоставляю, и надеюсь, что это может помочь решить проблему быстрее

Чего я пытаюсь достичь?

Мне нужно создать портативное (все-в-одном) приложение с поддержкой SSL.

В чем проблема?

Итак, основная проблема, с которой я сталкиваюсь, заключается в том, чтобы включить поддержку SSL в мое двоичное / переносное приложение.

A MCVE приложения просто:

Проект .pro Файл

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

Проект 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();
}

  • Вывод на мой DEV-аппарат :

    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"

Информация о 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

  • Запуск того же двоичного файла на новой машине с Windows 10 x86 приводит к:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Информация о тестовой машине (Совершенно новая установка - 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.

  • Запуск того же двоичного файла на новой машине с Windows 7 x64 приводит к:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Информация о тестовой машине (ноутбук с Windows 7 x64 с установленными драйверами)

    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.

Посмотрев на приведенные выше результаты, я пришел к выводучто установка OpenSSL решает проблему. Хорошо, но я хочу, чтобы он был включен в мое портативное приложение.

Для достижения этого мне необходимо

  1. Статическая компиляция Qt с поддержкой OpenSSL

Я сделал это с помощью этого сценария , адаптированного из ps1 сценария powershell найденного здесь, на вики Qt . Я сделал дополнения для:

  • OpenSSL home $OPENSSL_HOME

  • количество потоков $threads и

  • тип архитектуры $arch, который будет использоваться.

Детали компиляции Qt и информация OpenSSL

  • Компилятор: mingw32 находится в C:\Qt\Qt5.13.1\Tools\mingw730_32\bin

  • mkspec: win32-g++ (если это имеет какое-то значение).

  • Версия OpenSSL (32бит): 1.1.1d

Конфигурация следующая :

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)"

Примечание 1:

Я использую -openssl, а не -openssl-linked. Я пробовал несколько вариантов сборки Qt с -openssl и -openssl-linked. -openssl-linked никогда не смог бы успешно построить, см. этот пост Я объяснил причину.

Примечание 2:

Единственная успешная статическая компиляция Qt, с которой я работал, была с -ssl -openssl включенными флагами конфигурации

Установка OpenSSL (только на компьютере DEV) находится на

`$OPENSSL_HOME = "C:\OpenSSL-Win32"` 

, где я использую статически скомпилированные MinGW библиотеки для OpenSSL, найденные в

`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`

Содержимое файла C:\OpenSSL-Win32\lib\MinGW:

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

Добавление проекта ссылки .pro в библиотеки OpenSSL

Я добавил библиотеки OpenSSL в файл .pro, используя 2 метода (библиотеки - это статически скомпилированные библиотеки MinGW OpenSSL, найденныеat C:\OpenSSL-Win32\lib\MinGW)

Ручной ввод библиотек в файл .pro

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

Примечание 3

Двоичный размер с ибез вышеупомянутых связанных библиотек остается тот же самый размер

Вывод LDD двоичного файла (на моем компьютере разработчика) с добавленными выше библиотеками:

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

Вывод LDD изБинарный файл (на моем тестовом компьютере с Windows 10 x86) с добавленными выше библиотеками:

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

Импорт библиотеки Qt в файл .pro

Импорт с использованием (External Library> Импорт .a файл> Static & Windows только параметры с суффиксом no debug

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

Используя автоматический импорт двоичных файлов, вывод двоичного файла LDD (на моем устройствемашина) с библиотеками, добавленными выше:

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

И при использовании автоматического импорта библиотеки вывод двоичного файла LDD (на моем тестовом компьютере с Windows 10 x86) с добавленными выше библиотеками:

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

Выходные данные приложения для машины dev: SSL enabled как упоминалось ранее в моем посте (как для ручной, так и для автоматической записи в библиотеку):

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"

Выходные данные приложения для тестовых машин (без установленного OpenSSL) такие же, как и ранее (для обеих инструкций вручную). и автоматическая запись в библиотеку):

Is SSL Enabled?  false
SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
SSL Library Version String (available locally):  ""

Таким образом, если библиотека OpenSSL отсутствует, она вызывает приведенную ниже ошибку при запросе соединения SSL на компьютерах не-Dev (свежая / клиентская):

QSslSocket :: connectToHostEncrypted: инициализация TLS завершилась неудачно

, что является результатом того, что библиотека OpenSSL не включена в двоичный файл как зависимость. Поэтому в принципе добавление статической библиотеки OpenSSL в файл проекта не работает или я что-то делаю неправильно где-то внизу.

Примечание 4: Почему вопрос не озаглавлен: Как импортировать статическую библиотеку в Qt?

Импорт статической библиотеки прост и не сложен. Я предполагаю, что где-то допустил ошибку в статической компиляции Qt с включенной поддержкой SSL.

Будем весьма признательны за советы по решению этой проблемы.


Обновление 1

Я решил проблему с -openssl-linked. Причина (или скорее исправление) состоит в том, чтобы не устанавливать OpenSSL на ваш компьютер. Скорее, распакуйте директории .a & include в отдельный каталог. Так что все то же самое, за исключением того, что у вас есть lib s & include без установки.

Затем используйте стандартную конфигурацию (упомянутую выше), заменив -openssl на -openssl-linked, и у вас должна получиться успешная компиляция.

Обновленная проблема

При сборке и запуске моего приложения с новым Linked OpenSSL Qt kit я получаю сообщение:

Выполнение кода не может быть продолжено, поскольку libcrypto.dll не был найден. Переустановка программы может решить эту проблему.

За этим следует другое диалоговое окно

Невозможно продолжить выполнение кода, так как libssl.dll не был найден. Переустановка программы может решить эту проблему

Требования LDD:

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

Протестировали это с и без .pro LIBS & INCLUDEPATH. Оба результата приводят к отсутствию dll.

Ответы [ 3 ]

3 голосов
/ 20 октября 2019

Опция конфигурации -openssl конфигурирует Qt для динамической загрузки libopenssl с использованием LoadLibrary или другой эквивалентной функции платформы. Поэтому с этого момента все ваши усилия тщетны. Вам нужно вернуться и решить проблему, связанную с -openssl.

0 голосов
/ 26 октября 2019

Если вы правильно собрали Qt, ссылаясь на ssl как статический, вам больше не нужно явно связывать ssl с приложением, просто свяжите Qt.

Правильная форма для gcc: -Lrelative-or-absolute/path (I* использую * nix paths), -L для указания пути, где расположены библиотеки, и -lxyz, где xyz - имя библиотеки для ссылки, ssl (без префикса lib и без суффикса .a)

Но в итоге файл .a представляет собой набор файлов .o и может быть добавлен на этапе компоновки следующим образом: gcc -o target file.o libssl.a (следовательно, в некоторых случаях просто LIBS += /path/libssl.a можетработа)

Согласно документации Qt нет необходимости удалять системный ssl, просто передайте (экспортируйте) переменную среды OPENSSL_LIBS в сценарий настройки Qt (OPENSSL_LIBS='-L/opt/ssl/lib -lssl -lcrypto')

Если присутствуют оба файла (.a, .dll), gcc может по-прежнему предпочитать динамическую версию, чтобы убедиться, что вы связываете статическую версию, вы можете удалить файлы .dll.

Документация Qt не ясна (IMHO) наТот факт, что ssl поддерживает статическую связь, я предполагаю, что это так, но следует проверить

По умолчанию библиотека Qt с поддержкой SSL динамически загружает любую установленную библиотеку OpenSSL во время выполнения. Тем не менее, можно связать библиотеку во время компиляции, сконфигурировав Qt с опцией -openssl-connected.

Если я сделаю сборку для себя, я включу подробный вывод, иЯ бы проверил в журнале, что он на самом деле статически связан, я бы проверил, что он взят из правильного каталога и что конечная цель Qt содержит символы ssl.

0 голосов
/ 21 октября 2019

Просто отправьте 4 файла DLL из OpenSSL вместе с вашим приложением (то есть скопируйте libcrypto-1_1-x64.dll, libssl-1_1-x64.dll, libcrypto-1_1.dll и libssl-1_1.dll для установки вашего приложения). ).

Статическая сборка всех библиотек может привести к нарушению лицензии LGPL, если вы используете бесплатную версию Qt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...