Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create default.nix during niv init #95

Open
nmattia opened this issue Jun 18, 2019 · 14 comments
Open

Create default.nix during niv init #95

nmattia opened this issue Jun 18, 2019 · 14 comments
Labels
question Further information is requested

Comments

@nmattia
Copy link
Owner

nmattia commented Jun 18, 2019

The niv init command used to create a few files (default.nix, shell.nix, etc) which some people didn't like. Some people now complain that they want it back. I think the best solution here is to have niv init create a single extra file, default.nix, which

  1. shows how to import nix/sources.nix
  2. builds a single (pkgs.hello) package,
  3. potentially create a shell if inNixShell
@michaelpj
Copy link
Contributor

Why not just have options to niv init? e.g. niv init --sources --default --shell for everything.

@Skyfold
Copy link

Skyfold commented Jul 2, 2019

I'll be honest, requiring extra options is less than ideal. Instead have nix init check for a ./shell.nix file and a ./nix/default.nix file. If there is only a ./shell.nix then create a ./nix/default.nix that has comments at the top on how to import nix/sources.nix. If there is already a ./nix/default.nix, don't modify it and tell the user. Otherwise, generate everything.

@nmattia
Copy link
Owner Author

nmattia commented Jul 2, 2019

I gave this some thoughts over the past few days and came up with this (feedback welcome):

niv init generates nix/sources.json, nix/sources.nix and default.nix (unless they exist, of course). The default.nix would look like this:

let
  sources = import ./nix/sources.nix;
  pkgs = import sources.nixpkgs {};
in pkgs.hello

should be simple enough that people might actually use it, and still it showcases how to use niv.

@Skyfold
Copy link

Skyfold commented Jul 2, 2019

I agree that having a simple enough example to build off of is a good idea. I would extend this idea by also generating a shell.nix that imports everything from sources.nix. However, I just realized if you wanted to import every attribute (package) into your buildInputs then the way you generate sources.nix would need to be adjusted to be {nixpkgs = nixpkgs; buildInputs = [snack niv]; } instead of making each package a top level attribute. To be fair you could filter out nixpkgs and import the rest, but it would complicate the resulting shell.nix.

@michaelpj
Copy link
Contributor

So I think there are two big use cases for niv:

  • A repository specific package that has a default.nix that defines just that package.
  • A repository full of nix expressions for doing various things, maybe including packages, library functions, etc.

Importing dependencies and using them in buildInputs makes sense for the first kind and no sense at all for the second kind (e.g. nixpkgs). I don't think we should make assumptions about what people put in there, so I'm against doing anything with a source except importing it as a (mystery) attribute.

@Skyfold
Copy link

Skyfold commented Jul 2, 2019

Why not have both? Keep the existing behavior of sources.nix and just tack on an extra attribute called buildInputs to make creating a shell.nix easy (or have niv generate the shell.nix with an extra flag). So you could do:

{ sources ? ./nix/sources.nix }:
  pkgs.mkShell {
    buildInputs = (import sources).buildInputs;
  }

@nmattia nmattia added the question Further information is requested label Jan 7, 2020
@hazelweakly
Copy link

hazelweakly commented Jan 8, 2020

I end up setting up every repo I use niv in using an interesting method. I originally took inspiration for it from @nmattia's homies and have taken small ideas from other repos as well. I have a nix/default.nix that essentially acts as the standard "prelude" import. That is, let pkgs = import ./nix {}; imports the pinned nixpkgs. However, I also end up defining any overlays, nixpkgs configuration, and "globally available util stuff" in nix/default.nix which makes my life really convenient.

Recently, I've also taken to adding "sources" as an overlay so I can do pkgs.sources.my-niv-managed-dependency but I only do that to save on line-noise in the rest of the nix files.

So it seems to me that default.nix and shell.nix aren't really the biggest things I end up setting up every time but actually nix/default.nix. Specifically, something like:

# nix/default.nix
{ sources ? import ./sources.nix, system ? builtins.currentSystem }:
let
  srcs = self: super: { inherit sources; };
  overlays = [ srcs ];
  config = { };
in import sources.nixpkgs { inherit overlays config system; }

is essentially my starter boilerplate in nix/. Then, should niv want to bootstrap the default and the shell, they can be:

# default.nix (at repo root)
let pkgs = import ./nix {};
in pkgs.hello
# shell.nix (at repo root)
let pkgs = import ./nix {};
in pkgs.stdenv.mkShell {
  buildInputs = [ pkgs.hello ];
}

