OpenSSL под Windows (используя g++ и MSYS2) - не могу собрать проект

Господа, я пытаюсь из программы на C++ отправить письмо по SMTP через сервер gmail.com.

Беру очень старый и очень известный проект

В нём все хорошо и понятно, но это проект под Visual Studio и он 32-битный. И библиотеки (и инклуды от openssl) "вшиты" прямо в проект.

Я пытаюсь собрать его с использованием свеженькой openssl, установив её через MSYS2 командой pacman -S mingw-w64-x86_64-openssl

Проверяю: команда pacman -Q | grep ssl выводит

    libopenssl 1.1.1.g-3
    mingw-w64-x86_64-openssl 1.1.1.g-1
    openssl 1.1.1.g-3

и по пути C:\Programs\msys64\mingw64\include есть директория openssl со всеми *.h - файлами.

Захожу по ссылке, описывающий этот package, вижу там следующие бинарные файлы (то есть, не-инкулуды, не - доки и не-маны):

    /mingw64/bin/libcrypto-1_1-x64.dll
    /mingw64/bin/libssl-1_1-x64.dll
    /mingw64/bin/openssl.exe
    /mingw64/lib/engines-1_1/capi.dll
    /mingw64/lib/engines-1_1/padlock.dll
    /mingw64/lib/libcrypto.a
    /mingw64/lib/libcrypto.dll.a
    /mingw64/lib/libssl.a
    /mingw64/lib/libssl.dll.a
    /mingw64/lib/pkgconfig/libcrypto.pc
    /mingw64/lib/pkgconfig/libssl.pc
    /mingw64/lib/pkgconfig/openssl.pc

