What is the proper way of setting up nixos for C/C++ development?

I apologize in advance if this question has been answered before, but I’m still a noob to nixos.

TLDR: Is there a way to make header and ‘so’ files “available” (expose them) to other programs?
The files are there in the store files, I just can’t find a way to point the compiler to them outside of manually writing the store path.

I’m trying to set up my system for development, specifically for C/C++, and I am having trouble with system libraries (like OpenGL, X11 etc)
I am using vscode, with the default cmake and cmake-tools extensions to build things, as I’ve always used successfully on multiple other distros.

But anywhere I include X11/X.h (or other system libraries for that matter), the compiler can’t find it.

I’ve tried multiple solutions:
First, I tried to just plainly add the libraries to my configuration:

environment.systemPackages = with pkgs; [
  ...
  xorg.libX11
  libGL
  ...
];

Then, I tried making a nix shell to run vsode in:

{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
    nativeBuildInputs = with pkgs; [
      xorg.libX11
      libGL
    ];
}

But then I kind of lost the thread, and I found the amount of information a little overwhelming as a beginner with.
I understand that the philosophy of nixos goes against everything being dumped into a single bin, lib, or include folder, but there has to be a way of doing this.

I also tried to use system.extraDependencies to set those folders, kind of like this:

system.extraDependencies = [
  "${pkgs.xorg.libX11.dev}/include"
  ...
];

I’m sure the solution is simpler than I think, and I just misunderstand how some of the tools in nixos work, or I’m missing a magic option to make these required files available.

I would also prefer if I was able to make these files available system-wide, instead of just in a shell or environment, but not necessarily, I can live with having to open a shell before opening my editor.

Hey hi!

Here’s a list of templates for starting: GitHub - the-nix-way/dev-templates: Dev environments for numerous languages based on Nix flakes [maintainer=@lucperkins]

Hope you’ll find what you’re looking for!

Unfortunately what you shared doesn’t have anything C/C++, but that’s not the problem.
I looked at some of the flakes, for the languages that are similar enough, and they don’t do much more than what my configs do.

I’m not sure how to even ask this question properly, I’m sorry

What I am confused about is why can’t I see all the files from the packages I installed?
When in a nix-shell I can’t see any of the libraries I installed. libX11 has an include folder, which is supposed to be in /usr/include, same for libGL, and both should also have one or more ‘so’ files in the /usr/lib folder.

I understand they’re not supposed to be there normally, but why can’t I see them in nix-shell? Am I misunderstanding what nix-shell is supposed to do?

Try this:

{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
-   nativeBuildInputs = with pkgs; [
+   buildInputs = with pkgs; [
      xorg.libX11
      libGL
    ];
}

nativeBuildInputs is for tools (compilers, build systems…), buildInputs is for libraries.

Yeah, I tried both I should have mentioned (added everything everywhere, or just in one, or the other etc)
Must have tried 15 different combinations

Are you running VS Code from inside the nix-shell?

Yeah, tried in and out
Even more interesting, when in the normal shell /usr/bin contains only a file named “env”
But when opening a terminal window in vscode launched from the same shell, bin has a lot of files (although still not any of the files I want)

With the following shell.nix:

{ pkgs ? import <nixpkgs> { config.allowUnfree = true; } }:
pkgs.mkShell {
  buildInputs = with pkgs; [
    xorg.libX11
    libGL
    vscode
  ];
}

After I enter the nix-shell, I can successfully do the following:

$ wget https://gist.githubusercontent.com/whosaysni/5733660/raw/344d17b969a25ba1d12dc8f1afa09a071c17ae31/gistfile1.c -O main.c
$ cc -o main -lX11 main.c  # This emits some warnings though
$ ./main  # Displays a window

And the same also works if I launch code and then run cc via its included terminal. I did not bother testing with launch configurations in vscode, since It’s been a while since I worked with vscode and I’m a bit rusty :sweat_smile:

What I am confused about is why can’t I see all the files from the packages I installed?
When in a nix-shell I can’t see any of the libraries I installed. libX11 has an include folder, which is supposed to be in /usr/include, same for libGL, and both should also have one or more ‘so’ files in the /usr/lib folder.

That’s not how Nix achieves this. In fact, nix-shell sets some flags for the cc wrapper so that the compiler knows how to find the libraries without relying on FHS. See e.g.:

$ env | grep NIX_LDFLAGS  # I inserted linebreaks in the output for clarity
NIX_LDFLAGS=-rpath
/nix/store/k1cr5zbnb9cz161cwlfp923gmq2xp7mp-nix-shell/lib

-L/nix/store/7ihbjzic97238sq8bnpyyvbdygc6qdls-libxcb-1.16/lib
-L/nix/store/m81vwjvzw0js60ca2g1j02z30pfr68fw-libX11-1.8.7/lib
-L/nix/store/9vz6a0s6ryd5xbi5imkya3bbh8gkzi6k-libGL-1.7.0/lib
-L/nix/store/1bapla8zwlx128i42wi08zbiibwk6gm3-libglvnd-1.7.0/lib
-L/nix/store/7ihbjzic97238sq8bnpyyvbdygc6qdls-libxcb-1.16/lib
-L/nix/store/m81vwjvzw0js60ca2g1j02z30pfr68fw-libX11-1.8.7/lib
-L/nix/store/9vz6a0s6ryd5xbi5imkya3bbh8gkzi6k-libGL-1.7.0/lib
-L/nix/store/1bapla8zwlx128i42wi08zbiibwk6gm3-libglvnd-1.7.0/lib

$ echo | gcc -E -Wp,-v - 2>&1 | grep X11  # According to StackOverflow, this displays gcc's search paths
ignoring duplicate directory "/nix/store/9n6kwqffiqdrk5npzcmsvzc58krpdsxh-libX11-1.8.7-dev/include"
 /nix/store/9n6kwqffiqdrk5npzcmsvzc58krpdsxh-libX11-1.8.7-dev/include

Actually, the solution is almost as idiotic as me

I installed the wrong package
xorg.libX11 instead of xorg.xorgproto
edit: both are needed

nixos, in fact, works perfectly fine, and my project builds now