mirror of
https://github.com/NixOS/nix.dev.git
synced 2024-10-18 00:06:26 -04:00
Compare commits
6 commits
d0fb229be3
...
a961cac073
Author | SHA1 | Date | |
---|---|---|---|
a961cac073 | |||
53cbd112d7 | |||
1f6a1219ae | |||
2720a4121e | |||
e31f927878 | |||
c3679b07c5 |
|
@ -46,7 +46,7 @@ let
|
||||||
sed '/^#/d;/^$/d;s#^\(.*\) \(.*\) #/manual/nix/${version}\1 /manual/nix/${version}\2 #g' ${src version}/doc/manual/_redirects >> $out/_redirects
|
sed '/^#/d;/^$/d;s#^\(.*\) \(.*\) #/manual/nix/${version}\1 /manual/nix/${version}\2 #g' ${src version}/doc/manual/_redirects >> $out/_redirects
|
||||||
'';
|
'';
|
||||||
shortlink = release: version: ''
|
shortlink = release: version: ''
|
||||||
echo /nix/manual/${release} /nix/manual/${version} >> $out/_redirects
|
echo /manual/nix/${release} /manual/nix/${version}/ 302 >> $out/_redirects
|
||||||
'';
|
'';
|
||||||
versions = with pkgs.lib; lists.unique (attrsets.attrValues releases);
|
versions = with pkgs.lib; lists.unique (attrsets.attrValues releases);
|
||||||
in
|
in
|
||||||
|
|
|
@ -9,56 +9,9 @@
|
||||||
|
|
||||||
The Nix logo is inspired by [an idea for the Haskell logo](https://wiki.haskell.org/File:Sgf-logo-blue.png) and the fact that [*nix* is Latin for *snow*](https://nix-dev.science.uu.narkive.com/VDaaP1BY/nix-logo).
|
The Nix logo is inspired by [an idea for the Haskell logo](https://wiki.haskell.org/File:Sgf-logo-blue.png) and the fact that [*nix* is Latin for *snow*](https://nix-dev.science.uu.narkive.com/VDaaP1BY/nix-logo).
|
||||||
|
|
||||||
## Why are flakes controversial?
|
## What are flakes?
|
||||||
|
|
||||||
{ref}`Flakes <flakes>` were originally proposed in [RFC 49](https://github.com/NixOS/rfcs/pull/49), and have been in development since 2019.
|
See [](flakes-definition).
|
||||||
Nix introduced the implementation as its first [experimental feature] in 2021.
|
|
||||||
|
|
||||||
[experimental feature]: https://nix.dev/manual/nix/2.18/contributing/experimental-features.html
|
|
||||||
|
|
||||||
The subject is considered controversial among Nix users and developers in terms of design, development processes, and community governance.
|
|
||||||
In particular:
|
|
||||||
- The RFC was closed without conclusion, and some design and implementation issues are not yet resolved.
|
|
||||||
Examples include the notion of a global [flake registry], the [impossibility of parameterising flakes](https://github.com/NixOS/nix/issues/2861), and the [new command line interface and flakes being closely tied to each other](https://discourse.nixos.org/t/2023-03-06-nix-team-meeting-minutes-38/26056#cli-stabilisation-announcement-draft-4).
|
|
||||||
- The original implementation introduced [regressions](https://discourse.nixos.org/t/nix-2-4-and-what-s-next/16257) in the [Nix 2.4 release](https://nix.dev/manual/nix/2.18/release-notes/rl-2.4.html), breaking some stable functionality without a [major version](https://semver.org/) increment.
|
|
||||||
- New Nix users were and still are encouraged by various individuals to adopt flakes despite there being no concrete plan or timeline for stabilisation.
|
|
||||||
|
|
||||||
[flake registry]: https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-registry.html
|
|
||||||
|
|
||||||
This led to a situation where the stable interface was only sparsely maintained for multiple years, and repeatedly suffered breakages due to ongoing development.
|
|
||||||
Meanwhile, the new interface was adopted widely enough for evolving its design without negatively affecting users to become very challenging.
|
|
||||||
|
|
||||||
As of the [2022 community survey](https://discourse.nixos.org/t/2022-nix-survey-results/18983), more than half of the user base, a third of which were relative beginners, relied on experimental features.
|
|
||||||
{term}`Nixpkgs` as a contrasting example, while featuring a `flake.nix` for compatibility, does not depend on Nix experimental features in its code base.
|
|
||||||
|
|
||||||
## Should I enable flakes?
|
|
||||||
|
|
||||||
You have to judge for yourself based on your needs.
|
|
||||||
|
|
||||||
[Flakes](https://nix.dev/concepts/flakes) and the `nix` command suite bring multiple improvements that are relevant for both software users and package authors:
|
|
||||||
|
|
||||||
- The new command-line interface, together with flakes, makes dealing with existing packages significantly more convenient.
|
|
||||||
- The constraints imposed on flakes strengthen reproducibility by default, and enable various performance improvements when interacting with a large Nix package repository like {term}`Nixpkgs`.
|
|
||||||
- Flake references allow for easier handling of version upgrades for existing packages or project dependencies.
|
|
||||||
- The [flake schema](https://nixos.wiki/wiki/Flakes#Flake_schema) helps with composing Nix projects from multiple sources in an orderly fashion.
|
|
||||||
|
|
||||||
Other than that, and below the surface of the flake schema, Nix and the Nix language work exactly the same in both cases.
|
|
||||||
In principle, the same level of reproducibility can be achieved with or without flakes.
|
|
||||||
In particular, the process of adding software to {term}`Nixpkgs` or maintaining {term}`NixOS` modules and configurations is not affected by flakes at all.
|
|
||||||
|
|
||||||
Both paradigms have their own set of unique concepts and support tooling that have to be learned, with varying ease of use, implementation quality, and support status.
|
|
||||||
At the moment, neither the stable nor the experimental interface is clearly superior to the other in all aspects.
|
|
||||||
While flakes reduce complexity in some regards, they also introduce additional mechanisms and you will have to learn more about the system to fully understand how it works.
|
|
||||||
|
|
||||||
There are downsides to relying on [experimental features](https://nix.dev/manual/nix/2.18/command-ref/conf-file.html#conf-experimental-features) in general:
|
|
||||||
|
|
||||||
- Interfaces and behaviour of experimental features could still be changed by Nix developers.
|
|
||||||
This may require you to adapt your code at some point in the future, which will be more effort when it has grown in complexity.
|
|
||||||
Currently there is no agreed-upon plan or timeline for stabilising flakes.
|
|
||||||
- The [Nix maintainer team](https://nixos.org/community/teams/nix.html) focuses on fixing bugs and regressions in stable interfaces, supporting well-understood use cases, as well as improving the internal design and overall contributor experience in order to ease future development.
|
|
||||||
Improvements to experimental features have a low priority.
|
|
||||||
- The [Nix documentation team](https://nixos.org/community/teams/documentation.html) focuses on improving documentation and learning materials for stable features and common principles.
|
|
||||||
When using flakes, you will have to rely more heavily on user-to-user support, third-party documentation, and the source code.
|
|
||||||
|
|
||||||
(channel-branches)=
|
(channel-branches)=
|
||||||
## Which channel branch should I use?
|
## Which channel branch should I use?
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(flakes)=
|
(flakes-definition)=
|
||||||
# Flakes
|
# Flakes
|
||||||
|
|
||||||
What is usually referred to as "flakes" is:
|
What is usually referred to as "flakes" is:
|
||||||
|
@ -7,14 +7,18 @@ What is usually referred to as "flakes" is:
|
||||||
|
|
||||||
[experimental feature]: https://nix.dev/manual/nix/2.18/contributing/experimental-features.html
|
[experimental feature]: https://nix.dev/manual/nix/2.18/contributing/experimental-features.html
|
||||||
|
|
||||||
|
## What are flakes?
|
||||||
|
|
||||||
Technically, a [flake](https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#description) is a file system tree that contains a file named `flake.nix` in its root directory.
|
Technically, a [flake](https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#description) is a file system tree that contains a file named `flake.nix` in its root directory.
|
||||||
|
|
||||||
Flakes add the following behavior to Nix:
|
Flakes add the following behavior to Nix:
|
||||||
|
|
||||||
1. A `flake.nix` file offers a uniform [schema](https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#flake-format) , where:
|
1. A `flake.nix` file enforces a [schema], where:
|
||||||
- Other flakes can be referenced as dependencies providing {term}`Nix language` code or other files.
|
- Other flakes are referenced as dependencies providing {term}`Nix language` code or other files.
|
||||||
- The values produced by the {term}`Nix expression`s in `flake.nix` are structured according to pre-defined use cases.
|
- The values produced by the {term}`Nix expression`s in `flake.nix` are structured according to pre-defined use cases.
|
||||||
|
|
||||||
|
[schema]: https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#flake-format
|
||||||
|
|
||||||
1. References to other flakes can be specified using a dedicated [URL-like syntax](https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#flake-references).
|
1. References to other flakes can be specified using a dedicated [URL-like syntax](https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html#flake-references).
|
||||||
A [flake registry] allows using symbolic identifiers for further brevity.
|
A [flake registry] allows using symbolic identifiers for further brevity.
|
||||||
References can be automatically locked to their current specific version and later updated programmatically.
|
References can be automatically locked to their current specific version and later updated programmatically.
|
||||||
|
@ -25,7 +29,7 @@ Flakes add the following behavior to Nix:
|
||||||
|
|
||||||
[new command line interface]: https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix.html
|
[new command line interface]: https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix.html
|
||||||
|
|
||||||
Nix handles flakes differently than regular {term}`Nix file`s in the following ways:
|
Nix handles flakes differently than regular {term}`Nix files <Nix file>` in the following ways:
|
||||||
|
|
||||||
- The `flake.nix` file is checked for schema validity.
|
- The `flake.nix` file is checked for schema validity.
|
||||||
|
|
||||||
|
@ -40,3 +44,74 @@ Nix handles flakes differently than regular {term}`Nix file`s in the following w
|
||||||
|
|
||||||
It means full reproducibility of a Nix expression, and, by extension, the resulting build instructions by default, but also prohibits parameterisation of results by consumers.
|
It means full reproducibility of a Nix expression, and, by extension, the resulting build instructions by default, but also prohibits parameterisation of results by consumers.
|
||||||
|
|
||||||
|
(flakes-controversy)=
|
||||||
|
## Why are flakes controversial?
|
||||||
|
|
||||||
|
[Flakes](flakes-definition) were inspired by [Shea Levy's NixCon 2018 talk](https://www.youtube.com/watch?v=DHOLjsyXPtM), formally proposed in [RFC 49](https://github.com/NixOS/rfcs/pull/49), and have been in development since 2019.
|
||||||
|
Nix introduced the implementation as its first [experimental feature] in 2021.
|
||||||
|
|
||||||
|
The subject is considered controversial among Nix users and developers in terms of design, implementation quality, and decision making process.
|
||||||
|
In particular:
|
||||||
|
- The RFC was closed without conclusion, and some fundamental issues are not yet resolved.
|
||||||
|
For example:
|
||||||
|
- The notion of a [global flake registry](https://github.com/NixOS/flake-registry) saw [substantial criticism](https://github.com/NixOS/rfcs/pull/49#issuecomment-635635333) that was never addressed.
|
||||||
|
Additionally, local registry names in Nix expressions [introduce mutable system state](https://github.com/NixOS/nix/issues/7422) and are thus no improvement over [channels](https://nix.dev/manual/nix/2.18/command-ref/nix-channel) in that regard.
|
||||||
|
- It is [impossible to parameterise flakes](https://github.com/NixOS/nix/issues/2861).
|
||||||
|
This means that [flakes downgrade ease of use of the `system` parameter](https://github.com/NixOS/nix/issues/3843) of derivations, for producers and consumers.
|
||||||
|
- the flakes proposal was criticised for [trying to solve too many problems at once](https://github.com/nixos/rfcs/pull/49#issuecomment-521998933) and [at the wrong abstraction layer](https://discourse.nixos.org/t/nixpkgs-cli-working-group-member-search/30517).
|
||||||
|
Part of this is that [the new command line interface and flakes are closely tied to each other](https://discourse.nixos.org/t/2023-03-06-nix-team-meeting-minutes-38/26056#cli-stabilisation-announcement-draft-4).
|
||||||
|
- As [predicted by RFC reviewers](https://github.com/NixOS/rfcs/pull/49#issuecomment-588990425), the original implementation introduced [regressions](https://discourse.nixos.org/t/nix-2-4-and-what-s-next/16257) in the [Nix 2.4 release](https://nix.dev/manual/nix/2.18/release-notes/rl-2.4.html), breaking some stable functionality without a [major version](https://semver.org/) increment.
|
||||||
|
- Copying sources to the Nix store prior to evaluation adds a [significant performance penalty](https://github.com/NixOS/nix/issues/3121), especially for large repositories such as {term}`Nixpkgs`.
|
||||||
|
Work to address this has been [in progress since May 2022](https://github.com/NixOS/nix/pull/6530), but risks introducing [its own set of issues](https://github.com/NixOS/nix/pull/6530#issuecomment-1850565931).
|
||||||
|
- New Nix users were and still are encouraged by various individuals to adopt flakes despite there being no stability guarantees and no timeline to conclude the experiment.
|
||||||
|
|
||||||
|
This led to a situation where the stable interface was only sparsely maintained for multiple years, and repeatedly suffered breakages due to ongoing development.
|
||||||
|
Meanwhile, the new interface was adopted widely enough for evolving its design without negatively affecting users to become very challenging.
|
||||||
|
|
||||||
|
As of the [2022](https://discourse.nixos.org/t/2022-nix-survey-results/18983) and [2023](https://discourse.nixos.org/t/nix-community-survey-2023-results/33124) surveys, more than half of the respondents, a third of which are relative beginners, rely on experimental features.
|
||||||
|
{term}`Nixpkgs` as a contrasting example, while featuring a `flake.nix` for compatibility, does not depend on Nix experimental features in its code base.
|
||||||
|
|
||||||
|
## Should I use flakes in my project?
|
||||||
|
|
||||||
|
You have to judge for yourself based on your needs.
|
||||||
|
|
||||||
|
[Flakes](flakes-definition) emphasize reproducible artifacts and convenience for their consumers, while classic Nix tools center around composable building blocks and customisation options for developers.
|
||||||
|
Both paradigms have their own set of unique concepts and support tooling that have to be learned, with varying ease of use, implementation quality, and support status.
|
||||||
|
At the moment, neither the stable nor the experimental interface is clearly superior to the other in all aspects.
|
||||||
|
|
||||||
|
Flakes and the `nix` command suite bring multiple improvements that are relevant for both software users and package authors:
|
||||||
|
|
||||||
|
- The new command-line interface, together with flakes, makes dealing with existing packages significantly more convenient in many cases.
|
||||||
|
- The constraints imposed on flakes strengthen reproducibility by default, and enable some performance improvements when interacting with a large Nix package repository like {term}`Nixpkgs`.
|
||||||
|
- Flake references allow for easier handling of version upgrades for existing packages or project dependencies.
|
||||||
|
- The [flake schema][schema] helps with composing Nix projects from multiple sources in an orderly fashion.
|
||||||
|
|
||||||
|
At the same time, flakes have [fundamental architectural issues](flakes-controversy) and a number of [problems with the implementation](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+label%3Aflakes+sort%3Areactions-%2B1-desc), and there is no coordinated effort to resolve them systematically.
|
||||||
|
There are also still many [open design questions around the `nix` command line interface](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+label%3Anew-cli+sort%3Areactions-%2B1-desc), some of which are currently being worked on.
|
||||||
|
|
||||||
|
While flakes reduce complexity in some regards, they also introduce some with additional mechanisms.
|
||||||
|
You will have to learn more about the system to fully understand how it works.
|
||||||
|
|
||||||
|
Other than that, and below the surface of the flake schema, Nix and the Nix language work exactly the same in both cases.
|
||||||
|
In principle, the same level of reproducibility can be achieved with or without flakes.
|
||||||
|
In particular, the process of adding software to {term}`Nixpkgs` or maintaining {term}`NixOS` modules and configurations is not affected by flakes at all.
|
||||||
|
There is also no evidence that flakes could help solving the scalability challenges of either.
|
||||||
|
|
||||||
|
Finally, there are downsides to relying on [experimental features][experimental feature] in general:
|
||||||
|
|
||||||
|
- Interfaces and behavior of experimental features could still be changed by Nix developers.
|
||||||
|
This may require you to adapt your code at some point in the future, which will be more effort when it has grown in complexity.
|
||||||
|
[Currently there is no concrete timeline for stabilising flakes.](https://discourse.nixos.org/t/stabilising-the-new-nix-command-line-interface/35531#how-does-this-relate-to-flakes-3)
|
||||||
|
In contrast, stable features in Nix can be considered stable indefinitely.
|
||||||
|
- The [Nix maintainer team](https://nixos.org/community/teams/nix.html) focuses on fixing bugs and regressions in stable interfaces, supporting well-understood use cases, as well as improving the internal design and overall contributor experience in order to ease future development.
|
||||||
|
Improvements to experimental features have low priority.
|
||||||
|
- The [Nix documentation team](https://nixos.org/community/teams/documentation.html) focuses on improving documentation and learning materials for stable features and common principles.
|
||||||
|
When using flakes, you will have to rely more heavily on user-to-user support, third-party documentation, and the source code.
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
- [Flakes aren't real and cannot hurt you: a guide to using Nix flakes the non-flake way](https://jade.fyi/blog/flakes-arent-real/) (Jade Lovelace, January 2024)
|
||||||
|
- [Nix Flakes is an experiment that did too much at once...](https://samuel.dionne-riel.com/blog/2023/09/06/flakes-is-an-experiment-that-did-too-much-at-once.html) ([comments](https://discourse.nixos.org/t/nix-flakes-is-an-experiment-that-did-too-much-at-once/32707)) (Samuel Dionne-Riel, September 2023)
|
||||||
|
- [Experimental does not mean unstable](https://determinate.systems/posts/experimental-does-not-mean-unstable) ([comments](https://discourse.nixos.org/t/experimental-does-not-mean-unstable-detsyss-perspective-on-nix-flakes/32703)) (Graham Christensen, September 2023)
|
||||||
|
- [The Nix Hour: comparing flakes to traditional Nix](https://www.youtube.com/watch?v=atmoYyBAhF4) (Silvan Mosberger, November 2022)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
- [NixOS and Flakes - An unofficial book for beginners](https://nixos-and-flakes.thiscute.world) (2023)
|
- [NixOS and Flakes - An unofficial book for beginners](https://nixos-and-flakes.thiscute.world) (2023)
|
||||||
|
|
||||||
This tutorial is an introduction to {term}`NixOS` using the experimental Nix [Flakes](flakes) functionality.
|
This tutorial is an introduction to {term}`NixOS` using the experimental Nix [Flakes](flakes-definition) functionality.
|
||||||
|
|
||||||
- [Customizing packages in Nix](https://bobvanderlinden.me/customizing-packages-in-nix/) (2022)
|
- [Customizing packages in Nix](https://bobvanderlinden.me/customizing-packages-in-nix/) (2022)
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,9 @@ This file can be shared with anyone to recreate the same environment on a differ
|
||||||
|
|
||||||
30 minutes
|
30 minutes
|
||||||
|
|
||||||
### What will you need?
|
### What do you need?
|
||||||
|
|
||||||
- A basic understanding of the [Nix language](reading-nix-language)
|
- A rudimentary understanding of the [Nix language](reading-nix-language)
|
||||||
|
|
||||||
## Entering a temporary shell
|
## Entering a temporary shell
|
||||||
|
|
||||||
|
|
|
@ -8,26 +8,45 @@ myst:
|
||||||
(packaging-existing-software)=
|
(packaging-existing-software)=
|
||||||
# Packaging existing software with Nix
|
# Packaging existing software with Nix
|
||||||
|
|
||||||
One of Nix's primary use-cases is in addressing common difficulties encountered while packaging software, like managing dependencies.
|
One of Nix's primary use-cases is in addressing common difficulties encountered with packaging software, such as specifying and obtaining dependencies.
|
||||||
|
|
||||||
In the long term, Nix helps tremendously in alleviating that stress, but when *first* packaging existing software with Nix, it's common to encounter missing dependencies preventing builds from succeeding.
|
In the long term, Nix helps tremendously with alleviating such problems.
|
||||||
|
But when *first* packaging existing software with Nix, it's common to encounter errors that seem inscrutable.
|
||||||
|
|
||||||
In this tutorial, you'll create your first Nix derivations to package C/C++ software, taking advantage of the [Nixpkgs Standard Environment](https://nixos.org/manual/nixpkgs/stable/#part-stdenv) (`stdenv`) which automates much of the work of building self-contained C/C++ packages.
|
## Introduction
|
||||||
|
|
||||||
The tutorial begins by considering `hello`, an implementation of "hello world" which only requires dependencies provided by `stdenv`.
|
In this tutorial, you'll create your first [Nix derivations](https://nix.dev/manual/nix/2.18/language/derivations) to package C/C++ software, taking advantage of the [Nixpkgs Standard Environment](https://nixos.org/manual/nixpkgs/stable/#part-stdenv) (`stdenv`), which automates much of the work involved.
|
||||||
|
|
||||||
|
### What will you learn?
|
||||||
|
|
||||||
|
The tutorial begins with `hello`, an implementation of "hello world" which only requires dependencies already provided by `stdenv`.
|
||||||
Next, you will build more complex packages with their own dependencies, leading you to use additional derivation features.
|
Next, you will build more complex packages with their own dependencies, leading you to use additional derivation features.
|
||||||
|
|
||||||
You'll encounter and address Nix error messages, build failures, and a host of other issues, developing your iterative debugging techniques along the way.
|
You'll encounter and address Nix error messages, build failures, and a host of other issues, developing your iterative debugging techniques along the way.
|
||||||
|
|
||||||
:::{note}
|
### What do you need?
|
||||||
A _package_ is an informally defined Nixpkgs concept referring to a Nix derivation representing an installation of some project.
|
|
||||||
Packages have mostly standardised attributes and output layouts, allowing them to be discovered in searches and installed into environments alongside other packages.
|
|
||||||
|
|
||||||
For the purposes of this tutorial, "package" means something like "result of a derivation"; this is the artifact you or others will use, as a consequence of having "packaged existing software with Nix".
|
- Familiarity with the Unix shell and plain text editors
|
||||||
|
- You should be confident with [reading the Nix language](reading-nix-language). Feel free to go back and work through the tutorial first.
|
||||||
|
|
||||||
|
### How long does it take?
|
||||||
|
|
||||||
|
Going through all the steps carefully will take around 60 minutes.
|
||||||
|
|
||||||
|
## Your first package
|
||||||
|
|
||||||
|
:::{note}
|
||||||
|
<!--
|
||||||
|
TODO: link to the Nix manual glossary entry once it's in a released build:
|
||||||
|
https://hydra.nixos.org/job/nix/master/build.x86_64-linux/latest/download/manual/glossary.html#package
|
||||||
|
-->
|
||||||
|
A _package_ is a loosely defined concept that refers to either a collection of files and other data, or a {term}`Nix expression` representing such a collection before it comes into being.
|
||||||
|
Packages in Nixpkgs have a conventional structure, allowing them to be discovered in searches and composed in environments alongside other packages.
|
||||||
|
|
||||||
|
For the purposes of this tutorial, a "package" is a Nix language function that will evaluate to a derivation.
|
||||||
|
It will enable you or others to produce an artifact for practical use, as a consequence of having "packaged existing software with Nix".
|
||||||
:::
|
:::
|
||||||
|
|
||||||
## A simple project
|
|
||||||
To start, consider this skeleton derivation:
|
To start, consider this skeleton derivation:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
|
@ -38,37 +57,42 @@ stdenv.mkDerivation { };
|
||||||
|
|
||||||
This is a function which takes an attribute set containing `stdenv`, and produces a derivation (which currently does nothing).
|
This is a function which takes an attribute set containing `stdenv`, and produces a derivation (which currently does nothing).
|
||||||
|
|
||||||
As you progress through this tutorial, you will update this several times, adding more details while following the general pattern.
|
### A package function
|
||||||
|
|
||||||
### Hello, World!
|
|
||||||
GNU Hello is an implementation of the "hello world" program, with source code accessible [from the GNU Project's FTP server](https://ftp.gnu.org/gnu/hello/).
|
GNU Hello is an implementation of the "hello world" program, with source code accessible [from the GNU Project's FTP server](https://ftp.gnu.org/gnu/hello/).
|
||||||
|
|
||||||
To begin, you should add a `name` attribute to the set passed to `mkDerivation`; every derivation needs a name, and Nix will throw `error: derivation name missing` without one.
|
To begin, add a `name` attribute to the set passed to `mkDerivation`.
|
||||||
|
Every package needs a name and a version, and Nix will throw `error: derivation name missing` without.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
...
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
+ name = "hello";
|
+ pname = "hello";
|
||||||
...
|
+ version = "2.12.1";
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, you will download the [latest version](https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz) of `hello` using `fetchzip`, which takes the URI path to the download file and a SHA256 hash of its contents.
|
Next, you will declare a dependency on the latest version of `hello`, and instruct Nix to use `fetchzip` to download the [source code archive](https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz).
|
||||||
|
|
||||||
:::{note}
|
:::{note}
|
||||||
`fetchzip` can fetch [more archives](https://nixos.org/manual/nixpkgs/stable/#fetchurl) than just zip files!
|
`fetchzip` can fetch [more archives](https://nixos.org/manual/nixpkgs/stable/#fetchurl) than just] zip files!
|
||||||
:::
|
:::
|
||||||
|
|
||||||
The hash cannot be known until after the tarball has been downloaded and unpacked, but Nix will complain if the hash supplied to `fetchzip` was incorrect, so it is common practice to supply a fake one with `lib.fakeSha256` and change the derivation definition after Nix reports the correct hash:
|
The hash cannot be known until after the archive has been downloaded and unpacked.
|
||||||
|
Nix will complain if the hash supplied to `fetchzip` is incorrect.
|
||||||
|
It is common practice to supply a fake one with `lib.fakeSha256` and change the derivation definition after Nix reports the correct hash:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# hello.nix
|
# hello.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchzip
|
stdenv,
|
||||||
|
fetchzip,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "hello";
|
pname = "hello";
|
||||||
|
version = "2.12.1";
|
||||||
|
|
||||||
src = fetchzip {
|
src = fetchzip {
|
||||||
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz";
|
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz";
|
||||||
|
@ -77,7 +101,7 @@ stdenv.mkDerivation {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Save this file to `hello.nix` and try to build it with `nix-build`, observing your first build failure:
|
Save this file to `hello.nix` and run `nix-build` to observe your first build failure:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nix-build hello.nix
|
$ nix-build hello.nix
|
||||||
|
@ -97,22 +121,24 @@ error: cannot evaluate a function that has an argument without a value ('lib')
|
||||||
|
|
||||||
Problem: the expression in `hello.nix` is a *function*, which only produces its intended output if it is passed the correct *arguments*.
|
Problem: the expression in `hello.nix` is a *function*, which only produces its intended output if it is passed the correct *arguments*.
|
||||||
|
|
||||||
### A new command
|
### Building with `nix-build`
|
||||||
`lib` is available from `nixpkgs`, which must be imported with another Nix expression in order to pass it as an argument to this derivation.
|
|
||||||
|
|
||||||
The recommended way to do this is to create a `default.nix` in the same directory as `hello.nix`, with the following contents:
|
`lib` is available from [`nixpkgs`](https://github.com/NixOS/nixpkgs/), which must be imported with another Nix expression in order to pass it as an argument to this derivation.
|
||||||
|
|
||||||
|
The recommended way to do this is to create a `default.nix` file in the same directory as `hello.nix`, with the following contents:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# default.nix
|
# default.nix
|
||||||
let
|
let
|
||||||
pkgs = import <nixpkgs> { };
|
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-22.11";
|
||||||
|
pkgs = import nixpkgs { config = {}; overlays = []; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
hello = pkgs.callPackage ./hello.nix { };
|
hello = pkgs.callPackage ./hello.nix { };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This allows you to use `nix-build -A hello` to realize the derivation in `hello.nix`, similar to the current convention used in `nixpkgs`.
|
This allows you to run `nix-build -A hello` to realize the derivation in `hello.nix`, similar to the current convention used in Nixpkgs.
|
||||||
|
|
||||||
:::{note}
|
:::{note}
|
||||||
[`callPackage`] automatically passes attributes from `pkgs` to the given function, if they match attributes required by that function's argument attrset.
|
[`callPackage`] automatically passes attributes from `pkgs` to the given function, if they match attributes required by that function's argument attrset.
|
||||||
|
@ -141,17 +167,20 @@ error:
|
||||||
```
|
```
|
||||||
|
|
||||||
### Finding the file hash
|
### Finding the file hash
|
||||||
As expected, the incorrect file hash caused an error, and Nix helpfully provided the correct one, which you can now substitute into `hello.nix` to replace `lib.fakeSha256`:
|
As expected, the incorrect file hash caused an error, and Nix helpfully provided the correct one.
|
||||||
|
In `hello.nix`, replace `lib.fakeSha256` with the correct hash:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# hello.nix
|
# hello.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchzip
|
stdenv,
|
||||||
|
fetchzip,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "hello";
|
pname = "hello";
|
||||||
|
version = "2.12.1";
|
||||||
|
|
||||||
src = fetchzip {
|
src = fetchzip {
|
||||||
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz";
|
url = "https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz";
|
||||||
|
@ -179,7 +208,7 @@ building
|
||||||
Great news: the derivation built successfully!
|
Great news: the derivation built successfully!
|
||||||
|
|
||||||
The console output shows that `configure` was called, which produced a `Makefile` that was then used to build the project.
|
The console output shows that `configure` was called, which produced a `Makefile` that was then used to build the project.
|
||||||
It wasn't necessary to write any build instructions in this case because the `stdenv` build system is based on `autoconf`, which automatically detected the structure of the project directory.
|
It wasn't necessary to write any build instructions in this case because the `stdenv` build system is based on [GNU Autoconf](https://www.gnu.org/software/autoconf/), which automatically detected the structure of the project directory.
|
||||||
|
|
||||||
### Build result
|
### Build result
|
||||||
Check your working directory for the result:
|
Check your working directory for the result:
|
||||||
|
@ -189,7 +218,7 @@ $ ls
|
||||||
default.nix hello.nix result
|
default.nix hello.nix result
|
||||||
```
|
```
|
||||||
|
|
||||||
This `result` is a symbolic link to a Nix store location containing the built binary; you can call `./result/bin/hello` to execute this program:
|
This `result` is a [symbolic link](https://en.wikipedia.org/wiki/Symbolic_link) to a Nix store location containing the built binary; you can call `./result/bin/hello` to execute this program:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ ./result/bin/hello
|
$ ./result/bin/hello
|
||||||
|
@ -200,15 +229,17 @@ Congratulations, you have successfully packaged your first program with Nix!
|
||||||
|
|
||||||
Next, you'll package another piece of software with external-to-`stdenv` dependencies that present new challenges, requiring you to make use of more `mkDerivation` features.
|
Next, you'll package another piece of software with external-to-`stdenv` dependencies that present new challenges, requiring you to make use of more `mkDerivation` features.
|
||||||
|
|
||||||
## Something bigger
|
## A package with dependencies
|
||||||
|
|
||||||
Now you will package a somewhat more complicated program, [`icat`](https://github.com/atextor/icat), which allows you to render images in your terminal.
|
Now you will package a somewhat more complicated program, [`icat`](https://github.com/atextor/icat), which allows you to render images in your terminal.
|
||||||
|
|
||||||
To start, modify the `default.nix` from the previous section by adding a new attribute for `icat`:
|
Change the `default.nix` from the previous section by adding a new attribute for `icat`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# default.nix
|
# default.nix
|
||||||
let
|
let
|
||||||
pkgs = import <nixpkgs> { };
|
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-22.11";
|
||||||
|
pkgs = import nixpkgs { config = {}; overlays = []; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
hello = pkgs.callPackage ./hello.nix { };
|
hello = pkgs.callPackage ./hello.nix { };
|
||||||
|
@ -216,39 +247,44 @@ in
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now copy `hello.nix` to a new file, `icat.nix`, and update the `name` attribute in that file:
|
Copy `hello.nix` to a new file `icat.nix`, and update the `pname` and `version` attributes in that file:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchzip
|
stdenv,
|
||||||
|
fetchzip,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchzip {
|
src = fetchzip {
|
||||||
...
|
# ...
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now to download the source code.
|
Now to download the source code.
|
||||||
`icat`'s upstream repository is hosted on [GitHub](https://github.com/atextor/icat), so you should modify the previous [source fetcher](https://nixos.org/manual/nixpkgs/stable/#chap-pkgs-fetchers), this time using `fetchFromGitHub` instead of `fetchzip`, updating the argument attribute set to the function accordingly:
|
`icat`'s upstream repository is hosted on [GitHub](https://github.com/atextor/icat), so you should replace the previous [source fetcher](https://nixos.org/manual/nixpkgs/stable/#chap-pkgs-fetchers).
|
||||||
|
This time you will use [`fetchFromGitHub`](https://nixos.org/manual/nixpkgs/stable/#fetchfromgithub) instead of `fetchzip`, by updating the argument attribute set to the function accordingly:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchFromGitHub
|
stdenv,
|
||||||
|
fetchFromGitHub,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
...
|
# ...
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -256,19 +292,27 @@ stdenv.mkDerivation {
|
||||||
### Fetching source from GitHub
|
### Fetching source from GitHub
|
||||||
While `fetchzip` required `url` and `sha256` arguments, more are needed for [`fetchFromGitHub`](https://nixos.org/manual/nixpkgs/stable/#fetchfromgithub).
|
While `fetchzip` required `url` and `sha256` arguments, more are needed for [`fetchFromGitHub`](https://nixos.org/manual/nixpkgs/stable/#fetchfromgithub).
|
||||||
|
|
||||||
The source is hosted on GitHub at `https://github.com/atextor/icat`, which already gives the first two arguments:
|
The source is URL is `https://github.com/atextor/icat`, which already gives the first two arguments:
|
||||||
- `owner`: the name of the account controlling the repository; `owner = "atextor";`
|
- `owner`: the name of the account controlling the repository
|
||||||
- `repo`: the name of the repository to fetch; `repo = "icat";`
|
|
||||||
|
|
||||||
You can navigate to the project's [Tags page](https://github.com/atextor/icat/tags) to find a suitable `rev`, such as the git commit hash or tag (e.g. `v1.0`) corresponding to the release you want to fetch.
|
```
|
||||||
|
owner = "atextor";
|
||||||
|
```
|
||||||
|
- `repo`: the name of the repository to fetch
|
||||||
|
|
||||||
|
```
|
||||||
|
repo = "icat";
|
||||||
|
``````
|
||||||
|
|
||||||
|
Navigate to the project's [Tags page](https://github.com/atextor/icat/tags) to find a suitable [Git revision](https://git-scm.com/docs/revisions) (`rev`), such as the Git commit hash or tag (e.g. `v1.0`) corresponding to the release you want to fetch.
|
||||||
|
|
||||||
In this case, the latest release tag is `v0.5`.
|
In this case, the latest release tag is `v0.5`.
|
||||||
|
|
||||||
As in the `hello` example, a hash must also be supplied.
|
As in the `hello` example, a hash must also be supplied.
|
||||||
|
|
||||||
This time, instead of using `lib.fakeSha256` and letting `nix-build` report the correct one in an error, you can fetch the correct hash in the first place with the `nix-prefetch-url` command.
|
This time, instead of using `lib.fakeSha256` and letting `nix-build` report the correct one in an error, you can fetch the correct hash in the first place with the `nix-prefetch-url` command.
|
||||||
|
|
||||||
You need the SHA256 hash of the *contents* of the tarball (as opposed to the hash of the tarball file itself), so you will need to pass the `--unpack` and `--type sha256` arguments too:
|
You need the SHA256 hash of the *contents* of the tarball (as opposed to the hash of the tarball file itself).
|
||||||
|
Therefore pass the `--unpack` and `--type sha256` arguments:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nix-prefetch-url --unpack https://github.com/atextor/icat/archive/refs/tags/v0.5.tar.gz --type sha256
|
$ nix-prefetch-url --unpack https://github.com/atextor/icat/archive/refs/tags/v0.5.tar.gz --type sha256
|
||||||
|
@ -276,17 +320,19 @@ path is '/nix/store/p8jl1jlqxcsc7ryiazbpm7c1mqb6848b-v0.5.tar.gz'
|
||||||
0wyy2ksxp95vnh71ybj1bbmqd5ggp13x3mk37pzr99ljs9awy8ka
|
0wyy2ksxp95vnh71ybj1bbmqd5ggp13x3mk37pzr99ljs9awy8ka
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can supply the correct hash to `fetchFromGitHub`:
|
Set the correct hash for `fetchFromGitHub`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchFromGitHub
|
stdenv,
|
||||||
|
fetchFromGitHub,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "atextor";
|
owner = "atextor";
|
||||||
|
@ -298,7 +344,8 @@ stdenv.mkDerivation {
|
||||||
```
|
```
|
||||||
|
|
||||||
### Missing dependencies
|
### Missing dependencies
|
||||||
Running `nix-build` with the new `icat` attribute, an entirely new issue is reported:
|
|
||||||
|
Running `nix-build` with the new `icat` attribute, an entirely new issue is reported:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nix-build -A icat
|
$ nix-build -A icat
|
||||||
|
@ -324,20 +371,23 @@ error: builder for '/nix/store/l5wz9inkvkf0qhl8kpl39vpg2xfm2qpy-icat.drv' failed
|
||||||
A compiler error!
|
A compiler error!
|
||||||
The `icat` source was pulled from GitHub, and Nix tried to build what it found, but compilation failed due to a missing dependency: the `imlib2` header.
|
The `icat` source was pulled from GitHub, and Nix tried to build what it found, but compilation failed due to a missing dependency: the `imlib2` header.
|
||||||
|
|
||||||
If you [search for `imlib2` on search.nixos.org](https://search.nixos.org/packages?channel=23.05&from=0&size=50&sort=relevance&type=packages&query=imlib2), you'll find that `imlib2` is already in `nixpkgs`.
|
If you [search for `imlib2` on search.nixos.org](https://search.nixos.org/packages?query=imlib2), you'll find that `imlib2` is already in Nixpkgs.
|
||||||
|
|
||||||
You can add this package to your build environment by adding `imlib2` to the set of inputs to the expression in `icat.nix`, and then adding `imlib2` to the list of `buildInputs` in `stdenv.mkDerivation`:
|
Add this package to your build environment by adding `imlib2` to the arguments of the function in `icat.nix`.
|
||||||
|
Then add the argument's value `imlib2` to the list of `buildInputs` in `stdenv.mkDerivation`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchFromGitHub
|
stdenv,
|
||||||
, imlib2
|
fetchFromGitHub,
|
||||||
|
imlib2,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "atextor";
|
owner = "atextor";
|
||||||
|
@ -372,30 +422,99 @@ error: builder for '/nix/store/bw2d4rp2k1l5rg49hds199ma2mz36x47-icat.drv' failed
|
||||||
For full logs, run 'nix log /nix/store/bw2d4rp2k1l5rg49hds199ma2mz36x47-icat.drv'.
|
For full logs, run 'nix log /nix/store/bw2d4rp2k1l5rg49hds199ma2mz36x47-icat.drv'.
|
||||||
```
|
```
|
||||||
|
|
||||||
You can see a few warnings which should be corrected in the upstream code, but the important bit for this tutorial is `fatal error: X11/Xlib.h: No such file or directory`: another dependency is missing.
|
You can see a few warnings which should be corrected in the upstream code.
|
||||||
|
But the important bit for this tutorial is `fatal error: X11/Xlib.h: No such file or directory`: another dependency is missing.
|
||||||
|
|
||||||
|
## Finding packages
|
||||||
|
|
||||||
:::{note}
|
Determining from where to source a dependency is currently a somewhat involved, because package names don't always correspond to library or program names.
|
||||||
Determining from where to source a dependency is currently a somewhat-involved process: it helps to become familiar with searching the `nixpkgs` source for keywords.
|
|
||||||
|
|
||||||
Consider using `nix-locate` from the [`nix-index`](https://github.com/nix-community/nix-index) tool to find derivations that provide what you need.
|
|
||||||
:::
|
|
||||||
|
|
||||||
You will need the `Xlib.h` headers from the `X11` C package, the Nixpkgs derivation for which is `libX11`, available in the `xorg` package set.
|
You will need the `Xlib.h` headers from the `X11` C package, the Nixpkgs derivation for which is `libX11`, available in the `xorg` package set.
|
||||||
|
There are multiple ways to figure this out:
|
||||||
|
|
||||||
|
### `search.nixos.org`
|
||||||
|
|
||||||
|
:::{tip}
|
||||||
|
The easiest way to find what you need is on search.nixos.org/packages.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Unfortunately in this case, [searching for `x11`](https://search.nixos.org/packages?query=x11) produces too many irrelevant results because X11 is ubiquitous.
|
||||||
|
On the left side bar there is a list package sets, and [selecting `xorg`](https://search.nixos.org/packages?channel=23.11&buckets={%22package_attr_set%22%3A[%22xorg%22]%2C%22package_license_set%22%3A[]%2C%22package_maintainers_set%22%3A[]%2C%22package_platforms%22%3A[]}&query=x11) shows something promising.
|
||||||
|
|
||||||
|
In case all else fails, it helps to become familiar with searching the [Nixpkgs source code](https://github.com/nixos/nixpkgs) for keywords.
|
||||||
|
|
||||||
|
### Git and `rg`
|
||||||
|
|
||||||
|
To find name assignments in the source, search for `"<keyword> ="`.
|
||||||
|
For example, these are the search results for [`"x11 = "`](https://github.com/search?q=repo%3ANixOS%2Fnixpkgs+%22x11+%3D%22&type=code) or [`"libx11 ="`](https://github.com/search?q=repo%3ANixOS%2Fnixpkgs+%22libx11+%3D%22&type=code) on Github .
|
||||||
|
|
||||||
|
Or fetch a local clone of the repository and use `rg`.
|
||||||
|
Nixpkgs is huge.
|
||||||
|
Only clone the latest revision if you don't want to wait a long time:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ nix-shell -p git ripgrep
|
||||||
|
[nix-shell:~]$ git glone https://github.com/NixOS/nixpkgs --depth 1
|
||||||
|
```
|
||||||
|
|
||||||
|
To narrow down results, specify which subdirectory you want to search:
|
||||||
|
|
||||||
|
```console
|
||||||
|
[nix-shell:~]$ rg "x11 =" pkgs
|
||||||
|
pkgs/tools/X11/primus/default.nix
|
||||||
|
21: primus = if useNvidia then primusLib_ else primusLib_.override { nvidia_x11 = null; };
|
||||||
|
22: primus_i686 = if useNvidia then primusLib_i686_ else primusLib_i686_.override { nvidia_x11 = null; };
|
||||||
|
|
||||||
|
pkgs/applications/graphics/imv/default.nix
|
||||||
|
38: x11 = [ libGLU xorg.libxcb xorg.libX11 ];
|
||||||
|
|
||||||
|
pkgs/tools/X11/primus/lib.nix
|
||||||
|
14: if nvidia_x11 == null then libGL
|
||||||
|
|
||||||
|
pkgs/top-level/linux-kernels.nix
|
||||||
|
573: ati_drivers_x11 = throw "ati drivers are no longer supported by any kernel >=4.1"; # added 2021-05-18;
|
||||||
|
... <a lot more results>
|
||||||
|
```
|
||||||
|
|
||||||
|
Since `rg` is case sensitive by default,
|
||||||
|
Add `-i` to make sure you don't miss anything:
|
||||||
|
|
||||||
|
```
|
||||||
|
[nix-shell:~]$ rg -i "libx11 =" pkgs
|
||||||
|
pkgs/applications/version-management/monotone-viz/graphviz-2.0.nix
|
||||||
|
55: ++ lib.optional (libX11 == null) "--without-x";
|
||||||
|
|
||||||
|
pkgs/top-level/all-packages.nix
|
||||||
|
14191: libX11 = xorg.libX11;
|
||||||
|
|
||||||
|
pkgs/servers/x11/xorg/default.nix
|
||||||
|
1119: libX11 = callPackage ({ stdenv, pkg-config, fetchurl, xorgproto, libpthreadstubs, libxcb, xtrans, testers }: stdenv.mkDerivation (finalAttrs: {
|
||||||
|
|
||||||
|
pkgs/servers/x11/xorg/overrides.nix
|
||||||
|
147: libX11 = super.libX11.overrideAttrs (attrs: {
|
||||||
|
```
|
||||||
|
|
||||||
|
### `nix-locate`
|
||||||
|
|
||||||
|
Consider using `nix-locate` from the [`nix-index`](https://github.com/nix-community/nix-index) tool to find derivations that provide what you need.
|
||||||
|
|
||||||
|
### Adding package sets as dependencies
|
||||||
|
|
||||||
Add this to your derivation's input attribute set and to `buildInputs`:
|
Add this to your derivation's input attribute set and to `buildInputs`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchFromGitHub
|
stdenv,
|
||||||
, imlib2
|
fetchFromGitHub,
|
||||||
, xorg
|
imlib2,
|
||||||
|
xorg,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "atextor";
|
owner = "atextor";
|
||||||
|
@ -414,7 +533,10 @@ Only add the top-level `xorg` derivation to the input attrset, rather than the f
|
||||||
Because Nix is lazily-evaluated, using `xorg.libX11` means that we only include the `libX11` attribute and the derivation doesn't actually include all of `xorg` into the build context.
|
Because Nix is lazily-evaluated, using `xorg.libX11` means that we only include the `libX11` attribute and the derivation doesn't actually include all of `xorg` into the build context.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
## Fixing build failures
|
||||||
|
|
||||||
Run the last command again:
|
Run the last command again:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ nix-build -A icat
|
$ nix-build -A icat
|
||||||
this derivation will be built:
|
this derivation will be built:
|
||||||
|
@ -438,28 +560,36 @@ error: builder for '/nix/store/x1d79ld8jxqdla5zw2b47d2sl87mf56k-icat.drv' failed
|
||||||
The missing dependency error is solved, but there is now another problem: `make: *** No rule to make target 'install'. Stop.`
|
The missing dependency error is solved, but there is now another problem: `make: *** No rule to make target 'install'. Stop.`
|
||||||
|
|
||||||
### `installPhase`
|
### `installPhase`
|
||||||
The `stdenv` is automatically working with the `Makefile` that comes with `icat`: you can see in the console output that `configure` and `make` are executed without issue, so the `icat` binary is compiling successfully.
|
`stdenv` is automatically working with the `Makefile` that comes with `icat`.
|
||||||
|
The console output showas that `configure` and `make` are executed without issue, so the `icat` binary is compiling successfully.
|
||||||
|
|
||||||
The failure occurs when the `stdenv` attempts to run `make install`: the `Makefile` included in the project happens to lack an `install` target, and the `README` in the `icat` repository only mentions using `make` to build the tool, leaving the installation step up to users.
|
The failure occurs when the `stdenv` attempts to run `make install`.
|
||||||
|
The `Makefile` included in the project happens to lack an `install` target.
|
||||||
|
The `README` in the `icat` repository only mentions using `make` to build the tool, leaving the installation step up to users.
|
||||||
|
|
||||||
To add this step to your derivation, use the [`installPhase` attribute](https://nixos.org/manual/nixpkgs/stable/#ssec-install-phase), which contains a list of command strings to execute to perform the installation.
|
To add this step to your derivation, use the [`installPhase` attribute](https://nixos.org/manual/nixpkgs/stable/#ssec-install-phase).
|
||||||
|
It contains a list of command strings that are executed to perform the installation.
|
||||||
|
|
||||||
Because the `make` step completes successfully, the `icat` executable is available in the build directory, and you only need to copy it from there to the output directory.
|
Because `make` finishes successfully, the `icat` executable is available in the build directory.
|
||||||
|
You only need to copy it from there to the output directory.
|
||||||
|
|
||||||
In Nix, the output directory is stored in the `$out` variable, accessible in the derivation's component scripts.
|
In Nix, the output directory is stored in the `$out` variable.
|
||||||
|
That variable is accessible in the derivation's [`builder` execution environment](https://nix.dev/manual/nix/2.19/language/derivations#builder-execution).
|
||||||
Create a `bin` directory within the `$out` directory and copy the `icat` binary there:
|
Create a `bin` directory within the `$out` directory and copy the `icat` binary there:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
{ lib
|
{
|
||||||
, stdenv
|
lib,
|
||||||
, fetchFromGitHub
|
stdenv,
|
||||||
, imlib2
|
fetchFromGitHub,
|
||||||
, xorg
|
imlib2,
|
||||||
|
xorg,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "icat";
|
pname = "icat";
|
||||||
|
version = "v0.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "atextor";
|
owner = "atextor";
|
||||||
|
@ -478,35 +608,45 @@ stdenv.mkDerivation {
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phases and hooks
|
### Phases and hooks
|
||||||
Nixpkgs `stdenv.mkDerivation` derivations are separated into [phases](https://nixos.org/manual/nixpkgs/stable/#sec-stdenv-phases), each of which is intended to control some aspect of the build process.
|
|
||||||
|
|
||||||
You saw earlier how `stdenv.mkDerivation` expected the project's `Makefile` to have an `install` target, and failed when it didn't.
|
Nixpkgs `stdenv.mkDerivation` derivations are separated into [phases](https://nixos.org/manual/nixpkgs/stable/#sec-stdenv-phases).
|
||||||
|
Each is intended to control some aspect of the build process.
|
||||||
|
|
||||||
|
Earlier you observed how `stdenv.mkDerivation` expected the project's `Makefile` to have an `install` target, and failed when it didn't.
|
||||||
To fix this, you defined a custom `installPhase` containing instructions for copying the `icat` binary to the correct output location, in effect installing it.
|
To fix this, you defined a custom `installPhase` containing instructions for copying the `icat` binary to the correct output location, in effect installing it.
|
||||||
|
|
||||||
Up to that point, the `stdenv.mkDerivation` automatically determined the `buildPhase` information for the `icat` package.
|
Up to that point, the `stdenv.mkDerivation` automatically determined the `buildPhase` information for the `icat` package.
|
||||||
|
|
||||||
During derivation realisation, there are a number of shell functions ("hooks", in `nixpkgs`) which may execute in each derivation phase, which do things like set variables, source files, create directories, and so on.
|
During derivation realisation, there are a number of shell functions ("hooks", in Nixpkgs) which may execute in each derivation phase.
|
||||||
|
Hooks do things like set variables, source files, create directories, and so on.
|
||||||
|
|
||||||
These are specific to each phase, and run both before and after that phase's execution, controlling the build environment and helping to prevent environment-modifying behavior defined within packages from creating sources of nondeterminism within and between Nix derivations.
|
These are specific to each phase, and run both before and after that phase's execution.
|
||||||
|
They modify the build environment for common operations during the build.
|
||||||
|
|
||||||
It's good practice when packaging software with Nix to include calls to these hooks in the derivation phases you define, even when you don't make direct use of them; this facilitates easy [overriding](https://nixos.org/manual/nixpkgs/stable/#chap-overrides) of specific parts of the derivation later, in addition to the previously-mentioned reproducibility benefits.
|
It's good practice when packaging software with Nix to include calls to these hooks in the derivation phases you define, even when you don't make direct use of them.
|
||||||
|
This facilitates easy [overriding](https://nixos.org/manual/nixpkgs/stable/#chap-overrides) of specific parts of the derivation later.
|
||||||
|
And it keeps the code tidy and makes it easier to read.
|
||||||
|
|
||||||
You should now adjust your `installPhase` to call the appropriate hooks:
|
Adjust your `installPhase` to call the appropriate hooks:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
# icat.nix
|
# icat.nix
|
||||||
...
|
|
||||||
|
# ...
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
runHook preInstall
|
runHook preInstall
|
||||||
mkdir -p $out/bin
|
mkdir -p $out/bin
|
||||||
cp icat $out/bin
|
cp icat $out/bin
|
||||||
runHook postInstall
|
runHook postInstall
|
||||||
'';
|
'';
|
||||||
...
|
|
||||||
|
# ...
|
||||||
|
|
||||||
```
|
```
|
||||||
### A successful build
|
## A successful build
|
||||||
Running the `nix-build` command once more will finally do what you want, and more safely than before; you can `ls` in the local directory to find a `result` symlink to a location in the Nix store:
|
|
||||||
|
Running the `nix-build` command once more will finally do what you want, repeatably.
|
||||||
|
Call `ls` in the local directory to find a `result` symlink to a location in the Nix store:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ ls
|
$ ls
|
||||||
|
@ -524,6 +664,9 @@ default.nix hello.nix icat.nix result
|
||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
|
|
||||||
|
- [Add your own new packages to Nixpkgs](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md)
|
||||||
|
- [](../contributing/how-to-contribute.md)
|
||||||
|
- [](../contributing/how-to-get-help.md)
|
||||||
- [](sharing-dependencies)
|
- [](sharing-dependencies)
|
||||||
- [](automatic-direnv)
|
- [](automatic-direnv)
|
||||||
- [](python-dev-environment)
|
- [](python-dev-environment)
|
||||||
|
|
Loading…
Reference in a new issue