Итак, у меня есть директория с проектом, в ней есть файл main.cpp, я поставил все необходимые зависимости, пишу в консоли, запущенной в этой директории g++ -std=c++17 -LC:/Programs/msys64/mingw64/bin -lssl-1_1-x64 -lcrypto-1_1-x64 -IC:\Programs\msys64\mingw64\include main.cpp -o main.exe и получаю большой набор ошибок линкера, который начинается так:

    C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Konst\AppData\Local\Temp\ccF1y7VW.o:main.cpp:(.text+0x26): undefined reference to `CSmtp::CSmtp()'
    C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Konst\AppData\Local\Temp\ccF1y7VW.o:main.cpp:(.text+0x45): undefined reference to `CSmtp::SetSMTPServer(char const*, unsigned short, bool)'
    C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Konst\AppData\Local\Temp\ccF1y7VW.o:main.cpp:(.text+0x69): undefined reference to `CSmtp::SetLogin(char const*)'
    C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Konst\AppData\Local\Temp\ccF1y7VW.o:main.cpp:(.text+0x7c): undefined reference to `CSmtp::SetPassword(char const*)'
    C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\Konst\AppData\Local\Temp\ccF1y7VW.o:main.cpp:(.text+0x8f): undefined reference to `CSmtp::SetSenderName(char const*)'

Точно такой же набор ошибок я получаю, если я вообще не указываю библиотек.

и при сборке командой

    g++ -std=c++17 -LC:/Programs/msys64/mingw64/lib -lssl -lcrypto -IC:\Programs\msys64\mingw64\include main.cpp -o main.exe

или командой

   g++ -std=c++17 -LC:/Programs/msys64/mingw64/lib -llibssl -llibcrypto -IC:\Programs\msys64\mingw64\include main.cpp -o main.exe

-набор ошибок не меняется.

Значит, я что то не так указываю в ключах -l или -L ?

В исходном проекте используются только 2 библиотеки, называются libeay32.lib и ssleay32.lib.

Может быть, кто то знает, какие их аналоги надо указать при сборке проекта в 64-битной версии?

Спасибо.


Ответы (1 шт):

Автор решения: S.H.

Господа,

спасибо всем, кто обратил внимание на мой вопрос.

Фактически, на мой вопрос в комментариях ответил HolyBlackCat, который помогает мне уже не в первый раз.

И ответ на это вопрос хорош не только тем, что отвечает "как собрать конкретную программу", но и тем, что описывает общий способ решать такие проблемы.

Краткое содержание: мне понадобилось понять, какие ошибки я совершаю, когда формирую строку запуска компилятора. Затем мне понадобилось научиться пользоваться утилитой pkg-config и просто копировать ключи, которые подсказывает эта утилита, в команду запуска компилятора. И как вишенка на торте - я наконец то, через 3 года мучений научился статически линковаться в windows.

Мои шаги были следующими:

  1. упростить задачу до невозможности.

Давайте не будем отправлять email, это сложно, к тому же кто их читает сейчас... Давайте просто посчитаем хэш SHA1

Гуглим пример

Исправляем в примере ошибку, заменив SHA1(ibuf, strlen(ibuf), obuf); на SHA1(ibuf, strlen((const char*)ibuf), obuf);

Гуглим видео

На этом видео на 18:38 на экране на четверть секунды мелькает фолдер с либами, которые надо прилинковать.

Видно, что библиотека называется libcrypto

Перебираем все возможные файлы на диске, которые содержат это название.

На файле llibcrypto-1_1-x64.dll нам везет, и команда

    g++.exe -std=c++17 -llibcrypto-1_1-x64 -LC:/Programs/msys64/mingw64/bin/ -g shatest.cpp -o shatest.exe

успешно собирает проект.

  • А как же со статической линковкой? - спросит внимательный читатель

Забудьте. Это Windows, детка. Здесь такого не бывает.

Все мои попытки как то подсунуть g++'у либу и ключ -static свелись к одной и той же ошибке undefined reference to 'SHA1'

  1. Возвращаемся к исходной задаче. Мне user7860670 любезно подсказал, что нужно перечислить все C++ - файлы, входящие в проект.

Итак, на команде

    g++.exe -std=c++17  -g main.cpp CSmtp.cpp md5.cpp base64.cpp -llibcrypto-1_1-x64 -llibssl-1_1-x64 -LC:/Programs/msys64/mingw64/bin/ -o main.exe

линкер начинает ругаться совсем по-новому, и эта ругать уже относится к winsock.

Пробую добавить винсок в список зависимостей.

Мучаюсь некоторое время, подбирая имена библиотеки в -l и пути в -L - ключах компилятора. Жалуюсь на проблему в комментариях, и получаю очень ценные подсказки. я бы их высек в граните, если б мне попалась под руку подходящая плита.

I. Неправильно писать ключи -l (и, видимо, -L) слева от набора *.cpp фалов в команде для g++. Эти штуки надо писать справа.

II. Угадывание зависимостей - это, конечно, увлекательная игра, но большие мальчики просто получают эту информацию, выполнив команду (в моём случае) pkg-config --libs --cflags --static openssl. Эта команда выдает инфу в таком виде:

    pkg-config --libs --cflags --static openssl
    -IC:/Programs/msys64/mingw64/include -LC:/Programs/msys64/mingw64/lib -lssl -lcrypto -lws2_32 -lgdi32 -lcrypt32

-и все, что нужно сделать, это просто скопировать нужные ключи и пути в команду для g++

III. Чтобы это стало возможным - нужно установить этот самый pkg-config, что в моём случае делается командой pacman -S mingw-w64-x86_64-pkg-config, которую нужно написать в окне msys2-shell.

IIII. Статическая компиляция под windows существует! В это трудно поверить, после того, как я несколько лет не мог этого сделать и был готов откусить себе пальцы от зависти, видя, как просто это работает в той же убунте. Весь секрет, видимо, в той самой неправильной последовательности *.cpp файлов и ключей -l в команде g++...

В результате команда

    g++.exe -std=c++17 -static -g main.cpp CSmtp.cpp md5.cpp base64.cpp -lssl -lcrypto -lws2_32 -lgdi32 -lcrypt32 -o main.exe

успешно собирает проект!

Большое спасибо всем, кто подсказывал и вообще дочитал до этого места.

→ Ссылка