= A generic flake

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.

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'll explain the example in some detail.

[source,subs=quotes]
----
{
  description = "#_brief package description_#";

  inputs = {
    [.highlight01]#nixpkgs#.url = "github:NixOS/nixpkgs";
    [.highlight03]#..._other dependencies_...# ❶
  };

  outputs = { self, [.highlight01]#nixpkgs#, [.highlight03]#..._other dependencies_...# ❷ }: {

    devShells = #_shell definitions_#; ❸

    packages = #_package definitions_#; ❹

    apps = #_app definitions_#; ❺

  };
}
----

We discussed how to specify flake inputs `❶` 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 `❷`.

The `devShells` attribute `❸` 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't need a special development environment, you can omit this section.

The `packages` attribute `❹` 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 _language-name_", and try to find resources that were written or updated
recently.

The `apps` attribute `❺` identifies any applications provided by the flake.
In particular, it identifies the default executable that `nix run`
will run if you don't specify an app.


If we want the development shell, packages, and apps
to be available for multiple systems
(e.g., `x86_64-linux`, `aarch64-linux`, `x86_64-darwin`, and
`aarch64-darwin`),
we need to provide a definition for each of those systems.
The result _could_ be an outputs section like the one shown below.

[source,subs=quotes]
----
  outputs = { self, [.highlight01]#nixpkgs#, [.highlight03]#..._other dependencies_...# ❷ }: {

    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 = ...;
    . . .
  };
----

You won'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.

Below is a list of some functions that are commonly used in
the output section.

General-purpose::
- https://noogle.dev/f/pkgs/stdenv/mkDerivation[`mkDerivation`]
  is especially useful for the typical
  `./configure; make; make install` scenario.
  It's customisable.
- https://nixos.org/manual/nixpkgs/unstable/#sec-pkgs-mkShell[`mkShell`]
  simplifies writing a development shell definition.
- https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication[`writeShellApplication`]
  creates an executable shell script which also defines the appropriate environment.
Python::
- `buildPythonApplication`
- `buildPythonPackage`.
Haskell::
- `mkDerivation` (Haskell version, which is a wrapper around the
  standard environment version)
- `developPackage`
- `callCabal2Nix`.


[NOTE]
====
https://noogle.dev/[Noogλe] allows you to search for
documentation for Nix functions and other definitions.
====
