# Clang-tooling woes on NixOS

**URL:** https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314
**Category:** Help
**Created:** [March 6, 2019, 7:50am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314 "2019-03-06T07:50:40Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![jethrokuan](https://discourse.nixos.org/user_avatar/discourse.nixos.org/jethrokuan/32/864_2.png) [@jethrokuan](https://discourse.nixos.org/u/jethrokuan)
#### Post date: [March 6, 2019, 7:50am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/1 "2019-03-06T07:50:40Z")

</div>

I’ve been trying to get a good working C++ project environment in NixOS. My project requires that I use clang and cmake. These work great, with the help of the clang wrapper which sets the stdlib paths that make libraries like iostream available. The trouble comes with using clang-tooling like clang-tidy. These aren’t wrapped, and are unable to find these system libraries. The compile\_commands.json file produced by cmake also doesn’t contain reference to the system library paths, because that’s encapsulated within the clang binary wrapper. I couldn’t find any reference C++ projects that are built with nix. Any suggestions on how I can get it to clang-tidy to also locate stdlibs during compilation?

---

<div class="post-metadata">

### Author: ![matthewbauer](https://discourse.nixos.org/user_avatar/discourse.nixos.org/matthewbauer/32/31_2.png) [@matthewbauer](https://discourse.nixos.org/u/matthewbauer)
#### Post date: [March 7, 2019, 9:07pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/2 "2019-03-07T21:07:17Z")

</div>

This is definitely something that I think we should try to figure out. Right now the experience is pretty bad. You can do something like this:

```auto
CFLAGS=$(cat $(nix-build '<nixpkgs>' -A stdenv.cc)/nix-support/{cc,libc}-cflags)
LDFLAGS=$(cat $(nix-build '<nixpkgs>' -A stdenv.cc)/nix-support/cc-ldflags))

```

and pass these into clang-tidy. But ideally the user wouldn’t have to set this up.

---

<div class="post-metadata">

### Author: ![jethrokuan](https://discourse.nixos.org/user_avatar/discourse.nixos.org/jethrokuan/32/864_2.png) [@jethrokuan](https://discourse.nixos.org/u/jethrokuan)
#### Post date: [March 8, 2019, 2:02am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/3 "2019-03-08T02:02:43Z")

</div>

Thanks for getting back. Could you illustrate how you’d pass them to clang-tidy? I’ve tried it with `clang-tidy -p=build/ path/to/srcfile.cpp -- -DCFLAGS=$CFLAGS -DLDFLAGS=$LDFLAGS` to no avail.

---

<div class="post-metadata">

### Author: ![Mic92](https://discourse.nixos.org/user_avatar/discourse.nixos.org/mic92/32/5265_2.png) [@Mic92](https://discourse.nixos.org/u/Mic92)
#### Post date: [March 8, 2019, 12:19pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/5 "2019-03-08T12:19:56Z")

</div>

Would `clang-tidy -extra-arg="$CFLAGS"` work? In the end this should become a wrapper we can have in nixpkgs similar to what we do with ccls/cquery.

---

<div class="post-metadata">

### Author: ![jethrokuan](https://discourse.nixos.org/user_avatar/discourse.nixos.org/jethrokuan/32/864_2.png) [@jethrokuan](https://discourse.nixos.org/u/jethrokuan)
#### Post date: [March 11, 2019, 12:58am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/6 "2019-03-11T00:58:41Z")

</div>

```auto
[nix-shell:~/projects/SPA]$ clang-tidy -extra-arg="$CFLAGS" src/spa/src/simple_parser/parser.cpp 
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "src/spa/src/simple_parser/parser.cpp"
No compilation database found in /home/jethro/projects/SPA/src/spa/src/simple_parser or any parent directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning and 1 error generated.
Error while processing /home/jethro/projects/SPA/src/spa/src/simple_parser/parser.cpp.
warning: -B/nix/store/hlnxw4k6931bachvg5sv0cyaissimswb-gcc-7.4.0-lib/lib
-B/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ -idirafter /nix/store/sr4253np2gz2bpha4gn8gqlmiw604155-glibc-2.27-dev/include -idirafter /nix/store/d4n93jn9fdq8fkmkm1q8f32lfagvibjk-gcc-7.4.0/lib/gcc/*/*/include-fixed: 'linker' input unused [clang-diagnostic-unused-command-line-argument]
/home/jethro/projects/SPA/src/spa/src/simple_parser/parser.cpp:1:10: error: 'simple_parser/exceptions.h' file not found [clang-diagnostic-error]
#include "simple_parser/exceptions.h"
         ^

[nix-shell:~/projects/SPA]$ echo $CFLAGS
-B/nix/store/hlnxw4k6931bachvg5sv0cyaissimswb-gcc-7.4.0-lib/lib -B/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ -idirafter /nix/store/sr4253np2gz2bpha4gn8gqlmiw604155-glibc-2.27-dev/include -idirafter /nix/store/d4n93jn9fdq8fkmkm1q8f32lfagvibjk-gcc-7.4.0/lib/gcc/x86_64-unknown-linux-gnu/7.4.0/include-fixed

```

unfortunately not ): here it is missing project dependencies. If I pass it the cmake build directory:

