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 шт):
Господа,
спасибо всем, кто обратил внимание на мой вопрос.
Фактически, на мой вопрос в комментариях ответил HolyBlackCat, который помогает мне уже не в первый раз.
И ответ на это вопрос хорош не только тем, что отвечает "как собрать конкретную программу", но и тем, что описывает общий способ решать такие проблемы.
Краткое содержание: мне понадобилось понять, какие ошибки я совершаю, когда формирую строку запуска компилятора. Затем мне понадобилось научиться пользоваться утилитой pkg-config и просто копировать ключи, которые подсказывает эта утилита, в команду запуска компилятора. И как вишенка на торте - я наконец то, через 3 года мучений научился статически линковаться в windows.
Мои шаги были следующими:
- упростить задачу до невозможности.
Давайте не будем отправлять 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'
- Возвращаемся к исходной задаче. Мне 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
успешно собирает проект!
Большое спасибо всем, кто подсказывал и вообще дочитал до этого места.