How to correctly populate a clang and llvm development environment using nix-shell?

Thanks to the discussion in OpenSSL dependency for Rust - #4 by danieldk I learned you can add pkgconfig to a shell.nix that needs to use openssl. (I also updated the wiki).

I then thought to try the same trick for a shell.nix used to compile a Rust project, olm-rs, that needs clang and llvm. I started with the following shell.nix:

# copied expressions from https://nixos.wiki/wiki/Rust
# and Mozilla's nix overlay README
# https://www.scala-native.org/en/latest/user/setup.html
let
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
  pkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
in
  with pkgs;
  stdenv.mkDerivation {
    name = "clang-env-with-nightly-rust";
    buildInputs = [
      pkgs.latest.rustChannels.nightly.rust
      clang
      llvmPackages.libclang
      olm
    ];
    # why do we need to set the library path manually?
    shellHook = ''
      export LIBCLANG_PATH="${pkgs.llvmPackages.libclang}/lib";
    '';
  }

You’ll notice the ugly shellHook where I manually export the LIBCLANG_PATH.
When I remove the shellHook entirely and add pkgconfig to buildInputs, LIBCLANG_PATH is still not populated.

Am I specifying the wrong llvm and clang build inputs?
Or should I be doing something like what scala-native does?

1 Like

Yeah, clang does not provide pkgconfig files.

https://bugs.llvm.org/show_bug.cgi?id=9405

There are some other places it looks at:

https://crates.io/crates/clang-sys/0.8.0

You end up needing to set LIBCLANG_PATH no matter what here. It also looks for llvm-config, but we don’t put libclang there. So LIBCLANG_PATH is pretty much required. We could make this easier with a setup hook though.

PR here: LIBCLANG_PATH hook by matthewbauer · Pull Request #67725 · NixOS/nixpkgs · GitHub

2 Likes

Wow, thanks for the quick answer and solution @matthewbauer!
Confirms that I wasn’t crazy trying to write the shell.nix that way.

bumping since this is a top result when searching about LIBCLANG_PATH and nix shell
it seems the preferred way to do this now is to include the rustPlatform.bindgenHook defined by nixpkgs/pkgs/build-support/rust/hooks/default.nix at d6fd759574e957cad8699345deaee7fd014f1b75 · NixOS/nixpkgs · GitHub
in your shells nativeBuildInputs like so:

pkgs.mkShell {
  nativeBuildInputs = with pkgs; [
    rustc
    cargo
    rustfmt
    clippy
    rustPlatform.bindgenHook # required for libparted, sets LIBCLANG_PATH and friends
  ];

<rest of shell definition>
}