The papercut thread - post your small annoyances/confusions here

Here is a fully expanded example

# Feature simmilar to `let {mkOption, mkEnableOption} = lib;
let
  nixpkgs = import <nixpkgs> {};
in {
  example = let
    inherit (nixpkgs.lib) mkOption mkEnableOption;
  in [mkOption mkEnableOption];
}
4 Likes

Oh maybe we don’t. But we maybe we should!?

We have it in lambas, why not in let’s?

1 Like

These might be off topic for being too significant:

  • “Cannot coerce set to string”, and company being utterly useless for finding where the actually problem occurred in a string. There was a dead pull requests but I can’t find it.
  • better infinite recursion debugging
  • No consistent debugging interface. I want to just slap a function around any sufficiently advanced derivation and get it full stack debuggable with GDB or whatever. (may be reasonable to extend to other functionality)
  • fetchgit silently breaks .git, well, by design

Some more from my sticky notes, a lot of these seem controversial. or I’m just missing something:

  • I can’t stick NIX_DEBUG=1 on nix-build I have to put it in the expression somewhere

  • There is no trivial one-liner way to drop into a mutable build shell when a build fails (though maybe cntr alleviates this a bit)

  • The python calling conventions for nix-shell -p are weird and don’t work for some variations but do for others (???) (sticky note says: nix shell with python and a list of packages, not pythonWithPackages and why this breaks)

  • posix man pages are not installed by default

  • zsh: no such file or directory: ./ and company, for un-patchelfed binaries or whatever are severely misleading for new users

  • I can never remember the patchelf flags, is it just me or are they weird

  • language infrastructures that use something other than overrideAttrs

  • people use a lot of let expressions, which makes sense, but how can that be consolidated with wanting to override things?

  • more things that I guess I didn’t write down separately and would have to find in IRC logs…

3 Likes

That looks like the same issue as `nix search` needs an explicitly name `nixpkgs` entry in `NIX_PATH` · Issue #140 · LnL7/nix-darwin · GitHub

I would certainly be in favour, especially if it could accelerate the death of with by providing a better mechanism for the common usecase :slight_smile:

Maybe you could draft an RFC?

Edit: Actually, maybe the let inherit approach could be sufficient? I’ll have to think about this…

1 Like

Python package overlays don’t compose, because they need to use an explicit packageOverrides.

There’s a discussion about it here: Python's packageOverrides isn't composable · Issue #44426 · NixOS/nixpkgs · GitHub

But it doesn’t align with what you would expect using other overlays for system packages. :frowning:

Current workaround seem to be: Use lib.composeExtensions with previous packageOverrides.

2 Likes

I can’t tell when and if I should use nix build -f default.nix test
instead of nix-build -A test.

The nix repl is useful for iterating on derivations, but nix-shell
is simpler to launch a one-off command.

I haven’t found guidelines on their usage other than Eelco’s
presentation of the initial nix CLI in 2015 NixCon 0.

5 Likes

The output of a nix/os command should never be empty. Ever. What does it mean if a command takes 30 seconds to run and returns nothing? It’s incredibly context-dependent. Sometimes it means success, other times it means it has no idea what you’re talking about.

Seems like such a simple fix.

3 Likes

I filed an issue about this already, but the documentation does a very bad job of explaining that syntax.

https://github.com/NixOS/nix/issues/2876

2 Likes

Here’s my biggest pet peeve (other than the with keyword as mentioned above):

Sometimes I’m writing a derivation and realize I may need to use propagatedBuildInputs instead of the normal buildInputs. I have a vague understanding that propagatedBuildInputs will “propagate” those build inputs, but I don’t really know what’s going on, so I google for the difference.

I normally find the following section in the nixpkgs manual:

I try to read this section, get completely lost about half way through, give up, and go back to just randomly trying propagatedBuildInputs or buildInputs until something seems to work.


I think the explanation for how propagation works is too detailed for a user manual. I think the first thing in that section should really just be a couple examples of when propagatedBuildInputs is needed and not needed. I think the detailed explanation of exactly how dependencies are propagated and in what way should be saved for a different document. Maybe a wiki page?

11 Likes

And, oh, please, stop littering my tree with ./result* symlinks :wink: . The worst being nixos-rebuild build, which pins a whole system in whatever location you happen to be.

4 Likes

Running man nix on NixOS gives me

No manual entry for nix

While nix --help works.

8 Likes

12 posts were split to a new topic: Documentation improvements

I think it is sufficient! I think we should heavily document this; it seems very useful!!

Example usage that I am now using in a module I’m building

{ lib, config, ...}: 
let
  inherit (lib) mkIf mkMerge mkOption mkEnableOption ;
  inherit (lib.types) attrsOf str;