```auto
[nix-shell:~/projects/SPA]$ clang-tidy -p=build/ -extra-arg="$CFLAGS" src/spa/src/simple_parser/parser.cpp 
1 warning and 1 error generated.
Error while processing /home/jethro/projects/SPA/src/spa/src/simple_parser/parser.cpp.
warning: -B/nix/store/hlnxw4k6931bachvg5sv0cyaissimswb-gcc-7.4.0-lib/lib
-B/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ -idirafter /nix/store/sr4253np2gz2bpha4gn8gqlmiw604155-glibc-2.27-dev/include -idirafter /nix/store/d4n93jn9fdq8fkmkm1q8f32lfagvibjk-gcc-7.4.0/lib/gcc/*/*/include-fixed: 'linker' input unused [clang-diagnostic-unused-command-line-argument]
/home/jethro/projects/SPA/src/spa/src/simple_parser/exceptions.h:10:10: error: 'stdexcept' file not found [clang-diagnostic-error]
#include <stdexcept>

```

---

<div class="post-metadata">

### Author: ![ylixir](https://discourse.nixos.org/letter_avatar_proxy/v4/letter/y/ce7236/32.png) [@ylixir](https://discourse.nixos.org/u/ylixir)
#### Post date: [July 17, 2019, 8:07am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/7 "2019-07-17T08:07:23Z")

</div>

I managed to get this working. For -extra-arg to work, you have to put the flag on every single argument, not the whole batch of them.

You can also pass in the lot of flags after a double dash.

`clang-tidy src/spa/src/simple_parser/parser.cpp -- "$CFLAGS"`

The double dash would be less suitable for a wrapper, but easier to get working in a one off right now.

