^
< previous study | top | next study >
1. Bio / Persona
Math student. Programming experience: scientific programming and implementing algorithms. Hasn’t done any larger software projects yet, but confident with C, C++, Python, Matlab, Lisp, and has a bit of Haskell and Java knowledge.
2. Prior Nix experience
None.
3. Approaches to learning Nix
This session will be the first attempt.
4. Using Nix
Goal for this session: compile a C++ project on Arch Linux. Pre-Nix attemtps failed because the project needs gcc
11, but gcc
12 is installed, and manual downgrade is a pain. Presumes that Nix will solve this issue.
Goes to nixos.org, scrolls through the front page looking for examples, but not interested in videos, and simply installs Nix with yay -S nix
.
Wants to understand how to declaratively add packages to the shell, and starts the learning journey on nixos.org:
-
Chooses the Learn tab
-
Clicks on the First steps with Nix button. (At the time, it was linking to Set up a development environment article.)
Recreates
default.nix
, inspects first line - seems to be unspecific to Python, looks very mysterious, and?
and:
does not make any sense. Doesn’t know whatpkgs.python3Packages
means, then skims Python-specific lines. Skims rest of the page, and decides to go back to Learn. -
Chooses Ad hoc developer environments article after scanning the list of guides. “Probably not what I want, but it’s the first guide.” Somewhat confused when scanning each section as they appear to be unrelated mini-articles.
Comes across the link to search.nixos.org, navigates there, looks up
gcc
, and the most relevant result shows that its version number is 10.3.0. Finds this very arbitrary and wonders why that specific version?The next section demonstrates
nix-shell -p
. Givesnix-shell -p gcc
a try, and thegcc
’s version in the shell is indeed 10.3.0.Slightly frustrated now because none of the guides so far showed how to declaratively put a specific package into a Nix environment. “How does it work for something that is not Python?”
Goes back to Learn once again, scrolls past the guides, and examines the section headings of the manuals. Sees
nix-build
, and thinks that this may be it. -
Interviewer: Would you take a look at the Declarative and reproducible developer environments article?
Finds it promising as the ad hoc way (i.e.,
nix-shell -p
) works already. Looks at the example in the “Getting started” section, findsfetchTarball
kind of mysterious, but the note below is helpful; still a bit unclear about it, but accepts that there is a valid reason behind using it.Creates a
shell.nix
by copying the example, and runsnix-shell
as instructed. No errors, and a quick inspection withwhich htop
shows that thehtop
command in the shell links to the one in the Nix store and not to the system-wide one.Reads rest of the article, deems the sections about setting environment variables and
direnv
intriguing, but doesn’t need it right now.Exits the Nix shell, adds
gcc
to list of packages inshell.nix
, runsnix-shell
, and confirms again thatgcc
is provided by Nix.
-
Confident that all’s there that is needed for creating the C++ project’s development environment under Nix, and starts checking the dependencies on search.nixos.org:
-
nasm
- check -
gdb
- check -
qemu
- check
The results for the last one show several packages starting with qemu
, and all have the same descriptions, but isn’t fazed as Arch also has similar convention for splitting packages. Chooses qemu_full
, but nix-shell
throws an error:
error: attribute 'qemu_full' missing
at /home/my-user/shell.nix:5:5:
4| buildInputs = [
5| pkgs.qemu_full
| ^
6| pkgs.htop
(use '--show-trace' to show detailed location information)
nix-shell -p qemu
works, but takes a lot of time. Tries nix-shell -p qemu<TAB>
next, nothing happens so completes it to nix-shell -p qemu_full
and that also works. Odd. Re-checks the search results, but everything seems to be in order.
Interviewer explains that when pinning in
shell.nix
, the commit hash infetchTarball
references a revision of Nixpkgs which may be old enough not to containqemu_full
. On the other hand,nix-shell -p
works, because it is grabbing packages from the default channel. Advises usingqemu
for now as it should be good enough.
shell.nix
works now, but remarks that make
would be also good to have. Mild surprise when there are no search results for make
. “Why is something so basic not there? Is it provided by default?” Tests hypothesis, and make
is indeed available in the shell.
First attempt at compiling the project fails:
error: /nix/store/.../bin/ld architecture of input file `/nix/store/...-gcc/lib/gc/.../crtbegin.o` incompatible with i386 output
Notices that ld
is from the Nix store, but can’t do much with this information. Removes pinning from shell.nix
, but is greeted with another issue: root partition is full. Goes back to the Learn page, hoping to find a solution. Scrolls past the guides, and the nix-store
link in the Nix manual column seems to be what is needed. The description starts with:
You generally do not need to run this command manually.
It may not be relevant then, so goes back to the Nix manual column, and chooses “Basic package management” this time. At least, it seems to be the place to document how to clear up old or unneeded packages. Starts reading about nix-env
.
Interviewer: Don’t do that or you will get a Primer XKCD movie plot experience
Insists on trying nix-env
. Checks man nix-env
, and does
$ nix-env --uninstall qemu qemu_full
warning: selector 'qemu' matched no installed derivations
warning: selector 'qemu_full' matched no installed derivations
Next attempt is nix-collect-garbage
, which frees 5.3 GB. Re-run nix-shell
, but assumes it’s broken again as the command line still hangs after 10s on an x270. Finally, lines starts pouring in. Catches glimpses of Python being mentioned, and wonders why it is needed.
Participant: A status bar would inspire more confidence. With Arch, you may get onto the wrong mirror, and when you see that the download goes with 30K/s for example, you can take action right away.
Meanwhile, the compilation errored out with the same message. Appears to be a cross compilation error as we want to compile to i386
. Checks gcc -v
output, but confused as Configured with:
line is empty:
$ gcc -v
Using built-in specs.
COLLECT_GCC=/nix/store/kiwdwd6zw4svi9jlr95yg1p5pgpjxn1v-gcc-10.3.0/bin/gcc
COLLECT_LTO_WRAPPER=/nix/store/kiwdwd6zw4svi9jlr95yg1p5pgpjxn1v-gcc-10.3.0/libexec/gcc/x86_64-unknown-linux-gnu/10.3.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with:
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.3.0 (GCC)
Searches for gcc
on search.nixos.org, reads description, but it’s no help. Inspects the other gcc
packages, gcc_multi
sounds promising, but all prove irrelevant in the end.
Googles cross compiling with nix
:
-
NixOS wiki: Cross Compiling
First example of cross-compiling a package is dismissed promptly. Next section shows
crossShell.nix
, but unfamiliar with the syntax. The first lines look somehow similar though, but this doesn’t help much.-
Participant’s
shell.nix
:{ pkgs ? import <nixpkgs> {} }:
-
crossShell.nix
:with import <nixpkgs> {
Arrives at the line:
Examples of how to specify your target system can be found in
lib/systems/examples.nix
.Follows it, searches for “i386”, but the only result is something related to iPhones. Widens the search by using “86”, but no joy.
Participant: What could be the architecture’s name? Is it just
gnu32
? Maybe it’s just my lack of knowledge on computer architectures…Tries replacing the example line with
i386
(has both header lines at the top), but it doesn’t work. What abouti686
?gcc -v
output still does not visibly change.QUESTION TO @fricklerhandwerk: The notes here simply say:
- intervention: correct the Nix expr invocation
- that would have been the other option
- the weird thing
I have no clue what the fix could have been, and these lines are just cryptic.
It looks that
gcc
is being entirely re-built, and every single package on top of that. Abort. -
-
Looks at the Cross compilation article on nix.dev next:
“Looks helpful.” Only wants to change the host platform, and there is already a section on choosing host platform with Nix.
These attribute names for cross compilation packages have been chosen somewhat freely over the course of time. They usually do not match the corresponding platform config string.
“What does it mean that “these names have been chosen freely”? Which one would I want? Probably
gnu32
.” Goes forward withpkgs.pkgsCross.gnu32.gcc
, and re-runsnix-shell
. Looks good, dependencies appear to be relevant togcc
, but stumped when seeing a Linux kernel name pop up, wondering why it would need that.
The session ends here.