Cargo fails to build plotters due to missing /usr/bin/file

I’ve been using rust for a while and recently wanted to start using plotters for visualization. Unfortunately it looks like this is tricky on nixos due to its dependency on several system based crates. I’ve added most of them, but cargo still fails to build this trivial example below because it can’t build servo-fontconfig since something relies on /usr/bin/file which nixos does not have. I’ve tried using naersk as well to build this, but I still run into the same problem (and ideally would like quick development iteration with cargo instead of nix build the default package.

How can I fix this problem? It seems most likely that I won’t be able to use a simple cargo build in my nix develop shell anymore (which I would really like), but I can’t even get naersk or buildRustCrate to work.

flake.nix:

 {
  description = "Test";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11";
    flake-utils.url = "github:numtide/flake-utils";
    flake-utils.inputs.nixpkgs.follows = "nixpkgs";
    devshell.url = "github:numtide/devshell";
    devshell.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = inputs@{ self, ...}: with inputs;
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs { inherit system; overlays = [ devshell.overlay ]; };
        customCmd = p: { package = p; category = "terminal commands"; };
      in rec {
        devShell = pkgs.devshell.mkShell {
          packages = with pkgs; [
            cargo rustc nixfmt gcc
            gnumake fontconfig freetype expat libxml2 # plotters
          ];
        };
      });
}
[package]
name = "plotters_test"
version = "0.1.0"
authors = ["me <example@example.com>"]
edition = "2018"

[dependencies]
plotters = "0.3.1"

src/main.rs:

extern crate plotters;

fn main() {
   println!("Hello World!");
}

Command:

❯ cargo build
 ...
error: failed to run custom build command for `servo-fontconfig-sys v5.1.0`
...
  --- stderr
  ~/.cargo/registry/src/github.com-1ecc6299db9ec823/servo-fontconfig-sys-5.1.0/configure: line 7528: /usr/bin/file: No such file or directory
  configure: error: in `~/projects/tmp/target/debug/build/servo-fontconfig-sys-afbca9cff405bb2a/out':
  configure: error: The pkg-config script could not be found or is too old.  Make sure it
  is in your PATH or set the PKG_CONFIG environment variable to the full
  path to pkg-config.

  Alternatively, you may set the environment variables FREETYPE_CFLAGS
  and FREETYPE_LIBS to avoid the need to call pkg-config.
  See the pkg-config man page for more details.

  To get pkg-config, see <http://pkg-config.freedesktop.org/>.
  See `config.log' for more details
  make: *** [makefile.cargo:83: ~/projects/tmp/target/debug/build/servo-fontconfig-sys-afbca9cff405bb2a/out/Makefile] Error 1
  thread 'main' panicked at 'assertion failed: Command::new(\"make\").env(\"MAKEFLAGS\",\n                         env::var(\"CARGO_MAKEFLAGS\").unwrap_or_default()).args(&[\"-R\",\n
                                                               \"-f\",\n                                                                                 \"makefile.cargo\"]).status().unwrap().success(
)', ~/.cargo/registry/src/github.com-1ecc6299db9ec823/servo-fontconfig-sys-5.1.0/build.rs:41:5
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

1 Like

The “quick-and-dirty” downstream fix is figuring out how to run this build in an fhsUserEnv, and put that dependency in /usr/bin with it.

Personally I usually find that more hassle than just fixing the bug upstream, all they need to do is replace this with /usr/bin/env bash or /bin/sh (no bash features are used, so that’s completely pointlessly non-POSIX): https://github.com/v6x/servo-fontconfig/blob/a1d1a83a7afe4eed29cc0675d561000cab35ac3f/configure#L1

No idea why that shows up as /usr/bin/file, though, probably worth checking with a dependency on a private fork before coming in with PR-guns blazing :wink:

Thanks for the hint, but it looks like it is actually coming from here: https://github.com/servo/libfontconfig/blob/b65a31704b1bedc9670a4b5ce6d9d16d6a4d491e/configure#L7528

The package seems available on nixos (pkgs.fontconfig) but it looks like the servo-fontconfig crate is trying to build it from source. Any ideas on how to approach that?

There’s a force_system_lib feature, which may do what you want.

Looks like they’re vendoring that dependency, and doing so by dumping the whole source tree into their project.

autoconf should never call a binary like that, unless it’s distributed with it (in which case it will respect $PREFIX and not break on NixOS), which file isn’t. If you’re going to use file you should test for it, which will make autoconf resolve it from $PATH. Nothing in their configure.ac seems to suggest they’re even using file though, so I have absolutely no clue how that line ends up there, unless if they’re… manually editing that configure script, looks like someone committed a hand-edited pre-generated configure script and didn’t keep track of that with commits.

I don’t quite understand why this is done that way, but it’s no wonder it breaks. For your purposes just a PR replacing the /usr/bin/file with file is probably appropriate according to their use, but yeah, hopefully the force_system_lib feature just works and you don’t have to use this project.

The /usr/bin/file error is a red herring apparently. The real issue is missing dependencies. In this case, adding expat and fontconfig to nativeBuildInputs will fix the error. This is because the configure script is imported from a different package but doesn’t affect compilation. (not sure how this would be fixed to give correct errors)

Here is my nativeBuildInputs:

nativeBuildInputs = with pkgs; [cmake pkg-config freetype expat fontconfig];

The force_system_lib feature had no effect.

3 Likes

nativeBuildInputs = with pkgs; [cmake pkg-config freetype expat fontconfig];

worked for me, thanks for sharing! :slight_smile:
i had same error msg but for trying do some wgpu stuff

error: failed to run custom build command for servo-fontconfig-sys v5.1.0

[package]
name = "learn_wgpu"
version = "0.1.0"
edition = "2021"

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

[dependencies]
winit = "0.27"
env_logger = "0.10"
log = "0.4"
wgpu = "0.14"