Avatar ·

Ошибка сборки openssl-sys в Rust: решение проблемы даже после установки OpenSSL

Всем привет! Я новичок в Rust и пытаюсь собрать проект, который использует крейт `openssl`. Установил OpenSSL локально через менеджер пакетов (на Ubuntu — `sudo apt install libssl-dev`), но при запуске `cargo build` получаю ошибку: ``` error: failed to run custom build command for `openssl-sys v0.9.60` Caused by: process didn't exit successfully: `/path/to/target/debug/build/openssl-sys-...` (exit status: 101) --- stderr run pkg_config fail: "Could not run `\"pkg-config\" \"--libs\" \"--cflags\" \"openssl\"`" ``` Я проверил, что `libssl-dev` установлен, перезапускал терминал, даже переустанавливал Rust — ничего не помогает. Версия Rust: 1.65.0, Cargo: последняя. Вот мой `Cargo.toml`: ```toml [dependencies] openssl = "0.10.45" ``` Подскажите, в чем может быть проблема? Почему `openssl-sys` не видит установленную библиотеку, хотя она точно есть? Пробовал также установить `pkg-config` — ошибка осталась. Может, нужно что-то прописать в переменных окружения? Заранее спасибо! <<>>

Корень проблемы: pkg-config и переменные окружения

Ошибка, которую вы видите, типична для крейта openssl-sys. Он использует pkg-config для поиска установленного OpenSSL. Даже если libssl-dev установлен, pkg-config может не найти его по двум причинам:

  • Отсутствует сам pkg-config — нужно установить пакет pkg-config.
  • Не настроены переменные окружения — если OpenSSL установлен в нестандартный путь (например, через Homebrew на macOS или вручную), нужно указать его явно.

Решение 1: Установка pkg-config и libssl-dev (Linux)

На Ubuntu/Debian выполните:

sudo apt update
sudo apt install pkg-config libssl-dev

Затем перезапустите cargo build.

Решение 2: Переменные окружения для нестандартных путей

Если OpenSSL установлен в /usr/local/ssl или через пакетный менеджер вроде Homebrew (macOS) или vcpkg (Windows), задайте пути вручную:

export OPENSSL_DIR=/usr/local/ssl   # Путь к корню OpenSSL
export OPENSSL_LIB_DIR=$OPENSSL_DIR/lib
export OPENSSL_INCLUDE_DIR=$OPENSSL_DIR/include
cargo build

На macOS с Homebrew:

export OPENSSL_DIR=$(brew --prefix openssl)
cargo build

На Windows (с vcpkg):

$env:OPENSSL_DIR = "C:\vcpkg\installed\x64-windows"
cargo build

Решение 3: Использование крейта openssl с feature "vendored"

Если не хотите возиться с системными зависимостями, можно собрать OpenSSL статически вместе с проектом. Добавьте в Cargo.toml:

[dependencies]
openssl = { version = "0.10.45", features = ["vendored"] }

Это скачает и соберет OpenSSL автоматически (но увеличит время сборки и размер бинарника).

Проверка работоспособности

После любого из решений выполните cargo clean && cargo build. Если всё ещё ошибка — проверьте версию OpenSSL:

pkg-config --modversion openssl
# Должно вывести что-то вроде 1.1.1 или 3.0.0

Если pkg-config не выводит версию — значит, он не видит библиотеку, и нужно вернуться к Решению 2.

Дополнительный совет

Для macOS с Apple Silicon (M1/M2) OpenSSL часто устанавливается в /opt/homebrew/opt/openssl. В этом случае команда будет:

export OPENSSL_DIR=/opt/homebrew/opt/openssl
cargo build

Надеюсь, это поможет! Чаще всего проблема решается установкой pkg-config или указанием пути через OPENSSL_DIR.

<<>>

Альтернативный подход: использование Cross-компиляции или Docker

Если вы работаете в среде, где сложно управлять системными пакетами (например, на CI/CD или в контейнере), проще всего использовать Docker-образ с предустановленным OpenSSL. Например, официальный образ rust:latest уже содержит libssl-dev и pkg-config.

Пример Dockerfile:

FROM rust:latest
WORKDIR /usr/src/myapp
COPY . .
RUN cargo build --release

Также можно использовать крейт openssl-sys с feature "vendored" (как описано в первом ответе) — это полностью изолирует сборку от системы.

Ещё один вариант — заменить openssl на rustls, если вам не нужны специфические функции OpenSSL. rustls написан на чистом Rust и не требует внешних зависимостей:

[dependencies]
reqwest = { version = "0.11", features = ["rustls-tls"], default-features = false }

Это особенно удобно для веб-клиентов. Однако если проект использует openssl напрямую (например, для работы с сертификатами), этот вариант не подойдёт.