in
{
  options.services.journal-upload = {
    enable = mkEnableOption "journal-upload";
    config = mkOption {
      type = attrsOf str;
    };

  };
  options.services.journal-remote = {
    enable = mkEnableOption "journal-remote";
    config = mkOption {
      type = attrsOf str;
    };
  };

  config = mkMerge [

    (mkIf config.journal-upload.enable {
      systemd.sockets.systemd-journal-upload.wantedBy = [ "sockets.target"];
      environment.etc."journal-upload.conf".text = "";
    })

    (mkIf config.journal-remote.enable {
      systemd.sockets.systemd-journal-remote.wantedBy = [ "sockets.target"];
      environment.etc."journal-remote.conf".text = "";
    })
  ];
  
}


10 Likes

I have a lot of trouble finding the definitions of particular functions.

I have a lot of trouble with having to cleanroom a compiler toolchain (Rust in this case) when the version I want to use isn’t in nixpkgs.

Several compiler toolchains (again, Rust) depend on the auto-updater (rustup) instead of on a precise .tar.gz.

(I know I should really get involved with the Rust derivation maintenance, or at least talk to the people involved to understand the philosophy.)

4 Likes

Yeah, that explanation is really very internals-focused. Here’s a (hopefully) more comprehensible explanation that focuses more on how to use it, and only on implementation details that directly affect the use of it:

Putting a dependency a in the propagatedBuildInputs of derivation b has two main effects:

  1. It treats a as a dependecy of b, just as if you had buildInputs = [ a ]; in b
  2. It “propagates” this dependency relationship onwards to all derivations that depend (directly or transitively) on b

For example, if you have a derivation c with b specified as a buildInput, the underlying nixpkgs machinery will ensure that c also effectively has a as a propagatedBuildInput, meaning it gets a as a direct dependency (available in its builder) rather than simply depending on it transitively (as a result of b being built with it).

As a is effectively added to c’s propagatedBuildInputs, anything that depends on c will also get a added to their own propagatedBuildInputs. The overall effect is that anything that has b anywhere in its dependency closure gets a direct dependency on a (at least if we ignore cross-compilation cases).

This effect is used in several ways in nixpkgs and NixOS. A few of the language-specific infrastructures make use of it to ensure that executables have access to their run-time dependencies.

For example: Python library/module dependencies are specified as propagatedBuildInputs, and the Python mkDerivation wrapper (buildPythonPackage) wraps any Python executable scripts produced by it to give them references to the paths of all their Python dependencies. This ensures that Python scripts have access to their full (Python) dependency closure at run-time, which is necessary because it is an interpreted language.

For the languages-specific infrastructures that do this, propagatedBuildInputs can also be seen as “a list of dependencies that need to be available to $lang scripts at run-time”.

17 Likes

Thanks, this did indeed solve my problem!

@Shados This is a really great explanation. Thanks for taking the time to write this!

  1. It “propagates” this dependency relationship onwards to all derivations that depend (directly or transitively) on a

I guess this should be “derivations that depend (directly or transitively) on b”?

any propagatedBuildInputs in the dependency closure of a profile will also find their way into the profile’s paths.

The net effect is that propagatedBuildInputs can also be seen as a list of “dependencies that need to be available at run-time”.

I think this is the part I was really missing! This makes total sense, and I can see how useful it could be when writing derivations!

In general nix requires a lot of upfront investment to be efficient with it. Unlike guix a lot of things like generating arbitrary containers are relegated to 3rd party projects. For example using cntr to debug derivations is great but I’m not using it because it’s relatively hidden and forgot how to use it.

Some good old ones:

  • multiple installation instructions: nix-env -iA nixpkgs.hello vs nix-env -iA nixos.hello
  • too many channels; I think it’s confusing to have a nixos-* and nixpkgs-* channels.
  • channels don’t map to hydra jobset names. Eg nixpkgs-unstable is nixpkgs/trunk on Hydra.
  • nix-collect-garbage -d doesn’t clean the old /boot entries. This affects everyone using NixOS.
13 Likes

Are you sure about this? I thought we needed to use propagatedUserEnvPkgs for that, otherwise I do not see why would it exist.

For Python libraries, I think they are included in the runtime closure by buildPythonApplication, not that they are picked up from profile.

Edit: In my mental model, the profiles are managed by Nixʼs buildEnv which is different from Nixpkgsʼs so I do not see how it would know about Nix specific features like propagated build inputs.

Edit2: Thinking about that, Nix would have to know about propagatedUserEnvPkgs as well. And looking at the source code, it seems to. I see no such case for propagatedBuildInputs.

Edit3: Really, being a derivation is not anything magical. Rather Nixʼs derivation is rather useless by itself. There is a lot of orchestration done by the generic builder used by default by stdenv.mkGeneration which adds lot of data used by other such derivations instrumented by it. Look at Nix pills to learn how it works.

1 Like