This is an automated archive made by the Lemmit Bot.
The original was posted on /r/nixos by /u/aurescere on 2024-09-03 16:44:30+00:00.
Hi all;
I’ve discovered what I would consider to be the “most correct” C development environment in that the tooling functions as I would expect. I’m sharing this information so others can benefit.
You may prefer a basic flake so nix develop
can place you into a shell with everything you need. You can use flake-parts
or flake-utils
to abstract the selection of system
; this is kept simple for demonstration purposes. Additionally, I’m not going to discuss setting up an editor, but you’ll want your editor to run clangd
. The following flake will address everything else:
{
description = "Demo";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
};
outputs = { self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
};
stdenv = pkgs.gcc14Stdenv;
in
{
packages.${system} = {
default = stdenv.mkDerivation {
name = "demo";
src = pkgs.lib.cleanSource ./.;
nativeBuildInputs = with pkgs; [
cmake
keepBuildTree
];
buildInputs = with pkgs; [
# your runtime dependencies
];
};
};
devShells.${system} = {
default = pkgs.mkShell.override {
inherit stdenv;
} {
inputsFrom = [
self.packages.${system}.default
];
packages = with pkgs; [
llvmPackages_17.clang-tools
];
env = {
CLANGD_FLAGS = "--query-driver=${pkgs.lib.getExe stdenv.cc}";
};
shellHook = ''
ln -sfn ${self.packages.${system}.default}/.build/source/build/compile_commands.json .
'';
};
};
};
}
Here, I choose to use GCC 14.2 and CMakeLists.txt (not shown) is set to use C23 and to output the compilation database. The compilation database is placed into the working directory when you enter the shell via a symlink. keepBuildTree
is important for preserving the compilation database in the nix store. Without it, only the binary outputs would be preserved. cleanSource
puts the build directory in a predictable location. Crucially, you do not need to struggle to generate a “comprehensive” compilation database—headers are fed to the compiler via the wrapper scripts in nixpkgs. You can use the basic cmake
- or meson
-generated output and I would recommend that.
--query-driver
is required and can be provided to clangd
in a variety of ways (e.g. in your editor’s LSP configuration for running clangd
with $NIX_CC
), but I choose to provide it in my flake. If you don’t provide this, clangd
won’t consider itself to ‘have permission’ to run gcc
and you’ll end up with quirks like duplicated completions and #include
insertions with quotations rather than brackets (for system headers, for example).
There is significance to llvmPackages_17.clang-tools
. This is the only version of clang-tools
where clangd
correctly suggests completions for an assortment of items, like EXIT_SUCCESS
and BUFSIZ
. I did document this here at one point: . With this setup, however, you can use the latest libc features (e.g. char8_t
from uchar.h
will be suggested and the correct #include
will be inserted).
If you are aware of any improvements to this configuration, I’d be glad to refine this further.