[Nix-dev] some questions

Eelco Dolstra eelco at cs.uu.nl
Sat Apr 7 20:36:01 CEST 2007


Hi Erick,

Erick Tryzelaar wrote:

> Nix looks very interesting! I found my way here from
> http://lambda-the-ultimate.org/node/2163. I've got some questions.
> 
> 1. I'm running a mac, and so there's a very small amount of packages
> that will install from nixpkgs, but I know a good amount of them will
> actually install. Is the only way to get things to compile is either
> modify the pkgs/top-level/build-for-release.nix, or pretend to be
> another build target. Is there an easier way to do this? 

Yes, you can use the -f flag to use all-packages.nix, which provides all
packages, not just the ones pre-built for the channel:

$ nix-env -f path-to-nixpkgs/pkgs/top-level/all-packages.nix -i pkgname...

We've thought about getting rid of build-for-release.nix (at least, not making
that the top-level expression for the Nixpkgs channel) to make it easier to
allow people to use the non-prebuilt packages.  Maybe with a flag to hide/show
those packages.

> It would be
> nice if the system compatibility could be embedded in the package,
> instead of build-for-release.nix file. I think it'd make things a little
> more maintainable. Could it be automatically generated from a package's
> metadata, assuming the supported platforms was added to the package?

Good point, and actually this shouldn't be hard to implement.  We could just
write something like

meta = {
  description = "bla bla";
  systems = ["i686-linux" "i686-darwin" ...];
}

and rather than have a build-for-release.nix, we could just use those
meta.systems attributes to decide what to build in the channel.  Hm...

> 2. Is there a reason why the files in the store are named
> guid-project-version, instead of project-version-guid?

That point came up here:
http://www.osnews.com/read_thread.php?news_id=17601&comment_id=226502

Summary: there are advantages to both approaches.  Most of the time, it
shouldn't matter too much.

> Or even better,
> type/namespace/project-version/guid, where type is
> user-environment/channel/downloads/etc and namespace is the java-like
> nix.cs.uu.nl? It's a little hard to navigate this way.

This would be bad, because then you don't have sharing between user
environments.  I.e. if two users install the same package, it shouldn't be
stored twice.  Likewise for the channel: different channels can provide the same
store paths.  Example: the Nixpkgs channel and the Stratego/XT channel provide
exactly the same Glibc.

> 3. Along these lines, it's a little hard finding the channel files.
> They're currently something like:
> 
> /nix/store/0hr9wrwhiq18l3gils4s0vzhi9rkb795-channels/0
> /nix/store/0hr9wrwhiq18l3gils4s0vzhi9rkb795-channels/1
> 
> Instead of 0 and 1, it would be nice if they could also follow a
> namespace/project-version/guid. So it'd be something like:
> 
> /nix/store/nix/channels-0hr9wrwhiq18l3gils4s0vzhi9rkb795/nix.cs.uu.nl/nixpkgs-unstable
> 
> /nix/store/nix/channels-0hr9wrwhiq18l3gils4s0vzhi9rkb795/nix.cs.uu.nl/nix-unstable

Hm, that's a pretty good idea :-)  I haven't needed something like that myself
because I just have a Subversion checkout, but that's not true for users in
general, of course.  I'll make an issue about it.

> 4. From what I can tell from the documentation, it's possible to compile
> code while enabling different features, such as one build of subversion
> supporting mod_dav_svn, and another not. But I can't figure out how I'm
> supposed to do this. macports, another packaging system for the mac, has
> something similar called variants, where you just do this:
> 
> port install +mod_dav_svn
> 
> Which adds a dependency on apache2, and appends
> "--with-apxs=${prefix}/apache2/bin/apxs --disable-mod-activation" to the
> configure. It works out well, but the downside is that one package can't
> depend on another package's variants. I believe nix can do this. Is
> there a simple interface for it?

Not really a *simple* interface, but Nix expressions being a purely functional
language, it is certainly possible.  It's just that all-packages.nix isn't very
flexible: it calls the functions that build the various packages with mostly
fixed arguments.  You can of course make your own function that calls them with
different arguments.  For instance, all-packages.nix builds Subversion like this:

  subversion14 = import ../applications/version-management/subversion-1.4.x {
    inherit fetchurl stdenv apr aprutil neon expat swig zlib;
    bdbSupport = true;
    httpServer = false;
    sslSupport = true;
    compressionSupport = true;
    httpd = apacheHttpd;
  };

