Samson G.
Samson G.

Reputation: 459

How to work with OpenSSL for Rust within a Windows development environment

I can't build my Rust project when I add an SSL dependency in my cargo file. This isn't new to Windows, but I'd like to resolve the issue such that I can use Powershell and native Windows development to work on my Rust project.

The dependency in question is the following:

[dependencies.ws]
version = "0.8.0"
features = ["ssl"]

When I run cargo build, I get a lot of errors regarding SSL as I'm on Windows so let us begin debugging this step by step.

First errors:

PS C:\Users\sam\vcs\project> cargo build
   Compiling openssl-sys v0.9.43
error: failed to run custom build command for `openssl-sys v0.9.43`
process didn't exit successfully: `C:\Users\sam\vcs\project\target\debug\build\openssl-sys-d964f46e4c48d206\build-script-main` (exit code: 101)
--- stdout
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=X86_64_PC_WINDOWS_MSVC_OPENSSL_LIB_DIR
X86_64_PC_WINDOWS_MSVC_OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=X86_64_PC_WINDOWS_MSVC_OPENSSL_INCLUDE_DIR
X86_64_PC_WINDOWS_MSVC_OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=X86_64_PC_WINDOWS_MSVC_OPENSSL_DIR
X86_64_PC_WINDOWS_MSVC_OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_DIR
OPENSSL_DIR unset
note: vcpkg did not find openssl as libcrypto and libssl: Aborted because VCPKGRS_DYNAMIC is not set
note: vcpkg did not find openssl as ssleay32 and libeay32: Aborted because VCPKGRS_DYNAMIC is not set

Alright, lets set OPENSSL_LIB_DIR, OPENSSL_INCLUDE_DIR, and OPENSSL_DIR

$env:OPENSSL_LIB_DIR="C:\OpenSSL-Win64\lib"
$env:OPENSSL_INCLUDE_DIR="C:\OpenSSL-Win64\include"
$env:OPENSSL_DIR="C:\OpenSSL-Win64"

However, now running cargo build or cargo run actually compiles, but I don't think SSL works correctly since the code path that connects to the websocket fails with error none.

I installed the latest (1.1.0j) full (non-slim) version of OpenSSL from the following website: https://slproweb.com/products/Win32OpenSSL.html

The only environment variable it had set was:

OPENSSL_CONF: C:\OpenSSL-Win64\bin\openssl.cfg

But I also added C:\OpenSSL-Win64\bin to my PATH.

When cargo build actually compiled, the websocket fails with error None

The on_error block is executed on my Windows box, but my Linux machine never executes this code block.

Just so we're on the same page, this is the output of the print statement:

fn on_error(&mut self, err: ws::Error) {
    println!("On Error, {}", err)
}

None isn't a very descriptive answer. So I assumed that I just needed some certs since OpenSSL doesn't come with certs. I downloaded a cacert.pem from somewhere online and placed it into the certs folder of the OpenSSL installation but that didn't make much difference either. Still the same None error.

On my Linux box, I would expect the websocket connection to succeed and for the code to proceed to on_open:

fn on_open(&mut self, _: ws::Handshake) -> ws::Result<()> {
...
}

Has anyone worked through this OpenSSL issue on their Windows development environment?


UPDATE 0

As per Cloud's advice, I tried to use VCPKG. Unfortunately it didn't work.

PS C:\Users\sam\vcs\vcpkg> .\vcpkg.exe list
openssl-windows:x64-windows-static                 1.0.2q-2         OpenSSL is an open source project that provides ...
openssl-windows:x86-windows                        1.0.2q-2         OpenSSL is an open source project that provides ...
openssl:x64-windows-static                         0                OpenSSL is an open source project that provides ...
openssl:x86-windows                                0                OpenSSL is an open source project that provides ...

Then I set the variables in my powershell window:

