Packaging compiler-based tools in a portable way

I’m building a tool that parses C and C++ codebases using the LLVM LibTooling API.

When a parser sees an include directive in a source file, it uses the include search paths of the clang compiler it was built on to find that header file. On NixOS, the default unwrapped clang compiler only has one include path, so the parser is unable to find common headers like iostream, cassert, and so on.

The fundamental problem is that there needs to be a way for the executable to find these headers at runtime, or regenerate them on its own. In addition, I’m trying to develop a solution that works across NixOS, mainstream Linux distributions, and macOS.

Here are the approaches I have thought of to solve this problem:

  1. Wrap the executable, as is done in the NixOS ccls package definition. ccls can take in a list of include paths on the command line, so we pass it in the paths to stdenv’s libc and C++ standard library to create a wrapped executable. I don’t like this situation as it requires wrapping, I’d prefer a solution with the minimum amount of extra work required
  2. Compiling standard library headers into the executable, then dumping them to a directory at runtime and using that as the system include path. This solution would be ideal as it produces a self-contained binary, however on NixOS the clang compiler is missing the include paths to the C++ standard library and also libc. Therefore I’d need to compile all of those headers into my executable which seems excessive and may break when parsing packages that use an alternate libc or libc++. This will also be platform specific, as macOS does not use glibc like NixOS for examble.
  3. Something I’m missing?

I’m curious to hear if someone else has faced this problem or if anyone has ideas on how to approach it.

Thanks!

Hi. Yesterday I posted a similar question Developing clang tools within nix-shell. How to wrap the program within a nix shell?.
I guess we’re on the same boat :smile: