NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
17.64k stars 13.8k forks source link

Listing clang before or after clang-tools in buildInputs results in a different clangd version. #76486

Open spearman opened 4 years ago

spearman commented 4 years ago

Describe the bug The version of clangd depends on whether clang is listed before or after clang-tools in the buildInputs of mkShell.

To Reproduce

$ nix-shell --expr 'with import <nixpkgs> {}; mkShell { buildInputs = [ clang clang-tools ]; }'
% clangd --version
clangd version 7.1.0 (tags/RELEASE_710/final)
% exit
$ nix-shell --expr 'with import <nixpkgs> {}; mkShell { buildInputs = [ clang-tools clang ]; }'
% clangd --version
/nix/store/1awkf4hm1ljmg47hm2yk1bmrqr13n3zi-clang-tools-8.0.1/bin/clangd: line 9: $path${path':'}$1: bad substitution
clangd version 8.0.1 (tags/RELEASE_801/final)

Expected behavior I could be misusing the clang-tools package, but I wouldn't expect the order of buildInputs to determine which version of a tool gets installed.

Additional context Even though there is a 'bad substitution' error in the second case with 8.0.1 (clang listed after clang-tools), this is the order that "works" for me. If clang is listed before clang-tools resulting in clangd 7.0.1, clangd is unable to find stdio.h when using it with vim-lsp. If clang is listed after clang-tools, then clangd 8.0.1 can find stdio.h.

Metadata

$ nix run nixpkgs.nix-info -c nix-info -m
 - system: `"x86_64-linux"`
 - host os: `Linux 4.19.91, NixOS, 19.09.1685.e9ef090eb54 (Loris)`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3`
 - channels(root): `"nixos-19.09.1685.e9ef090eb54"`
 - channels(spearman): `""`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`

Maintainer information:

# a list of nixpkgs attributes affected by the problem
attribute: [ clang, clang-tools ]
# a list of nixos modules affected by the problem
module:
spearman commented 4 years ago

So the latest clang-tools/wrapper does fix the version mismatch (now it is clangd 7.1.0 in both cases), but whether or not clangd can find stdio.h still seems to depend on the order. Here are the logs using vim-lsp:

buildInputs = [ clang clang-tools ];

buildInputs = [ clang-tools clang ];

NilsIrl commented 4 years ago

cc @aherrmann

aherrmann commented 4 years ago

@NilsIrl clang-tools creates a wrapper for clangd that defines the environment variables CPATH and CPLUS_INCLUDE_PATH. So, both clang and clang-tools provide different clangd. It seems that clangd in LSP is only able to find stdio.h with the clang-tools version of clangd. That's why the order matters.

Looking at the definitions of clang and clang-tools in pkgs/top-level/all-packages.nix I also noticed that they are using different LLVM versions by default. clang is defined using llvmPackages and clang-tools using llvmPackages_latest. See https://github.com/NixOS/nixpkgs/commit/8dddd6d4a1a276e00501595f19d6eaaede41c1b1 (couldn't find a related PR). I'm not sure if that could cause further problems. CC @orivej who authored that commit.

stale[bot] commented 4 years ago

Thank you for your contributions.

This has been automatically marked as stale because it has had no activity for 180 days.

If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.

Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse.
  3. Ask on the #nixos channel on irc.freenode.net.
MagicRB commented 2 years ago

Still relevant and OK to be like it is, it should just be more clear that this order dependent situation exists. I stumbled upon it by accident

Dettorer commented 2 years ago

I just fought with clangd not being able to find system headers for some time, I'm happy to find that adding clang-tools before clang in buildInputs indeed fixes that! Out of curiosity, why does the clang package outputs binaries for clangd and other tools if they aren't wrapped? Or why doesn't it define wrappers like it does for the compiler itself?

acowley commented 2 years ago

I've stumbled into a variation of this problem where I have a shell made with, mkShell.override { stdenv = pkgs.clang11Stdenv; }. I'm not sure what the best way to list clang-tools before clang is in such a case.

Dettorer commented 2 years ago

I've stumbled into a variation of this problem where I have a shell made with, mkShell.override { stdenv = pkgs.clang11Stdenv; }. I'm not sure what the best way to list clang-tools before clang is in such a case.

I initially was in that same situation too, what you can do here to achieve the same thing is forcing clang-tools' bin folder to appear first in PATH, for example with a shellHook:


mkShell {
  buildInputs = [ pkgs.clang-tools ];
  shellHook = ''
     PATH="${pkgs.clang-tools}/bin:$PATH"
  '';
}
acowley commented 2 years ago

@Dettorer Thank you! That doesn't get picked up by direnv, though, does it?

MagicRB commented 2 years ago

It will, but only in a shell, if youre using direnv from within an editor like Emacs, no it wont get picked up

acowley commented 2 years ago

Thank you @MagicRB, that was my conclusion on the issue, too.

It does seem unfortunate that clang includes the unwrapped executable. Is there any objection to removing it from clang's output?

MagicRB commented 2 years ago

I see no reason why it should even be there, it doesn't work afterall.

nixos-discourse commented 2 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/c-c-analyzers-not-working-due-to-includes/21295/5

Radvendii commented 1 year ago

Maybe this is a silly question, but why don't we fix the version of clangd in the clang package?