List and role of all "special" folders in $out

When creating a package, one need to copy stuff in various subfolders in the $out directory. The most useful subfolder is certainly $out/bin in which all executable must stay. However, there is many more such folders: $out/share, $out/lib… There is some special folders to put .desktop files, to deal with kernel modules, printer drivers…

Is there a place where I can find all (or most of) the “special” folders used in nix (either because they receive a special treatment by nix or by any famous program, or because the name is a well used convention)? Ideally, this place would describe for each subfolder:

  • a description of why it is useful
  • an example of a file that could be put here (for instance, one can put a library in $out/lib/mylib.so), and, if nix provides some methods to help creating these files it could be great to put the name of the related functions (like makeWrapper, makeDesktopItem…)
  • a description of the special treatment they receive by nix or by the software, and if possible a link to the code that is doing this treatment. The treatment could be to be linked in some /run/ folders, if the files are read recursively or not (for example can I put an executable in $out/bin/myprogram/myexec), and if the files are expected to live in $out/subfolder directly or in some sub-subfolders like $out/subfolder/myprogram (or if it does not matter)…
  • an example of a (if possible simple) derivation in nixpkgs that uses this folder.

If there exists no such resource, it could be helpful to start a list. I started here a page on NixOs Wiki. Since I understand it can take quite some time to get them all, find all the related links and helpers, I don’t expect the first list to be complete, so feel free to drop a line in this thread without giving the helpers, link to code…

Notably, I’m wondering, is there also a “dummy” subfolder that would play the role of /opt, i.e. in which I could copy basically the whole program structure (binary + assets) before linking/wrapping executables in $out/bin? Also, in which code file can I find how nix adds the $out/bin folder in the PATH?

7 Likes

one need to copy stuff in various subfolders

A sophisticated package should have an install script where you set the prefix to $out and everything should be where it belongs.

receive a special treatment by nix or by any famous program

Nix does not treat the directories different than apt or rpm does. They are just at a different place and symlinked in place rather than copied.

Those directories are almost identically to FHS with some slight modifications:

  • no sbin
  • no system or runtime directories like proc, sys, run, tmp, media in the package itself which is not different to apt or rpm
  • nixos does not really use local because it does not need to

You can read up about the others here Filesystem Hierarchy Standard - Wikipedia

for example can I put an executable in $out/bin/myprogram/myexec

You could do that but it would be equal of doing /bin/myprogram/myexec on Debian which would also be most likely not what you want. If you need sub directories for your binaries they belong into libexec which would be /usr/libexec on other distros and NixOS just strips the usr to keep things simple.

an example of a (if possible simple) derivation in nixpkgs that uses this folder

The normal process is to find a package which does something similar and copy what it does. If there is no such package you look what other Linux distros do and where upstream recommends to put those files. Nix is not fundamentally different than any other Linux. It just removes some extra directories like /usr, /local and /opt which it does not require by design.

Notably, I’m wondering, is there also a “dummy” subfolder that would play the role of /opt

You don’t need such dummy directory by design. If you are building a package you have your working directory where you build the program and then you copy/install things to $out.

Also, in which code file can I find how nix adds the $out/bin folder in the PATH ?

That is all over the place. For example nix-shell adds $out/bin to your PATH but also home-manager which build a buildEnv which then gets added to PATH.

2 Likes

This page should be a good start: Directory Variables (GNU Coding Standards)

Start with prefix set to $out.

1 Like

Thanks for your answer, it’s clearer now. The GNU Coding Standards file is particularly useful.

Also, even if I agree that many such file are “standard” accross distribution, I still think it can be useful to list common folders and helpers for newcomers. For instance, it is not obvious if you are packaging your first program that icons should go in share/icons/hicolor/256x256/apps/youricon.png, that .desktop files must go in $out/share/applications and that there exists a wrapper makeDesktopItem to help with that… The page I created was also to help with that.

Well, some programs do not directly have an install procedure that put binaries in $prefix/bin and architecture-independant data in $datadir/program-name: some of them just assume that the program will be located somewhere next to the data, and they also put the necessary .so files next to the program. This is the case of many proprietary programs that just provide a simple tarball with data+binaries, and some open source program also behave similarly. Since $out/share is made for architecture-independent programs, in theory it it not the right place to put these data. So my question is where should I put this folder? Right now, I just create a folder with a dummy name (usually I take $out/opt) and then I put wrappers/symlink in $out/bin to points to $out/opt. Apparently, I’m not the only one doing that, many packages seem to do similar things, see for instance cypress. So my question is “is there a convention in NixOs for the name of this folders”?

Not really. Git for example puts those things into libexec.

$out/opt/appname is a good place for stuff not built from source as it mirrors FHS.

Having architecture-dependent files in $out/share is not a problem for us without global / but it is probably still a good idea to avoid it to minimize unnecessary divergence from FHS.

$out/libexec is for “executable programs to be run by other programs rather than by users” so some subset of the binaries might fit but not the data files or stuff that should go to $out/bin. And if the project expects everything in the same directory, splitting it into more semantic directories will not work without binary patching or extra symlinks.

Ok, thanks a lot, I’ll use $out/opt/appname than, thanks!