[Nix-dev] nix-env and nixpkgs usability improvements
Eelco Dolstra
eelco at cs.uu.nl
Wed Feb 1 15:06:45 CET 2006
Hi,
I'm thinking about making a number of changes to Nixpkgs and nix-env
to make them more user- (and developer-) friendly. There are
currently a number of problems:
- The situation in the pkgs/system directory is quite confusing: we
have quite a few files there involved in defining the "top level"
available packages (all-packages-generic.nix, all-packages.nix,
i686-linux.nix and friends, populate-cache.nix).
- It's bad that we have two sets of "available" packages: those in
i686-linux.nix (which is in turn an instantiation of
all-packages-generic.nix), and populate-cache.nix (which contains a
subset of the former, namely the pre-built binary packages in the
channel).
- Even worse is that "nix-env -qa" doesn't work on (for instance)
powerpc-darwin.nix, since many packages have assertions of the form
'assert system == "i686-linux"'. This causes evaluation to fail on
all other platforms. Right now i686-linux is the only platform
where all-packages-generic.nix evaluates entirely.
- For people who use a channel, it is hard to install packages that
are not pre-built by the Nixpkgs release. They only get to see the
packages available in populate-cache.nix.
- There are too many name conflicts in all-packages-generic.nix. For
instance, there are four packages named "gcc-4.0.2" (all but one are
cross-compilers).
- "nix-env -qa" on all-packages-generic.nix prints out lots of
garbage, in particular "packages" that shouldn't be in the list like
tarballs. For example:
$ nix-env -f ~/Dev/nixpkgs/pkgs/system/i686-linux.nix -qa
...
libgnomecanvas-2.10.0
libgnomecanvas-2.10.0.tar.bz2
...
This is because it currently recurses into attribute sets.
- It is hard to maintain local modifications of a Nixpkgs tree. For
instance, Firefox in the channel is built without the RealPlayer
plugin enabled (for legal reasons). If you have a Nixpkgs tree
checked out, this is easy to change by editing the appropriate lines
in all-packages-generic.nix. But this makes it hard to upgrade
later: "nix-channel --update; nix-env -u firefox" will just install
a new Firefox *without* RealPlayer.
Other examples are whether to build Subversion's Apache modules,
whether to build GnuPG with (patent-encumbered) IDEA support, and
configuration settings like the path of the MythTV database or the
Quake 3 game files.
- It is too hard to easily build a package without installing it.
That's what "nix-build" is for, but nix-build has a quite different
interface than nix-env: e.g., it only works on top-level Nix
expressions (i.e., you cannot select a package by symbolic name).
- A better default policy for resolving file collisions between
packages (i.e., when two packages both have a file "bin/foo") is
required. Right now the user environment builder just bails out. A
more user-friendly default would be to let the most recently added
package override older ones.
- Finally, there are some user interface warts in nix-env, such as
https://bugs.cs.uu.nl/browse/NIX-17 and
https://bugs.cs.uu.nl/browse/NIX-31.
===
So I propose a number of changes to nix-env and Nixpkgs:
- Rename all-packages-generic.nix to all-packages.nix, get rid of
the old all-packages.nix and i686-linux and friends. The latter are
all redundant: default arguments can be used for that. The new
all-packages.nix would be function like this:
{system ? __currentSystem}:
rec {
stdenvs = ...;
stdenv =
if system == "i686-linux" then stdenvs.stdenvLinuxPkgs
else if system == "powerpc-darwin" then ...
... all packages ...
}
- Rename populate-cache.nix to build-for-release.nix or something like
that ("cache" is a misnomer).
So the result is that we have only two files:
* all-packages.nix
* build-for-release.nix (which can be ignored by most people)
- Make all-packages.nix the default Nix expression for the channel
instead of populate-cache.nix. This makes all packages in Nixpkgs,
including those not available in binary form, visible to channel
users.
- Of course, this gives assertion failures on platforms other than
i686-linux. So nix-env should be modified to silently ignore
derivations that evaluate to an assertion failure.
- Since all-packages.nix now shows everything, including source-only
packages, it may be useful to have a flag "--prebuilt-only" (or
something like that) to filter out packages for which there are no
substitutes.
- Since all-packages.nix is now a function, nix-env should be modified
to automatically call functions whose arguments all have defaults
(nix-build already does this!). So
$ nix-env -f .../pkgs/system/all-packages.nix -i foo
will call the function in all-packages.nix with "system" set to
"__currentSystem" (like "i686-linux") and do the right thing.
- nix-env shouldn't recurse into attribute sets anymore. Sometimes
this is desirable though, so maybe an attribute like "nixenvRecurse"
could be specified in an attribute set for which we do want this.
- Add a flag "nix-env -A" to select packages by attribute name, e.g.
$ nix-env -i -A subversionWithJava
$ nix-env -i -A xlibs.xorgserver
(This is equivalent to "nix-env -i -E 'x: x.xlibs.xorgserver'", but
rather easier.)
- Merge nix-build into nix-env, for instance by adding a flag "nix-env
--build-only".
- Maintaining local configuration: all-packages.nix could read in a
file like ~/.nixpkgs/config.nix containing stuff like
{ subversionApacheSupport = true;
firefoxRealplayerSupport = true;
quake3Paks = "/bla/quake3/baseq3";
mythtvState = "/var/db/mythtv";
}
The only catch is that the Nix expression language needs a way to
find this file (through $HOME) and only read it if exists.
Something like this (in all-package.nix):
rec {
defaults = {
subversionApacheSupport = false;
firefoxRealplayerSupport = false;
...
}
config = loadWithDefault defaults
((getEnv "HOME") + "/.nixpkgs/config.nix");
...
subversion = import .../subversion {
inherit fetchurl stdenv ...;
httpServer = subversionApacheSupport;
};
...
}
- We could even allow users to override entire packages. For
instance, we can wrap all-packages.nix like this:
(rec {
.. all packages ...
})
//
(loadWithDefault {}
((getEnv "HOME") + "/.nixpkgs/overrides.nix"));
where ~/.nixpkgs/overrides.nix can contain definitions like
firefox = { ... };
- In Gentoo style, it should be possible to "mask" packages so they
won't be installed or upgraded automatically.
- Eliminate the naming conflicts in all-packages.nix. For instance, a
gcc cross-compiler for Sparc might be called
"gcc-x86-to-sparc-4.0.2" instead of "gcc-4.0.2".
Okay, this post was way too long. Comments?
--
Eelco Dolstra | http://www.cs.uu.nl/~eelco
More information about the nix-dev
mailing list