PS C:\Users\sam\vcs\project> $env:OPENSSL_DIR = 'C:\Users\sam\vcs\vcpkg\installed\x64-windows-static'
PS C:\Users\sam\vcs\project> $env:OPENSSL_STATIC = 'Yes'
PS C:\Users\sam\vcs\project> $env:VCPKGRS_DYNAMIC='1'

Then I ran cargo clean and then cargo build and I still got the same error where my websocket throws the error None.

Still no luck here.

Upvotes: 37

Views: 36189

Answers (10)

etaloof
etaloof

Reputation: 662

None of the other answers worked for me but I got it working with vcpkg and static linking. Here is what I did (I was trying to install wrangler, it worked after following the steps below and running cargo install wrangler).

  1. Install vcpkg (following the instructions from https://github.com/Microsoft/vcpkg#quick-start-windows). I ran this in a Visual Studio 2019 Developer Command Prompt (%comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat") but I don't know if this is necessary.

    cd C:\
    git clone https://github.com/microsoft/vcpkg
    cd vcpkg
    vcpkg\bootstrap-vcpkg.bat
    
  2. From the same command prompt, install openssl

    vcpkg\vcpkg install openssl:x64-windows-static
    
  3. Install the CA certificates (as described by Fatih Karan's answer and the old README of the rust-openssl project)

    mkdir "C:\Program Files\OpenSSL-Win64\certs"
    curl --remote-name --time-cond "C:\Program Files\OpenSSL-Win64\certs\cacert.pem" -o "C:\Program Files\OpenSSL-Win64\certs\cacert.pem" https://curl.se/ca/cacert.pem
    
  4. In a command prompt in your Rust project (or any other directory if you don't have a Rust project and just need to cargo install something), set the following environment variables:

    set OPENSSL_NO_VENDOR=1
    set RUSTFLAGS=-Ctarget-feature=+crt-static
    set SSL_CERT_FILE=C:\Program Files\OpenSSL-Win64\certs\cacert.pem
    
    • OPENSSL_NO_VENDOR to 1: Instruct the openssl-sys crate to use a pre-compiled openssl library. If this is not set it will try to compile it and fail (because perl is typically not available on Windows).
    • RUSTFLAGS to -Ctarget-feature=+crt-static: Instruct the Rust compiler (or more precisely the linker invoked by the Rust compiler) to produce a statically linked binary. If this is missing, the vcpkg crate (which is used by the openssl-sys crate to find the pre-compiled openssl library) will use the vcpkg triplet x64-windows-static-md. It seems that this triplet does not exist for openssl. With this environment variable, vcpkg will use the triplet x64-windows-static and this worked for me.
    • SSL_CERT_FILE to the location of cacert.pem: You need the root certificates in this file to make secure connections to servers.

Upvotes: 10

Azr
Azr

Reputation: 1143

This one worked for me:

in admin:

choco install openssl

not in admin

scoop install perl

Upvotes: 4

Arpad Palinkas
Arpad Palinkas

Reputation: 11

I've tried all of it above, seems like not really working right now. The only thing worked for me (maybe combined with the above solution since I've tried everything :D)

vcpkg install --triplet=x64-windows-static-md openssl

Found here: link to github

Upvotes: 1

Antonin GAVREL
Antonin GAVREL

Reputation: 11259

After installing OpenSSL Win64 .msi latest version just enter the following in terminal:

$env:X86_64_PC_WINDOWS_MSVC_OPENSSL_DIR="C:\Program Files\OpenSSL-Win64"

(This is the default path where it was installed)

Upvotes: 1

FatihAziz
FatihAziz

Reputation: 453

I do a little tweak from ZZ 5 answer,

so for me to fix it:

  1. run on elevated/run as administrator command promt/powershell git clone [email protected]:microsoft/vcpkg.git d:\dev\vcpkg it will install the vcpkg to d:\dev. why D:? because on C: it you might get problem with files permissions.
  2. then run, cd d:\dev\vcpkg
  3. run ./bootstrap-vcpkg.bat
  4. run ./vcpkg.exe install openssl:x64-windows-release
  5. run set VCPKGRS_DYNAMIC=1 or set it manually on edit environment variables GUI interface, add new variable VCPKGRS_DYNAMIC with value 1
  6. run choco install openssl (install choco here: https://chocolatey.org/, referrence: https://github.com/sfackler/rust-openssl/issues/1542#issuecomment-954434032)
  7. run winget install -e --id Microsoft.VisualStudio.2022.BuildTools && winget install -e --id Microsoft.VisualStudio.2019.BuildTools
  8. lastly install perl: https://strawberryperl.com/

then, on your RUST project, delete target directory. then run cargo clean && cargo build

I hope it work for you!

Upvotes: 2

Joshua Estes
Joshua Estes

Reputation: 91

I just had this issue and none of them worked, but here is what worked for me on Windows 11.

  1. Install OpenSSL from http://slproweb.com/products/Win32OpenSSL.html into C:\Program Files\OpenSSL-Win64

  2. Set all your env variables, for me I set OPENSSL_CONF to C:\Program Files\OpenSSL-Win64\bin\openssl.cfg and added C:\Program Files\OpenSSL-Win64\bin to my path.

  3. Download the cert, assuming you have wget installed, wget https://curl.se/ca/cacert.pem -o cacert.pem into C:\Program Files\OpenSSL-Win64\certs

  4. Next step is to set up your environment for building openssl run in powershell:

 $env:OPENSSL_NO_VENDOR=1
 $env:RUSTFLAGS='-Ctarget-feature=+crt-static'
 $env:SSL_CERT = 'C:\OpenSSL-Win64\certs\cacert.pem'
 $env:OPENSSL_DIR = 'C:\Program Files\OpenSSL-Win64'

and run cargo build

Upvotes: 8

ZZ 5
ZZ 5

Reputation: 1964

  1. clone vcpkg
  2. open directory where you've cloned vcpkg
  3. run ./bootstrap-vcpkg.bat
  4. run ./vcpkg.exe install openssl-windows:x64-windows
  5. run ./vcpkg.exe install openssl:x64-windows-static
  6. run ./vcpkg.exe integrate install
  7. run set VCPKGRS_DYNAMIC=1 (or simply set it as your environment variable)

Upvotes: 50

Kyroath
Kyroath

Reputation: 346

I had the same issue. Older version of the README of rust-openssl has the installation process for the Windows.

Precompiled Binaries

Download the precompiled binaries from here(non-light version), and install it. After the installation, set the environment variable OPENSSL_DIR to the installation path.

set OPENSSL_DIR=path\to\the\installation\dir

If you chose the Copy OpenSSL DLLs to: The OpenSSL binaries (/bin) directory option during the installation, add that directory to your path as well.

set PATH=%PATH%;path\to\the\installation\dir\bin

Then, you need to install the root certificate.

Using vcpkg

Install vcpkg by following the instructions on the README. After installation, run these commands.

vcpkg install openssl:x64-windows
set VCPKG_ROOT=c:\path\to\vcpkg\installation

Then, you need to install the root certificate.

Installing the root certificate

Download the cacert.pem file. Save it to somewhere (i.e C:\Program Files\OpenSSL-Win64\certs\cacert.pem), and add the SSL_CERT_FILE environment variable and point it to the file.

set SSL_CERT_FILE=C:\Program Files\OpenSSL-Win64\certs\cacert.pem

Upvotes: 20

maple
maple

Reputation: 1

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
#Add the current folder into PATH environment variable
vcpkg install openssl-windows:x64-windows
#Switch to the rust project
cargo build

Upvotes: -3

Cloud
Cloud

Reputation: 1412

the cargo build logic for C/C++ libraries is quite simple actually, it just compiles a rust program which searches for include path and libs and then produce some text output and cargo will consume it.

From https://github.com/sfackler/rust-openssl/blob/master/openssl-sys/build/find_normal.rs I can see some vcpkg keywords, then I would suggest you simply using vcpkg to resolve all your dependencies, and get rid of those env variables.

Upvotes: -2

Related Questions