Rust & OpenSSL woes

I read this thread, but there is no solution for my problem there.

It looks like Rust support in Nix is rather suboptimal compared to that of Haskell. I’m attempting to build GitHub - soywod/himalaya: CLI to manage emails with the following default.nix

let 
  pkgs = import <nixpkgs> {};
in 
pkgs.rustPlatform.buildRustPackage rec {
  pname = "himalaya";
  version = "0.0.1";

  src = ./.;

  buildInputs = with pkgs; [
    pkg-config 
    openssl
    openssl.dev
  ];

  cargoSha256 = "sha256-i8YKE5Z2xoNyjFktRRVA45zD6Qa0aPNC0AOjHUIglgk=";

  meta = with pkgs.stdenv.lib; {
    description = "...";
    homepage = "https://github.com/...";
  };
}

This throws,

run pkg_config fail: "Failed to run `\"pkg-config\" \"--libs\" \"--cflags\" \"openssl\"`: No such file or directory (os error 2)"

--- 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.

Why? I don’t understand. OpenSSL is specified as a build-time dependency.


After I added OPENSSL_DIR = pkgs.openssl.dev;,

thread 'main' panicked at 'OpenSSL libdir at `/nix/store/nwyjl66jl3hyyp45rphgbknjm1pqq29j-openssl-1.1.1k-dev/lib` does not contain the required files to either statically or dynamically link OpenSSL', /build/himalaya-0.0.1-vendor.tar.gz/openssl-sys/build/main.rs:326:13

/nix/store/nwyjl66jl3hyyp45rphgbknjm1pqq29j-openssl-1.1.1k-dev/lib/pkgconfig/ contains:

libcrypto.pc  libssl.pc  openssl.pc
3 Likes

Try putting pkg-config in nativeBuildInputs (which is the more appropriate place for it anyway).

2 Likes

For the record, adding the following worked:

  PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig";

If this is supposed to be configured automatically, then something in nixos-unstable is broken.

5 Likes

Here is a full working example that worked for me:

{ pkgs, ... }:

let
  auto-sound-system = with pkgs; rustPlatform.buildRustPackage rec {
    pname = "auto-sound-system";
    version = "1.0.0";
    src = /home/rajas/Documents/rust-esp32c3-examples/smart-power-button;
    buildAndTestSubdir = "computer";
    cargoLock = {
      lockFile = ./Cargo.lock;
    };
    nativeBuildInputs = [
      pkg-config
      openssl
      openssl.dev
    ];
    PKG_CONFIG_PATH = "${pkgs.openssl.dev}/lib/pkgconfig";
  };
in
{
  systemd.services.auto-sound-system = {
    enable = true;
    description = "Automatically turn on/off the sound system";
    serviceConfig = {
      Type = "exec";
      ExecStart = "${auto-sound-system}/bin/smart-power-button-computer";
    };
    wantedBy = [ "multi-user.target" ];
  };
}
1 Like

Hrm, I’d caution against using that as a template, the input handling is a bit messy. It’ll work for local builds, but not for the right reasons.

nativeBuildInputs is for stuff that should run on the build machine, buildInputs is for libraries & stuff that should be linked against. You also should not explicitly need openssl.dev in buildInputs, since the dev output should automatically be used.

pkg-config comes with a setup hook. This only executes if it’s in nativeBuildInputs. This setup hook will look for buildInputs which have a pkgconfig directory and add it to the PKG_CONFIG_PATH.

So, if we put packages in the correct input locations to begin with like so:

auto-sound-system = rustPlatform.buildRustPackage {
  pname = "auto-sound-system";
  version = "1.0.0";
  src = /home/rajas/Documents/rust-esp32c3-examples/smart-power-button;
  buildAndTestSubdir = "computer";
  cargoLock.lockFile = ./Cargo.lock;

  nativeBuildInputs = with pkgs; [
    pkg-config
  ];
  buildInputs = with pkgs; [
    openssl
  ];
};

The build will work without having to hack around with PKG_CONFIG_PATH, and cross-compilation won’t break.

8 Likes

I’ll try that. I thought that I had to use PKG_CONFIG_PATH because of Rust & OpenSSL woes - #3 by srid.

Yeah, I haven’t actively tested that this works, of course. 3 years may have changed things, or there may be a bug.

For future readers: You may want to try crate2nix, which exposes the nixpkgs built-in buildRustCrate builder instead - they have special features to set up your build env correctly for the dependency crates you use most of the time, that way you don’t need to worry about adding openssl yourself at all.

1 Like

I ran into this exact issue when I tried to help (and fork for my own idea) the Lemmy project by adding a nix flakey alternative to spinning up their complicated, Docker-dependent dev environment. I think I’ve almost recovered enough from the burnout of failing to do it the first time to take another stab!

This may be a tough nut, nix builds are sandboxed and so don’t play well with host dependencies (like running docker services), share if you ever figure it out :slight_smile:

1 Like

Edited my comment to be clearer. My mission was to entirely bypass their docker dependency and build it all natively with nix.

Some said that I was reinventing the wheel since nixpkgs already had packaged Lemmy. But, this is in the context of dev environment not running an instance.