Can't cross-compile project with OpenSSL

Hello

This is my Cargo.toml:

[package]
name = "kaddo"
version = "0.1.0"
authors = [""]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
env_logger = "0.8"
actix-web = {version = "3" }
actix-http = "2"
actix-session = "0.4.1"
actix-cors = "0.5.4"
askama = "0.9"
actix-files = "0.5.0"
actix-multipart = "0.3.0"
actix_extract_multipart = "0.3.1"
actix-form-data = "0.5.0"
mime = "0.3.16"
chrono = { version = "0.4", features = ["serde"] }
sqlx = { version = "0.4.2", features = [ "runtime-actix-native-tls", "mysql", "chrono" ] }
lazy_static="*"
async-std="*"
once_cell="*"
futures = "*"
serde = { version = "1.0", features = ["derive"] }
reqwest = { version = "0.10.10", features = ["json"] }
serde_json = "*"
lettre = "0.10.0-alpha.5"
lettre_email = "0.9.4"
hyperx = "1.4.0"
rust-crypto = "0.2.36"
rand = "0.8.3"
num-format = "0.4.0"
num-traits = "0.2"
num-derive = "0.2"
rust-argon2 = "0.8"
validator = { version = "0.12", features = ["derive"] }
derive_more = "0.99.16"
uuid = { version = "0.7.4", features = ["serde", "v4"] }
failure = "0.1.5"
sanitize-filename = "0.3.0"
itertools = "0.10.1"

Doing a cargo build works just fine on my Mac OS machine. But my VPS runs Debian 11 so I want to be able to cross-compile it from Mac OS to Debian 11.

I run this command for that:

cross build --release --target x86_64-unknown-linux-gnu

It kinda works fine until it tries to build OpenSSL. (Of course it's OpenSSL that needs to cause the problem... :roll_eyes:)

This is the error I get:

error: failed to run custom build command for `openssl-sys v0.9.70`

Caused by:
  process didn't exit successfully: `/target/release/build/openssl-sys-dbc2338194fceb35/build-script-main` (exit status: 101)
  --- stdout
  cargo:rustc-cfg=const_fn
  cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR
  X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR unset
  cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
  OPENSSL_LIB_DIR unset
  cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR
  X86_64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR unset
  cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
  OPENSSL_INCLUDE_DIR unset
  cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR
  X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR unset
  cargo:rerun-if-env-changed=OPENSSL_DIR
  OPENSSL_DIR unset
  cargo:rerun-if-env-changed=OPENSSL_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=OPENSSL_STATIC
  cargo:rerun-if-env-changed=OPENSSL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC
  cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_PATH
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
  cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
  run pkg_config fail: "`\"pkg-config\" \"--libs\" \"--cflags\" \"openssl\"` did not exit successfully: exit status: 1\n--- stderr\nPackage openssl was not found in the pkg-config search path.\nPerhaps you should add the directory containing `openssl.pc'\nto the PKG_CONFIG_PATH environment variable\nNo package 'openssl' found\n"

  --- stderr
  thread 'main' panicked at '

  Could not find directory of OpenSSL installation, and this `-sys` crate cannot
  proceed without this knowledge. If OpenSSL is installed and this crate had
  trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
  compilation process.

  Make sure you also have the development packages of openssl installed.
  For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.

  If you're in a situation where you think the directory *should* be found
  automatically, please open a bug at https://github.com/sfackler/rust-openssl
  and include information about your system as well as this message.

  $HOST = x86_64-unknown-linux-gnu
  $TARGET = x86_64-unknown-linux-gnu
  openssl-sys = 0.9.70

  ', /cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.70/build/find_normal.rs:180:5
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...
error: build failed

I do have OpenSSL and it's developer tools installed, otherwise the cargo build for my own Mac OS also wouldn't work. Do I maybe somehow also have to install the OpenSSL for Debian 11? Maybe I need to instal OpenSSL and the dev tools on the Docker image cargo cross uses?

To build for Linux you would need to install Linux libraries on macOS, and as far as I know, there's no such thing available. Rust's ability to cross-compile from macOS to Linux is only theoretical, and in practice it doesn't work.

1 Like

That sucks.

I’m not sure your requirements but you can look and see if your dependencies allow using rustls in lieu of OpenSSL. Since it’s pure rust, i think it should cross compile.

Yeah, system deps sucks when it comes to cross compile. Replace the reqwest = and sqlx = lines with this to use rustls instead.

sqlx = { version = "0.4.2", features = [ "runtime-actix-rustls", "mysql", "chrono" ] }
reqwest = { version = "0.10.10", features = [ "json", "rustls-tls" ], default-features = false }

OpenSSL is not the problem here. Even a pure-Rust "hello world" project will fail, because:

  • macOS doesn't ship with a cross-linker for Linux (and IIRC Rust's hidden lld isn't supported on macOS either)

  • macOS doesn't ship with glibc.

Setting up Zig and configuring Rust to use zig cc may be a way to get it working, but sadly it's easier to just compile in a Linux VM or a remote server.

If you have an M1 Mac, then cross-compilation from ARM Linux to x86 Linux is relatively easy on Debian (even cross-OpenSSL works).

1 Like

Using musl may work. Rustc ships musl's libc.a together with libstd for x86_64-unknown-linux-musl.

Rust's lld is shipped on macOS. Lld doesn't really support compiling for macOS right now AFAIK, but I would expect it to support compiling on macOS for other targets. You still need a gcc or clang that knows which flags to pass to the linker to compile for linux though. -Clinker=clang -Clink-args="-target x86_64-unknown-linux-musl" --target x86_64-unknown-linux-musl -Zgcc-ld=lld may work on nightly. I haven't tested this at all though.

Indeed

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.