[Tentative Solved]I try to build a Nickel example, but gap at openssl-sys-0.6.4

I try to create a Nickel sample and try cargo build it.
Everything seem correct until I encounter a compile error for openssl-sys-0.6-4

I am use Windows7, 64bit, Rust1.2

Errors:
--- stderr
C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\openssl-sys-0.6.4\src/openssl_shim.c:1:0: warning: -fPIC ignored for target (all code is position independent)
C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\openssl-sys-0.6.4\src/openssl_shim.c:1:0: sorry, unimplemented: 64-bit mode not compiled in
C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\openssl-sys-0.6.4\src/openssl_shim.c:1:26: fatal error: openssl/hmac.h: No such file or directory
compilation terminated.
thread '' panicked at 'explicit panic', C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\gcc-0.3.13\src\lib.rs:510
Can anybody help on it?
Thanks.

This would imply to me that you don't have OpenSSL installed. I don't know Windows well enough to give more suggestion than that, though. :confused:

1 Like

There was some talk about it in this thread, some time ago. I don't know what the best way of doing this on Windows is, but you need to have OpenSSL installed somewhere or somehow. That thread may give you some clues.

I download and install OpenSSL 64 bit version into C:\OpenSSL-Win64

Set ENV for
OPENSSL_LIB_DIR=C:\OpenSSL-Win64
OPENSSL_INCLUDE_DIR=C:\OpenSSL-Win64\include

And start build, have some improvement since reduce 1 error:
(... openssl/hmac.h: No such file or directory
compilation terminated.) if compare to my last post.

But still have below errors:
...
.../openssl_shim.c:1:0: sorry , unimplemented: 64-bit mode not compiled in
..

Can any body continue help on it? Thanks.

You may have to use 32bit Rust, 32bit MinGW and 32bit OpenSSL.

1 Like

Thanks for quickly response.
My system is 64 bit, so the Rust web directly recommend to download 64bit Rust.

I think that is rust openssl issue, rust better resolve for users:)
Thanks.

Yeah, it's a rust-openssl issue or a rust-gcc issue, I think. Picking 64bit Rust would have been the right choice if it wasn't for this.

I wrote the following angry rant a while ago after getting apoplectic at how stupid this whole song-and-dance is. I've cut the screenshots (because I'd have to upload them somewhere and they've SVG and just urgh). It's not entirely waterproof, but if nothing else helps, this might do it.

Also: I tested these instructions on a brand new, totally fresh Windows 10 install in 64-bit.


[cut rambling about installing Rust; short version: this doesn't work with the msvc compilers.]

Installing MSYS2

This is a little more involved. First, you will need to get the MSYS2 installer.

[blah blah blah, SourceForge evil, blah, blah, blah]

You can get the appropriate downloader from the MSYS2 installer website.

Note: You should select whatever "bitness" your version of Windows is. Whatever you select has no bearing whatsoever on the bitness of the binaries you intend to produce. msys2-i686-*.exe is for 32-bit Windows, msys2-x86_64-*.exe is for 64-bit Windows. I am not aware of any actual problems with using 32-bit MSYS2 on 64-bit Windows.

When installing MSYS2, you will most likely want to install to a location that does not contain spaces. As noted above, UNIX tools are notoriously bad at dealing with spaces in path names, and MSYS is full of them; it only takes one to ruin your day.

You should now follow the rest of the installation instructions on the installer website. You can get an appropriate MSYS2 shell using the creatively named "MSYS2 Shell" shortcut the installer added to the start menu under the "MSYS2 32bit" or "MSYS2 64bit" group (as appropriate).

[cut image]

MSYS2 and MinGW-w64

And now I have to explain this mess.

When you install MSYS2, it actually adds three Start Menu entries, each of which does something slightly different.

[cut image]

  • MSYS2 Shell: just drops you into a regular MSYS2 bash shell.

  • MinGW-w64 Win32 Shell: drops you into a MSYS2 bash shell configured to use the MinGW-w64 32-bit toolchain.

  • MinGW-w64 Win64 Shell: drops you into a MSYS2 bash shell configured to use the MinGW-w64 64-bit toolchain.

Now, despite the name, MinGW-w64 is not specific to 64-bit versions of Windows, nor does it only create 64-bit executables. Really, "MinGW-w64" is a brand name, more than anything technically meaningful. It's terribly named, but there's really nothing we can do about that.

For the purposes of building Rust software, you need to pick either "MinGW-w64 Win32 Shell" or "MinGW-w64 Win64 Shell", based on which bitness your Rust compiler is. 32-bit Rust, use "Win32"; 64-bit Rust, use "Win64".

If you get this wrong, system library crates will not link properly!

Now, open a MSYS2 shell (preferably of the kind you will use with Rust).

MSYS2 has its a package manager for taking care of installing libraries and tools, as well as their dependencies. Unfortunately, it's the package manager from Arch Linux, which means almost all of the documentation and instructions you'll find for it apply to Arch Linux and not necessarily MSYS2. You can use man pacman from a MSYS2 shell to get the manual page, or pacman -h for brief usage instructions.

Since we're going to want a full GCC install for compiling *-sys crates, let's find out what the appropriate package is called. You can do this by running pacman -Ss 'gcc$' from the shell. [^pacman-ss-gcc]

[cut image]

If you look carefully, you'll note that there are actually three versions of GCC in this list:

  • mingw32/mingw-w64-i686-gcc
  • mingw64/mingw-w64-x86_64-gcc
  • msys/gcc

You want exactly one of these. If you are using 32-bit Rust, you want mingw32/mingw-w64-i686-gcc. If you are using 64-bit Rust, you want mingw64/mingw-w64-x86_64-gcc.

You do not want msys/gcc, because that is for compiling software that is meant to be used with MSYS2. We want to build software that is targetting a particular bitness of Windows, using a compiler built for MSYS2.

So, install the appropriate package now with pacman -S followed by the package's name. This will also install all of its dependencies.

At this point, you should be able to use gcc --version to verify that GCC is, indeed, installed.

OpenSSL

For this part, we'll need an example crate. The easiest one is probably the "Hello, World" example for Iron, a Rust HTTP server framework.

Drop into a shell or command prompt and execute:

cargo new --bin iron-test

This will create a new directory called iron-test for us to put our code in. Drop in and edit Cargo.toml to read as follows:

[package]
name = "iron-test"
version = "0.1.0"
authors = ["your name will be here"]

[dependencies]
iron = "*"

Then, edit src/main.rs to the following:

extern crate iron;

use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(|_: &mut Request| {
        Ok(Response::with((status::Ok, "Hello world!")))
    }).http("localhost:3000").unwrap();
}

