nix-book/index.html
Amy de Buitléir c015c357fe temp
2025-10-14 11:04:01 +01:00

5978 lines
No EOL
260 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.23">
<meta name="author" content="Amy de Buitléir">
<title>Wombat&#8217;s Book of Nix</title>
<style>
@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";
@import "https://cdn.jsdelivr.net/gh/asciidoctor/asciidoctor@2.0/data/stylesheets/asciidoctor-default.css";
.highlight01 {background: #66ffff}
.highlight02 {background: #b3ff66}
.highlight03 {background: #ffd966}
.highlight04 {background: #b366ff}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
pre.pygments .hll { background-color: #ffffcc }
pre.pygments { background: #f8f8f8; }
pre.pygments .tok-c { color: #3D7B7B; font-style: italic } /* Comment */
pre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */
pre.pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */
pre.pygments .tok-o { color: #666666 } /* Operator */
pre.pygments .tok-ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
pre.pygments .tok-cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
pre.pygments .tok-cp { color: #9C6500 } /* Comment.Preproc */
pre.pygments .tok-cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
pre.pygments .tok-c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
pre.pygments .tok-cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
pre.pygments .tok-gd { color: #A00000 } /* Generic.Deleted */
pre.pygments .tok-ge { font-style: italic } /* Generic.Emph */
pre.pygments .tok-ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
pre.pygments .tok-gr { color: #E40000 } /* Generic.Error */
pre.pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */
pre.pygments .tok-gi { color: #008400 } /* Generic.Inserted */
pre.pygments .tok-go { color: #717171 } /* Generic.Output */
pre.pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
pre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */
pre.pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
pre.pygments .tok-gt { color: #0044DD } /* Generic.Traceback */
pre.pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
pre.pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
pre.pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
pre.pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */
pre.pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
pre.pygments .tok-kt { color: #B00040 } /* Keyword.Type */
pre.pygments .tok-m { color: #666666 } /* Literal.Number */
pre.pygments .tok-s { color: #BA2121 } /* Literal.String */
pre.pygments .tok-na { color: #687822 } /* Name.Attribute */
pre.pygments .tok-nb { color: #008000 } /* Name.Builtin */
pre.pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */
pre.pygments .tok-no { color: #880000 } /* Name.Constant */
pre.pygments .tok-nd { color: #AA22FF } /* Name.Decorator */
pre.pygments .tok-ni { color: #717171; font-weight: bold } /* Name.Entity */
pre.pygments .tok-ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
pre.pygments .tok-nf { color: #0000FF } /* Name.Function */
pre.pygments .tok-nl { color: #767600 } /* Name.Label */
pre.pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
pre.pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */
pre.pygments .tok-nv { color: #19177C } /* Name.Variable */
pre.pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
pre.pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */
pre.pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */
pre.pygments .tok-mf { color: #666666 } /* Literal.Number.Float */
pre.pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */
pre.pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */
pre.pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */
pre.pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */
pre.pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */
pre.pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */
pre.pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */
pre.pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
pre.pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */
pre.pygments .tok-se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
pre.pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */
pre.pygments .tok-si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
pre.pygments .tok-sx { color: #008000 } /* Literal.String.Other */
pre.pygments .tok-sr { color: #A45A77 } /* Literal.String.Regex */
pre.pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */
pre.pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */
pre.pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */
pre.pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */
pre.pygments .tok-vc { color: #19177C } /* Name.Variable.Class */
pre.pygments .tok-vg { color: #19177C } /* Name.Variable.Global */
pre.pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */
pre.pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */
pre.pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
</head>
<body class="book toc2 toc-left">
<div id="header">
<h1>Wombat&#8217;s Book of Nix</h1>
<div class="details">
<span id="author" class="author">Amy de Buitléir</span><br>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_acknowledgments">Acknowledgments</a></li>
<li><a href="#_introduction">1. Introduction</a>
<ul class="sectlevel2">
<li><a href="#_why_nix">1.1. Why Nix?</a></li>
<li><a href="#_why_flakes">1.2. Why <em>flakes</em>?</a></li>
<li><a href="#_prerequisites">1.3. Prerequisites</a></li>
<li><a href="#_see_an_error_have_a_suggestion_or_want_more">1.4. See an error? Have a suggestion? Or want more?</a></li>
</ul>
</li>
<li><a href="#_the_nix_language">2. The Nix language</a>
<ul class="sectlevel2">
<li><a href="#_introducing_the_nix_language">2.1. Introducing the Nix language</a></li>
<li><a href="#_data_types">2.2. Data types</a>
<ul class="sectlevel3">
<li><a href="#type-string">2.2.1. Strings</a></li>
<li><a href="#type-integer">2.2.2. Integers</a></li>
<li><a href="#type-float">2.2.3. Floating point numbers</a></li>
<li><a href="#type-boolean">2.2.4. Boolean</a></li>
<li><a href="#type-path">2.2.5. Paths</a></li>
<li><a href="#type-list">2.2.6. Lists</a></li>
<li><a href="#type-set">2.2.7. Attribute sets</a></li>
<li><a href="#type-lambda">2.2.8. Functions</a></li>
<li><a href="#type-derivation">2.2.9. Derivations</a></li>
</ul>
</li>
<li><a href="#_stop_reading_this_chapter">2.3. Stop reading this chapter!</a></li>
<li><a href="#_the_nix_repl">2.4. The Nix REPL</a></li>
<li><a href="#_variables">2.5. Variables</a>
<ul class="sectlevel3">
<li><a href="#_assignment">2.5.1. Assignment</a></li>
<li><a href="#_immutability">2.5.2. Immutability</a></li>
</ul>
</li>
<li><a href="#_numeric_operations">2.6. Numeric operations</a>
<ul class="sectlevel3">
<li><a href="#_arithmetic_operators">2.6.1. Arithmetic operators</a></li>
<li><a href="#_floating_point_calculations">2.6.2. Floating-point calculations</a></li>
</ul>
</li>
<li><a href="#_string_operations">2.7. String operations</a>
<ul class="sectlevel3">
<li><a href="#_string_comparison">2.7.1. String comparison</a></li>
<li><a href="#_string_concatenation">2.7.2. String concatenation</a></li>
<li><a href="#_string_interpolation">2.7.3. String interpolation</a></li>
<li><a href="#_useful_built_in_functions_for_strings">2.7.4. Useful built-in functions for strings</a></li>
</ul>
</li>
<li><a href="#_boolean_operations">2.8. Boolean operations</a></li>
<li><a href="#_path_operations">2.9. Path operations</a>
<ul class="sectlevel3">
<li><a href="#_concatenating_paths">2.9.1. Concatenating paths</a></li>
<li><a href="#_concatenating_a_path_a_string">2.9.2. Concatenating a path + a string</a></li>
<li><a href="#_concatenating_a_string_a_path">2.9.3. Concatenating a string + a path</a></li>
<li><a href="#_useful_built_in_functions_for_paths">2.9.4. Useful built-in functions for paths</a></li>
</ul>
</li>
<li><a href="#_list_operations">2.10. List operations</a>
<ul class="sectlevel3">
<li><a href="#_list_concatenation">2.10.1. List concatenation</a></li>
<li><a href="#_useful_built_in_functions_for_lists">2.10.2. Useful built-in functions for lists</a></li>
</ul>
</li>
<li><a href="#_attribute_set_operations">2.11. Attribute set operations</a>
<ul class="sectlevel3">
<li><a href="#_selection">2.11.1. Selection</a></li>
<li><a href="#_query">2.11.2. Query</a></li>
<li><a href="#_union">2.11.3. Union</a></li>
<li><a href="#rec-attrset">2.11.4. Recursive attribute sets</a></li>
<li><a href="#_useful_built_in_functions_for_attribute_sets">2.11.5. Useful built-in functions for attribute sets</a></li>
</ul>
</li>
<li><a href="#functions">2.12. Functions</a>
<ul class="sectlevel3">
<li><a href="#_anonymous_functions">2.12.1. Anonymous functions</a></li>
<li><a href="#_named_functions_and_function_application">2.12.2. Named functions and function application</a></li>
<li><a href="#_multiple_parameters_using_nested_functions">2.12.3. Multiple parameters using nested functions</a></li>
<li><a href="#_multiple_parameters_using_attribute_sets">2.12.4. Multiple parameters using attribute sets</a></li>
</ul>
</li>
<li><a href="#argument-sets">2.13. Argument sets</a>
<ul class="sectlevel3">
<li><a href="#_set_patterns">2.13.1. Set patterns</a></li>
<li><a href="#_optional_parameters">2.13.2. Optional parameters</a></li>
<li><a href="#_variadic_attributes">2.13.3. Variadic attributes</a></li>
<li><a href="#at-patterns">2.13.4. @-patterns</a></li>
</ul>
</li>
<li><a href="#derivations">2.14. Derivations</a>
<ul class="sectlevel3">
<li><a href="#_instantiation_vs_realisation">2.14.1. Instantiation vs Realisation</a></li>
<li><a href="#_instantiate_evaluate_a_derivation">2.14.2. Instantiate (evaluate) a derivation</a></li>
<li><a href="#_find_out_where_the_package_would_be_or_was_installed">2.14.3. Find out where the package would be (or was) installed</a></li>
<li><a href="#_build_realise_a_derivation">2.14.4. Build (realise) a derivation.</a></li>
<li><a href="#_remove_a_derivation">2.14.5. Remove a derivation</a></li>
</ul>
</li>
<li><a href="#_if_expressions">2.15. If expressions</a></li>
<li><a href="#_let_expressions">2.16. Let expressions</a></li>
<li><a href="#_with_expressions">2.17. With expressions</a></li>
<li><a href="#_inherit">2.18. Inherit</a></li>
<li><a href="#_import">2.19. Import</a></li>
</ul>
</li>
<li><a href="#_nixpkgs">3. Nixpkgs</a>
<ul class="sectlevel2">
<li><a href="#genAttrs">3.1. <code>lib.genAttrs</code></a></li>
<li><a href="#getExe">3.2. <code>lib.getExe</code> and <code>lib.getExe'</code></a></li>
<li><a href="#flakeExposed">3.3. <code>lib.systems.flakeExposed</code></a></li>
<li><a href="#mkShell">3.4. <code>pkgs.mkShell</code> and <code>pkgs.mkShellNoCC</code></a></li>
<li><a href="#mkDerivation">3.5. <code>stdenv.mkDerivation</code></a></li>
</ul>
</li>
<li><a href="#_hello_flake">4. Hello, flake!</a>
<ul class="sectlevel2">
<li><a href="#_flake_outputs">4.1. Flake outputs</a></li>
</ul>
</li>
<li><a href="#_the_hello_flake_repo">5. The hello-flake repo</a></li>
<li><a href="#_flake_structure">6. Flake structure</a>
<ul class="sectlevel2">
<li><a href="#flake-inputs">6.1. Inputs</a></li>
<li><a href="#flake-outputs">6.2. Outputs</a></li>
</ul>
</li>
<li><a href="#_a_generic_flake">7. A generic flake</a></li>
<li><a href="#_another_look_at_hello_flake">8. Another look at hello-flake</a>
<ul class="sectlevel2">
<li><a href="#standard-environment">8.1. The Nix standard environment</a></li>
</ul>
</li>
<li><a href="#_a_new_flake_from_scratch">9. A new flake from scratch</a>
<ul class="sectlevel2">
<li><a href="#_haskell">9.1. Haskell</a>
<ul class="sectlevel3">
<li><a href="#_a_simple_haskell_program">9.1.1. A simple Haskell program</a></li>
<li><a href="#_running_the_program_manually_optional">9.1.2. Running the program manually (optional)</a>
<ul class="sectlevel4">
<li><a href="#_some_unsuitable_shells">Some unsuitable shells</a></li>
<li><a href="#_a_suitable_shell_for_a_quick_test">A suitable shell for a quick test</a></li>
</ul>
</li>
<li><a href="#_the_cabal_file">9.1.3. The cabal file</a></li>
<li><a href="#_building_the_program_manually_optional">9.1.4. Building the program manually (optional)</a></li>
<li><a href="#haskell-flake">9.1.5. The Nix flake</a></li>
<li><a href="#_building_the_program">9.1.6. Building the program</a></li>
<li><a href="#_running_the_program">9.1.7. Running the program</a></li>
</ul>
</li>
<li><a href="#_python">9.2. Python</a>
<ul class="sectlevel3">
<li><a href="#_a_simple_python_program">9.2.1. A simple Python program</a></li>
<li><a href="#_running_the_program_manually_optional_2">9.2.2. Running the program manually (optional)</a></li>
<li><a href="#_configuring_setuptools">9.2.3. Configuring setuptools</a></li>
<li><a href="#_building_the_program_manually_optional_2">9.2.4. Building the program manually (optional)</a></li>
<li><a href="#python-flake">9.2.5. The Nix flake</a></li>
<li><a href="#_building_the_program_2">9.2.6. Building the program</a></li>
<li><a href="#_running_the_program_2">9.2.7. Running the program</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_recipes">10. Recipes</a>
<ul class="sectlevel2">
<li><a href="#_running_programs_directly_without_installing_them">10.1. Running programs directly (without installing them)</a>
<ul class="sectlevel3">
<li><a href="#_run_a_top_level_package_from_the_nixpkgsnixos_repo">10.1.1. Run a top level package from the Nixpkgs/NixOS repo</a></li>
<li><a href="#flakeref">10.1.2. Run a flake</a>
<ul class="sectlevel4">
<li><a href="#_run_a_flake_defined_in_a_local_file">Run a flake defined in a local file</a></li>
<li><a href="#_run_a_flake_defined_in_a_remote_git_repo">Run a flake defined in a remote git repo</a></li>
<li><a href="#_run_a_flake_defined_in_a_zip_archive">Run a flake defined in a zip archive</a></li>
<li><a href="#_run_a_flake_defined_in_a_compressed_tar_archive">Run a flake defined in a compressed tar archive</a></li>
<li><a href="#_run_other_types_of_flake_references">Run other types of flake references</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_ad_hoc_environments">10.2. Ad hoc environments</a>
<ul class="sectlevel3">
<li><a href="#_access_a_top_level_package_from_the_nixpkgsnixos_repo">10.2.1. Access a top level package from the Nixpkgs/NixOS repo</a></li>
<li><a href="#_access_a_flake">10.2.2. Access a flake</a></li>
</ul>
</li>
<li><a href="#shebang">10.3. Scripts</a>
<ul class="sectlevel3">
<li><a href="#_access_a_top_level_package_from_the_nixpkgsnixos_repo_2">10.3.1. Access a top level package from the Nixpkgs/NixOS repo</a></li>
<li><a href="#_access_a_flake_2">10.3.2. Access a flake</a></li>
<li><a href="#_access_a_haskell_library_package_in_the_nixpkgs_repo_without_a_cabal_file">10.3.3. Access a Haskell library package in the nixpkgs repo (without a <code>.cabal</code> file)</a></li>
<li><a href="#_access_a_python_library_package_in_the_nixpkgs_repo_without_using_a_python_builder">10.3.4. Access a Python library package in the nixpkgs repo (without using a Python builder)</a></li>
</ul>
</li>
<li><a href="#_development_environments">10.4. Development environments</a>
<ul class="sectlevel3">
<li><a href="#_access_a_top_level_package_from_the_nixpkgsnixos_repo_3">10.4.1. Access a top level package from the Nixpkgs/NixOS repo</a></li>
<li><a href="#_access_a_flake_3">10.4.2. Access a flake</a></li>
<li><a href="#_access_a_haskell_library_package_in_the_nixpkgs_repo_without_using_a_cabal_file">10.4.3. Access a Haskell library package in the nixpkgs repo (without using a <code>.cabal</code> file)</a></li>
<li><a href="#_set_an_environment_variable">10.4.4. Set an environment variable</a></li>
<li><a href="#devshell-nix-non-flake">10.4.5. Access a non-flake package (not in nixpkgs)</a>
<ul class="sectlevel4">
<li><a href="#devshell-pure">If the nix derivation does not require nixpkgs</a></li>
<li><a href="#devshell-impure">If the nix derivation requires <code>nixpkgs</code></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_buildruntime_environments">10.5. Build/runtime environments</a>
<ul class="sectlevel3">
<li><a href="#_access_a_flake_4">10.5.1. Access a flake</a></li>
<li><a href="#_access_a_haskell_library_package_in_the_nixpkgs_repo">10.5.2. Access a Haskell library package in the nixpkgs repo</a></li>
<li><a href="#_access_to_a_haskell_package_defined_in_a_flake">10.5.3. Access to a Haskell package defined in a flake</a></li>
<li><a href="#_access_a_non_flake_package_not_in_nixpkgs">10.5.4. Access a non-flake package (not in nixpkgs)</a></li>
</ul>
</li>
<li><a href="#_an_old_style_nix_shell_with_access_to_a_flake">10.6. An (old-style) Nix shell with access to a flake</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="images/wombat.svg" alt="wombat reclining against a lambda">
</div>
</div>
<div class="paragraph">
<p>This book is available
<a href="https://mhwombat.codeberg.page/nix-book/">online</a>
and as a downloadable
<a href="https://codeberg.org/mhwombat/nix-book/raw/branch/pages/wombats-book-of-nix.pdf">PDF</a>.</p>
</div>
<div class="paragraph">
<p><em>Last updated 2025-10-14 at 11:02:03 IST</em>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_acknowledgments">Acknowledgments</h2>
<div class="sectionbody">
<div class="paragraph">
<p>I would like to thank the patient people on the
<a href="https://discourse.nixos.org/">NixOS Discourse Forum</a>
who answered my many questions,
especially <code>cdepillabout</code>, <code>FedericoSchonborn</code>, <code>tejing</code> and <code>smkuehnhold</code>.
Any mistakes in this book are my own, however.</p>
</div>
<div class="paragraph">
<p>I would also like to thank Luca Bruno (aka Lethalman).
Although I have never interacted with them personally,
I learned a great deal from
their series of tutorials called <a href="https://nixos.org/guides/nix-pills/">Nix pills</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_introduction">1. Introduction</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_why_nix">1.1. Why Nix?</h3>
<div class="paragraph">
<p>If you&#8217;ve opened this PDF, you already have your own motivation for
learning Nix. Here&#8217;s how it helps me. As a researcher, I tend to work on
a series of short-term projects, mostly demos and prototypes. For each
one, I typically develop some software using a compiler, often with some
open source libraries. Often I use other tools to analyse data or
generate documentation, for example.</p>
</div>
<div class="paragraph">
<p>Problems would arise when handing off the project to colleagues; they
would report errors when trying to build or run the project. Belatedly I
would realise that my code relies on a library that they need to
install. Or perhaps they had installed the library, but the version
they&#8217;re using is incompatible.</p>
</div>
<div class="paragraph">
<p>Using containers helped with the problem. However, I didn&#8217;t want to
<em>develop</em> in a container. I did all my development in my nice, familiar,
environment with my custom aliases and shell prompt. and <em>then</em> I
containerised the software. This added step was annoying for me, and if
my colleague wanted to do some additional development, they would
probably extract all of the source code from the container first anyway.
Containers are great, but this isn&#8217;t the ideal use case for them.</p>
</div>
<div class="paragraph">
<p>Nix allows me to work in my custom environment, but forces me to specify
any dependencies. It automatically tracks the version of each dependency
so that it can replicate the environment wherever and whenever it&#8217;s
needed.</p>
</div>
</div>
<div class="sect2">
<h3 id="_why_flakes">1.2. Why <em>flakes</em>?</h3>
<div class="paragraph">
<p>Flakes are labeled as an experimental feature, so it might seem safer to
avoid them. However, they have been in use for years, and there is
widespread adoption, so the aren&#8217;t going away any time soon. Flakes are
easier to understand, and offer more features than the traditional Nix
approach. After weighing the pros and cons, I feel it&#8217;s better to learn
and use flakes; and this seems to be the general consensus.</p>
</div>
</div>
<div class="sect2">
<h3 id="_prerequisites">1.3. Prerequisites</h3>
<div class="paragraph">
<p>To follow along with the examples in this book, you will need access to a computer
or (virtual machine) with Nix (or NixOS) installed and <em>flakes enabled</em>.</p>
</div>
<div class="paragraph">
<p>I recommend the installer from
<a href="https://zero-to-nix.com/start/install">zero-to-nix.com</a>. This installer
automatically enables flakes.</p>
</div>
<div class="paragraph">
<p>More documentation (and another installer) available at
<a href="https://nixos.org/">nixos.org</a>.</p>
</div>
<div class="paragraph">
<p>To <em>enable flakes on an existing Nix or NixOS installation</em>,
see the instructions in the <a href="https://nixos.wiki/wiki/Flakes">NixOS wiki</a>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>There are hyphenated and un-hyphenated versions of many Nix commands.
For example, <code>nix-shell</code> and <code>nix shell</code> are two different commands.
Don&#8217;t confuse them!</p>
</div>
<div class="paragraph">
<p>Generally speaking, the un-hyphenated versions are for working directly
with flakes, while the hyphenated versions are for everything else.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_see_an_error_have_a_suggestion_or_want_more">1.4. See an error? Have a suggestion? Or want more?</h3>
<div class="paragraph">
<p>If notice an error in this book, have a suggestion on how to improve it,
or you&#8217;re interested in an area that isn&#8217;t covered, feel free to open an
<a href="https://codeberg.org/mhwombat/nix-book/issues">issue</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_nix_language">2. The Nix language</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_introducing_the_nix_language">2.1. Introducing the Nix language</h3>
<div class="paragraph">
<p>Nix and NixOS use a functional programming language called <em>Nix</em>
to specify how to build and install software,
and how to configure system, user, and project-specific environments.
(Yes, “Nix” is the name of both the package manager and the language it uses.)</p>
</div>
<div class="paragraph">
<p>Nix is a <em>functional</em> language.
In a <em>procedural</em> language such as C or Java,
the focus is on writing a series of <em>steps</em> (statements) to achieve a desired result.
By contrast, in a functional language the focus is on <em>defining</em> the desired result.</p>
</div>
<div class="paragraph">
<p>In the case of Nix, the desired result is usually a <em>derivation</em>:
a software package that has been built and made available for use.
The Nix language has been designed for that purpose,
and thus has some features you don&#8217;t typically find in general-purpose languages.</p>
</div>
</div>
<div class="sect2">
<h3 id="_data_types">2.2. Data types</h3>
<div class="sect3">
<h4 id="type-string">2.2.1. Strings</h4>
<div class="paragraph">
<p>Strings are enclosed by double quotes (<code>"</code>), or <em>two</em> single quotes (<code>'</code>).</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">"Hello, world!"</pre>
</div>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">''This string contains "double quotes"''</pre>
</div>
</div>
<div class="paragraph">
<p>They can span multiple lines.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">''Old pond
A frog jumps in
The sound of water
-- Basho''</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="type-integer">2.2.2. Integers</h4>
<div class="literalblock">
<div class="content">
<pre class="nowrap">7
256</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="type-float">2.2.3. Floating point numbers</h4>
<div class="literalblock">
<div class="content">
<pre class="nowrap">3.14
6.022e23</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="type-boolean">2.2.4. Boolean</h4>
<div class="paragraph">
<p>The Boolean values in Nix are <code>true</code> and <code>false</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="type-path">2.2.5. Paths</h4>
<div class="paragraph">
<p>File paths play an important role in building software, so Nix has a special data type for them.
Paths may be absolute (e.g. <code>/bin/sh</code>) or relative (e.g. <code>./data/file1.csv</code>).
Note that paths are not enclosed in quotation marks; they are not strings!</p>
</div>
<div class="paragraph">
<p>Enclosing a path in angle brackets, e.g. &lt;nixpkgs&gt; causes the directories
listed in the environment variable NIX_PATH to be searched for the given
file or directory name.
These are called <em>lookup paths</em>.</p>
</div>
</div>
<div class="sect3">
<h4 id="type-list">2.2.6. Lists</h4>
<div class="paragraph">
<p>List elements are enclosed in square brackets and separated by spaces (not commas).
The elements need not be of the same type.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">[ "apple" 123 ./build.sh false ]</pre>
</div>
</div>
<div class="paragraph">
<p>Lists can be empty.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">[]</pre>
</div>
</div>
<div class="paragraph">
<p>List elements can be of any type, and can even be lists themselves.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">[ [ 1 2 ] [ 3 4 ] ]</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="type-set">2.2.7. Attribute sets</h4>
<div class="paragraph">
<p>Attribute sets associate keys with values.
They are enclosed in curly brackets, and the associations are terminated by semi-colons.
Note that the final semi-colon before the closing bracket is required.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">{ name = "Professor Paws"; age = 10; species = "cat"; }</pre>
</div>
</div>
<div class="paragraph">
<p>The keys of an attribute set must be strings.
When the key is not a valid identifier, it must be enclosed in quotation marks.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">{ abc = true; "123" = false; }</pre>
</div>
</div>
<div class="paragraph">
<p>Attribute sets can be empty.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">{}</pre>
</div>
</div>
<div class="paragraph">
<p>Values of attribute sets can be of any type, and can even be attribute sets themselves.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">{ name = { first = "Professor"; last = "Paws"; }; age = 10; species = "cat"; }</pre>
</div>
</div>
<div class="paragraph">
<p>In <a href="#rec-attrset">Section 2.11.4, &#8220;Recursive attribute sets&#8221;</a> you will be introduced to a special type of attribute set.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In some Nix documentation, and in many articles about Nix,
attribute sets are simply called "sets".</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="type-lambda">2.2.8. Functions</h4>
<div class="paragraph">
<p>We&#8217;ll learn how to write functions in <a href="#functions">Section 2.12, &#8220;Functions&#8221;</a>.
For now, note that functions are "first-class values",
meaning that they can be treated like any other data type.
For example, a function can be assigned to a variable, appear as an element in a list,
be associated with a key in an attribute set, or be passed as input to another function.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">[ "apple" 123 ./build.sh false (x: x*x) ]
{ name = "Professor Paws"; age = 10; species = "cat"; formula = (x: x*2); }</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="type-derivation">2.2.9. Derivations</h4>
<div class="paragraph">
<p>A <a href="https://nix.dev/manual/nix/latest/store/derivation/">derivation</a>
is an attribute set, but one which is a recipe for producing a Nix package.
We&#8217;ll learn how to write derivations in <a href="#derivations">Section 2.14, &#8220;Derivations&#8221;</a>.
For now, note that derivations are "first-class values",
meaning that they can be treated like any other data type.
For example, a derivation can be assigned to a variable, appear as an element in a list,
be associated with a key in an attribute set, or be passed as input to a function.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stop_reading_this_chapter">2.3. Stop reading this chapter!</h3>
<div class="paragraph">
<p>When I first began using Nix, it seemed logical to start by learning the Nix language.
However, after following an in-depth tutorial,
I found that I didn&#8217;t know how to do anything useful with the language!
It wasn&#8217;t until later that I understood what I was missing:
a guide to the most useful library functions.</p>
</div>
<div class="paragraph">
<p>When working with Nix or NixOS,
it&#8217;s very rare that you&#8217;ll want to write something from scratch.
Instead, you&#8217;ll use one of the many library functions
that make things easier and shield you from the underlying complexity.
Many of these functions are language-specific,
and the documentation for them may be inadequate.
Often the easiest (or only) way to learn to use them
is to find an example that does something similar to what you want,
and then modify the function parameters to suit your needs.</p>
</div>
<div class="paragraph">
<p>At this point you&#8217;ve learned enough of the Nix language
to do the majority of common Nix tasks.
So when I say "Stop reading this chapter!", I&#8217;m only half-joking.
Instead I suggest that you <em>skim</em> the rest of this chapter,
paying special attention to anything marked with <span class="icon"><i class="fa fa-exclamation-circle"></i></span>.
Then move on to the following chapters
where you will learn how to develop and package software using Nix.
Afterward, come back to this chapter and read it in more detail.</p>
</div>
<div class="paragraph">
<p>While writing this book, I anticipated that readers would want to skip around,
alternating between pure learning and learning-by-doing.
I&#8217;ve tried to structure the book to support that;
providing extensive cross-references to earlier and later sections,
and sometimes repeating information from earlier chapters that you might have skipped.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_nix_repl">2.4. The Nix REPL</h3>
<div class="paragraph">
<p>The Nix REPL (REPL is an acronym for Read-Eval-Print-Loop)
is an interactive environment for evaluating and debugging Nix code.
It&#8217;s also a good place to begin learning Nix.
Enter it using the command <code>nix repl</code>.
Within the REPL, type <code>:?</code> to see a list of available commands.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>$ nix repl
Welcome to Nix 2.18.1. Type :? for help.
nix-repl&gt; :?
The following commands are available:
&lt;expr&gt; Evaluate and print expression
&lt;x&gt; = &lt;expr&gt; Bind expression to variable
:a, :add &lt;expr&gt; Add attributes from resulting set to scope
:b &lt;expr&gt; Build a derivation
:bl &lt;expr&gt; Build a derivation, creating GC roots in the
working directory
:e, :edit &lt;expr&gt; Open package or function in $EDITOR
:i &lt;expr&gt; Build derivation, then install result into
current profile
:l, :load &lt;path&gt; Load Nix expression and add it to scope
:lf, :load-flake &lt;ref&gt; Load Nix flake and add it to scope
:p, :print &lt;expr&gt; Evaluate and print expression recursively
:q, :quit Exit nix-repl
:r, :reload Reload all files
:sh &lt;expr&gt; Build dependencies of derivation, then start
nix-shell
:t &lt;expr&gt; Describe result of evaluation
:u &lt;expr&gt; Build derivation, then start nix-shell
:doc &lt;expr&gt; Show documentation of a builtin function
:log &lt;expr&gt; Show logs for a derivation
:te, :trace-enable [bool] Enable, disable or toggle showing traces for
errors
:?, :help Brings up this help menu</code></pre>
</div>
</div>
<div class="paragraph">
<p>A command that is useful to beginners is <code>:t</code>, which tells you the type of an expression.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :t { abc = true; &quot;123&quot; = false; }
a set
nix-repl&gt; f = x: y: x * y
nix-repl&gt; :t f
a function</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that the command to exit the REPL is <code>:q</code> (or <code>:quit</code> if you prefer).</p>
</div>
</div>
<div class="sect2">
<h3 id="_variables">2.5. Variables</h3>
<div class="sect3">
<h4 id="_assignment">2.5.1. Assignment</h4>
<div class="paragraph">
<p>You can declare variables in Nix and assign values to them.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a = 7
nix-repl&gt; b = 3
nix-repl&gt; a - b
4</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The spaces before and after operators aren&#8217;t always required.
However, you can get unexpected results when you omit them, as shown in the following example.
Nix allows hyphens (<code>-</code>) in variable names,
so <code>a-b</code> is interpreted as the name of a variable rather than a subtraction operation.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a-b
error: undefined variable &#39;a-b&#39;
at «string»:1:1:
1| a-b
| ^</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_immutability">2.5.2. Immutability</h4>
<div class="paragraph">
<p>In Nix, values are <em>immutable</em>;
once you assign a value to a variable, you cannot change it.
You can, however, create a new variable with the same name, but in a different scope.
Don&#8217;t worry if you don&#8217;t completely understand the previous sentence;
we will see some examples in <a href="#functions">Section 2.12, &#8220;Functions&#8221;</a>, <a href="#_let_expressions">Section 2.16, &#8220;Let expressions&#8221;</a>, and <a href="#_with_expressions">Section 2.17, &#8220;With expressions&#8221;</a>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In the Nix REPL, it may seem like the values of variables can be changed,
in <em>apparent</em> contradiction to the previous paragraph.
In truth, the REPL works some behind-the-scenes "magic",
effectively creating a new nested scope with each assignment.
This makes it much easier to experiment in the REPL.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; x = 1
nix-repl&gt; x
1
nix-repl&gt; x = x + 1 # creates a new variable called &quot;x&quot;; the original is no longer in scope
nix-repl&gt; x
2</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_numeric_operations">2.6. Numeric operations</h3>
<div class="sect3">
<h4 id="_arithmetic_operators">2.6.1. Arithmetic operators</h4>
<div class="paragraph">
<p>The usual arithmetic operators are provided.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; 1 + 2 # addition
3
nix-repl&gt; 5 - 3 # subtraction
2
nix-repl&gt; 3 * 4 # multiplication
12
nix-repl&gt; 6 / 2 # division
3
nix-repl&gt; -1 # negation
-1</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>As mentioned in <a href="#_variables">Section 2.5, &#8220;Variables&#8221;</a>,
you can get unexpected results when you omit spaces around operators.
Consider the following example.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; 6/2
/home/amy/codeberg/nix-book/6/2</code></pre>
</div>
</div>
<div class="paragraph">
<p>What happened?
Let&#8217;s use the <code>:t</code> command to find out the type of the expression.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :t 6/2
a path</code></pre>
</div>
</div>
<div class="paragraph">
<p>If an expression can be interpreted as a path, Nix will do so.
This is useful, because paths are <em>far</em> more commonly used in Nix expressions
than arithmetic operators.
In this case, Nix interpreted <code>6/2</code> as a relative path from the current directory,
which in the above example was <code>/home/amy/codeberg/nix-book</code>.</p>
</div>
<div class="paragraph">
<p>Adding a space after the <code>/</code> operator produces the expected result.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; 6/ 2
3</code></pre>
</div>
</div>
<div class="paragraph">
<p>To avoid surprises and improve readability, I prefer to use spaces before and after all operators.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_floating_point_calculations">2.6.2. Floating-point calculations</h4>
<div class="paragraph">
<p>Numbers without a decimal point are assumed to be integers.
To ensure that a number is interpreted as a floating-point value, add a decimal point.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :t 5
an integer
nix-repl&gt; :t 5.0
a float
nix-repl&gt; :t 5.
a float</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the example below, the first expression results in integer division (rounding down),
while the second produces a floating-point result.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; 5 / 3
1
nix-repl&gt; 5.0 / 3
1.66667</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_string_operations">2.7. String operations</h3>
<div class="sect3">
<h4 id="_string_comparison">2.7.1. String comparison</h4>
<div class="paragraph">
<p>Nix provides the usual lexicographic comparison operations.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &quot;apple&quot; == &quot;banana&quot; # equality
false
nix-repl&gt; &quot;apple&quot; != &quot;banana&quot; # inequality
true
nix-repl&gt; &quot;apple&quot; &lt; &quot;banana&quot; # comes alphabetically before?
true
nix-repl&gt; &quot;apple&quot; &lt;= &quot;banana&quot; # equal or comes alphabetically before?
true
nix-repl&gt; &quot;apple&quot; &gt; &quot;banana&quot; # comes alphabetically after?
false
nix-repl&gt; &quot;apple&quot; &gt;= &quot;banana&quot; # equal or comes alphabetically after?
false</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_string_concatenation">2.7.2. String concatenation</h4>
<div class="paragraph">
<p>String concatenation uses the <code>+</code> operator.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &quot;Hello, &quot; + &quot;world!&quot;
&quot;Hello, world!&quot;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_string_interpolation">2.7.3. String interpolation</h4>
<div class="paragraph">
<p>You can use the <code>${<em>variable</em>}</code> syntax to insert the value of a variable within a string.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; name = &quot;Wombat&quot;
nix-repl&gt; &quot;Hi, I&#39;m ${name}.&quot;
&quot;Hi, I&#39;m Wombat.&quot;</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>You cannot mix numbers and strings.
Earlier we set <code>a = 7</code>, so the following expression fails.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &quot;My favourite number is ${a}.&quot;
error:
… while evaluating a path segment
at «string»:1:25:
1| &quot;My favourite number is ${a}.&quot;
| ^
error: cannot coerce an integer to a string</code></pre>
</div>
</div>
<div class="paragraph">
<p>Nix does provide functions for converting between types; we&#8217;ll see these in the
<a href="#convert-to-string">next section</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_useful_built_in_functions_for_strings">2.7.4. Useful built-in functions for strings</h4>
<div class="paragraph">
<p>Nix provides some built-in functions for working with strings;
a few examples are shown below.
For more information on these and other built-in functions, see the Nix Manual
(<a href="https://nixos.org/manual/nix/stable/language/builtins" class="bare">https://nixos.org/manual/nix/stable/language/builtins</a>).</p>
</div>
<div class="paragraph">
<p>How long is this string?</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.stringLength &quot;supercalifragilisticexpialidocious&quot;
34</code></pre>
</div>
</div>
<div class="paragraph">
<p>Given a starting position and a length, extract a substring.
The first character of a string has index <code>0</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.substring 3 6 &quot;hayneedlestack&quot;
&quot;needle&quot;</code></pre>
</div>
</div>
<div id="convert-to-string" class="paragraph">
<p>Convert an expression to a string.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.toString 7
&quot;7&quot;
nix-repl&gt; builtins.toString (3*4 + 1)
&quot;13&quot;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_boolean_operations">2.8. Boolean operations</h3>
<div class="paragraph">
<p>The usual boolean operators are available.
Recall that earlier we set <code>a = 7</code> and <code>b = 3</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a == 7 # equality test
true
nix-repl&gt; b != 3 # inequality
false
nix-repl&gt; a &gt; 12 # greater than
false
nix-repl&gt; b &gt;= 2 # greater than or equal
true
nix-repl&gt; a &lt; b # less than
false
nix-repl&gt; b &lt;= a # less than or equal
true
nix-repl&gt; !true # logical negation
false
nix-repl&gt; (3 * a == 21) &amp;&amp; (a &gt; b) # logical AND
true
nix-repl&gt; (b &gt; a) || (b &gt; 10) # logical OR
false</code></pre>
</div>
</div>
<div class="paragraph">
<p>One operator that might be unfamiliar to you is <em>logical implication</em>, which uses the symbol <code>&#8594;</code>.
The expression <code>u &#8594; v</code> is equivalent to <code>!u || v</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; u = false
nix-repl&gt; v = true
nix-repl&gt; u -&gt; v
true
nix-repl&gt; v -&gt; u
false</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_path_operations">2.9. Path operations</h3>
<div class="paragraph">
<p>Any expression that contains a forward slash (<code>/</code>) <em>not</em> followed by a space
is interpreted as a path.
To refer to a file or directory relative to the current directory, prefix it with <code>./</code>.
You can specify the current directory as <code>./.</code></p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; ./file.txt
/home/amy/codeberg/nix-book/file.txt
nix-repl&gt; ./.
/home/amy/codeberg/nix-book</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_concatenating_paths">2.9.1. Concatenating paths</h4>
<div class="paragraph">
<p>Paths can be concatenated to produce a new path.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; /home/wombat + /bin/sh
/home/wombat/bin/sh
nix-repl&gt; :t /home/wombat + /bin/sh
a path</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Relative paths are made absolute when they are parsed, which occurs before concatenation.
This is why the result in the example below is not <code>/home/wombat/file.txt</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; /home/wombat + ./file.txt
/home/wombat/home/amy/codeberg/nix-book/file.txt</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_concatenating_a_path_a_string">2.9.2. Concatenating a path + a string</h4>
<div class="paragraph">
<p>A path can be concatenated with a string to produce a new path.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; /home/wombat + &quot;/file.txt&quot;
/home/wombat/file.txt
nix-repl&gt; :t /home/wombat + &quot;/file.txt&quot;
a path</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The Nix reference manual says that the string must not "have a string context" that refers to a store path.
String contexts are beyond the scope of this book;
for more information see <a href="https://nixos.org/manual/nix/stable/language/operators#path-concatenation" class="bare">https://nixos.org/manual/nix/stable/language/operators#path-concatenation</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_concatenating_a_string_a_path">2.9.3. Concatenating a string + a path</h4>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Strings can be concatenated with paths, but with a side-effect that may surprise you:
if the path exists, the file is copied to the Nix store!
The result is a string, not a path.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>In the example below, you might expect the result to be <code>"home/wombat/file.nix"</code>.
However, the file <code>file.txt</code> is copied to <code>/nix/store/gp8ba25gpwvbqizqfr58jr014gmv1hd8-file.txt</code>
before concatenating it to the string.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &quot;/home/wombat&quot; + ./file.txt
&quot;/home/wombat/nix/store/gp8ba25gpwvbqizqfr58jr014gmv1hd8-file.txt&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>When concatenating a string with a path, the path must exist.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &quot;/home/wombat&quot; + ./no-such-file.txt
error (ignored): error: end of string reached
error: getting status of &#39;/home/amy/codeberg/nix-book/no-such-file.txt&#39;: No such file or directory</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_useful_built_in_functions_for_paths">2.9.4. Useful built-in functions for paths</h4>
<div class="paragraph">
<p>Nix provides some built-in functions for working with paths;
a few examples are shown below.
For more information on these and other built-in functions, see the Nix Manual
(<a href="https://nixos.org/manual/nix/stable/language/builtins" class="bare">https://nixos.org/manual/nix/stable/language/builtins</a>).</p>
</div>
<div class="paragraph">
<p>Does the path exist?</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.pathExists ./index.html
true
nix-repl&gt; builtins.pathExists /no/such/path
false</code></pre>
</div>
</div>
<div class="paragraph">
<p>Get a list of the files in a directory, along with the type of each file.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.readDir ./.
{ &quot;.envrc&quot; = &quot;regular&quot;; &quot;.git&quot; = &quot;directory&quot;; &quot;.gitignore&quot; = &quot;regular&quot;; Makefile = &quot;regular&quot;; images = &quot;directory&quot;; &quot;index.html&quot; = &quot;regular&quot;; &quot;shell.nix&quot; = &quot;regular&quot;; source = &quot;directory&quot;; themes = &quot;directory&quot;; &quot;wombats-book-of-nix.pdf&quot; = &quot;regular&quot;; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Read the contents of a file into a string.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.readFile ./.envrc
&quot;use nix\n&quot;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_list_operations">2.10. List operations</h3>
<div class="sect3">
<h4 id="_list_concatenation">2.10.1. List concatenation</h4>
<div class="paragraph">
<p>Lists can be concatenated using the <code>++</code> operator.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; [ 1 2 3 ] ++ [ &quot;apple&quot; &quot;banana&quot; ]
[ 1 2 3 &quot;apple&quot; &quot;banana&quot; ]</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_useful_built_in_functions_for_lists">2.10.2. Useful built-in functions for lists</h4>
<div class="paragraph">
<p>Nix provides some built-in functions for working with lists;
a few examples are shown below.
For more information on these and other built-in functions, see the Nix Manual
(<a href="https://nixos.org/manual/nix/stable/language/builtins" class="bare">https://nixos.org/manual/nix/stable/language/builtins</a>).</p>
</div>
<div class="paragraph">
<p>Testing if an element appears in a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; fruit = [ &quot;apple&quot; &quot;banana&quot; &quot;cantaloupe&quot; ]
nix-repl&gt; builtins.elem &quot;apple&quot; fruit
true
nix-repl&gt; builtins.elem &quot;broccoli&quot; fruit
false</code></pre>
</div>
</div>
<div class="paragraph">
<p>Selecting an item from a list by index.
The first element in a list has index <code>0</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.elemAt fruit 0
&quot;apple&quot;
nix-repl&gt; builtins.elemAt fruit 2
&quot;cantaloupe&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Determining the number of elements in a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.length fruit
3</code></pre>
</div>
</div>
<div class="paragraph">
<p>Accessing the first element of a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.head fruit
&quot;apple&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Dropping the first element of a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.tail fruit
[ &quot;banana&quot; &quot;cantaloupe&quot; ]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Functions are useful for working with lists.
Functions will be introduced in <a href="#functions">Section 2.12, &#8220;Functions&#8221;</a>,
but the following examples should be somewhat self-explanatory.</p>
</div>
<div class="paragraph">
<p>Using a function to filter (select elements from) a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; numbers = [ 1 3 6 8 9 15 25 ]
nix-repl&gt; isBig = n: n &gt; 10 # is the number &quot;big&quot; (greater than 10)?
nix-repl&gt; builtins.filter isBig numbers # get just the &quot;big&quot; numbers
[ 15 25 ]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Applying a function to all the elements in a list.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; double = n: 2*n # multiply by two
nix-repl&gt; builtins.map double numbers # double each element in the list
[ 2 6 12 16 18 30 50 ]</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_attribute_set_operations">2.11. Attribute set operations</h3>
<div class="sect3">
<h4 id="_selection">2.11.1. Selection</h4>
<div class="paragraph">
<p>The <code>.</code> operator selects an attribute from a set.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; animal = { name = { first = &quot;Professor&quot;; last = &quot;Paws&quot;; }; age = 10; species = &quot;cat&quot;; }
nix-repl&gt; animal . age
10
nix-repl&gt; animal . name . first
&quot;Professor&quot;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_query">2.11.2. Query</h4>
<div class="paragraph">
<p>We can use the <code>?</code> operator to find out if a set has a particular attribute.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; animal ? species
true
nix-repl&gt; animal ? bicycle
false</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_union">2.11.3. Union</h4>
<div class="paragraph">
<p>We can use the <code>//</code> operator to combine two attribute sets.
Attributes in the right-hand set take preference.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a = { x = 7; y = &quot;hello&quot;; }
nix-repl&gt; b = { y = &quot;wombat&quot;; z = 3; }
nix-repl&gt; a // b
{
x = 7;
y = &quot;wombat&quot;;
z = 3;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is often used to "modify" one or more values in the set.
Recall that Nix values are immutable, so the result is a new value (the original is not actually modified).</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; animal // { species = &quot;tiger&quot;; }
{ age = 10; name = { ... }; species = &quot;tiger&quot;; }</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="rec-attrset">2.11.4. Recursive attribute sets</h4>
<div class="paragraph">
<p>An ordinary attribute set cannot refer to its own elements.
To do this, you need a <em>recursive</em> attribute set.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; { x = 3; y = 4*x; }
error: undefined variable &#39;x&#39;
at «string»:1:16:
1| { x = 3; y = 4*x; }
| ^
nix-repl&gt; rec { x = 3; y = 4*x; }
{ x = 3; y = 12; }</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_useful_built_in_functions_for_attribute_sets">2.11.5. Useful built-in functions for attribute sets</h4>
<div class="paragraph">
<p>Nix provides some built-in functions for working with attribute sets;
a few examples are shown below.
For more information on these and other built-in functions, see the Nix Manual
(<a href="https://nixos.org/manual/nix/stable/language/builtins" class="bare">https://nixos.org/manual/nix/stable/language/builtins</a>).</p>
</div>
<div class="paragraph">
<p>Get an alphabetical list of the keys.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.attrNames animal
[ &quot;age&quot; &quot;name&quot; &quot;species&quot; ]</code></pre>
</div>
</div>
<div class="paragraph">
<p>Get the values associated with each key, in alphabetical order by the key names.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.attrValues animal
[ 10 &quot;Professor Paws&quot; &quot;cat&quot; ]</code></pre>
</div>
</div>
<div class="paragraph">
<p>What value is associated with a key?</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.getAttr &quot;age&quot; animal
10</code></pre>
</div>
</div>
<div class="paragraph">
<p>Does the set have a value for a key?</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.hasAttr &quot;name&quot; animal
true
nix-repl&gt; builtins.hasAttr &quot;car&quot; animal
false</code></pre>
</div>
</div>
<div class="paragraph">
<p>Remove one or more keys and associated values from a set.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.removeAttrs animal [ &quot;age&quot; &quot;species&quot; ]
{ name = &quot;Professor Paws&quot;; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Display an attribute set, including nested sets.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; builtins.toJSON animal
&quot;{\&quot;age\&quot;:10,\&quot;name\&quot;:{\&quot;first\&quot;:\&quot;Professor\&quot;,\&quot;last\&quot;:\&quot;Paws\&quot;},\&quot;species\&quot;:\&quot;cat\&quot;}&quot;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="functions">2.12. Functions</h3>
<div class="sect3">
<h4 id="_anonymous_functions">2.12.1. Anonymous functions</h4>
<div class="paragraph">
<p>Functions are defined using the syntax <code><em>parameter</em>: <em>expression</em></code>,
where the <em>expression</em> typically involves the <em>parameter</em>.
Consider the following example.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; x: x + 1
«lambda @ «string»:1:1»</code></pre>
</div>
</div>
<div class="paragraph">
<p>We created a function that adds <code>1</code> to its input.
However, it doesn&#8217;t have a name, so we can&#8217;t use it directly.
Anonymous functions do have their uses, as we shall see shortly.</p>
</div>
<div class="paragraph">
<p>Note that the message printed by the Nix REPL when we created the function uses the term <em>lambda</em>.
This derives from a branch of mathematics called <em>lambda calculus</em>.
Lambda calculus was the inspiration for most functional languages such as Nix.
Functional programmers often call anonymous functions "lambdas".</p>
</div>
<div class="paragraph">
<p>The Nix REPL confirms that the expression <code>x: x + 1</code> defines a function.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :t x: x + 1
a function</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_named_functions_and_function_application">2.12.2. Named functions and function application</h4>
<div class="paragraph">
<p>How can we use a function?
Recall from <a href="#type-lambda">Section 2.2.8, &#8220;Functions&#8221;</a> that functions can be treated like any other data type.
In particular, we can assign it to a variable.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; f = x: x + 1
nix-repl&gt; f
«lambda @ «string»:1:2»</code></pre>
</div>
</div>
<div class="paragraph">
<p>Procedural languages such as C or Java often use parenthesis to apply a function to a value, e.g. <code>f(5)</code>.
Nix, like lambda calculus and most functional languages, does not require parenthesis for function application.
This reduces visual clutter when chaining a series of functions.</p>
</div>
<div class="paragraph">
<p>Now that our function has a name, we can use it.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; f 5
6</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_multiple_parameters_using_nested_functions">2.12.3. Multiple parameters using nested functions</h4>
<div class="paragraph">
<p>Functions in Nix always have a single parameter.
To define a calculation that requires more than one parameter,
we create functions that return functions!</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; add = a: (b: a+b)</code></pre>
</div>
</div>
<div class="paragraph">
<p>We have created a function called <code>add</code>.
When applied to a parameter <code>a</code>, it returns a new function that adds <code>a</code> to its input.
Note that the expression <code>(b: a+b)</code> is an anonymous function.
We never call it directly, so it doesn&#8217;t need a name.
Anonymous functions are useful after all!</p>
</div>
<div class="paragraph">
<p>I used parentheses to emphasise the inner function, but they aren&#8217;t necessary.
More commonly we would write the following.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; add = a: b: a+b</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we only supply one parameter to <code>add</code>, the result is a new function rather than a simple value.
Invoking a function without supplying all of the expected parameters is called <em>partial application</em>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; add 3 # Returns a function that adds 3 to any input
«lambda @ «string»:1:6»</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now let&#8217;s apply <code>add 3</code> to the value <code>5</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; (add 3) 5
8</code></pre>
</div>
</div>
<div class="paragraph">
<p>In fact, the parentheses aren&#8217;t needed.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; add 3 5
8</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;ve never used a functional programming language, this all probably seems very strange.
Imagine that you want to add two numbers, but you have a very unusual calculator labeled "add".
This calculator never displays a result, it only produces more calculators!
If you enter the value <code>3</code> into the "add" calculator, it gives you a second calculator labeled "add 3".
You then enter <code>5</code> into the "add 3" calculator, which displays the result of the addition, <code>8</code>.</p>
</div>
<div class="paragraph">
<p>With that image in mind, let&#8217;s walk through the steps again in the REPL, but this time in more detail.
The function <code>add</code> takes a single parameter <code>a</code>,
and returns a new function that takes a single parameter <code>b</code>, and returns the value <code>a + b</code>.
Let&#8217;s apply <code>add</code> to the value <code>3</code>, and give the resulting new function a name, <code>g</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; g = add 3</code></pre>
</div>
</div>
<div class="paragraph">
<p>The function <code>g</code> takes a single parameter and adds <code>3</code> to it.
The Nix REPL confirms that <code>g</code> is indeed a function.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :t g
a function</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we can apply <code>g</code> to a number to get a new number.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; g 5
8</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_multiple_parameters_using_attribute_sets">2.12.4. Multiple parameters using attribute sets</h4>
<div class="paragraph">
<p>I said earlier that a function in Nix always has a single parameter.
However, that parameter need not be a simple value; it could be a list or an attribute set.
This approach is widely used in Nix, and the language has some special features to support it.
This is an important topic, so we will cover it separately in <a href="#argument-sets">Section 2.13, &#8220;Argument sets&#8221;</a>.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="argument-sets">2.13. Argument sets</h3>
<div class="paragraph">
<p>An attribute set that is used as a function parameter is often called an <em>argument set</em>.</p>
</div>
<div class="sect3">
<h4 id="_set_patterns">2.13.1. Set patterns</h4>
<div class="paragraph">
<p>To specify an attribute set as a function parameter, we use a <em>set pattern</em>,
which has the form</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code>{ <em>name1</em>, <em>name2</em>, ... }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that while the key-value associations in attribute sets are separated by semi-colons,
the key names in the attribute set _pattern are separated by commas.
Here&#8217;s an example of a function that has an attribute set as an input parameter.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; greet = { first, last }: &quot;Hello ${first} ${last}! May I call you ${first}?&quot;
nix-repl&gt; greet { first=&quot;Amy&quot;; last=&quot;de Buitléir&quot;; }
&quot;Hello Amy de Buitléir! May I call you Amy?&quot;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_optional_parameters">2.13.2. Optional parameters</h4>
<div class="paragraph">
<p>We can make some values in an argument set optional by providing default values,
using the syntax <code><em>name</em> ? <em>value</em></code>.
This is illustrated below.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; greet = { first, last ? &quot;whatever-your-lastname-is&quot;, topic ? &quot;Nix&quot; }: &quot;Hello ${first} ${last}! May I call you ${first}? Are you enjoying learning ${topic}?&quot;
nix-repl&gt; greet { first=&quot;Amy&quot;; }
&quot;Hello Amy whatever-your-lastname-is! May I call you Amy? Are you enjoying learning Nix?&quot;
nix-repl&gt; greet { first=&quot;Amy&quot;; topic=&quot;Mathematics&quot;;}
&quot;Hello Amy whatever-your-lastname-is! May I call you Amy? Are you enjoying learning Mathematics?&quot;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_variadic_attributes">2.13.3. Variadic attributes</h4>
<div class="paragraph">
<p>A function can allow the caller to supply argument sets that contain "extra" values.
This is done with the special parameter <code>&#8230;&#8203;</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; formatName = { first, last, ... }: &quot;${first} ${last}&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>One reason for doing this is to allow the caller to pass the same argument set to multiple functions,
even though each function may not need all of the values.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; person = { first=&quot;Joe&quot;; last=&quot;Bloggs&quot;; address=&quot;123 Main Street&quot;; }
nix-repl&gt; formatName person
&quot;Joe Bloggs&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Another reason for allowing variadic arguments is when a function calls another function,
supplying the same argument set.
An example is shown in <a href="#at-patterns">Section 2.13.4, &#8220;@-patterns&#8221;</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="at-patterns">2.13.4. @-patterns</h4>
<div class="paragraph">
<p>It can be convenient for a function to be able to reference the argument set as a whole.
This is done using an <em>@-pattern</em>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; formatPoint = p@{ x, y, ... }: builtins.toXML p
nix-repl&gt; formatPoint { x=5; y=3; z=2; }
&quot;&lt;?xml version=&#39;1.0&#39; encoding=&#39;utf-8&#39;?&gt;\n&lt;expr&gt;\n &lt;attrs&gt;\n &lt;attr name=\&quot;x\&quot;&gt;\n &lt;int value=\&quot;5\&quot; /&gt;\n &lt;/attr&gt;\n &lt;attr name=\&quot;y\&quot;&gt;\n &lt;int value=\&quot;3\&quot; /&gt;\n &lt;/attr&gt;\n &lt;attr name=\&quot;z\&quot;&gt;\n &lt;int value=\&quot;2\&quot; /&gt;\n &lt;/attr&gt;\n &lt;/attrs&gt;\n&lt;/expr&gt;\n&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively, the @-pattern can appear <em>after</em> the argument set, as in the example below.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; formatPoint = { x, y, ... } @ p: builtins.toXML p</code></pre>
</div>
</div>
<div class="paragraph">
<p>An @-pattern is the only way a function can access variadic attributes,
so they are often used together.
In the example below, the function <code>greet</code> passes its argument set, including the variadic arguments,
to the function <code>confirmAddress</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; confirmAddress = { address, ... }: &quot;Do you still live at ${address}?&quot;
nix-repl&gt; greet = args@{ first, last, ... }: &quot;Hello ${first}. &quot; + confirmAddress args
nix-repl&gt; greet person
&quot;Hello Joe. Do you still live at 123 Main Street?&quot;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="derivations">2.14. Derivations</h3>
<div class="paragraph">
<p>Derivations can be created using the primitive built-in <code>derivation</code> function.
It takes the following arguments.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>system</code> (e.g. <code>x86_64-linux</code>).</p>
</li>
<li>
<p><code>name</code>, the package name.</p>
</li>
<li>
<p><code>builder</code>, the executable that builds the package.
Attributes are passed to the builder as environment variables.</p>
</li>
<li>
<p><code>args</code> (optional), command line arguments to be passed to the builder.</p>
</li>
<li>
<p><code>outputs</code> (optional, defaults to <code>out</code>), output names.
Nix will pass them to the builder as environment variables containing
the output paths.</p>
<div class="literalblock">
<div class="content">
<pre class="nowrap">d = derivation { name = "myname"; builder = "mybuilder"; system = "mysystem"; }</pre>
</div>
</div>
</li>
</ul>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; d = derivation { name = &quot;myname&quot;; builder = &quot;mybuilder&quot;; system = &quot;mysystem&quot;; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>In place of using <code>derivation</code>, it is generally more convenient to use
<code>stdenv.mkDerivation</code>, which will be be introduced in
<a href="#mkDerivation">Section 3.5, &#8220;<code>stdenv.mkDerivation</code>&#8221;</a></p>
</div>
<div class="sect3">
<h4 id="_instantiation_vs_realisation">2.14.1. Instantiation vs Realisation</h4>
<div class="paragraph">
<p>When a derivation is <em>instantiated</em> (<em>evaluated</em>),
the Nix expression is parsed and interpreted.
The result is a <code>.drv</code> file containing a derivation set.
The package is not built in this step.</p>
</div>
<div class="paragraph">
<p>The package itself is created when the derivation is <em>built</em> (<em>realised</em>).
Any dependencies are also built at this time.</p>
</div>
</div>
<div class="sect3">
<h4 id="_instantiate_evaluate_a_derivation">2.14.2. Instantiate (evaluate) a derivation</h4>
<div class="paragraph">
<p>Using the derivation "d" created above&#8230;&#8203;</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; d
«derivation /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv»</code></pre>
</div>
</div>
<div class="paragraph">
<p>That <code>.drv</code> file is plain text; it contains the derivation in a different format.
The mysterious sequence of characters in the filename is a hash of the derivation.
The hash is unique to this derivation.
We could have multiple derivations for a package, perhaps different versions or with different options enabled,
but each one would have a unique hash.
Any changes to the derivation would result in a new hash.
Using the hash, Nix can tell the different derivations apart,
and avoid rebuilding a derivation that has already been built.</p>
</div>
<div class="paragraph">
<p>We can inspect the derivation in the Nix repl.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; d.drvAttrs
{ builder = &quot;mybuilder&quot;; name = &quot;myname&quot;; system = &quot;mysystem&quot;; }</code></pre>
</div>
</div>
<div class="paragraph">
<p>We can examine the <code>.drv</code> file.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>$ cat /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
Derive([(&quot;out&quot;,&quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;,&quot;&quot;,&quot;&quot;)],[],[],&quot;mysystem&quot;,&quot;mybuilder&quot;,[],[(&quot;builder&quot;,&quot;mybuilder&quot;),(&quot;name&quot;,&quot;myname&quot;),(&quot;out&quot;,&quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;),(&quot;system&quot;,&quot;mysystem&quot;)])%</code></pre>
</div>
</div>
<div class="paragraph">
<p>Or get a nicely formatted version.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>$ nix show-derivation /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
{
&quot;/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv&quot;: {
&quot;outputs&quot;: {
&quot;out&quot;: {
&quot;path&quot;: &quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;
}
},
&quot;inputSrcs&quot;: [],
&quot;inputDrvs&quot;: {},
&quot;system&quot;: &quot;mysystem&quot;,
&quot;builder&quot;: &quot;mybuilder&quot;,
&quot;args&quot;: [],
&quot;env&quot;: {
&quot;builder&quot;: &quot;mybuilder&quot;,
&quot;name&quot;: &quot;myname&quot;,
&quot;out&quot;: &quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;,
&quot;system&quot;: &quot;mysystem&quot;
}
}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_find_out_where_the_package_would_be_or_was_installed">2.14.3. Find out where the package would be (or was) installed</h4>
<div class="paragraph">
<p>Using the derivation "d" created above&#8230;&#8203;</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; d.outPath
&quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;
nix-repl&gt; builtins.toString d # also works
&quot;/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname&quot;</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_build_realise_a_derivation">2.14.4. Build (realise) a derivation.</h4>
<div class="paragraph">
<p>In the Nix REPL, using the derivation "d" created above&#8230;&#8203;</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :b d
error: a &#39;mysystem&#39; with features {} is required to build &#39;/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv&#39;, but I am a &#39;x86_64-linux&#39; with features {benchmark, big-parallel, kvm, nixos-test}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Of course, this example failed to build because the builder and system are fake.
We can achieve the same result at the command line.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-build /nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
this derivation will be built:
/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv
error: a &#39;mysystem&#39; with features {} is required to build &#39;/nix/store/z3hhlxbckx4g3n9sw91nnvlkjvyw754p-myname.drv&#39;, but I am a &#39;x86_64-linux&#39; with features {benchmark, big-parallel, kvm, nixos-test}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_remove_a_derivation">2.14.5. Remove a derivation</h4>
<div class="paragraph">
<p>Delete a path from the store <strong>if it is safe to do so</strong> (i.e. if it is
eligible for garbage collection).</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-store --delete /nix/store/rc3n0lc4aijyi9wwpmcss7hbxryz6bnh-foo</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_if_expressions">2.15. If expressions</h3>
<div class="paragraph">
<p>The conditional construct in Nix is an <em>expression</em>, not a <em>statement</em>.
Since expressions must have values in all cases, you must specify both the <code>then</code> and the <code>else</code> branch.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a = 7
nix-repl&gt; b = 3
nix-repl&gt; if a &gt; b then &quot;yes&quot; else &quot;no&quot;
&quot;yes&quot;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_let_expressions">2.16. Let expressions</h3>
<div class="paragraph">
<p>A <code>let</code> expression defines a value with a local scope.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; let x = 3; in x*x
9
nix-repl&gt; let x = 3; y = 2; in x*x + y
11</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can also nest <code>let</code> expressions.
The previous expression is equivalent to the following.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; let x = 3; in let y = 2; in x*x + y
11</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>A variable defined inside a <code>let</code> expression will "shadow" an outer variable with the same name.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; x = 100
nix-repl&gt; let x = 3; in x*x
9
nix-repl&gt; let x = 3; in let x = 7; in x+1
8</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>A variable in a let expression can refer to another variable in the expression.
This is similar to how recursive attribute sets work.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; let x = 3; y = x + 1; in x*y
12</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_with_expressions">2.17. With expressions</h3>
<div class="paragraph">
<p>A <code>with</code> expression is somewhat similar to a <code>let</code> expression,
but it brings all of the associations in an attribute set into scope.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; point = { x1 = 3; x2 = 2; }
nix-repl&gt; with point; x1*x1 + x2
11</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Unlike a <code>let</code> expression, a variable defined inside a <code>with</code> expression will <em>not</em>
"shadow" an outer variable with the same name.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; name = &quot;Amy&quot;
nix-repl&gt; animal = { name = &quot;Professor Paws&quot;; age = 10; species = &quot;cat&quot;; }
nix-repl&gt; with animal; &quot;Hello, &quot; + name
&quot;Hello, Amy&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>However, you can refer to the variable in the inner scope
using the attribute selection operator (<code>.</code>).</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; with animal; &quot;Hello, &quot; + animal.name
&quot;Hello, Professor Paws&quot;</code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="_inherit">2.18. Inherit</h3>
<div class="paragraph">
<p>The <code>inherit</code> keyword causes the specified attributes to be bound to
whatever variables with the same name happen to be in scope.</p>
</div>
<div class="paragraph">
<p>When defining a set or in a let-expression it is often convenient to copy variables
from the surrounding lexical scope (e.g., when you want to propagate attributes).
This can be shortened using <code>inherit</code>.</p>
</div>
<div class="paragraph">
<p>For instance,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-k">let</span> <span class="tok-ss">x</span> <span class="tok-o">=</span> <span class="tok-mi">123</span><span class="tok-p">;</span> <span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-k">inherit</span> x<span class="tok-p">;</span>
<span class="tok-ss">y</span> <span class="tok-o">=</span> <span class="tok-mi">456</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-k">let</span> <span class="tok-ss">x</span> <span class="tok-o">=</span> <span class="tok-mi">123</span><span class="tok-p">;</span> <span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">x</span> <span class="tok-o">=</span> x<span class="tok-p">;</span>
<span class="tok-ss">y</span> <span class="tok-o">=</span> <span class="tok-mi">456</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_import">2.19. Import</h3>
<div class="paragraph">
<p>The built-in <code>import</code> function provides a way to parse a <code>.nix</code> file.</p>
</div>
<div class="listingblock">
<div class="title">a.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-p">{</span>
<span class="tok-ss">message</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;You successfully imported me!&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">b</span> <span class="tok-o">=</span> <span class="tok-mi">12</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; a = import ./a.nix
nix-repl&gt; a.message
&quot;You successfully imported me!&quot;
nix-repl&gt; a.b
12</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>If path supplied to the <code>import</code> function is a directory,
the file default.nix in that directory is imported.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The scope of the imported file does not inherit the scope of the importer.</p>
</div>
<div class="listingblock">
<div class="title">b.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>x <span class="tok-o">+</span> <span class="tok-mi">7</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; x = 12
nix-repl&gt; y = import ./b.nix
nix-repl&gt; y
error:
… while calling the &#39;import&#39; builtin
at «string»:1:2:
1| import ./b.nix
| ^
error: undefined variable &#39;x&#39;
at /home/amy/codeberg/nix-book/b.nix:1:1:
1| x + 7
| ^
2|</code></pre>
</div>
</div>
<div class="paragraph">
<p>So to pass information when importing something, use a function.</p>
</div>
<div class="listingblock">
<div class="title">c.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>x<span class="tok-p">:</span> x <span class="tok-o">+</span> <span class="tok-mi">7</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; f = import ./c.nix
nix-repl&gt; f 12
19</code></pre>
</div>
</div>
<div class="paragraph">
<p>The imported file may import other files, which may in turn import more files.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_nixpkgs">3. Nixpkgs</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Nix Packages collection (nixpkgs) is a large set of Nix expressions containing hundreds of software packages.
The collection includes functions, definitions and other tools provided by Nix for
creating, using, and maintaining Nix packages.
This chapter will explore some of the most useful tools provided by nixpkgs.</p>
</div>
<div class="paragraph">
<p>In order to use nixpkgs, you must import it.
As discussed in <a href="#type-path">Section 2.2.5, &#8220;Paths&#8221;</a>, enclosing a path in angle brackets, e.g. &lt;nixpkgs&gt; causes the directories
listed in the environment variable NIX_PATH to be searched for the given
file or directory name.
In the REPL, the command <code>:l &lt;nixpkgs&gt;</code> will import nixpkgs.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; :l &lt;nixpkgs&gt;
Added 25694 variables.</code></pre>
</div>
</div>
<div class="paragraph">
<p>Alternatively, you can automatically import nixpkgs when you enter the REPL
using the command <code>nix repl '&lt;nixpkgs&gt;'</code>.</p>
</div>
<div class="paragraph">
<p>Within a Nix flake or module, you would use the <code>import</code> command.
For example,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-k">with</span> <span class="tok-p">(</span><span class="tok-nb">import</span> <span class="tok-l">&lt;nixpkgs&gt;</span> <span class="tok-p">{});</span> <span class="tok-o">...</span></code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>When you import nixpkgs, you are importing a file, which imports other files, which import still more files.
You can find the location of the nixpkgs directory.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; &lt;nixpkgs&gt;
/nix/store/5izw1shpjxb9qhlf67bx427cih5czj8w-source</code></pre>
</div>
</div>
<div class="paragraph">
<p>In that directory is a file called <code>default.nix</code>, which is what is actually imported.
That file contains an import directive, which triggers more imports, and so on.
As a result, tens of thousands of variables are added to the scope.
Don&#8217;t worry; this doesn&#8217;t cause those hundreds of packages to be installed on your system.
It merely gives you access to the recipes for those packages,
plus some tools for working with packages.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This chapter will focus on a few especially useful Nixpkgs library functions.
You can find a full list in the
<a href="https://nixos.org/manual/nixpkgs/unstable/#sec-functions-library">Nixpkgs manual</a>.</p>
</div>
<div class="sect2">
<h3 id="genAttrs">3.1. <code>lib.genAttrs</code></h3>
<div class="paragraph">
<p>The function
<a href="https://nixos.org/manual/nixpkgs/stable/#function-library-lib.attrsets.genAttrs"><code>lib.genAttrs</code></a>
generates an attribute set by mapping a function over a list of attribute names.
It is an alias for <code>lib.attrsets.genAttrs</code>.</p>
</div>
<div class="paragraph">
<p>It takes two arguments:
- names of values in the resulting attribute set
- a function which, given the name of the attribute, returns the attribute&#8217;s value</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; lib.genAttrs [ &quot;x86_64-linux&quot; &quot;aarch64-linux&quot; ] (system: &quot;some definitions for ${system}&quot;)
{
aarch64-linux = &quot;some definitions for aarch64-linux&quot;;
x86_64-linux = &quot;some definitions for x86_64-linux&quot;;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>As we shall see later, this is very useful when writing flakes.</p>
</div>
</div>
<div class="sect2">
<h3 id="getExe">3.2. <code>lib.getExe</code> and <code>lib.getExe'</code></h3>
<div class="paragraph">
<p>The function
<a href="https://nixos.org/manual/nixpkgs/stable/#function-library-lib.meta.getExe"><code>lib.getExe</code></a>
returns the path to the main program of a package.
It is an alias for <code>lib.meta.getExe</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; system = &quot;x86_64-linux&quot;
nix-repl&gt; pkgs = import &lt;nixpkgs&gt; { inherit system; }
nix-repl&gt; lib.getExe pkgs.hello
&quot;/nix/store/s9p0adfpzarzfa5kcnqhwargfwiq8qmj-hello-2.12.2/bin/hello&quot;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The function
<a href="https://nixos.org/manual/nixpkgs/stable/#function-library-lib.meta.getExe"><code>lib.getExe'</code></a>
returns the path to the specified program of a package.
It is an alias for <code>lib.meta.getExe'</code>.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; lib.getExe&#39; pkgs.imagemagick &quot;convert&quot;
&quot;/nix/store/rn6ck85zkpkgdnm00jmn762z22wz86w6-imagemagick-7.1.2-3/bin/convert&quot;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="flakeExposed">3.3. <code>lib.systems.flakeExposed</code></h3>
<div class="paragraph">
<p>This attribute is a list of systems that can support flakes.</p>
</div>
<div class="listingblock">
<div class="title">Example</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><span></span>nix-repl&gt; lib.systems.flakeExposed
[
&quot;x86_64-linux&quot;
&quot;aarch64-linux&quot;
&quot;x86_64-darwin&quot;
&quot;armv6l-linux&quot;
&quot;armv7l-linux&quot;
&quot;i686-linux&quot;
&quot;aarch64-darwin&quot;
&quot;powerpc64le-linux&quot;
&quot;riscv64-linux&quot;
&quot;x86_64-freebsd&quot;
]</code></pre>
</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This attribute is considered experimental and is subject to change.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="mkShell">3.4. <code>pkgs.mkShell</code> and <code>pkgs.mkShellNoCC</code></h3>
<div class="paragraph">
<p>The function
<a href="https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell"><code>pkgs.mkShell</code></a>
defines a Bash environment.
It is a wrapper around <code>stdenv.mkDerivation</code>, discussed in <a href="#mkDerivation">Section 3.5, &#8220;<code>stdenv.mkDerivation</code>&#8221;</a>.</p>
</div>
<div class="paragraph">
<p>The following attributes are accepted,
along with all attributes of <code>stdenv.mkDerivation</code>.</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">attribute</th>
<th class="tableblock halign-left valign-top">description</th>
<th class="tableblock halign-left valign-top">default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>name</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">the name of the derivation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>nix-shell</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>packages</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">executable packages to add the shell</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>[]</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>inputsFrom</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">build dependencies to add to the shell</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>[]</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>shellHook</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bash statements to be executed by the shell</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>""</code></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>If you don&#8217;t need a C compiler, you can use <code>mkShellNoCC</code> instead.</p>
</div>
</div>
<div class="sect2">
<h3 id="mkDerivation">3.5. <code>stdenv.mkDerivation</code></h3>
<div class="paragraph">
<p>The function
<a href="https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-mkShell"><code>pkgs.mkShell</code></a>
is a wrapper around the primitive <code>derivation</code> function, discussed in <a href="#derivations">Section 2.14, &#8220;Derivations&#8221;</a>.
Some of the commonly used attributes are listed below.</p>
</div>
<table class="tableblock frame-all grid-all fit-content">
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">attribute</th>
<th class="tableblock halign-left valign-top">description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>pname</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">package name</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>version</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">version number. Use <a href="https://semver.org/">semantic versioning</a>, i.e., MAJOR.MINOR.PATCH</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>src</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">location of the source files</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>unpackPhase</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bash command to copy/unpack the source files. If set to <code>"true"</code>, copies/unpacks all files in <code>src</code>, including subdirectories.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>buildPhase</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bash commands to build the package. If no action is required, use the no-op <code>":"</code> command.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>installPhase</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Bash commands to install the package into the Nix store.</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Older Nix flakes combined the package name and version number into a single <code>name</code> attribute;
however, this is now discouraged.</p>
</div>
<div class="paragraph">
<p>A complete list of phases is available in the
<a href="https://nixos.org/manual/nixpkgs/stable/#sec-stdenv-phases">Nixpkgs manual</a>.
Additional arguments are also listed in the
<a href="https://nixos.org/manual/nixpkgs/stable/#ssec-stdenv-attributes">Nixpkgs manual</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_hello_flake">4. Hello, flake!</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before learning to write Nix flakes, let&#8217;s learn how to use them. I&#8217;ve
created a simple example of a flake in this git repository:
<a href="https://codeberg.org/mhwombat/hello-flake" class="bare">https://codeberg.org/mhwombat/hello-flake</a>.
To run this flake, you don&#8217;t need to install anything;
simply run the command below.
The first time you use a flake, Nix has to fetch and build it, which
may take time. Subsequent invocations should be instantaneous.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run "git+https://codeberg.org/mhwombat/hello-flake"
Hello from your flake!</pre>
</div>
</div>
<div class="paragraph">
<p>That&#8217;s a lot to type every time we want to use this package. Instead, we
can enter a shell with the package available to us, using the
<code>nix shell</code> command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell "git+https://codeberg.org/mhwombat/hello-flake"</pre>
</div>
</div>
<div class="paragraph">
<p>In this shell, the command is on our <code>$PATH</code>, so we can execute the
command by name.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ hello-flake
Hello from your flake!</pre>
</div>
</div>
<div class="paragraph">
<p>Nix didn&#8217;t <em>install</em> the package; it merely built and placed it in a
directory called the &#8220;Nix store&#8221;. Thus we can have multiple versions
of a package without worrying about conflicts. We can find out the
location of the executable, if we&#8217;re curious.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ which hello-flake
/nix/store/pki997yy2drky7s07q1zcm9qs608y080-hello-flake/bin/hello-flake</pre>
</div>
</div>
<div class="paragraph">
<p>Once we exit that shell, the <code>hello-flake</code> command is no longer
directly available.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ exit
$ hello-flake # Fails outside development shell
bash: line 24: hello-flake: command not found</pre>
</div>
</div>
<div class="paragraph">
<p>However, we can still run the command using the store path we found
earlier. That&#8217;s not particularly convenient, but it does demonstrate
that the package remains in the store for future use.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ /nix/store/pki997yy2drky7s07q1zcm9qs608y080-hello-flake/bin/hello-flake
Hello from your flake!</pre>
</div>
</div>
<div class="sect2">
<h3 id="_flake_outputs">4.1. Flake outputs</h3>
<div class="paragraph">
<p>You can find out what packages and apps a flake provides using the <code>nix flake show</code> command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix flake show --all-systems git+https://codeberg.org/mhwombat/hello-flake
git+https://codeberg.org/mhwombat/hello-flake?ref=refs/heads/main&amp;rev=60de6f2ab044e8020d2100e0fcac57c5c1e5f8ae
├───apps
│ ├───aarch64-darwin
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───aarch64-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───armv6l-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───armv7l-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───i686-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───powerpc64le-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───riscv64-linux
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───x86_64-darwin
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ ├───x86_64-freebsd
│ │ ├───default: app: no description
│ │ └───hello: app: no description
│ └───x86_64-linux
│ ├───default: app: no description
│ └───hello: app: no description
└───packages
├───aarch64-darwin
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───aarch64-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───armv6l-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───armv7l-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───i686-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───powerpc64le-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───riscv64-linux
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───x86_64-darwin
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
├───x86_64-freebsd
│ ├───default: package 'hello-flake'
│ └───hello: package 'hello-flake'
└───x86_64-linux
├───default: package 'hello-flake'
└───hello: package 'hello-flake'</pre>
</div>
</div>
<div class="paragraph">
<p>Examining the output of this command,
we see that this flake supports multiple architectures
(aarch64-darwin, aarch64-linux, x86_64-darwin and x86_64-linux)
and provides both a package and an app called <code>hello</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_hello_flake_repo">5. The hello-flake repo</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let&#8217;s clone the repository and see how the flake is defined.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git clone https://codeberg.org/mhwombat/hello-flake
Cloning into 'hello-flake'...
$ cd hello-flake
$ ls
flake.lock
flake.nix
hello-flake
LICENSE
README.md</pre>
</div>
</div>
<div class="paragraph">
<p>This is a simple repo with just a few files. Like most git repos, it
includes <code>LICENSE</code>, which contains the software license, and <code>README.md</code>
which provides information about the repo.</p>
</div>
<div class="paragraph">
<p>The <code>hello-flake</code> file is the executable we ran earlier.
This particular executable is just a shell script, so we can view it.
It&#8217;s an extremely simple script with just two lines.</p>
</div>
<div class="listingblock">
<div class="title">hello-flake</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="bash"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-ch">#!/usr/bin/env sh</span>
<span class="tok-nb">echo</span><span class="tok-w"> </span><span class="tok-s2">&quot;Hello from your flake!&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Now that we have a copy of the repo, we can execute this script
directly.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ ./hello-flake
Hello from your flake!</pre>
</div>
</div>
<div class="paragraph">
<p>Not terribly exciting, I know. But starting with such a simple package
makes it easier to focus on the flake system without getting bogged down
in the details. We&#8217;ll make this script a little more interesting later.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s look at another file. The file that defines how to package a flake
is always called <code>flake.nix</code>.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;a very simple and friendly flake&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-parts<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:hercules-ci/flake-parts&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> inputs<span class="tok-p">@{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-parts<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span>
flake-parts<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkFlake <span class="tok-p">{</span> <span class="tok-k">inherit</span> inputs<span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">{</span>
<span class="tok-ss">systems</span> <span class="tok-o">=</span> nixpkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>systems<span class="tok-o">.</span>flakeExposed<span class="tok-p">;</span>
<span class="tok-ss">perSystem</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self&#39;<span class="tok-p">,</span> pkgs<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span> <span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>stdenv<span class="tok-o">.</span>mkDerivation <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">name</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;hello-flake&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">src</span> <span class="tok-o">=</span> <span class="tok-l">./.</span><span class="tok-p">;</span>
<span class="tok-ss">unpackPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;true&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">buildPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;:&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">installPhase</span> <span class="tok-o">=</span>
<span class="tok-s tok-s-Multiline">&#39;&#39;</span>
<span class="tok-s tok-s-Multiline"> mkdir -p $out/bin</span>
<span class="tok-s tok-s-Multiline"> cp $src/hello-flake $out/bin/hello-flake</span>
<span class="tok-s tok-s-Multiline"> chmod +x $out/bin/hello-flake</span>
<span class="tok-s tok-s-Multiline"> &#39;&#39;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span> <span class="tok-c1"># packages</span>
<span class="tok-ss">apps</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-ss">type</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;app&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">program</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>getExe&#39; self&#39;<span class="tok-o">.</span>packages<span class="tok-o">.</span>hello <span class="tok-s2">&quot;hello-flake&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span> <span class="tok-c1"># apps</span>
<span class="tok-p">};</span> <span class="tok-c1"># perSystem</span>
<span class="tok-p">};</span> <span class="tok-c1"># mkFlake</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>If this is your first time seeing a flake definition, it probably looks
intimidating.
Flakes are written in the Nix language, introduced in <a href="#_the_nix_language">Chapter 2, <em>The Nix language</em></a>.
However, you don&#8217;t really need to know Nix to follow this example.
For now, I&#8217;d like to focus on the inputs section.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>There are just two entries, one for <code>nixpkgs</code> and one for <code>flake-utils</code>.
The first one, <code>nixpkgs</code> refers to the collection of standard software
packages that can be installed with the Nix package manager. The second,
<code>flake-utils</code>, is a collection of utilities that simplify writing
flakes. The important thing to note is that the <code>hello-flake</code> package
<em>depends</em> on <code>nixpkgs</code> and <code>flake-utils</code>.</p>
</div>
<div class="paragraph">
<p>Finally, let&#8217;s look at <code>flake.lock</code>, or rather, just part of it.</p>
</div>
<div class="listingblock">
<div class="title">flake.lock</div>
<div class="content">
<pre class="pygments highlight nowrap"><code><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span></pre></div></td><td class="code"><div><pre><span></span>{
&quot;nodes&quot;: {
&quot;flake-parts&quot;: {
&quot;inputs&quot;: {
&quot;nixpkgs-lib&quot;: &quot;nixpkgs-lib&quot;
},
&quot;locked&quot;: {
&quot;lastModified&quot;: 1759362264,
&quot;narHash&quot;: &quot;sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=&quot;,
&quot;owner&quot;: &quot;hercules-ci&quot;,
&quot;repo&quot;: &quot;flake-parts&quot;,
&quot;rev&quot;: &quot;758cf7296bee11f1706a574c77d072b8a7baa881&quot;,
&quot;type&quot;: &quot;github&quot;
},
&quot;original&quot;: {
&quot;owner&quot;: &quot;hercules-ci&quot;,
&quot;repo&quot;: &quot;flake-parts&quot;,
&quot;type&quot;: &quot;github&quot;
}
},
&quot;nixpkgs&quot;: {
&quot;locked&quot;: {
&quot;lastModified&quot;: 1757873102,
&quot;narHash&quot;: &quot;sha256-kYhNxLlYyJcUouNRazBufVfBInMWMyF+44xG/xar2yE=&quot;,
&quot;owner&quot;: &quot;NixOS&quot;,
&quot;repo&quot;: &quot;nixpkgs&quot;,
&quot;rev&quot;: &quot;88cef159e47c0dc56f151593e044453a39a6e547&quot;,
&quot;type&quot;: &quot;github&quot;
},
&quot;original&quot;: {
&quot;owner&quot;: &quot;NixOS&quot;,
&quot;repo&quot;: &quot;nixpkgs&quot;,
&quot;type&quot;: &quot;github&quot;
}
},
&quot;nixpkgs-lib&quot;: {
&quot;locked&quot;: {
&quot;lastModified&quot;: 1754788789,
&quot;narHash&quot;: &quot;sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=&quot;,
&quot;owner&quot;: &quot;nix-community&quot;,
. . .
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>If <code>flake.nix</code> seemed intimidating, then this file looks like an
invocation for Cthulhu. The good news is that this file is automatically
generated; you never need to write it. It contains information about all
of the dependencies for the flake, including where they came from, the
exact version/revision, and hash. This lockfile <em>uniquely</em> specifies all
flake dependencies, (e.g., version number, branch, revision, hash), so
that <em>anyone, anywhere, any time, can re-create the exact same
environment that the original developer used.</em></p>
</div>
<div class="paragraph">
<p>No more complaints of "but it works on my machine!". That is the
benefit of using flakes.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flake_structure">6. Flake structure</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The basic structure of a flake is shown below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix">{
description = <em>package description</em>
inputs = <em>dependencies</em>
outputs = <em>what the flake produces</em>
nixConfig = <em>advanced configuration options</em>
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>description</code> part is self-explanatory; it&#8217;s just a string. You
probably won&#8217;t need <code>nixConfig</code> unless you&#8217;re doing something fancy. I&#8217;m
going to focus on what goes into the <code>inputs</code> and <code>outputs</code> sections,
and highlight some of the things I found confusing when I began using flakes.</p>
</div>
<div class="sect2">
<h3 id="flake-inputs">6.1. Inputs</h3>
<div class="paragraph">
<p>This section specifies the dependencies of a flake. It&#8217;s an <em>attribute
set</em>; it maps keys to values.</p>
</div>
<div class="paragraph">
<p>To ensure that a build is reproducible, the build step runs in a <em>pure</em>
environment with no network access. Therefore, any external dependencies
must be specified in the &#8220;inputs&#8221; section so they can be fetched in
advance (before we enter the pure environment).</p>
</div>
<div class="paragraph">
<p>Each entry in this section maps an input name to a <em>flake reference</em>.
This commonly takes the following form.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">NAME.url = URL-LIKE-EXPRESSION</pre>
</div>
</div>
<div class="paragraph">
<p>As a first example of a flake reference, all (almost all?) flakes depend on &#8220;nixpkgs&#8221;,
which is a large Git repository of programs and libraries that are
pre-packaged for Nix. We can write that as</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix">nixpkgs.url = "github:NixOS/nixpkgs/nixos-<em>version</em>";</code></pre>
</div>
</div>
<div class="paragraph">
<p>where <em>version</em> is replaced with the version number that you used to build
the package, e.g. <code>22.11</code>. Information about the latest nixpkgs releases
is available at <a href="https://status.nixos.org/" class="bare">https://status.nixos.org/</a>. You can also write the entry
without the version number</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs/nixos&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>or more simply,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;nixpkgs&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>You might be concerned that omitting the version number would make the
build non-reproducible. If someone else builds the flake, could they end
up with a different version of nixpkgs? No! remember that the lockfile
(<code>flake.lock</code>) <em>uniquely</em> specifies all flake inputs.</p>
</div>
<div class="paragraph">
<p>Git and Mercurial repositories are the most common type of flake
reference, as in the examples below.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">A Git repository</dt>
<dd>
<p><code>git+https://github.com/NixOS/patchelf</code></p>
</dd>
<dt class="hdlist1">A specific branch of a Git repository</dt>
<dd>
<p><code>git+https://github.com/NixOS/patchelf?ref=master</code></p>
</dd>
<dt class="hdlist1">A specific revision of a Git repository</dt>
<dd>
<p><br>
<code>git+https://github.com/NixOS/patchelf?ref=master&amp;rev=f34751b88bd07d7f44f5cd3200fb4122bf916c7e</code></p>
</dd>
<dt class="hdlist1">A tarball</dt>
<dd>
<p><code><a href="https://github.com/NixOS/patchelf/archive/master.tar.gz" class="bare">https://github.com/NixOS/patchelf/archive/master.tar.gz</a></code></p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>You can find more examples of flake references in the
<a href="https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html#examples">Nix
Reference Manual</a>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Although you probably won&#8217;t need to use it, there is another syntax for
flake references that you might encounter. This example</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>inputs<span class="tok-o">.</span><span class="tok-nb">import</span><span class="tok-o">-</span><span class="tok-ss">cargo</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-ss">type</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">owner</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;edolstra&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">repo</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;import-cargo&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>is equivalent to</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span>inputs<span class="tok-o">.</span><span class="tok-nb">import</span><span class="tok-o">-</span>cargo<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:edolstra/import-cargo&quot;</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Each of the <code>inputs</code> is fetched, evaluated and passed to the <code>outputs</code>
function as a set of attributes with the same name as the corresponding
input.</p>
</div>
</div>
<div class="sect2">
<h3 id="flake-outputs">6.2. Outputs</h3>
<div class="paragraph">
<p>This section is a function that essentially returns the recipe for
building the flake.</p>
</div>
<div class="paragraph">
<p>We said above that <code>inputs</code> are passed to the <code>outputs</code>, so we need to
list them as parameters. This example references the <code>import-cargo</code>
dependency defined in the previous example.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix">outputs = { self, nixpkgs, import-cargo }: {
<mark><em>definitions for outputs</em></mark>
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>So what actually goes in the highlighted section?
That depends on the programming languages your software is written in,
the build system you use, and more. There are Nix functions and tools
that can simplify much of this, and new, easier-to-use ones are released
regularly. We&#8217;ll look at some of these in the next section.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_a_generic_flake">7. A generic flake</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The previous section presented a very high-level view of flakes,
focusing on the basic structure. In this section, we will add a bit more
detail.</p>
</div>
<div class="paragraph">
<p>Flakes are written in the Nix programming language, which is a
functional language. As with most programming languages, there are many
ways to achieve the same result. Below is an example you can follow when
writing your own flakes. I&#8217;ll explain the example in some detail.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code>{
description = "<mark><em>brief package description</em></mark>";
inputs = {
<span class="highlight01">nixpkgs</span>.url = "github:NixOS/nixpkgs";
<span class="highlight03">...<em>other dependencies</em>...</span>
};
outputs = { self, <span class="highlight01">nixpkgs</span>, <span class="highlight03">...<em>other dependencies</em>...</span> ❷ }: {
devShells = <mark><em>shell definitions</em></mark>; ❸
packages = <mark><em>package definitions</em></mark>; ❹
apps = <mark><em>app definitions</em></mark>; ❺
};
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We discussed how to specify flake inputs <code></code> in the previous section, so
this part of the flake should be familiar. Remember also that any
dependencies in the input section should also be listed at the beginning
of the outputs section <code></code>.</p>
</div>
<div class="paragraph">
<p>The <code>devShells</code> attribute <code></code> specifies the environment that should be
available when doing development on the package.
This includes any tools
(e.g., compilers and other language-specific build tools and packages).
If you don&#8217;t need a special development environment, you can omit this section.</p>
</div>
<div class="paragraph">
<p>The <code>packages</code> attribute <code></code> defines the packages that this flake provides.
The definition depends on the programming languages your
software is written in, the build system you use, and more.
There are Nix functions and tools that can simplify much of this, and new,
easier-to-use ones are released regularly.
These functions are very language-specific, and not always well-documented.
We will see examples for some languages later in the tutorial.
In general, I recommend that you do a web search for
"nix <em>language-name</em>", and try to find resources that were written or updated
recently.</p>
</div>
<div class="paragraph">
<p>The <code>apps</code> attribute <code></code> identifies any applications provided by the flake.
In particular, it identifies the default executable that <code>nix run</code>
will run if you don&#8217;t specify an app.</p>
</div>
<div class="paragraph">
<p>If we want the development shell, packages, and apps
to be available for multiple systems
(e.g., <code>x86_64-linux</code>, <code>aarch64-linux</code>, <code>x86_64-darwin</code>, and
<code>aarch64-darwin</code>),
we need to provide a definition for each of those systems.
The result <em>could</em> be an outputs section like the one shown below.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code> outputs = { self, <span class="highlight01">nixpkgs</span>, <span class="highlight03">...<em>other dependencies</em>...</span> ❷ }: {
devShells.x86_64-linux.default = ...;
devShells.aarch64-linux.default = ...;
. . .
packages.x86_64-linux.my-app = ...;
packages.aarch64-linux.my-app = ...;
. . .
apps.x86_64-linux.my-app = ...;
apps.aarch64-linux.my-app = ...;
. . .
apps.x86_64-linux.default = ...;
apps.aarch64-linux.default = ...;
. . .
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>You won&#8217;t see definitions like that in most flakes.
Typically the definitions for each shell, package or app
would be identical, apart from a reference to the system name.
There are techniques and tools that allow you to write a single definition
and use it to automatically generate the definitions for multiple architectures.
We will see some examples of this later in the tutorial.</p>
</div>
<div class="paragraph">
<p>Below is a list of some functions that are commonly used in
the output section.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">General-purpose</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><a href="https://noogle.dev/f/pkgs/stdenv/mkDerivation"><code>mkDerivation</code></a>
is especially useful for the typical
<code>./configure; make; make install</code> scenario.
It&#8217;s customisable.</p>
</li>
<li>
<p><a href="https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs-mkShell"><code>mkShell</code></a>
simplifies writing a development shell definition.</p>
</li>
<li>
<p><a href="https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication"><code>writeShellApplication</code></a>
creates an executable shell script which also defines the appropriate environment.</p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">Python</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><code>buildPythonApplication</code></p>
</li>
<li>
<p><code>buildPythonPackage</code>.</p>
</li>
</ul>
</div>
</dd>
<dt class="hdlist1">Haskell</dt>
<dd>
<div class="ulist">
<ul>
<li>
<p><code>mkDerivation</code> (Haskell version, which is a wrapper around the
standard environment version)</p>
</li>
<li>
<p><code>developPackage</code></p>
</li>
<li>
<p><code>callCabal2Nix</code>.</p>
</li>
</ul>
</div>
</dd>
</dl>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p><a href="https://noogle.dev/">Noogλe</a> allows you to search for
documentation for Nix functions and other definitions.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_another_look_at_hello_flake">8. Another look at hello-flake</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Now that we have a better understanding of the structure of <code>flake.nix</code>,
let&#8217;s have a look at the one we saw earlier, in the <code>hello-flake</code> repo.
If you compare this flake definition to the colour-coded template
presented in <a href="#_a_generic_flake">Chapter 7, <em>A generic flake</em></a>, most of it should look familiar.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;a very simple and friendly flake&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span>
<span class="tok-o">.</span> <span class="tok-o">.</span> <span class="tok-o">.</span>
_SOME UNFAMILIAR STUFF_
<span class="tok-o">.</span> <span class="tok-o">.</span> <span class="tok-o">.</span>
<span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">apps</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkApp <span class="tok-p">{</span> <span class="tok-ss">drv</span> <span class="tok-o">=</span> self<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This <code>flake.nix</code> doesn&#8217;t have a <code>devShells</code> section, because development
on the current version doesn&#8217;t require anything beyond
the &#8220;bare bones&#8221; linux commands. Later we will add a feature that requires
additional development tools.</p>
</div>
<div class="paragraph">
<p>Now let&#8217;s look at the section I labeled <code>SOME UNFAMILIAR STUFF</code> and
see what it does.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"> packages = rec {
hello = pkgs.stdenv.mkDerivation rec { ❶
name = "hello-flake";
src = ./.; ❷
unpackPhase = "true";
buildPhase = ":";
installPhase =
''
mkdir -p $out/bin ❸
cp $src/hello-flake $out/bin/hello-flake ❹
chmod +x $out/bin/hello-flake ❺
'';
};</code></pre>
</div>
</div>
<div class="paragraph">
<p>This flake uses <a href="https://noogle.dev/f/pkgs/stdenv/mkDerivation"><code>mkDerivation</code></a> <code></code>
which is a very useful general-purpose package builder provided by the Nix standard
environment. It&#8217;s especially useful for the typical
<code>./configure; make; make install</code> scenario, but for this flake we don&#8217;t
even need that.</p>
</div>
<div class="paragraph">
<p>The <code>name</code> variable is the name of the flake, as it would appear in a
package listing if we were to add it to Nixpkgs or another package
collection. The <code>src</code> variable <code></code> supplies the location of the source
files, relative to <code>flake.nix</code>. When a flake is accessed for the first
time, the repository contents are fetched in the form of a tarball. The
<code>unpackPhase</code> variable indicates that we do want the tarball to be
unpacked.</p>
</div>
<div class="paragraph">
<p>The <code>buildPhase</code> variable is a sequence of Linux commands to build the
package. Typically, building a package requires compiling the source
code. However, that&#8217;s not required for a simple shell script. So
<code>buildPhase</code> consists of a single command, <code>:</code>,
which is a no-op or &#8220;do nothing&#8221; command.</p>
</div>
<div class="paragraph">
<p>The <code>installPhase</code> variable is a sequence of Linux commands that will do
the actual installation. In this case, we create a directory <code></code> for the
installation, copy the <code>hello-flake</code> script there <code></code>, and make the
script executable <code></code>. The environment variable <code>$src</code> refers to the
source directory, which we specified earlier <code></code>.</p>
</div>
<div class="paragraph">
<p>Earlier we said that the build step runs in a pure environment to ensure
that builds are reproducible. This means no Internet access; indeed no
access to any files outside the build directory. During the build and
install phases, the only commands available are those provided by the
Nix standard environment and the external dependencies identified in the
<code>inputs</code> section of the flake.</p>
</div>
<div class="sect2">
<h3 id="standard-environment">8.1. The Nix standard environment</h3>
<div class="paragraph">
<p>I&#8217;ve mentioned the Nix standard environment before, but I didn&#8217;t explain
what it is. The standard environment, or <code>stdenv</code>, refers to the
functionality that is available during the build and install phases of a
Nix package (or flake). It includes the commands listed
below.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The GNU C Compiler, configured with C and C++ support.</p>
</li>
<li>
<p>GNU coreutils (contains a few dozen standard Unix commands).</p>
</li>
<li>
<p>GNU findutils (contains find).</p>
</li>
<li>
<p>GNU diffutils (contains diff, cmp).</p>
</li>
<li>
<p>GNU sed.</p>
</li>
<li>
<p>GNU grep.</p>
</li>
<li>
<p>GNU awk.</p>
</li>
<li>
<p>GNU tar.</p>
</li>
<li>
<p>gzip, bzip2 and xz.</p>
</li>
<li>
<p>GNU Make.</p>
</li>
<li>
<p>Bash.</p>
</li>
<li>
<p>The patch command.</p>
</li>
<li>
<p>On Linux, stdenv also includes the patchelf utility.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Only a few environment variables are available. The most interesting
ones are listed below.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>$name</code> is the package name.</p>
</li>
<li>
<p><code>$src</code> refers to the source directory.</p>
</li>
<li>
<p><code>$out</code> is the path to the location in the Nix store where the package
will be added.</p>
</li>
<li>
<p><code>$system</code> is the system that the package is being built for.</p>
</li>
<li>
<p><code>$PWD</code> and <code>$TMP</code> both point to temporary build directories</p>
</li>
<li>
<p><code>$HOME</code> and <code>$PATH</code> point to nonexistent directories, so the build
cannot rely on them.</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>For more information on the standard environment, see the
<a href="https://nixos.org/manual/nixpkgs/stable/#sec-tools-of-stdenv">Nixpkgs
manual</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_a_new_flake_from_scratch">9. A new flake from scratch</h2>
<div class="sectionbody">
<div class="paragraph">
<p>At last we are ready to create a flake from scratch!
No matter what programming languages you normally use,
I recommend that you start by reading the <a href="#_bash">[_bash]</a> section.
In it, I start with an extremely simple flake, and show how to improve and extend it.</p>
</div>
<div class="paragraph">
<p>The remaining sections in this chapter are very similar;
read the one for your language of choice.
If you&#8217;re interested in a language that I haven&#8217;t covered, feel free to suggest it by creating an
<a href="https://codeberg.org/mhwombat/nix-book/issues">issue</a>.</p>
</div>
<div class="paragraph">
<p>sh: line 1: run-code-inline: command not found</p>
</div>
<div class="sect2">
<h3 id="_haskell">9.1. Haskell</h3>
<div class="paragraph">
<p>Start with an empty directory and create a git repository.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ mkdir hello-haskell
$ cd hello-haskell
$ git init
Initialized empty Git repository in /home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell/.git/</pre>
</div>
</div>
<div class="sect3">
<h4 id="_a_simple_haskell_program">9.1.1. A simple Haskell program</h4>
<div class="paragraph">
<p>Next, we&#8217;ll create a simple Haskell program.</p>
</div>
<div class="listingblock">
<div class="title">Main.hs</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="haskell"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-kr">import</span><span class="tok-w"> </span><span class="tok-nn">Network.HostName</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">::</span><span class="tok-w"> </span><span class="tok-kt">IO</span><span class="tok-w"> </span><span class="tok-nb">()</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-kr">do</span>
<span class="tok-w"> </span><span class="tok-n">putStrLn</span><span class="tok-w"> </span><span class="tok-s">&quot;Hello from Haskell inside a Nix flake!&quot;</span>
<span class="tok-w"> </span><span class="tok-n">h</span><span class="tok-w"> </span><span class="tok-ow">&lt;-</span><span class="tok-w"> </span><span class="tok-n">getHostName</span>
<span class="tok-w"> </span><span class="tok-n">putStrLn</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-s">&quot;Your hostname is: &quot;</span><span class="tok-w"> </span><span class="tok-o">++</span><span class="tok-w"> </span><span class="tok-n">h</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_the_program_manually_optional">9.1.2. Running the program manually (optional)</h4>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In this section you will learn how to do some development tasks manually, the "hard" way.
This can help you understand the distinction between Nix&#8217;s role and
the Haskell build system you&#8217;ve chosen.
Also, if you have a build problem but you&#8217;re not sure if the fault is in
your flake definition or some other configuration file,
these commands can help you narrow it down.
But you may wish to skip to the <a href="#_the_cabal_file">next section</a>
and come back here later.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Before we package the program, let&#8217;s verify that it runs. We&#8217;re going to
need Haskell. By now you&#8217;ve probably figured out that we can write a
<code>flake.nix</code> and define a development shell that includes Haskell. We&#8217;ll
do that shortly, but first I want to show you a handy shortcut. We can
launch a <em>temporary</em> shell with any Nix packages we want. This is
convenient when you just want to try out some new software and you&#8217;re
not sure if you&#8217;ll use it again. It&#8217;s also convenient when you&#8217;re not
ready to write <code>flake.nix</code> (perhaps you&#8217;re not sure what tools and
packages you need), and you want to experiment a bit first.</p>
</div>
<div class="paragraph">
<p>The command to enter a temporary shell is</p>
</div>
<div class="paragraph">
<p><code>nix shell -p <em>installables</em></code></p>
</div>
<div class="paragraph">
<p>Where <em>installables</em> are flakes and other types of packages that you need.
(You can learn more about these in the
<a href="https://nix.dev/manual/nix/stable/command-ref/new-cli/nix#installables">Nix manual</a>.)</p>
</div>
<div class="sect4">
<h5 id="_some_unsuitable_shells">Some unsuitable shells</h5>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In this section, we will try commands that fail in subtle ways.
Examining these failures will give you a much better understanding of Haskell development with Nix,
and help you avoid (or at least diagnose) similar problems in future.
If you&#8217;re impatient, you can skip to the next section to see the right way to do it.
You can come back to this section later to learn more.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Let&#8217;s enter a shell with the Glasgow Haskell Compiler ("ghc") and try to run the program.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell nixpkgs#ghc
$ runghc Main.hs # Fails
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
Use :set -v to see a list of the files searched for.
|
1 | import Network.HostName
| ^^^^^^^^^^^^^^^^^^^^^^^</pre>
</div>
</div>
<div class="paragraph">
<p>The error message tells us that we need the module <code>Network.HostName</code>.
That module is provided by the Haskell package called <code>hostname</code>.
Let&#8217;s exit that shell and try again, this time adding the <code>hostname</code> package.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ exit
$ nix shell nixpkgs#ghc nixpkgs#hostname
$ runghc Main.hs # Fails
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
Use :set -v to see a list of the files searched for.
|
1 | import Network.HostName
| ^^^^^^^^^^^^^^^^^^^^^^^</pre>
</div>
</div>
<div class="paragraph">
<p>That reason that failed is that we asked for the wrong package.
The Nix package <code>hostname</code> isn&#8217;t the Haskell package we wanted,
it&#8217;s a different package entirely (an alias for <code>hostname-net-tools</code>.)
The package we want is in the <em>package set</em> called <code>haskellPackages</code>, so we can refer to it as <code>haskellPackages.hostname</code>.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s try that again, with the correct package.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ exit
$ nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname
$ runghc Main.hs # Fails
Main.hs:1:1: error: [GHC-87110]
Could not find module Network.HostName.
Use :set -v to see a list of the files searched for.
|
1 | import Network.HostName
| ^^^^^^^^^^^^^^^^^^^^^^^</pre>
</div>
</div>
<div class="paragraph">
<p>Now what&#8217;s wrong?
The syntax we used in the <code>nix shell</code> command above is fine,
but it doesn&#8217;t make the package <em>available to GHC</em>!</p>
</div>
</div>
<div class="sect4">
<h5 id="_a_suitable_shell_for_a_quick_test">A suitable shell for a quick test</h5>
<div class="paragraph">
<p>Now we will create a shell that can run the program.
When you need support for both a language and some of
its packages, it&#8217;s best to use one of the Nix functions that are
specific to the programming language and build system.
For Haskell, we can use the <code>ghcWithPackages</code> function.
The command below is rather complex,
and a complete explanation would be rather lengthy.</p>
</div>
<div id="haskell-nix-shell" class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell --impure --expr 'with import &lt;nixpkgs&gt; {}; haskellPackages.ghcWithPackages (p: [ p.hostname ])'
$ runghc Main.hs
Hello from Haskell inside a Nix flake!
Your hostname is: wombat11k</pre>
</div>
</div>
<div class="paragraph">
<p>Success! Now we know the program works.</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_the_cabal_file">9.1.3. The cabal file</h4>
<div class="paragraph">
<p>It&#8217;s time to write a Cabal file for this program.
This is just an ordinary Cabal file; we don&#8217;t need to do anything special for Nix.</p>
</div>
<div class="listingblock">
<div class="title">hello-flake-haskell.cabal</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="cabal"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div><pre><span></span>cabal-version: 3.0
name: hello-flake-haskell
version: 1.0.0
synopsis: A simple demonstration using a Nix flake to package a Haskell program.
description:
For more information and a tutorial on how to use this package,
please see the README at &lt;https://codeberg.org/mhwombat/hello-flake-haskell#readme&gt;.
homepage: https://codeberg.org/mhwombat/nix-book
bug-reports: https://codeberg.org/mhwombat/nix-book/issues
license: GPL-3.0-only
license-file: LICENSE
author: Amy de Buitléir
maintainer: amy@nualeargais.ie
copyright: (c) 2023 Amy de Buitléir
category: Text
build-type: Simple
executable hello-flake-haskell
main-is: Main.hs
build-depends:
base,
hostname
-- NOTE: Best practice is to specify version constraints for the packages we depend on.
-- However, I&#39;m confident that this package will only be used as a Nix flake.
-- Nix will automatically ensure that anyone running this program is using the
-- same library versions that I used to build it.
default-language: Haskell2010
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_building_the_program_manually_optional">9.1.4. Building the program manually (optional)</h4>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In this section you will learn how to do some development tasks manually, the "hard" way.
This can help you understand the distinction between Nix&#8217;s role and
the Haskell build system you&#8217;ve chosen.
Also, if you have a build problem but you&#8217;re not sure if the fault is in
your flake definition or some other configuration file,
these commands can help you narrow it down.
But you may wish to skip to the <a href="#haskell-flake">next section</a>
and come back here later.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>We won&#8217;t write <code>flake.nix</code> just yet.
First we&#8217;ll try building the package manually.
(If you didn&#8217;t run the <code>nix shell</code> command from <a href="#haskell-nix-shell">earlier</a>, do so now.)</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cabal build
sh: line 42: cabal: command not found</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>cabal</code> command is provided by the <code>cabal-install</code> package.
The error happens because we don&#8217;t have <code>cabal-install</code> available
in the temporary shell.
We can correct that.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell --impure --expr 'with import &lt;nixpkgs&gt; {}; haskellPackages.ghcWithPackages (p: [ p.hostname p.cabal-install ])'</pre>
</div>
</div>
<div class="paragraph">
<p>Note that we&#8217;re now inside a temporary shell inside the previous
temporary shell! To get back to the original shell, we have to <code>exit</code>
twice.
Alternatively, we could have done <code>exit</code> followed by the
second <code>nix-shell</code> command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cabal build
. . .
Preprocessing executable 'hello-flake-haskell' for hello-flake-haskell-1.0.0...
Building executable 'hello-flake-haskell' for hello-flake-haskell-1.0.0...
[1 of 1] Compiling Main ( Main.hs, dist-newstyle/build/x86_64-linux/ghc-9.8.4/hello-flake-haskell-1.0.0/x/hello-flake-haskell/build/hello-flake-haskell/hello-flake-haskell-tmp/Main.o )
[2 of 2] Linking dist-newstyle/build/x86_64-linux/ghc-9.8.4/hello-flake-haskell-1.0.0/x/hello-flake-haskell/build/hello-flake-haskell/hello-flake-haskell</pre>
</div>
</div>
<div class="paragraph">
<p>After a lot of output messages, the build succeeds.</p>
</div>
</div>
<div class="sect3">
<h4 id="haskell-flake">9.1.5. The Nix flake</h4>
<div class="paragraph">
<p>Now we should write <code>flake.nix</code>.
We already know how to write most of the flake from the examples we did earlier.
The two parts that will be different are the development shell and the package builder.</p>
</div>
<div class="paragraph">
<p>However, there&#8217;s a <em>much</em> simpler way, using <code>haskell-flake</code>.
The following command will create <code>flake.nix</code> based on their template.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix flake init -t github:srid/haskell-flake
wrote: "/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell/flake.nix"</pre>
</div>
</div>
<div class="paragraph">
<p>Examining the flake,
you&#8217;ll notice that it is well-commented.
The only thing we need to change for now is the name in <code>packages.default</code>;
I&#8217;ve highlighted the change below.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;</span><span class="tok-p">;</span>
flake-parts<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:hercules-ci/flake-parts&quot;</span><span class="tok-p">;</span>
haskell-flake<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:srid/haskell-flake&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> inputs<span class="tok-p">@{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-parts<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span>
flake-parts<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkFlake <span class="tok-p">{</span> <span class="tok-k">inherit</span> inputs<span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">{</span>
<span class="tok-ss">systems</span> <span class="tok-o">=</span> nixpkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>systems<span class="tok-o">.</span>flakeExposed<span class="tok-p">;</span>
<span class="tok-ss">imports</span> <span class="tok-o">=</span> <span class="tok-p">[</span> inputs<span class="tok-o">.</span>haskell-flake<span class="tok-o">.</span>flakeModule <span class="tok-p">];</span>
<span class="tok-ss">perSystem</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self&#39;<span class="tok-p">,</span> pkgs<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span> <span class="tok-p">{</span>
<span class="tok-c1"># Typically, you just want a single project named &quot;default&quot;. But</span>
<span class="tok-c1"># multiple projects are also possible, each using different GHC version.</span>
haskellProjects<span class="tok-o">.</span><span class="tok-ss">default</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-c1"># The base package set representing a specific GHC version.</span>
<span class="tok-c1"># By default, this is pkgs.haskellPackages.</span>
<span class="tok-c1"># You may also create your own. See https://community.flake.parts/haskell-flake/package-set</span>
<span class="tok-c1"># basePackages = pkgs.haskellPackages;</span>
<span class="tok-c1"># Extra package information. See https://community.flake.parts/haskell-flake/dependency</span>
<span class="tok-c1">#</span>
<span class="tok-c1"># Note that local packages are automatically included in `packages`</span>
<span class="tok-c1"># (defined by `defaults.packages` option).</span>
<span class="tok-c1">#</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-c1"># aeson.source = &quot;1.5.0.0&quot;; # Override aeson to a custom version from Hackage</span>
<span class="tok-c1"># shower.source = inputs.shower; # Override shower to a custom source path</span>
<span class="tok-p">};</span>
<span class="tok-ss">settings</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-c1"># aeson = {</span>
<span class="tok-c1"># check = false;</span>
<span class="tok-c1"># };</span>
<span class="tok-c1"># relude = {</span>
<span class="tok-c1"># haddock = false;</span>
<span class="tok-c1"># broken = false;</span>
<span class="tok-c1"># };</span>
<span class="tok-p">};</span>
<span class="tok-ss">devShell</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-c1"># Enabled by default</span>
<span class="tok-c1"># enable = true;</span>
<span class="tok-c1"># Programs you want to make available in the shell.</span>
<span class="tok-c1"># Default programs can be disabled by setting to &#39;null&#39;</span>
<span class="tok-c1"># tools = hp: { fourmolu = hp.fourmolu; ghcid = null; };</span>
<span class="tok-c1"># Check that haskell-language-server works</span>
<span class="tok-c1"># hlsCheck.enable = true; # Requires sandbox to be disabled</span>
<span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-c1"># haskell-flake doesn&#39;t set the default package, but you can do it here.</span>
<span class="hll"> packages<span class="tok-o">.</span><span class="tok-ss">default</span> <span class="tok-o">=</span> self&#39;<span class="tok-o">.</span>packages<span class="tok-o">.</span>hello-flake-haskell<span class="tok-p">;</span>
</span> <span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>We also need a <code>LICENSE</code> file.
For now, this can be empty.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ touch LICENSE</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_building_the_program">9.1.6. Building the program</h4>
<div class="paragraph">
<p>Let&#8217;s try out the new flake.
Nix flakes only &#8220;see&#8221; files that are
part of the repository. We need to add all of the important files to the
repo before building or running the flake.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git add flake.nix hello-flake-haskell.cabal LICENSE Main.hs
$ nix build
warning: Git tree '/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell' is dirty
warning: creating lock file '"/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell/flake.lock"':
• Added input 'flake-parts':
'github:hercules-ci/flake-parts/758cf7296bee11f1706a574c77d072b8a7baa881?narHash=sha256-wfG0S7pltlYyZTM%2BqqlhJ7GMw2fTF4mLKCIVhLii/4M%3D' (2025-10-01)
• Added input 'flake-parts/nixpkgs-lib':
'github:nix-community/nixpkgs.lib/a73b9c743612e4244d865a2fdee11865283c04e6?narHash=sha256-x2rJ%2BOvzq0sCMpgfgGaaqgBSwY%2BLST%2BWbZ6TytnT9Rk%3D' (2025-08-10)
• Added input 'haskell-flake':
'github:srid/haskell-flake/3ab2a076aba01d932644f6f21e8aa507d28bb36b?narHash=sha256-k6ctrfZ%2B5jO1vnqmQpkog0yXcXDGDbHxF6o5MWa2vKk%3D' (2025-10-12)
• Added input 'nixpkgs':
'github:nixos/nixpkgs/362791944032cb532aabbeed7887a441496d5e6e?narHash=sha256-gKl2Gtro/LNf8P%2B4L3S2RsZ0G390ccd5MyXYrTdMCFE%3D' (2025-10-11)
warning: Git tree '/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell' is dirty</pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;ll deal with those warnings later.
The important thing for now is that the build succeeded.</p>
</div>
</div>
<div class="sect3">
<h4 id="_running_the_program">9.1.7. Running the program</h4>
<div class="paragraph">
<p>Now we can run the program.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run
warning: Git tree '/home/amy/codeberg/nix-book/source/new-flake/haskell-flake/hello-haskell' is dirty
Hello from Haskell inside a Nix flake!
Your hostname is: wombat11k</pre>
</div>
</div>
<div class="paragraph">
<p>By the way, we didn&#8217;t need to do <code>nix build</code> earlier.
The <code>nix run</code> command will first build the program for us if needed.</p>
</div>
<div class="paragraph">
<p>We&#8217;d like to share this package with others, but first we should do some
cleanup.
It&#8217;s time to deal with those warnings.
When the package was built, Nix created a <code>flake.lock</code> file.
We need to add this to the repo, and commit all important files.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git add flake.lock
$ git commit -a -m 'initial commit'
[master (root-commit) e59ea35] initial commit
5 files changed, 170 insertions(+)
create mode 100644 LICENSE
create mode 100644 Main.hs
create mode 100644 flake.lock
create mode 100644 flake.nix
create mode 100644 hello-flake-haskell.cabal</pre>
</div>
</div>
<div class="paragraph">
<p>You can test that your package is properly configured by going to
another directory and running it from there.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cd ..
$ nix run ./hello-haskell
Hello from Haskell inside a Nix flake!
Your hostname is: wombat11k</pre>
</div>
</div>
<div class="paragraph">
<p>If you move the project to a public repo, anyone can run it. Recall from
the beginning of the tutorial that you were able to run <code>hello-flake</code>
directly from my repo with the following command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">nix run "git+https://codeberg.org/mhwombat/hello-flake"</pre>
</div>
</div>
<div class="paragraph">
<p>Modify the URL accordingly and invite someone else to run your new
Haskell flake.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_python">9.2. Python</h3>
<div class="paragraph">
<p>Start with an empty directory and create a git repository.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ mkdir hello-python
$ cd hello-python
$ git init
Initialized empty Git repository in /home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python/.git/</pre>
</div>
</div>
<div class="sect3">
<h4 id="_a_simple_python_program">9.2.1. A simple Python program</h4>
<div class="paragraph">
<p>Next, we&#8217;ll create a simple Python program.</p>
</div>
<div class="listingblock">
<div class="title">hello.py</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="python"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-ch">#!/usr/bin/env python</span>
<span class="tok-k">def</span> <span class="tok-nf">main</span><span class="tok-p">():</span>
<span class="tok-nb">print</span><span class="tok-p">(</span><span class="tok-s2">&quot;Hello from inside a Python program built with a Nix flake!&quot;</span><span class="tok-p">)</span>
<span class="tok-k">if</span> <span class="tok-vm">__name__</span> <span class="tok-o">==</span> <span class="tok-s2">&quot;__main__&quot;</span><span class="tok-p">:</span>
<span class="tok-n">main</span><span class="tok-p">()</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_running_the_program_manually_optional_2">9.2.2. Running the program manually (optional)</h4>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In this section you will learn how to do some development tasks manually, the "hard" way.
This can help you understand the distinction between Nix&#8217;s role and
the Python build system you&#8217;ve chosen.
Also, if you have a build problem but you&#8217;re not sure if the fault is in
your flake definition or some other configuration file,
these commands can help you narrow it down.
But you may wish to skip to the <a href="#_configuring_setuptools">next section</a>
and come back here later.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Before we package the program, let&#8217;s verify that it runs. We&#8217;re going to
need Python. By now you&#8217;ve probably figured out that we can write a
<code>flake.nix</code> and define a development shell that includes Python. We&#8217;ll
do that shortly, but first I want to show you a handy shortcut. We can
launch a <em>temporary</em> shell with any Nix packages we want. This is
convenient when you just want to try out some new software and you&#8217;re
not sure if you&#8217;ll use it again. It&#8217;s also convenient when you&#8217;re not
ready to write <code>flake.nix</code> (perhaps you&#8217;re not sure what tools and
packages you need), and you want to experiment a bit first.</p>
</div>
<div class="paragraph">
<p>The command to enter a temporary shell is</p>
</div>
<div class="paragraph">
<p><code>nix shell -p <em>installables</em></code></p>
</div>
<div class="paragraph">
<p>Where <em>installables</em> are flakes and other types of packages that you need.
(You can learn more about these in the
<a href="https://nix.dev/manual/nix/stable/command-ref/new-cli/nix#installables">Nix manual</a>.)</p>
</div>
<div class="paragraph">
<p>Let&#8217;s enter a shell with Python so we can test the program.</p>
</div>
<div id="python-nix-shell" class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell nixpkgs#python3
$ python hello.py
Hello from inside a Python program built with a Nix flake!</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_configuring_setuptools">9.2.3. Configuring setuptools</h4>
<div class="paragraph">
<p>Next, configure the package. We&#8217;ll use Python&#8217;s
setuptools, but you can use other build tools. For more information on
setuptools, see the
<a href="https://setuptools.pypa.io/en/latest/index.html">Setuptools documentation</a>, especially the section on
<a href="https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html">pyproject.toml</a>.</p>
</div>
<div class="listingblock">
<div class="title">pyproject.toml</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="toml"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-k">[project]</span>
<span class="tok-n">name</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s2">&quot;hello&quot;</span>
<span class="tok-n">version</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s2">&quot;0.1.0&quot;</span>
<span class="tok-n">dependencies</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-p">[</span><span class="tok-w"> </span><span class="tok-p">]</span>
<span class="tok-k">[build-system]</span>
<span class="tok-n">requires</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-p">[</span><span class="tok-s2">&quot;setuptools&quot;</span><span class="tok-p">]</span>
<span class="tok-n">build-backend</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s2">&quot;setuptools.build_meta&quot;</span>
<span class="tok-k">[project.scripts]</span>
<span class="tok-n">hello</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s2">&quot;hello:main&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_building_the_program_manually_optional_2">9.2.4. Building the program manually (optional)</h4>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>In this section you will learn how to do some development tasks manually, the "hard" way.
This can help you understand the distinction between Nix&#8217;s role and
the Python build system you&#8217;ve chosen.
Also, if you have a build problem but you&#8217;re not sure if the fault is in
your flake definition or some other configuration file,
these commands can help you narrow it down.
But you may wish to skip to the <a href="#python-flake">next section</a>
and come back here later.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>We won&#8217;t write <code>flake.nix</code> just yet.
First we&#8217;ll try building the package manually.
(If you didn&#8217;t run the <code>nix shell</code> command from <a href="#python-nix-shell">earlier</a>, do so now.)</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ python -m build # Fails
/nix/store/iyff8129iampdw13nlfqalzhxy8y1hi9-python3-3.13.6/bin/python: No module named build</pre>
</div>
</div>
<div class="paragraph">
<p>The missing module error happens because we don&#8217;t have <code>build</code> available
in the temporary shell. We can fix that by adding &#8220;build&#8221; to the
temporary shell. When you need support for both a language and some of
its packages, it&#8217;s best to use one of the Nix functions that are
specific to the programming language and build system. For Python, we
can use the <code>withPackages</code> function.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix-shell -p "python3.withPackages (ps: with ps; [ build ])"</pre>
</div>
</div>
<div class="paragraph">
<p>Note that we&#8217;re now inside a temporary shell inside the previous
temporary shell! To get back to the original shell, we have to <code>exit</code>
twice.
Alternatively, we could have done <code>exit</code> followed by the
second <code>nix-shell</code> command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ python -m build</pre>
</div>
</div>
<div class="paragraph">
<p>After a lot of output messages, the build succeeds.</p>
</div>
</div>
<div class="sect3">
<h4 id="python-flake">9.2.5. The Nix flake</h4>
<div class="paragraph">
<p>Now we should write <code>flake.nix</code>.
We already know how to write most of the flake from the examples we did earlier.
The two parts that will be different are the development shell and the package builder.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s start with the development shell. It seems logical to write
something like the following.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap"> devShells = forAllSupportedSystems (system:
let
pkgs = nixpkgsFor.${system};
pythonEnv = pkgs.python3.withPackages (ps: [ ps.build ]);
in {
default = pkgs.mkShell {
packages = [ pythonEnv ];
};
});</pre>
</div>
</div>
<div class="paragraph">
<p>Note that we need the parentheses to prevent <code>python.withPackages</code> and
the argument from being processed as two separate tokens. Suppose we
wanted to work with <code>virtualenv</code> and <code>pip</code> instead of <code>build</code>. We could
write something like the following.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap"> devShells = forAllSupportedSystems (system:
let
pkgs = nixpkgsFor.${system};
pythonEnv = pkgs.python3.withPackages (ps: [ ps.virtualenv ps.pip ]);
in {
default = pkgs.mkShell {
packages = [ pythonEnv ];
};
});</pre>
</div>
</div>
<div class="paragraph">
<p>For the package builder, we can use the <code>buildPythonApplication</code>
function.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap"> packages = forAllSupportedSystems (system:
let pkgs = nixpkgsFor.${system}; in rec {
hello-flake-python = pkgs.python3Packages.buildPythonApplication {
name = "hello-flake-python";
pyproject = true;
src = ./.;
build-system = with pkgs.python3Packages; [ setuptools ];
};
});</pre>
</div>
</div>
<div class="paragraph">
<p>If you put all the pieces together, your <code>flake.nix</code> should look
something like this.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;a very simple and friendly flake written in Python&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs <span class="tok-p">}:</span>
<span class="tok-k">let</span>
<span class="tok-ss">supportedSystems</span> <span class="tok-o">=</span> nixpkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>systems<span class="tok-o">.</span>flakeExposed<span class="tok-p">;</span>
<span class="tok-ss">forAllSupportedSystems</span> <span class="tok-o">=</span> nixpkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>genAttrs supportedSystems<span class="tok-p">;</span>
<span class="tok-ss">nixpkgsFor</span> <span class="tok-o">=</span> forAllSupportedSystems <span class="tok-p">(</span>system<span class="tok-p">:</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span>
<span class="tok-k">inherit</span> system<span class="tok-p">;</span>
<span class="tok-ss">config</span> <span class="tok-o">=</span> <span class="tok-p">{</span> <span class="tok-p">};</span>
<span class="tok-ss">overlays</span> <span class="tok-o">=</span> <span class="tok-p">[</span> <span class="tok-p">];</span>
<span class="tok-p">});</span>
<span class="tok-k">in</span> <span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> forAllSupportedSystems <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> nixpkgsFor<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-p">;</span>
<span class="tok-ss">pythonEnv</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>python3<span class="tok-o">.</span>withPackages <span class="tok-p">(</span>ps<span class="tok-p">:</span> <span class="tok-p">[</span> ps<span class="tok-o">.</span>build <span class="tok-p">]);</span>
<span class="tok-k">in</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-p">[</span> pythonEnv <span class="tok-p">];</span>
<span class="tok-p">};</span>
<span class="tok-p">});</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> forAllSupportedSystems <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span> <span class="tok-ss">pkgs</span> <span class="tok-o">=</span> nixpkgsFor<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-p">;</span> <span class="tok-k">in</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello-flake-python</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>python3Packages<span class="tok-o">.</span>buildPythonApplication <span class="tok-p">{</span>
<span class="tok-ss">name</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;hello-flake-python&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">pyproject</span> <span class="tok-o">=</span> <span class="tok-no">true</span><span class="tok-p">;</span>
<span class="tok-ss">src</span> <span class="tok-o">=</span> <span class="tok-l">./.</span><span class="tok-p">;</span>
<span class="tok-ss">build-system</span> <span class="tok-o">=</span> <span class="tok-k">with</span> pkgs<span class="tok-o">.</span>python3Packages<span class="tok-p">;</span> <span class="tok-p">[</span> setuptools <span class="tok-p">];</span>
<span class="tok-p">};</span>
<span class="tok-p">});</span>
<span class="tok-ss">apps</span> <span class="tok-o">=</span> forAllSupportedSystems <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span> <span class="tok-ss">pkgs</span> <span class="tok-o">=</span> nixpkgsFor<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-p">;</span> <span class="tok-k">in</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello-flake-python</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-ss">type</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;app&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">program</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>getExe&#39; self<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello-flake-python <span class="tok-s2">&quot;hello&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello-flake-python<span class="tok-p">;</span>
<span class="tok-p">});</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_building_the_program_2">9.2.6. Building the program</h4>
<div class="paragraph">
<p>Let&#8217;s try out the new flake.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix build # Fails
error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" is not tracked by Git.
To make it visible to Nix, run:
git -C "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" add "flake.nix"</pre>
</div>
</div>
<div class="paragraph">
<p>Nix flakes only &#8220;see&#8221; files that are part of the repository.
We need to add all of the important files to the
repo before building or running the flake.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git add flake.nix setup.py hello.py
fatal: pathspec 'setup.py' did not match any files
$ nix build
error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" is not tracked by Git.
To make it visible to Nix, run:
git -C "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" add "flake.nix"</pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;ll deal with those warnings later.
The important thing for now is that the build succeeded.</p>
</div>
</div>
<div class="sect3">
<h4 id="_running_the_program_2">9.2.7. Running the program</h4>
<div class="paragraph">
<p>Now we can run the program.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run
error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" is not tracked by Git.
To make it visible to Nix, run:
git -C "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" add "flake.nix"</pre>
</div>
</div>
<div class="paragraph">
<p>By the way, we didn&#8217;t need to do <code>nix build</code> earlier.
The <code>nix run</code> command will first build the program for us if needed.</p>
</div>
<div class="paragraph">
<p>We&#8217;d like to share this package with others, but first we should do some
cleanup.
It&#8217;s time to deal with those warnings.
When the package was built, Nix created a <code>flake.lock</code> file.
We need to add this to the repo, and commit all important files.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ git add flake.lock
fatal: pathspec 'flake.lock' did not match any files
$ git commit -a -m 'initial commit'
On branch master
Initial commit
Untracked files:
(use "git add &lt;file&gt;..." to include in what will be committed)
dist/
flake.nix
hello.egg-info/
hello.py
pyproject.toml
nothing added to commit but untracked files present (use "git add" to track)</pre>
</div>
</div>
<div class="paragraph">
<p>You can test that your package is properly configured by going to
another directory and running it from there.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cd ..
$ nix run ./hello-python
error: Path 'flake.nix' in the repository "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" is not tracked by Git.
To make it visible to Nix, run:
git -C "/home/amy/codeberg/nix-book/source/new-flake/python-flake/hello-python" add "flake.nix"</pre>
</div>
</div>
<div class="paragraph">
<p>If you move the project to a public repo, anyone can run it. Recall from
the beginning of the tutorial that you were able to run <code>hello-flake</code>
directly from my repo with the following command.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">nix run "git+https://codeberg.org/mhwombat/hello-flake"</pre>
</div>
</div>
<div class="paragraph">
<p>Modify the URL accordingly and invite someone else to run your new
Python flake.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_recipes">10. Recipes</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This chapter provides examples of how to use Nix in a variety of scenarios.
Multiple types of recipes are provided are provided for some scenarios;
comparing the different recipes will help you better understand Nix.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><em>"Ad hoc" shells</em>
are useful when you want to quickly create an environment
for a one-off task.</p>
</li>
<li>
<p><em>Nix flakes</em>
are the recommended approach for development projects,
including defining environments that you will use more than once.</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_running_programs_directly_without_installing_them">10.1. Running programs directly (without installing them)</h3>
<div class="sect3">
<h4 id="_run_a_top_level_package_from_the_nixpkgsnixos_repo">10.1.1. Run a top level package from the Nixpkgs/NixOS repo</h4>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run nixpkgs#cowsay "Moo!"
______
&lt; Moo! &gt;
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="flakeref">10.1.2. Run a flake</h4>
<div class="sect4">
<h5 id="_run_a_flake_defined_in_a_local_file">Run a flake defined in a local file</h5>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run ~/codeberg/hello-flake
Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_run_a_flake_defined_in_a_remote_git_repo">Run a flake defined in a remote git repo</h5>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run git+https://codeberg.org/mhwombat/hello-flake
Hello from your flake!</pre>
</div>
</div>
<div class="paragraph">
<p>To use a package from GitHub, GitLab, or any other public platform,
modify the URL accordingly.
To run a specific branch, use the command below.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">nix run git+https://codeberg.org/mhwombat/hello-flake?ref=main</pre>
</div>
</div>
<div class="paragraph">
<p>To run a specific branch and revision, use the command below.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">nix run git+https://codeberg.org/mhwombat/hello-flake?ref=main&amp;rev=d44728bce88a6f9d1d37dbf4720ece455e997606</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_run_a_flake_defined_in_a_zip_archive">Run a flake defined in a zip archive</h5>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run https://codeberg.org/mhwombat/hello-flake/archive/main.zip
Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_run_a_flake_defined_in_a_compressed_tar_archive">Run a flake defined in a compressed tar archive</h5>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run https://codeberg.org/mhwombat/hello-flake/archive/main.tar.gz
Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_run_other_types_of_flake_references">Run other types of flake references</h5>
<div class="paragraph">
<p>See <a href="https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-reference-attributes" class="bare">https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-reference-attributes</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_ad_hoc_environments">10.2. Ad hoc environments</h3>
<div class="sect3">
<h4 id="_access_a_top_level_package_from_the_nixpkgsnixos_repo">10.2.1. Access a top level package from the Nixpkgs/NixOS repo</h4>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell nixpkgs#cowsay
$ cowsay "moo"
_____
&lt; moo &gt;
-----
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_flake">10.2.2. Access a flake</h4>
<div class="paragraph">
<p>In this example, we will use a flake defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix shell git+https://codeberg.org/mhwombat/hello-flake
$ hello-flake
Hello from your flake!</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="shebang">10.3. Scripts</h3>
<div class="paragraph">
<p>You can use <code>nix shell</code> to run scripts in arbitrary languages, providing
the necessary dependencies.
This is particularly convenient for standalone scripts
because you don&#8217;t need to create a repo and write a separate <code>flake.nix</code>.
The script should start with two <em>"shebang"</em> (<code>#!</code>) commands.
The first should invoke <code>nix</code>.
The second should declares the script interpreter and any dependencies.</p>
</div>
<div class="sect3">
<h4 id="_access_a_top_level_package_from_the_nixpkgsnixos_repo_2">10.3.1. Access a top level package from the Nixpkgs/NixOS repo</h4>
<div class="listingblock">
<div class="title">Script</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="bash"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="hll"><span class="tok-ch">#! /usr/bin/env nix</span>
</span><span class="hll"><span class="tok-c1">#! nix shell nixpkgs#hello nixpkgs#cowsay --command bash</span>
</span>hello
cowsay<span class="tok-w"> </span><span class="tok-s2">&quot;Pretty cool, huh?&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="literalblock">
<div class="title">Output</div>
<div class="content">
<pre class="nowrap">Hello, world!
___________________
&lt; Pretty cool, huh? &gt;
-------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_flake_2">10.3.2. Access a flake</h4>
<div class="paragraph">
<p>In this example, we will use a flake defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="listingblock">
<div class="title">Script</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="bash"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="hll"><span class="tok-ch">#! /usr/bin/env nix</span>
</span><span class="hll"><span class="tok-c1">#! nix shell git+https://codeberg.org/mhwombat/hello-flake --command bash</span>
</span>hello-flake
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="literalblock">
<div class="title">Output</div>
<div class="content">
<pre class="nowrap">Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_haskell_library_package_in_the_nixpkgs_repo_without_a_cabal_file">10.3.3. Access a Haskell library package in the nixpkgs repo (without a <code>.cabal</code> file)</h4>
<div class="paragraph">
<p>Occasionally you might want to run a short Haskell program that depends on a Haskell library,
but you don&#8217;t want to bother writing a cabal file.</p>
</div>
<div class="paragraph">
<p>Example: Access the <code>extra</code> package from the <code>haskellPackages</code> set in the nixpkgs repo.</p>
</div>
<div class="listingblock">
<div class="title">Script</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="haskell"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-o">/</span><span class="tok-n">usr</span><span class="tok-o">/</span><span class="tok-n">bin</span><span class="tok-o">/</span><span class="tok-n">env</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span>
<span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-n">p</span><span class="tok-w"> </span><span class="tok-s">&quot;haskellPackages.ghcWithPackages (p: [p.extra])&quot;</span>
<span class="tok-o">#!</span><span class="tok-w"> </span><span class="tok-n">nix</span><span class="tok-o">-</span><span class="tok-n">shell</span><span class="tok-w"> </span><span class="tok-o">-</span><span class="tok-n">i</span><span class="tok-w"> </span><span class="tok-n">runghc</span>
<span class="tok-kr">import</span><span class="tok-w"> </span><span class="tok-nn">Data.List.Extra</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">::</span><span class="tok-w"> </span><span class="tok-kt">IO</span><span class="tok-w"> </span><span class="tok-nb">()</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-kr">do</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">lower</span><span class="tok-w"> </span><span class="tok-s">&quot;ABCDE&quot;</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">upper</span><span class="tok-w"> </span><span class="tok-s">&quot;XYZ&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="literalblock">
<div class="title">Output</div>
<div class="content">
<pre class="nowrap">"abcde"
"XYZ"</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_python_library_package_in_the_nixpkgs_repo_without_using_a_python_builder">10.3.4. Access a Python library package in the nixpkgs repo (without using a Python builder)</h4>
<div class="paragraph">
<p>Occasionally you might want to run a short Python program that depends on a Python library,
but you don&#8217;t want to bother configuring a builder.</p>
</div>
<div class="paragraph">
<p>Example: Access the <code>html_sanitizer</code> package from the <code>python3nnPackages</code> set in the nixpkgs repo.</p>
</div>
<div class="listingblock">
<div class="title">Script</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="python"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-ch">#! /usr/bin/env nix-shell</span>
<span class="tok-c1">#! nix-shell -i python3 -p python3Packages.html-sanitizer</span>
<span class="tok-kn">from</span> <span class="tok-nn">html_sanitizer</span> <span class="tok-kn">import</span> <span class="tok-n">Sanitizer</span>
<span class="tok-n">sanitizer</span> <span class="tok-o">=</span> <span class="tok-n">Sanitizer</span><span class="tok-p">()</span> <span class="tok-c1"># default configuration</span>
<span class="tok-n">original</span><span class="tok-o">=</span><span class="tok-s1">&#39;&lt;span style=&quot;font-weight:bold&quot;&gt;some text&lt;/span&gt;&#39;</span>
<span class="tok-nb">print</span><span class="tok-p">(</span><span class="tok-s1">&#39;original: &#39;</span><span class="tok-p">,</span> <span class="tok-n">original</span><span class="tok-p">)</span>
<span class="tok-n">sanitized</span><span class="tok-o">=</span><span class="tok-n">sanitizer</span><span class="tok-o">.</span><span class="tok-n">sanitize</span><span class="tok-p">(</span><span class="tok-n">original</span><span class="tok-p">)</span>
<span class="tok-nb">print</span><span class="tok-p">(</span><span class="tok-s1">&#39;sanitized: &#39;</span><span class="tok-p">,</span> <span class="tok-n">sanitized</span><span class="tok-p">)</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="literalblock">
<div class="title">Output</div>
<div class="content">
<pre class="nowrap">original: &lt;span style="font-weight:bold"&gt;some text&lt;/span&gt;
sanitized: &lt;strong&gt;some text&lt;/strong&gt;</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_development_environments">10.4. Development environments</h3>
<div class="sect3">
<h4 id="_access_a_top_level_package_from_the_nixpkgsnixos_repo_3">10.4.1. Access a top level package from the Nixpkgs/NixOS repo</h4>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="hll"> <span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-p">[</span> pkgs<span class="tok-o">.</span>cowsay <span class="tok-p">];</span>
</span> <span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the shell.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ cowsay "Moo!" # Fails; dependency not available
bash: line 17: cowsay: command not found
$ nix develop
$ cowsay "Moo!" # Works in development environment
______
&lt; Moo! &gt;
------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_flake_3">10.4.2. Access a flake</h4>
<div class="paragraph">
<p>In this example, we will use a flake defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="hll"> hello-flake<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;git+https://codeberg.org/mhwombat/hello-flake&quot;</span><span class="tok-p">;</span>
</span> <span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils<span class="tok-p">,</span> hello-flake <span class="tok-p">}:</span>
</span> flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="hll"> <span class="tok-ss">buildInputs</span> <span class="tok-o">=</span> <span class="tok-p">[</span> hello-flake<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello <span class="tok-p">];</span>
</span> <span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Line 5 adds <code>hello-flake</code> as an input to this flake.
Line 8 allows the output function to reference <code>hello-flake</code>.
Line 16 adds <code>hello-flake</code> as a build input for this flake.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s take a closer look at the <code>buildInputs</code> expression from line 16.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">hello-flake.packages.${system}.hello</pre>
</div>
</div>
<div class="paragraph">
<p>Why is the first part <code>hello-flake</code> and the last part <code>hello</code>?
The first part refers to the name we assigned in the input section of our flake,
and the last part is the name of the package or app we want.
(See <a href="#_flake_outputs">Section 4.1, &#8220;Flake outputs&#8221;</a> for how to identify flake outputs.)</p>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the shell.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ hello-flake # Fails; dependency not available
bash: line 35: hello-flake: command not found
$ nix develop
$ hello-flake # Works in development environment
Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_haskell_library_package_in_the_nixpkgs_repo_without_using_a_cabal_file">10.4.3. Access a Haskell library package in the nixpkgs repo (without using a <code>.cabal</code> file)</h4>
<div class="paragraph">
<p>Occasionally you might want to run a short Haskell program that depends on a Haskell library,
but you don&#8217;t want to bother writing a cabal file.
In this example, we will access the <code>extra</code> package from the <code>haskellPackages</code> set in the nixpkgs repo.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>For non-trivial Haskell development projects,
it&#8217;s usually more convenient to use <code>haskell-flake</code> as described in <a href="#haskell-flake">Section 9.1.5, &#8220;The Nix flake&#8221;</a>,
together with the <em>high-level workflow</em> described in <a href="#_development_workflows">[_development_workflows]</a>.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">customGhc</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>haskellPackages<span class="tok-o">.</span>ghcWithPackages <span class="tok-p">(</span>p<span class="tok-p">:</span> <span class="tok-k">with</span> p<span class="tok-p">;</span> <span class="tok-p">[</span> p<span class="tok-o">.</span>extra <span class="tok-p">]);</span>
</span> <span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="hll"> <span class="tok-ss">buildInputs</span> <span class="tok-o">=</span> <span class="tok-p">[</span> customGhc <span class="tok-p">];</span>
</span> <span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Line 12 makes a custom GHC that knows about <code>extra</code>,
and line 16 makes that custom GHC available in the development environment.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s a short Haskell program that uses the new flake.</p>
</div>
<div class="listingblock">
<div class="title">Main.hs</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="haskell"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-kr">import</span><span class="tok-w"> </span><span class="tok-nn">Data.List.Extra</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">::</span><span class="tok-w"> </span><span class="tok-kt">IO</span><span class="tok-w"> </span><span class="tok-nb">()</span>
<span class="tok-nf">main</span><span class="tok-w"> </span><span class="tok-ow">=</span><span class="tok-w"> </span><span class="tok-kr">do</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">lower</span><span class="tok-w"> </span><span class="tok-s">&quot;ABCDE&quot;</span>
<span class="tok-w"> </span><span class="tok-n">print</span><span class="tok-w"> </span><span class="tok-o">$</span><span class="tok-w"> </span><span class="tok-n">upper</span><span class="tok-w"> </span><span class="tok-s">&quot;XYZ&quot;</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the program.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ runghc Main.hs # Fails; dependency not available
Main.hs:1:1: error: [GHC-87110]
Could not find module Data.List.Extra.
Use :set -v to see a list of the files searched for.
|
1 | import Data.List.Extra
| ^^^^^^^^^^^^^^^^^^^^^^
$ nix develop
$ runghc Main.hs # Works in development environment
"abcde"
"XYZ"</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_set_an_environment_variable">10.4.4. Set an environment variable</h4>
<div class="paragraph">
<p>Set the value of the environment variable FOO to “bar”.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="tok-ss">shellHook</span> <span class="tok-o">=</span> <span class="tok-s tok-s-Multiline">&#39;&#39;</span>
<span class="tok-s tok-s-Multiline"> export FOO=&quot;bar&quot;</span>
<span class="tok-s tok-s-Multiline"> &#39;&#39;</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the shell.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ echo "FOO=${FOO}"
FOO=
$ nix develop
$ echo "FOO=${FOO}"
FOO=bar</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="devshell-nix-non-flake">10.4.5. Access a non-flake package (not in nixpkgs)</h4>
<div class="paragraph">
<p>In this example, we will use a nix package (not a flake) defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="paragraph">
<p>The <code>hello-nix</code> <a href="https://codeberg.org/mhwombat/hello-nix">repo</a> provides a <code>default.nix</code>.
If the derivation in that file allows us to supply our own package set,
then our flake can call it to build <code>hello nix</code>.
If instead it requires <code>&lt;nixpkgs&gt;</code>, it is not pure and we cannot use it.</p>
</div>
<div class="paragraph">
<p>For example, if the file begins with an expression such as</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-k">with</span> <span class="tok-p">(</span><span class="tok-nb">import</span> <span class="tok-l">&lt;nixpkgs&gt;</span> <span class="tok-p">{});</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>then it requires <code>nixpkgs</code> so we cannot use it.
Instead, we have to write our own derivation (see <a href="#devshell-impure">Section 10.4.5.2, &#8220;If the nix derivation requires <code>nixpkgs</code>&#8221;</a>).</p>
</div>
<div class="paragraph">
<p>Fortunately the file begins with</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span><span class="tok-p">{</span> pkgs <span class="tok-o">?</span> <span class="tok-nb">import</span> <span class="tok-l">&lt;nixpkgs&gt;</span> <span class="tok-p">{}</span> <span class="tok-p">}:</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>then it accepts a package set as an argument,
only using <code>&lt;nixpkgs&gt;</code> if no argument is provided.
We can use it directly to build <code>hello-nix</code> (see <a href="#devshell-pure">Section 10.4.5.1, &#8220;If the nix derivation does not require nixpkgs&#8221;</a>).</p>
</div>
<div class="sect4">
<h5 id="devshell-pure">If the nix derivation does not require nixpkgs</h5>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="hll"> <span class="tok-ss">hello-nix</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
</span><span class="hll"> <span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;git+https://codeberg.org/mhwombat/hello-nix&quot;</span><span class="tok-p">;</span>
</span><span class="hll"> <span class="tok-ss">flake</span> <span class="tok-o">=</span> <span class="tok-no">false</span><span class="tok-p">;</span>
</span><span class="hll"> <span class="tok-p">};</span>
</span> <span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils<span class="tok-p">,</span> hello-nix <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span>
<span class="tok-k">inherit</span> system<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">helloNix</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> hello-nix <span class="tok-p">{</span> <span class="tok-k">inherit</span> pkgs<span class="tok-p">;</span> <span class="tok-p">};</span>
</span> <span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">devShells</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>mkShell <span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-p">[</span> helloNix <span class="tok-p">];</span>
<span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Lines 5-8 fetches the git repo for <code>hello-nix</code>.
However, it is not a flake, so we have to build it;
this is done in line 15.</p>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the shell.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ hello-nix # Fails outside development shell
bash: line 53: hello-nix: command not found
$ nix develop
$ hello-nix
Hello from your nix package!</pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="devshell-impure">If the nix derivation requires <code>nixpkgs</code></h5>
<div class="paragraph">
<p>In this case, we need to write the derivation ourselves.
We can use <code>default.nix</code> (from the hello-nix repo) as a model.
Line 15 should be replaced with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><span></span> <span class="tok-ss">helloNix</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>stdenv<span class="tok-o">.</span>mkDerivation <span class="tok-p">{</span>
<span class="tok-ss">name</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;hello-nix&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">src</span> <span class="tok-o">=</span> hello-nix<span class="tok-p">;</span>
<span class="tok-ss">installPhase</span> <span class="tok-o">=</span>
<span class="tok-s tok-s-Multiline">&#39;&#39;</span>
<span class="tok-s tok-s-Multiline"> mkdir -p $out/bin</span>
<span class="tok-s tok-s-Multiline"> cp $src/hello-nix $out/bin/hello-nix</span>
<span class="tok-s tok-s-Multiline"> chmod +x $out/bin/hello-nix</span>
<span class="tok-s tok-s-Multiline"> &#39;&#39;</span><span class="tok-p">;</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_buildruntime_environments">10.5. Build/runtime environments</h3>
<div class="paragraph">
<p>sh: line 1: run-code-inline: command not found</p>
</div>
<div class="sect3">
<h4 id="_access_a_flake_4">10.5.1. Access a flake</h4>
<div class="paragraph">
<p>In this example, we will use a flake defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="listingblock">
<div class="title">hello-again</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="bash"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-ch">#!/usr/bin/env sh</span>
<span class="tok-nb">echo</span><span class="tok-w"> </span><span class="tok-s2">&quot;I&#39;m a flake, and I&#39;m running a command defined in a another flake.&quot;</span>
hello-flake
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="hll"> hello-flake<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;git+https://codeberg.org/mhwombat/hello-flake&quot;</span><span class="tok-p">;</span>
</span> <span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils<span class="tok-p">,</span> hello-flake <span class="tok-p">}:</span>
</span> flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>stdenv<span class="tok-o">.</span>mkDerivation <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">name</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;hello-again&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">src</span> <span class="tok-o">=</span> <span class="tok-l">./.</span><span class="tok-p">;</span>
<span class="tok-ss">unpackPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;true&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">buildPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;:&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">installPhase</span> <span class="tok-o">=</span>
<span class="tok-s tok-s-Multiline">&#39;&#39;</span>
<span class="tok-s tok-s-Multiline"> mkdir -p $out/bin</span>
<span class="tok-s tok-s-Multiline"> cp $src/hello-again $out/bin</span>
<span class="tok-s tok-s-Multiline"> chmod +x $out/bin/hello-again</span>
<span class="hll"><span class="tok-s tok-s-Multiline"> # modify the hello-again script so it can find hello-flake</span>
</span><span class="hll"><span class="tok-s tok-s-Multiline"> HELLO=$(type -p hello-flake)</span>
</span><span class="hll"><span class="tok-s tok-s-Multiline"> sed &quot;s_hello-flake_&quot;$HELLO&quot;_&quot; --in-place $out/bin/hello-again</span>
</span><span class="tok-s tok-s-Multiline"> &#39;&#39;</span><span class="tok-p">;</span>
<span class="hll"> <span class="tok-ss">buildInputs</span> <span class="tok-o">=</span> <span class="tok-p">[</span> hello-flake<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello <span class="tok-p">];</span>
</span> <span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">apps</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkApp <span class="tok-p">{</span> <span class="tok-ss">drv</span> <span class="tok-o">=</span> self<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Line 5 adds <code>hello-flake</code> as an input to this flake,
Line 8 allows the output function to reference <code>hello-flake</code>.
As expected, we need to add <code>hello-flake</code> as a build input, which we do in line 35.
Let&#8217;s take a closer look at the <code>buildInputs</code> expression from line 35.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">hello-flake.packages.${system}.hello</pre>
</div>
</div>
<div class="paragraph">
<p>Why is the first part <code>hello-flake</code> and the last part <code>hello</code>?
The first part refers to the name we assigned in the input section of our flake,
and the last part is the name of the package or app we want.
(See <a href="#_flake_outputs">Section 4.1, &#8220;Flake outputs&#8221;</a> for how to identify flake outputs.)</p>
</div>
<div class="paragraph">
<p>Line 35 does make <code>hello-flake</code> available at build and runtime,
but it doesn&#8217;t put it on the path,
so our <code>hello-again</code> script won&#8217;t be able to find it.
There are various ways to deal with this problem.
In this case we simply edited the script (lines 30-32) as we install it,
by specifying the full path to <code>hello-nix</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>When you&#8217;re packaging a program written in a more powerful language such as
Haskell, Python, Java, C, C#, or Rust,
the language build system will usually do all that is required
to make the dependencies visible to the program at runtime.
In that case, adding the dependency to <code>buildInputs</code> is sufficient.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the flake.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run
I'm a flake, and I'm running a command defined in a another flake.
Hello from your flake!</pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_haskell_library_package_in_the_nixpkgs_repo">10.5.2. Access a Haskell library package in the nixpkgs repo</h4>
<div class="paragraph">
<p>If you use <code>haskell-flake</code> (see <a href="#haskell-flake">Section 9.1.5, &#8220;The Nix flake&#8221;</a>)
nothing special needs to be added to <code>flake.nix</code>.
Simply list your Haskell package dependencies to your cabal file as you normally would.</p>
</div>
</div>
<div class="sect3">
<h4 id="_access_to_a_haskell_package_defined_in_a_flake">10.5.3. Access to a Haskell package defined in a flake</h4>
<div class="paragraph">
<p>In this example we will access three Haskell packages
(<code>pandoc-linear-table</code>, <code>pandoc-logic-proof</code>, and <code>pandoc-columns</code>)
that are defined as flakes on my hard drive.
We are using <code>haskell-flake</code>, so the development environment is
set up automatically; no need to define <code>devShells</code>.</p>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">description</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;Pandoc build system for maths web&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;</span><span class="tok-p">;</span>
flake-parts<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:hercules-ci/flake-parts&quot;</span><span class="tok-p">;</span>
haskell-flake<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:srid/haskell-flake&quot;</span><span class="tok-p">;</span>
<span class="hll"> pandoc-linear-table<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;/home/amy/github/pandoc-linear-table&quot;</span><span class="tok-p">;</span>
</span><span class="hll"> pandoc-logic-proof<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;/home/amy/github/pandoc-logic-proof&quot;</span><span class="tok-p">;</span>
</span><span class="hll"> pandoc-columns<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;/home/amy/github/pandoc-columns&quot;</span><span class="tok-p">;</span>
</span><span class="hll"> pandoc-query<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;/home/amy/codeberg/pandoc-query&quot;</span><span class="tok-p">;</span>
</span> <span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">outputs</span> <span class="tok-o">=</span> inputs<span class="tok-p">@{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-parts<span class="tok-p">,</span> pandoc-linear-table<span class="tok-p">,</span> pandoc-logic-proof<span class="tok-p">,</span> pandoc-columns<span class="tok-p">,</span> pandoc-query<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span>
</span> flake-parts<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkFlake <span class="tok-p">{</span> <span class="tok-k">inherit</span> inputs<span class="tok-p">;</span> <span class="tok-p">}</span> <span class="tok-p">{</span>
<span class="tok-ss">systems</span> <span class="tok-o">=</span> nixpkgs<span class="tok-o">.</span>lib<span class="tok-o">.</span>systems<span class="tok-o">.</span>flakeExposed<span class="tok-p">;</span>
<span class="tok-ss">imports</span> <span class="tok-o">=</span> <span class="tok-p">[</span> inputs<span class="tok-o">.</span>haskell-flake<span class="tok-o">.</span>flakeModule <span class="tok-p">];</span>
<span class="tok-ss">perSystem</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self&#39;<span class="tok-p">,</span> pkgs<span class="tok-p">,</span> <span class="tok-o">...</span> <span class="tok-p">}:</span> <span class="tok-p">{</span>
haskellProjects<span class="tok-o">.</span><span class="tok-ss">default</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
<span class="tok-c1"># use my versions of some Haskell pagkages instead of the nixpkgs versions</span>
<span class="hll"> <span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
</span><span class="hll"> pandoc-linear-table<span class="tok-o">.</span><span class="tok-ss">source</span> <span class="tok-o">=</span> inputs<span class="tok-o">.</span>pandoc-linear-table<span class="tok-p">;</span>
</span><span class="hll"> pandoc-logic-proof<span class="tok-o">.</span><span class="tok-ss">source</span> <span class="tok-o">=</span> inputs<span class="tok-o">.</span>pandoc-logic-proof<span class="tok-p">;</span>
</span><span class="hll"> pandoc-columns<span class="tok-o">.</span><span class="tok-ss">source</span> <span class="tok-o">=</span> inputs<span class="tok-o">.</span>pandoc-columns<span class="tok-p">;</span>
</span><span class="hll"> pandoc-query<span class="tok-o">.</span><span class="tok-ss">source</span> <span class="tok-o">=</span> inputs<span class="tok-o">.</span>pandoc-query<span class="tok-p">;</span>
</span><span class="hll"> <span class="tok-p">};</span>
</span> <span class="tok-p">};</span>
<span class="tok-c1"># haskell-flake doesn&#39;t set the default package, but you can do it here.</span>
packages<span class="tok-o">.</span><span class="tok-ss">default</span> <span class="tok-o">=</span> self&#39;<span class="tok-o">.</span>packages<span class="tok-o">.</span>pandoc-maths-web<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_access_a_non_flake_package_not_in_nixpkgs">10.5.4. Access a non-flake package (not in nixpkgs)</h4>
<div class="paragraph">
<p>In this example, we will use a nix package (not a flake) defined in a remote git repo.
However, you can use any of the flake reference styles defined in <a href="#flakeref">Section 10.1.2, &#8220;Run a flake&#8221;</a>.</p>
</div>
<div class="paragraph">
<p>We already covered how to add a non-flake input to a flake and build it in <a href="#devshell-nix-non-flake">Section 10.4.5, &#8220;Access a non-flake package (not in nixpkgs)&#8221;</a>;
here we will focus on making it available at runtime.
We will write a flake to package a very simple shell script.
All it does is invoke <code>hello-nix</code>, which is the input we added <a href="#devshell-nix-non-flake">earlier</a>.</p>
</div>
<div class="listingblock">
<div class="title">hello-again</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="bash"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-ch">#!/usr/bin/env sh</span>
<span class="tok-nb">echo</span><span class="tok-w"> </span><span class="tok-s2">&quot;I&#39;m a flake, but I&#39;m running a command defined in a non-flake package.&quot;</span>
hello-nix
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">flake.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-p">{</span>
<span class="tok-ss">inputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
nixpkgs<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:NixOS/nixpkgs&quot;</span><span class="tok-p">;</span>
flake-utils<span class="tok-o">.</span><span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;github:numtide/flake-utils&quot;</span><span class="tok-p">;</span>
<span class="hll"> <span class="tok-ss">hello-nix</span> <span class="tok-o">=</span> <span class="tok-p">{</span>
</span><span class="hll"> <span class="tok-ss">url</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;git+https://codeberg.org/mhwombat/hello-nix&quot;</span><span class="tok-p">;</span>
</span><span class="hll"> <span class="tok-ss">flake</span> <span class="tok-o">=</span> <span class="tok-no">false</span><span class="tok-p">;</span>
</span><span class="hll"> <span class="tok-p">};</span>
</span> <span class="tok-p">};</span>
<span class="tok-ss">outputs</span> <span class="tok-o">=</span> <span class="tok-p">{</span> self<span class="tok-p">,</span> nixpkgs<span class="tok-p">,</span> flake-utils<span class="tok-p">,</span> hello-nix <span class="tok-p">}:</span>
flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>eachDefaultSystem <span class="tok-p">(</span>system<span class="tok-p">:</span>
<span class="tok-k">let</span>
<span class="tok-ss">pkgs</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> nixpkgs <span class="tok-p">{</span> <span class="tok-k">inherit</span> system<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="hll"> <span class="tok-ss">helloNix</span> <span class="tok-o">=</span> <span class="tok-nb">import</span> hello-nix <span class="tok-p">{</span> <span class="tok-k">inherit</span> pkgs<span class="tok-p">;</span> <span class="tok-p">};</span>
</span> <span class="tok-k">in</span>
<span class="tok-p">{</span>
<span class="tok-ss">packages</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> pkgs<span class="tok-o">.</span>stdenv<span class="tok-o">.</span>mkDerivation <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">name</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;hello-again&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">src</span> <span class="tok-o">=</span> <span class="tok-l">./.</span><span class="tok-p">;</span>
<span class="tok-ss">unpackPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;true&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">buildPhase</span> <span class="tok-o">=</span> <span class="tok-s2">&quot;:&quot;</span><span class="tok-p">;</span>
<span class="tok-ss">installPhase</span> <span class="tok-o">=</span>
<span class="tok-s tok-s-Multiline">&#39;&#39;</span>
<span class="tok-s tok-s-Multiline"> mkdir -p $out/bin</span>
<span class="tok-s tok-s-Multiline"> cp $src/hello-again $out/bin</span>
<span class="tok-s tok-s-Multiline"> chmod +x $out/bin/hello-again</span>
<span class="hll"><span class="tok-s tok-s-Multiline"> # modify the hello-again script so it can find hello-nix</span>
</span><span class="hll"><span class="tok-s tok-s-Multiline"> HELLO=$(type -p hello-nix)</span>
</span><span class="hll"><span class="tok-s tok-s-Multiline"> sed &quot;s_hello-nix_&quot;$HELLO&quot;_&quot; --in-place $out/bin/hello-again</span>
</span><span class="tok-s tok-s-Multiline"> &#39;&#39;</span><span class="tok-p">;</span>
<span class="hll"> <span class="tok-ss">buildInputs</span> <span class="tok-o">=</span> <span class="tok-p">[</span> helloNix <span class="tok-p">];</span>
</span> <span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-ss">apps</span> <span class="tok-o">=</span> <span class="tok-k">rec</span> <span class="tok-p">{</span>
<span class="tok-ss">hello</span> <span class="tok-o">=</span> flake-utils<span class="tok-o">.</span>lib<span class="tok-o">.</span>mkApp <span class="tok-p">{</span> <span class="tok-ss">drv</span> <span class="tok-o">=</span> self<span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span>system<span class="tok-si">}</span><span class="tok-o">.</span>hello<span class="tok-p">;</span> <span class="tok-p">};</span>
<span class="tok-ss">default</span> <span class="tok-o">=</span> hello<span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-p">}</span>
<span class="tok-p">);</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Lines 5-8 and 15 were explained in <a href="#devshell-nix-non-flake">Section 10.4.5, &#8220;Access a non-flake package (not in nixpkgs)&#8221;</a>.
As expected, we need to add <code>helloNix</code> as a build input, which we do in line 40.
That does make it available at build and runtime, but it doesn&#8217;t put it on the path,
so our <code>hello-again</code> script won&#8217;t be able to find it.</p>
</div>
<div class="paragraph">
<p>There are various ways to deal with this problem.
In this case we simply edited the script (lines 34-36) as we install it,
by specifying the full path to <code>hello-nix</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>When you&#8217;re packaging a program written in a more powerful language such as
Haskell, Python, Java, C, C#, or Rust,
the language build system will usually do all that is required
to make the dependencies visible to the program at runtime.
In that case, adding the dependency to <code>buildInputs</code> is sufficient.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the flake.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix run
I'm a flake, but I'm running a command defined in a non-flake package.
Hello from your nix package!</pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_an_old_style_nix_shell_with_access_to_a_flake">10.6. An (old-style) Nix shell with access to a flake</h3>
<div class="paragraph">
<p>If you are maintaining legacy code,
you may need to provide access to a flake in a <code>nix-shell</code>.
Here&#8217;s how.</p>
</div>
<div class="listingblock">
<div class="title">shell.nix</div>
<div class="content">
<pre class="pygments highlight nowrap"><code data-lang="nix"><div class="lineno"><table class="linenotable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="tok-k">with</span> <span class="tok-p">(</span><span class="tok-nb">import</span> <span class="tok-l">&lt;nixpkgs&gt;</span> <span class="tok-p">{});</span>
<span class="tok-k">let</span>
<span class="tok-ss">hello-flake</span> <span class="tok-o">=</span> <span class="tok-p">(</span> <span class="tok-nb">builtins</span><span class="tok-o">.</span>getFlake
<span class="tok-l">git+https://codeberg.org/mhwombat/hello-flake?ref=main&amp;rev=3aa43dbe7be878dde7b2bdcbe992fe1705da3150</span>
<span class="tok-p">)</span><span class="tok-o">.</span>packages<span class="tok-o">.</span><span class="tok-si">${</span><span class="tok-nb">builtins</span><span class="tok-o">.</span>currentSystem<span class="tok-si">}</span><span class="tok-o">.</span>default<span class="tok-p">;</span>
<span class="tok-k">in</span>
mkShell <span class="tok-p">{</span>
<span class="tok-ss">buildInputs</span> <span class="tok-o">=</span> <span class="tok-p">[</span>
hello-flake
<span class="tok-p">];</span>
<span class="tok-p">}</span>
</pre></div></td></tr></table></div></code></pre>
</div>
</div>
<div class="paragraph">
<p>Here&#8217;s a demonstration using the shell.</p>
</div>
<div class="literalblock">
<div class="content">
<pre class="nowrap">$ nix-shell
$ hello-flake
Hello from your flake!</pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2025-10-14 11:02:03 IST
</div>
</div>
</body>
</html>