Nix Friday: C/C++ questions for next stream

Please put any questions/topic you want to be answered/handled in our next Nix Friday stream here.

2 Likes

How does the rewriting of buildInputs and friends work so that cross-compilation works? This feels like black magic to me.

4 Likes

This is a bit of an advance topic, but I will put it on the list. tl;dr: pkgs/stdenv/generic/make-derivation.nix creates 6 package sets for the different targets and mkDerivation will pull from the right package set based on which input is used and push it forward to the arguments given to callPackage.

1 Like

Not sure what is the question, or if it should be answered, but I had a hard time packaging mozart2 with nix. (See https://github.com/mozart/mozart2/blob/4806504b103e11be723e7813be8f69e4d85875cf/ci/mozart-overlay.nix) Some things I discovered/had to fight:

  1. You cannot use both gcc and clang.

The project uses libclang to parse it’s own code and generate some additional boilerplate code. This needs clang+llvm4 as the internal libclang api is evolving quickly. The resulting code can be compiled with an up-to-date c++ compiler. I had to use clang because using gcc in an environment where clang exists is just not working. (maybe fixed since ?)

  1. A wrapper is a best-effort tool.

The project uses -emit-ast to serialize the ast. In the absence of a -c flag, the nix-added wrapper thinks we are linking, and passes a lot of irrelevant flags breaking the build. The fix is quite funny (see comments in the file)

  1. CMake, cmake, cmake…

cmake has good integration in these toolchains, but remains prone to breakage. The good side is that it’s structure of text variables makes it quite simple to fix, with some patience. For example, ${pkgs.clang}/lib/cmake/clang/*.cmake contains information about clang libs generated at build time. But moving these files around during packaging often breaks them, or makes them hard to find.

Things are made worse in the case of clang because it is built as an llvm plugin. Some tools rely on finding clang inside an llvm source tree.

  1. That being said, for a tremendous amount of packages it just works flawlessly, with very little tuning.

Compiler plugins and operating systems/embedded code definitely stress test our compiler infrastructure.

1 Like

I cannot really formulate the question entirely. I’d like to make better use of the clang tooling in a nix-shell environment where I build stuff using the regular gcc + GNU libstdc++ toolchain and somehow the include paths clash to produce a lot of:

In included file: no member named 'signbit' in the global namespace; did you mean '__signbit'?clang(no_member_suggest)

See: https://github.com/NixOS/nixpkgs/commit/a10ef1aa4fe62aa97859d24921f501183861b7b6#commitcomment-36463293

Despite me commenting on this I have never really fully understood what is going on here and what would be a proper fix for that. I also don’t really get how closely the C++ standard includes are bound to the stdenv that I’m using. Should there be an stdenv.cxx.cxx.lib? Why the double cc in stdenv.cc.cc.lib? Can I mix and match standard library headers in a nix-shell environment using some environment variables (CPATH/…) or do I need to write my nix-expressions in a special way (overrideCC, etc.)?

Sorry that I’m so vague, but I guess I’d really appreciate some general insights on how the stdenv relates to it’s shipped C and C++ compiler to be able to fully understand why the above issues occurs. What is fixed after nix has built the toolchain and what is still configurable. :clap:

There is libcxxStdenv and clangStdenv that uses clang and the libllvm’s libcxx, which should be less of a problem when used to with clang based tooling. Our clangd uses libcxx always, which might clashes if your stdenv uses gcc’s libc++. The fix for this would be also to pass libc++ in the wrapper for clangd: https://github.com/NixOS/nixpkgs/blob/412c9c883bbba8553f6c5e33cd8e7a985d05bba3/pkgs/development/tools/clang-tools/default.nix#L17