From the appropriate MinGW-w64 MSYS2 shell, run cargo build from anywhere in the package directory. The build will first update the crates.io registry, then download packages, then start compiling.

At some point after you see Compiling openssl-sys v0.6.2 (or whatever version), the build should fail.

[cut image]

The openssl/hmac.h: No such file or directory implies that the problem is missing headers. Let's fix that. First, look for an OpenSSL package with pacman -Ss 'openssl'.

[cut image]

Again, there is more than one plausible option. Again, you want the one under either mingw32/ or mingw64/, not the one under msys/. Specifically, for 32-bit Rust you want mingw32/mingw-w64-i686-openssl; for 64-bit you want mingw64/mingw-w64-x86_64-openssl.

Again, install with pacman -S PACKAGE_NAME.

[cut image]

Re-running cargo build should give us a new and excitingly different error message:

[cut image: error in question is explained below]

If you got an error about missing headers, you probably installed the wrong OpenSSL package; just go back and install the right one.

Note the ld: cannot find -leay32 and ld: cannot find -lssl32 lines near the bottom. This is because the linker Rust is using cannot find the OpenSSL libraries.

Note: The gcc and ld that Rust uses are different to the ones you installed. Rust comes with its own, private copies, since it uses gcc as the linker on Windows. Yes, this can be confusing as hell if you're not aware of it.

The solution is to put the OpenSSL libraries where Rust can find them. First, the libraries you want are libeay32.dll and ssleay32.dll from MSYS2\mingw32\bin or MSYS2\mingw64\bin.

You may have noticed that the names don't match. Of course they don't, because we're using Windows and software from a UNIX background always manages to throw a spanner in the works. [^damn-unix]

The official way to solve this is to write a build script, but build scripts tend to be written on the assumption that libraries are all installed system-wide, which doesn't help us, and forking an entire project just to make the build script work gets old fast. As such, we can abuse the fact that when you build a Cargo package from the same directory as the Cargo.toml is in (i.e. not in a subdirectory), rustc will coincidentally search the following folders for libraries:

  • For 32-bit Rust: iron-test\bin\i686-pc-windows-gnu.
  • For 64-bit Rust: iron-test\bin\x86_64-pc-windows-gnu.

You will almost certainly have to create these directories. Don't make a typo!

At this point, you can rename the libraries.

  • libeay32.dlleay32.dll
  • ssleay32.dllssl32.dll

Now, finally, you can re-run cargo build. It should build cleanly. You can start the server using cargo run and point your browser at http://localhost:3000/ to see the result. Do note that you should not try killing the server using Ctrl+C from within MSYS2: this has a habit of leaving the server running invisibly in the background, requiring it to be killed from the Task Manager or similar.

That's (finally) it. Have fun with Rust.

Optional: Freeing Yourself From MSYS2