[Here is how I handled -extra-arg in a makefile](https://github.com/ylixir/les-squelettes/blob/a47a6ef6db2905dd20dc9a0f1c3410cc12479100/Makefile#L7)

---

<div class="post-metadata">

### Author: ![tfc](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tfc/32/382_2.png) [@tfc](https://discourse.nixos.org/u/tfc)
#### Post date: [July 18, 2019, 11:45am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/8 "2019-07-18T11:45:41Z")

</div>

Hey @ylixir i just had a look at your makefile. This looks awesome, but unfortunately the variable

$NIX\_x86\_64\_unknown\_linux\_gnu\_CXXSTDLIB\_COMPILE

is completely empty for me, while

$NIX\_x86\_64\_unknown\_linux\_gnu\_CFLAGS\_COMPILE

contains all the normal things.

When i grep through the whole gcc/clang packages, i can see that only the actual `g++`/`clang++` wrappers contain the interesting C++ STL include paths.

So it looks like i can only get at those include paths by _running_ the c++ wrappers with `NIX_DEBUG=1` and then extract the headers from there, is that correct?

---

<div class="post-metadata">

### Author: ![tfc](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tfc/32/382_2.png) [@tfc](https://discourse.nixos.org/u/tfc)
#### Post date: [July 18, 2019, 12:50pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/9 "2019-07-18T12:50:06Z")

</div>

So… i got at least include-what-you-use to work with the following frankenstein-trick that reuses the clang++ wrapper script to wrap iwyu.

```auto
{
  include-what-you-use,
  clangStdenv
}:
clangStdenv.mkDerivation {
  name = "include-what-you-use-fix";
  src = include-what-you-use;

  phases = ["installPhase"];

  installPhase = ''
    mkdir $out/
    cp -r $src/bin $out
    chmod +w -R $out/bin

    # copy the c++ wrapper and patch the last exec line to use iwyu
    mv $out/bin/include-what-you-use $out/bin/.include-what-you-use
    cp ${clangStdenv.cc}/bin/c++ $out/bin/include-what-you-use
    sed -i "s;^exec[^\\]*;exec $out/bin/.include-what-you-use ;" $out/bin/include-what-you-use

    # the python tool is hardcoded to the original iwyu, fix that too
    sed -i "s;${include-what-you-use};$out;" $out/bin/iwyu_tool.py
  '';
}

```

For my use case, this turned out to work pretty well.

Of course that does not work with clang-tidy… although i got that running by creating an “echo wrapper” of the clang++ wrapper, and a tiny python script that simply “fixes” all command lines in the compile\_commands.json file. This of course still does not fix the cmake integration of clang-tidy

---

<div class="post-metadata">

### Author: ![tfc](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tfc/32/382_2.png) [@tfc](https://discourse.nixos.org/u/tfc)
#### Post date: [July 20, 2019, 10:21am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/10 "2019-07-20T10:21:55Z")

</div>

I got the following clang-tidy workflow to work:

```bash
# assume we are in CMake C++ project folder
$ mkdir build && cd build
$ cmake -DCMAKE_CXX_CLANG_TIDY="clang-tidy" ..
$ make
# clang-tidy is automatically run by cmake on every compiled file

```

This works by wrapping clang-tidy: I provide a package `clang-tools-wrapper` here: [https://github.com/tfc/nur-packages](https://github.com/tfc/nur-packages)

It’s not perfectly generic, but at least one can get static analysis during normal compilation

---

<div class="post-metadata">

### Author: ![ylixir](https://discourse.nixos.org/letter_avatar_proxy/v4/letter/y/ce7236/32.png) [@ylixir](https://discourse.nixos.org/u/ylixir)
#### Post date: [July 20, 2019, 8:32pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/11 "2019-07-20T20:32:44Z")

</div>

That’s fantastic. I finally got around to sitting down to make this thing nicer and…tada, I’m not going to bother because what you have looks much nicer than what I was going to do.

How would one go about getting that thing merged into the nix repo?

For me, clang tools are pretty useless in their current form. Something like what you have in nur-packages is gold

---

<div class="post-metadata">

### Author: ![tfc](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tfc/32/382_2.png) [@tfc](https://discourse.nixos.org/u/tfc)
#### Post date: [July 21, 2019, 10:33am UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/12 "2019-07-21T10:33:58Z")

</div>

> [@ylixir](#):
>
> That’s fantastic. I finally got around to sitting down to make this thing nicer and…tada, I’m not going to bother because what you have looks much nicer than what I was going to do.

Awesome to hear that it looks useful to fellow nix users, too!

> [@ylixir](#):
>
> How would one go about getting that thing merged into the nix repo?

I am not sure. It feels like “the right way” to do this is to ship the clang package (since it contains `clang-tidy`) with the same kind of wrapper around `clang-tidy` as `clang++`. I don’t however dare to modify this nix expression and wrapper (yet) as it’s horribly complicated.

Until then i would battle-test this wrapper more to be more certain that it works for all possible use cases. I also started writing tests and run them regularly on unstable nixpkgs. ([https://hydra.kosmosgame.com/jobset/github/nur-packages#tabs-jobs](https://hydra.kosmosgame.com/jobset/github/nur-packages#tabs-jobs))

---

<div class="post-metadata">

### Author: ![chkno](https://discourse.nixos.org/user_avatar/discourse.nixos.org/chkno/32/1649_2.png) [@chkno](https://discourse.nixos.org/u/chkno)
#### Post date: [September 24, 2019, 3:26pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/13 "2019-09-24T15:26:31Z")

</div>

@tfc: Thanks for the example about borrowing the clang wrapper! I’m using this to get a working stand-alone clang-tidy:

```auto
$ cat .config/nixpkgs/overlays/clang-tidy.nix
# From https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/9
self: super:
{
  clang-tools = super.symlinkJoin {
    name = super.clang-tools.name;
    paths = [super.clang-tools];
    postBuild = ''
      mv $out/bin/{,.}clang-tidy
      cp ${self.clangStdenv.cc}/bin/c++ $out/bin/clang-tidy
      sed -i "
        /^exec[^\\]*/{
          s;;exec $out/bin/.clang-tidy ;
          ifor arg in \''${extraBefore+\"\''${extraBefore[@]}\"};do
          i extraBeforePrefixed+=( -extra-arg \"\$arg\" )
          idone
          ifor arg in \''${extraAfter+\"\''${extraAfter[@]}\"};do
          i extraAfterPrefixed+=( -extra-arg \"\$arg\" )
          idone
          iextraBefore=(\''${extraBeforePrefixed+\"\''${extraBeforePrefixed[@]}\"})
          iextraAfter=(\''${extraAfterPrefixed+\"\''${extraAfterPrefixed[@]}\"})
        }
      " $out/bin/clang-tidy
    '';
  };
}

```

---

<div class="post-metadata">

### Author: ![tfc](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tfc/32/382_2.png) [@tfc](https://discourse.nixos.org/u/tfc)
#### Post date: [September 29, 2019, 4:32pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/14 "2019-09-29T16:32:39Z")

</div>

@chkno:

Your wrapper script looks great.

It works for me if i run it like `clang-tidy main.cpp`, but if i use it through `cmake` with `-DCMAKE_CXX_CLANG_TIDY=clang-tidy`, then clang-tidy fails to find the STL includes. Does that work for you?

---

<div class="post-metadata">

### Author: ![knedlsepp](https://discourse.nixos.org/user_avatar/discourse.nixos.org/knedlsepp/32/532_2.png) [@knedlsepp](https://discourse.nixos.org/u/knedlsepp)
#### Post date: [November 17, 2019, 8:30pm UTC](https://discourse.nixos.org/t/clang-tooling-woes-on-nixos/2314/15 "2019-11-17T20:30:45Z")

</div>

Might be solved by: [https://github.com/NixOS/nixpkgs/pull/73345](https://github.com/NixOS/nixpkgs/pull/73345) (Thx: @Mic92)
