I’m working on switching over to NixOS on my desktop and one of the last things I haven’t got fully working is my neovim config. My LSP’s are able to start, and all of them work fine except for clangd. For some reason, it can’t find C/C++ header files for any installed libraries. I have all of the LSPs themselves installed through Mason in Neovim, and I have programs.nix-ld.enable = true enabled so they can be run correctly.

screenshot showing 'file not found' error on '#include <fcntl.h>'

screenshot showing 'file not found' error on '#include <SDL2/SDL2.h>'

Here is the shell.nix file I’m using for this project:

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell.override { stdenv = pkgs.gccStdenv; } {
  nativeBuildInputs = with pkgs.buildPackages; [
    glibc libgcc
    clang-tools libclang
    SDL2 SDL2_image SDL2_sound
  ]; 
  CPATH = pkgs.lib.makeSearchPathOutput "dev" "include" pkgs.glibc pkgs.SDL2 pkgs.SDL2_Image pkgs.SDL2_sound;
}

Is there something extra I need to do to get clangd to find the C headers being used by the project? when I actually run gcc it compiles fine, it just can’t seem to find them correctly in Neovim

Edit: Forgot to mention that I’m using this shell with direnv and launching nvim directly from the same shell that I’m compiling from

  • balsoft@lemmy.ml
    link
    fedilink
    English
    arrow-up
    5
    ·
    edit-2
    2 days ago

    Because C++ doesn’t have a single well-defined build system, clangd doesn’t know how exactly to compile the files you are asking it to - in this case, it doesn’t know what headers to include. On some other distros it might “just work” because all headers are lumped together somewhere in /usr/include or something, and something somewhere tells clangd to just look in there. This isn’t the case on NixOS (in fact the headers are not installed at all with your system), and so you have to tell clangd where to look for them.

    Typically, your build system will have that information somehow. The process can vary depending on the build system you are using - some (like CMake or meson) can do it natively, for others you have to resort to a very useful hack called bear. Judging by your shell.nix, I would guess it’s make, which doesn’t have native compile_commands.json support, so what you have to do is:

    1. Add bear to your nativeBuildInputs
    2. Enter the shell again so that you have it in $PATH
    3. Run make clean (or otherwise ensure there are no build artifacts already present - maybe git clean -fx but be careful with that)
    4. Run bear -- make from the project root.

    make should then build your entire project, compiling every file in the process. bear will inspect the system calls that make is executing and determine which commands (and hence which command arguments) it used to compile each file, and create a file called compile_commands.json recording this information. clangd should then automatically find that file and use it to figure out which headers (and other arguments) it needs to compile each file.

    This is the setup I personally use to hack on Nix itself BTW, and it works great. Although I’m using helix and not neovim, but that shouldn’t matter.

    • Zangoose@lemmy.worldOP
      link
      fedilink
      English
      arrow-up
      1
      ·
      5 hours ago

      I’m actually using CMake for this project (I just haven’t moved it over from my system config yet) so I was able to set an environment variable to get that successfully. Is there a specific place I need to put the json to get clangd to recognize it?

      It would probably work if I used the python script from the other project but I want to try getting it working directly first.