How well do you think that pattern would work?

One thing I'd be concerned about is adding a bunch of extra utility to the nix/default.nix or nix/sources.nix, but only really for keeping maintenance burden to a minimum.


edit: updated proposed default.nix to account for system.

@nmattia
Copy link
Owner Author

nmattia commented Jan 8, 2020

👍 , I think that's close to the perfect nix/default.nix! One thing that we may add as well is a system parameter, if you want to build stuff on a difference architecture (through a remote builder):

{ sources ? ...
, system ? builtins.currentSystem
}: 
...
in sources.nixpkgs { inherit overlays config system; }

I think we should just go for it, maybe hiding it behind a flag (e.g. niv init --full).

@michaelpj
Copy link
Contributor

I find injecting the niv sources into nixpkgs via an overlay feels somewhat unhygienic: the sources aren't packages, and I usually want to manage them separately. A matter of taste, I guess, I appreciate the appeal of "everything is all in one attribute set".

I want something different from nix/default.nix, which is just to give me a shortcut to precisely the bits managed by niv, i.e. sources.nix. So it's usually exactly import sources.nix.

@michaelpj
Copy link
Contributor

(One small rant: importing nixpkgs is pretty non-trivial (it has a lot of significant arguments), and the number of things that do it wrong (e.g. not passing system as you're doing here), is high. I really wish tools would let me do it the way I want to do it and pass it in, rather than trying to import nixpkgs for me and doing it wrong.)

@zimbatm
Copy link
Contributor

zimbatm commented Jan 8, 2020

@michaelpj the nix flakes branch actually does a lot of that for you, they replace 80% of what niv does (sorry nmattia), creates a standard entrypoint for repositories, handles system and a few other things. You can test it by setting nix.package = pkgs.nixFlakes; in NixOS.

@hazelweakly
Copy link

(One small rant: importing nixpkgs is pretty non-trivial (it has a lot of significant arguments), and the number of things that do it wrong (e.g. not passing system as you're doing here), is high.

You're absolutely right, my apologies; I didn't actually know I should include system as I've only seen it done once in someone's config online. Is there a wiki page for "how to import nixpkgs properly" or is it a sort of cult knowledge that's acquired by making mistakes over time?

I really wish tools would let me do it the way I want to do it and pass it in, rather than trying to import nixpkgs for me and doing it wrong.)

Fortunately, even if niv had a default.nix, it can easily be replaced or modified to suit your needs.

Although, since niv includes nixpkgs by default in its init, that actually suggests to me that it's even more important that niv's init also come with a way to fully correctly import nixpkgs. Otherwise it's far too easy to just make the mistake of writing the naive let sources = import ./nix/sources.nix; pkgs = import sources.nixpkgs {}; and then, whoops, that'll no longer work correctly on mac systems as you've pointed out.

@michaelpj
Copy link
Contributor

I know about flakes :) my feeling is rather that niv does 80% of what flakes do...

Is there a wiki page for "how to import nixpkgs properly" or is it a sort of cult knowledge that's acquired by making mistakes over time?

I got it the latter way 😅

Although, since niv includes nixpkgs by default in its init, that actually suggests to me that it's even more important that niv's init also come with a way to fully correctly import nixpkgs.

Is it? I like that niv does one thing: get me a set of sources. It could do more, and be a full-fledged Nix project scaffolding manager. But I, personally, would prefer if it continued just doing the one thing well.

orther added a commit to orther/nix-home that referenced this issue Jun 13, 2020
toraritte added a commit to toraritte/nixos-config that referenced this issue Aug 7, 2020
It seems to be easier to pin nixpkgs directly in
`shell.nix`/`default.nix`. It's functionality also overlaps with `nix-wrangle` and, more importantly, `nix flakes`.

From `zimbatm` in `niv` issue #95:
nmattia/niv#95 (comment)
> the nix flakes branch  actually does a lot
> of  that  for  you, they  replace  80%  of
> what  niv  does (sorry  nmattia),  creates
> a  standard  entrypoint for  repositories,
> handles system and a few other things. You
> can  test  it  by  setting  nix.package  =
> pkgs.nixFlakes; in NixOS.
@nmattia
Copy link
Owner Author

nmattia commented Aug 22, 2020

Hey guys, would love your feedback on #272

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants