Context
Our team is currently struggling with development environments.
- We develop C++/Python applications, for which we need all sorts of tools:
gcc, clang, cmake, conandifferent python modules (even interpreters with different versions), etc. So far, every developer gets a computer with Ubuntu and they are responsible for setting up their own environment. There are some lose guidelines (i.e.gcc-12.0.0,clang-14.0.1,conan-1.59.0, etc.), but it happened already more than once that some had installedgcc-11instead of12, etc. which then further down in the build process caused issues. - What further complicates the situation is that build servers are RedHat or CentOS, some specific parts of the team use macOS, etc. Our software compiles on all those platforms just fine, but getting to that point can be a quite a bit of work.
So we are basically looking for a way to have reproducible development environments, that still leave enough flexibility to each developer (i.e. our build system is based around conan and cmake, so any modern IDE can be used to build, debug, and run the projects).
Now this is not a new problem, but the information on Stack Overflow is unfortunately not that easy to find and maybe even outdated (e.g. here).
Question
From reading on the internet, it seems that one possible solution to the problem is called nix. What I don't understand is the role of nix in the context of an OS and package manager. Assuming I have a Ubuntu computer in front of me. This has all the standard locations on the filesystem (i.e. /, /bin, /home, etc.). I can now:
- install
nixon said computer - use the language to write a "config".
- Use nix and this config to build and install all those packages into a separate location, i.e.
/nix/store, (i.e. thegccbuild there does not go into/binor/usr/bin).
Now presumably I can then later use these installed packages to build the software I want to build, but how exactly? If they are not in $PATH, then how do I use them? If I add them to $PATH, then whats the point of having them and how do I guarantee that they don't clash with what is already installed and inside $PATH? Can I use this setup with any IDE of my choosing?
Sidenote
If nix is the wrong tool for the problem I described above, I am more than happy to consider others. docker seems to be one alternative, but this has its own downsides...
Nix is a great tool for this sort of thing. But don't think about a "config" (that term usually refers to NixOS, which you are not using and don't need to use).
What you should do is write a file named
shell.nixthat contains an expression in the Nix language that calls mkShell to define all the dependencies you need. Then you runnix-shellin that directory and Nix will automatically build/install all the dependencies that you need, and then launch a special shell with those dependencies on your PATH, in front of the default stuff from your system. Then you can do your development work in that shell.Here's an example
shell.nixI wrote recently when I wanted to compile the LLVM project from source:What I did above was just import the user's current
nixpkgschannel, but for reproducibility you'll want to pin a specific version of Nixpkgs in your expression so that everyone gets the same version of GCC and all the other packages.To really understand what Nix is doing and what it gets you, I recommend reading Eelco Dolstra's thesis.