i.e. since httpServer = false, it doesn't build the DAV module.  For our
Subversion server (svn.cs.uu.nl), we need Subversion with the DAV module, so in
one of the Nix expressions for the server
(https://svn.cs.uu.nl:12443/repos/trace/services/trunk/subversion/default.nix)
we call it like this:

  subversion = import ../pkgs/applications/version-management/subversion-1.4.x {
    inherit (pkgs) fetchurl stdenv apr aprutil neon expat swig zlib;
    bdbSupport = true;
    httpServer = true;
    sslSupport = true;
    compressionSupport = true;
    pythonBindings = true;
    httpd = pkgs.apacheHttpd;
  };

Nixpkgs does have support for user customization, it's just not used a lot yet.
  You can put configuration flags in ~/.nixpkgs/config.nix like

{
  firefox = {
    enableRealPlayer = true; # Firefox with RealPlayer plugin.
  };
  acroread = {
    fastStart = true; # Leave out most plugins.
  };
}

but those are actually the only two options right now ;-)  They're easy to add
thought, for instance, we could do

  subversion14 = import ../applications/version-management/subversion-1.4.x {
    ...
    httpServer = getConfig ["subversion" "withDAVodule"] false;

would allow a user to set subversion.withDAVModule to true to always get
Subversion with the DAV module.  (However, that configuration wouldn't be built
in the channel, so Nix reverts automatically to building from source.)

> 5. rpm and apt have a nice feature where one .spec file can generate
> multiple packages. This lets you split up bundling development files and
> libraries. Can nix do this?

No, not yet, but it's been a long-time to-do item.  The problem is that it's not
quite trivial.  If a derivation has multiple outputs in the Nix store, then
presumably those outputs can be downloaded *and* garbage-collected separately
(otherwise there would be no point).  But if output A is garbage-collected and
output B is still in the Nix store, and you then need A, you would have to
rebuild, but this would overwrite B, leaving the system temporarily in an
inconsistent state.  (Since there might be other packages referring to B.)  I do
have a rough idea of how to fix this, though.

> 6. I read that I can either build a package, or install a prebuilt one.
> How can I select between the two?

You can't - if you've nix-pulled, then Nix will download a pre-built binary if
it's available.  If you really do want to build from source in that case, you
can do "nix-store --clear-substitutes" to get rid of the nix-pull registrations.

> 7. The documentation is a little long for one page. Could it be broken
> up into a couple pages?

Yes, good idea (or even better, I would like both, since having it on one page
is useful if you want to grep for something).  Martin already did this for the
Stratego/XT manual, so I just need to copy that :-)

> 8. At work, we have a pretty elaborate build system for maintaining
> multiple active versions of a project. So, we'd have:
> 
> /global/foo/
>  1 -> 1.1.0
>  1.0 -> 1.0.1
>  1.0.1/...
>  1.1 -> 1.1.0
>  1.1.0/...
> /global/bar/
>  2 -> 2.0.1
>  2.0 -> 2.0.1
>  2.0.1/...
>  3 -> 3.0.0
>  3.0 -> 3.0.0
>  3.0.1/...
> /local/foo -> 1
> /local/bar -> 2
> 
> Where "bar-2.x.x" depends on "foo-1.0", and "bar-3.x.x" depends on
> "foo-1.1". We save the last number for binary-compatible bug fixes. The
> global/local version is like the nix profiles, where a local machine can
> be switched from one version to another of a netmount shared global
> version. It seems like it'd be pretty easy to use the profiles for this,
> but I'm not sure how I can set up a package to depend on, say, only the
> major version of a library, which allows for the package to be upgradeable.

Yes, you probably could use profiles for that, but nobody has ever done that I
think :-)  We use profiles only for "top-level" packages installed by users, not
to handle inter-packages dependencies.  Also, you can't really express
dependencies between packages in profiles.

-- 
Eelco Dolstra | http://www.cs.uu.nl/~eelco




More information about the nix-dev mailing list