If you're comfortable with doing so, you can free yourself from the need to build some Rust *-sys packages from the MSYS2 shell by adding GCC to the system PATH. Specifically, you want to add MSYS2\mingw32\bin or MSYS2\mingw64\bin, depending on which you installed.

Note that this will not help in the presence of crates that, say, use a Makefile to build a dependency. In these cases, you will still need to drop into an MSYS2 shell in order to get make and the other UNIX tools, or just fork and modify the crate to not need a Makefile in the first place.


Footnotes, because Markdown is a toy and they don't work on the forum:

[^pacman-ss-gcc]: The -S tells pacman to look at the remote package repository (as opposed to working with what's locally available), then to search (s) for a package matching the regex gcc$. This was used to eliminate the mountain of related-to GCC packages.

[^damn-unix]: UNIX advocates will insist that this is Window's fault for not being a UNIX system. This is textbook victim-blaming and bullying, and such people should be ruthlessly shamed on social media for their regressive and oppressive views. Especially if they use a Mac. Damn hipsters.

3 Likes

Thanks for your reply.

I think the key thing is how to tell rustc link the correct ssl related dll.
I try to read the compile err info carefully, and find below:
--- stdout
cargo:rustc-link-search=native=C:\OpenSSL-Win64
cargo:rustc-link-lib=dylib=eay32
cargo:rustc-link-lib=dylib=ssl32
TARGET = Some("x86_64-pc-windows-gnu")
TARGET = Some("x86_64-pc-windows-gnu")
...

It means, the compile does find my installed open ssl and try to find eay32 and ssl32
So I try to copy libeay32.dll to eay32.dll and libssl32.dll to ssl32.dll.
And try build again. However, still show error like below:

--- stderr
C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\openssl-sys-0.6.4\src/openssl_shim.c:1:0: warning: -fPIC ignored for target (all code is position independent)
C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\openssl-sys-0.6.4\src/openssl_shim.c:1:0: sorry, unimplemented: 64-bit mode not compiled in
thread '' panicked at 'explicit panic', C:\Users\scott_huang.cargo\registry\src\github.com-0a35038f75765ae4\gcc-0.3.13\src\lib.rs:510

So, I think Ogeon should be correct, the rusl open ssl crate did not consider 64 bit
since "openssl-sys-0.6.4\src/openssl_shim.c:1:0: sorry, unimplemented: 64-bit mode not compiled in"
I may be need change rust to 32 bit, ssl to 32 bit too if I want use that ssl lib.

Btw:
As for MSYS2 64bit, I can use pacman to list the the mingw related info,
However, when I use "pacman -S mingw64/mingw-w64-x86_64-gcc" it will pop up option for me to choose
install, but failed to retrieve files due the the requested URL return error:404

As of the release notes of Rust 1.2, Rust now works with msvc. Does this guide still apply?

asking as a GNU/Linux user who doesn't need to care, just wondering

The problem is that there are incompatibilities between libraries produced by GCC and those produced by MSVC... depending on what exactly you're doing and how it was compiled and linked and how you're linking them together. Stupid things like having two libraries using different allocators, or ABI calls not being entirely the same in corner cases.

Basically, you just try to avoid mixing the two wherever possible. It's easier to say "it doesn't work" then spend half an hour detailing all the obscure ways it can break. I honestly don't even remember most of them any more. I just know that mixing MSVC and GCC libraries (especially static ones) leads to nothing but pain and suffering, so don't do it.

1 Like

AFAIR, you don't need to rename anything, cargo:rustc-link-lib=dylib=eay32 will search for both eay32.dll and libeay32.dll (with and without lib prefix).

I think you misunderstood. For better understanding why it's failing for you read this and this. Basically, build fails because you lacking gcc which can compile openssl_shim.

Try installing mingw-w64-x86_64-toolchain (e.g. $ pacman -S mingw-w64-x86_64-toolchain for 64-bit target), this should give you all needed for building Nickel examples.

Thanks for pointing that out.

Case can close now.
I successfully complete that Nickel sample after use Rust1.2 32bit and OpenSSL 32 bit. Thanks.

String strong request RUST or RUST-OPENSSL team help to resolve OpenSSL 64bit issue ASAP! thanks.

Thanks for providing more motivation for me to work on an schannel library so Hyper can have SSL/TLS without relying on OpenSSL.

I download MSYS2 already, but just like I state at before post, I am failed to download migw-w64-x86_64-toolchain due to target web return 404. I try several times, but failed due to network issue.
So I have to choose change to rust1.2 32 bit and openssl 32 bit at last. And resolve the issue already.

The issue better resolve by Hyper crate don't rely to openssl OR openssl author resolve itself issue OR RUST team resolve it from top down solutions.

btw, I am sure I always download 64 bit software, including gcc 64 bit before, since I use 64bit Windows.

Thanks.