mirror of
https://codeberg.org/mhwombat/nix-book.git
synced 2026-07-17 13:35:09 +08:00
expanded
This commit is contained in:
parent
97a04e49ea
commit
90b9c96dc5
13 changed files with 288 additions and 73826 deletions
|
|
@ -8,7 +8,7 @@
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg5913"
|
id="svg5913"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||||
sodipodi:docname="wombat.svg"
|
sodipodi:docname="wombat.svg"
|
||||||
inkscape:export-filename="wombat.png"
|
inkscape:export-filename="wombat.png"
|
||||||
inkscape:export-xdpi="96"
|
inkscape:export-xdpi="96"
|
||||||
|
|
@ -27,14 +27,14 @@
|
||||||
inkscape:deskcolor="#d1d1d1"
|
inkscape:deskcolor="#d1d1d1"
|
||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
inkscape:zoom="2.4607825"
|
inkscape:zoom="2.8284271"
|
||||||
inkscape:cx="474.84896"
|
inkscape:cx="455.9071"
|
||||||
inkscape:cy="168.84873"
|
inkscape:cy="180.66578"
|
||||||
inkscape:window-width="2556"
|
inkscape:window-width="3436"
|
||||||
inkscape:window-height="1383"
|
inkscape:window-height="1383"
|
||||||
inkscape:window-x="0"
|
inkscape:window-x="0"
|
||||||
inkscape:window-y="0"
|
inkscape:window-y="0"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="0"
|
||||||
inkscape:current-layer="layer1" /><defs
|
inkscape:current-layer="layer1" /><defs
|
||||||
id="defs5910" /><g
|
id="defs5910" /><g
|
||||||
inkscape:label="Layer 1"
|
inkscape:label="Layer 1"
|
||||||
|
|
@ -73,15 +73,13 @@
|
||||||
sodipodi:nodetypes="cc" /><path
|
sodipodi:nodetypes="cc" /><path
|
||||||
style="fill:#ba9c6a;fill-opacity:1;stroke:#000000;stroke-width:0.6;stroke-linecap:round;stroke-dasharray:none;stop-color:#000000"
|
style="fill:#ba9c6a;fill-opacity:1;stroke:#000000;stroke-width:0.6;stroke-linecap:round;stroke-dasharray:none;stop-color:#000000"
|
||||||
d="m 94.548277,130.43371 c 0,0 -6.90332,-5.91092 -9.37557,-3.55446 -2.47226,2.35646 0.10844,10.24541 0.10844,10.24541 l -3.06306,-2.69648 2.34121,4.77336 -2.57053,-2.28643 3.49402,5.16987"
|
d="m 94.548277,130.43371 c 0,0 -6.90332,-5.91092 -9.37557,-3.55446 -2.47226,2.35646 0.10844,10.24541 0.10844,10.24541 l -3.06306,-2.69648 2.34121,4.77336 -2.57053,-2.28643 3.49402,5.16987"
|
||||||
id="path6412" /><g
|
id="path6412" /><path
|
||||||
id="g2485"
|
id="path6368-4"
|
||||||
transform="translate(4.3585838,0.17055041)"><path
|
style="fill:#e3dedb;stroke:#000000;stroke-width:0.4;stroke-dasharray:none;stop-color:#000000"
|
||||||
id="path6368-4"
|
d="m 114.26024,131.61933 a 1.9215461,2.2434674 65.850277 0 1 -1.26096,2.67123 1.9215461,2.2434674 65.850277 0 1 -2.83326,-0.83553 1.9215461,2.2434674 65.850277 0 1 1.26096,-2.67122 1.9215461,2.2434674 65.850277 0 1 2.83326,0.83552 z" /><path
|
||||||
style="fill:#e3dedb;stroke:#000000;stroke-width:0.4;stroke-dasharray:none;stop-color:#000000"
|
id="path11906"
|
||||||
d="m 110.09801,132.36663 a 2.2434674,1.9215461 0 0 1 -2.24346,1.92155 2.2434674,1.9215461 0 0 1 -2.24346,-1.92155 2.2434674,1.9215461 0 0 1 2.24346,-1.92154 2.2434674,1.9215461 0 0 1 2.24346,1.92154 z" /><path
|
style="fill:#000000;stroke:none;stroke-width:0.900003;stop-color:#000000"
|
||||||
id="path11906"
|
d="m 113.92504,132.07651 a 1.260413,0.73756917 60.207704 0 1 -0.0139,1.46031 1.260413,0.73756917 60.207704 0 1 -1.26632,-0.72736 1.260413,0.73756917 60.207704 0 1 0.0139,-1.4603 1.260413,0.73756917 60.207704 0 1 1.26633,0.72734 z" /><path
|
||||||
style="fill:#000000;stroke:none;stroke-width:0.900003;stop-color:#000000"
|
|
||||||
d="m 108.52917,132.54659 a 0.73756917,1.260413 5.7418555 0 1 -0.86001,1.18029 0.73756917,1.260413 5.7418555 0 1 -0.60776,-1.32787 0.73756917,1.260413 5.7418555 0 1 0.86001,-1.18028 0.73756917,1.260413 5.7418555 0 1 0.60778,1.32787 z" /></g><path
|
|
||||||
id="path12434"
|
id="path12434"
|
||||||
style="fill:#000000;fill-opacity:1;stroke-width:0.900004;stop-color:#000000"
|
style="fill:#000000;fill-opacity:1;stroke-width:0.900004;stop-color:#000000"
|
||||||
d="m 158.72308,200.87103 c -2.39891,-0.60203 -3.49657,3.28976 -5.13291,1.0768 -1.35531,-1.83291 3.89675,-2.86693 5.13291,-1.0768 z"
|
d="m 158.72308,200.87103 c -2.39891,-0.60203 -3.49657,3.28976 -5.13291,1.0768 -1.35531,-1.83291 3.89675,-2.86693 5.13291,-1.0768 z"
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
4454
index.html
4454
index.html
File diff suppressed because it is too large
Load diff
|
|
@ -84,7 +84,7 @@ the version in `result`.
|
||||||
Now we're ready to make the flake a little more interesting.
|
Now we're ready to make the flake a little more interesting.
|
||||||
Instead of using the `echo` command in the script, we can use the Linux `cowsay`
|
Instead of using the `echo` command in the script, we can use the Linux `cowsay`
|
||||||
command.
|
command.
|
||||||
Here's the `hello-flake` file, with the modified line highlighted.
|
Here's the modified `hello-flake` file.
|
||||||
|
|
||||||
////
|
////
|
||||||
$ sed -i 's/echo/cowsay/' hello-flake
|
$ sed -i 's/echo/cowsay/' hello-flake
|
||||||
|
|
@ -107,6 +107,7 @@ What went wrong? Remember that we are in a _development_ shell. Since
|
||||||
shell only includes the Nix standard environment. In particular, the
|
shell only includes the Nix standard environment. In particular, the
|
||||||
`cowsay` command is not available.
|
`cowsay` command is not available.
|
||||||
|
|
||||||
|
[#hello-flake-dependency]
|
||||||
To fix the problem, we can modify `flake.nix`.
|
To fix the problem, we can modify `flake.nix`.
|
||||||
We don't need to add `cowsay` to the `inputs` section because it's included in `nixpkgs`,
|
We don't need to add `cowsay` to the `inputs` section because it's included in `nixpkgs`,
|
||||||
which is already an input.
|
which is already an input.
|
||||||
|
|
|
||||||
7
source/new-flake/haskell-flake/Main.hs
Normal file
7
source/new-flake/haskell-flake/Main.hs
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import Network.HostName
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
putStrLn "Hello from Haskell inside a Nix flake!"
|
||||||
|
h <- getHostName
|
||||||
|
putStrLn $ "Your hostname is: " ++ h
|
||||||
|
|
@ -13,7 +13,7 @@ $ git init
|
||||||
Next, we'll create a simple Haskell program.
|
Next, we'll create a simple Haskell program.
|
||||||
|
|
||||||
////
|
////
|
||||||
$ curl https://codeberg.org/mhwombat/hello-flake-haskell/raw/branch/main/Main.hs --silent --output Main.hs
|
$ cp ../Main.hs .
|
||||||
////
|
////
|
||||||
|
|
||||||
[source,haskell,linenums]
|
[source,haskell,linenums]
|
||||||
|
|
@ -22,10 +22,22 @@ $ curl https://codeberg.org/mhwombat/hello-flake-haskell/raw/branch/main/Main.hs
|
||||||
$# cat Main.hs
|
$# cat Main.hs
|
||||||
....
|
....
|
||||||
|
|
||||||
== (Optional) Testing before packaging
|
== Running the program manually (optional)
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
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's role and
|
||||||
|
the Haskell build system you've chosen.
|
||||||
|
Also, if you have a build problem but you'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 <<_the_cabal_file,next section>>
|
||||||
|
and come back here later.
|
||||||
|
====
|
||||||
|
|
||||||
Before we package the program, let's verify that it runs. We're going to
|
Before we package the program, let's verify that it runs. We're going to
|
||||||
need a Haskell compiler. By now you've probably figured out that we can write a
|
need Haskell. By now you've probably figured out that we can write a
|
||||||
`flake.nix` and define a development shell that includes Haskell. We'll
|
`flake.nix` and define a development shell that includes Haskell. We'll
|
||||||
do that shortly, but first I want to show you a handy shortcut. We can
|
do that shortly, but first I want to show you a handy shortcut. We can
|
||||||
launch a _temporary_ shell with any Nix packages we want. This is
|
launch a _temporary_ shell with any Nix packages we want. This is
|
||||||
|
|
@ -36,21 +48,11 @@ packages you need), and you want to experiment a bit first.
|
||||||
|
|
||||||
The command to enter a temporary shell is
|
The command to enter a temporary shell is
|
||||||
|
|
||||||
`nix-shell -p __packages__`
|
`nix shell -p __installables__`
|
||||||
|
|
||||||
If there are multiple packages, they should be separated by spaces.
|
Where __installables__ are flakes and other types of packages that you need.
|
||||||
|
(You can learn more about these in the
|
||||||
[IMPORTANT]
|
https://nix.dev/manual/nix/stable/command-ref/new-cli/nix#installables[Nix manual].)
|
||||||
====
|
|
||||||
The command used here is `nix-shell` with a hyphen, not `nix shell`
|
|
||||||
with a space; those are two different commands. In fact there are
|
|
||||||
hyphenated and non-hyphenated versions of many Nix commands, and yes,
|
|
||||||
it's confusing. The non-hyphenated commands were introduced when support
|
|
||||||
for flakes was added to Nix. I predict that eventually all hyphenated
|
|
||||||
commands will be replaced with non-hyphenated versions. Until then, a
|
|
||||||
useful rule of thumb is that non-hyphenated commands are for working
|
|
||||||
directly with flakes; hyphenated commands are for everything else.
|
|
||||||
====
|
|
||||||
|
|
||||||
=== Some unsuitable shells
|
=== Some unsuitable shells
|
||||||
|
|
||||||
|
|
@ -66,8 +68,8 @@ You can come back to this section later to learn more.
|
||||||
Let's enter a shell with the Glasgow Haskell Compiler ("ghc") and try to run the program.
|
Let's enter a shell with the Glasgow Haskell Compiler ("ghc") and try to run the program.
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ nix-shell -p ghc'
|
$# echo '$ nix shell nixpkgs#ghc'
|
||||||
$# nix-shell -p ghc --command sh
|
$# nix shell nixpkgs#ghc --command sh
|
||||||
$ runghc Main.hs
|
$ runghc Main.hs
|
||||||
....
|
....
|
||||||
|
|
||||||
|
|
@ -77,8 +79,8 @@ Let's exit that shell and try again, this time adding the `hostname` package.
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ exit'
|
$# echo '$ exit'
|
||||||
$# echo '$ nix-shell -p "[ghc hostname]"'
|
$# echo '$ nix shell nixpkgs#ghc nixpkgs#hostname'
|
||||||
$# nix-shell -p "[ghc hostname]" --command sh
|
$# nix shell nixpkgs#ghc nixpkgs#hostname --command sh
|
||||||
$ runghc Main.hs
|
$ runghc Main.hs
|
||||||
....
|
....
|
||||||
|
|
||||||
|
|
@ -91,39 +93,29 @@ Let's try that again, with the correct package.
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ exit'
|
$# echo '$ exit'
|
||||||
$# echo '$ nix-shell -p "[ghc haskellPackages.hostname]"'
|
$# echo '$ nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname'
|
||||||
$# nix-shell -p "[ghc haskellPackages.hostname]" --command sh
|
$# nix shell nixpkgs#ghc nixpkgs#haskellPackages.hostname --command sh
|
||||||
$ runghc Main.hs
|
$ runghc Main.hs
|
||||||
....
|
....
|
||||||
|
|
||||||
Now what's wrong?
|
Now what's wrong?
|
||||||
The syntax we used in the `nix-shell` command above is fine, but it doesn't make the package _available to GHC_!
|
The syntax we used in the `nix shell` command above is fine,
|
||||||
|
but it doesn't make the package _available to GHC_!
|
||||||
|
|
||||||
=== A suitable shell for a quick test
|
=== A suitable shell for a quick test
|
||||||
|
|
||||||
Consider the Haskell "pandoc" package, which provides both an executable (the Nix package `pandoc`)
|
Now we will create a shell that can run the program.
|
||||||
and a library (the Nix package `haskellPackages.pandoc`).
|
When you need support for both a language and some of
|
||||||
There are several different shells we could create involving both Pandoc and GHC,
|
its packages, it's best to use one of the Nix functions that are
|
||||||
and it's important to understand the differences between them.
|
specific to the programming language and build system.
|
||||||
|
For Haskell, we can use the `ghcWithPackages` function.
|
||||||
[cols="1,1"]
|
The command below is rather complex,
|
||||||
|===
|
and a complete explanation would be rather lengthy.
|
||||||
|`nix-shell -p "[ghc pandoc]"`
|
|
||||||
|Makes the Pandoc _executable_ available at the command line, but the _library_ won't be visible to GHC.
|
|
||||||
|
|
||||||
|`nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ pandoc ])"`
|
|
||||||
|Makes the Pandoc _library_ visible to GHC, but we won't be able to run the _executable_.
|
|
||||||
|
|
||||||
|`nix-shell -p "[pandoc (haskellPackages.ghcWithPackages (pkgs: with pkgs; [ pandoc ]))]"`
|
|
||||||
|Makes the Pandoc _executable_ available at the command line, and the _library_ visible to GHC.
|
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
Now we can create a shell that can run the program.
|
|
||||||
|
|
||||||
|
[#haskell-nix-shell]
|
||||||
....
|
....
|
||||||
$# echo '$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hostname ])"'
|
$# echo '$ nix shell --impure --expr '"'"'with import <nixpkgs> {}; haskellPackages.ghcWithPackages (p: [ p.hostname ])'"'"
|
||||||
$# nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hostname ])" --command sh
|
$# nix shell --impure --expr 'with import <nixpkgs> {}; haskellPackages.ghcWithPackages (p: [ p.hostname ])' --command sh
|
||||||
$ runghc Main.hs
|
$ runghc Main.hs
|
||||||
....
|
....
|
||||||
|
|
||||||
|
|
@ -133,14 +125,13 @@ Success! Now we know the program works.
|
||||||
$# echo '$ exit'
|
$# echo '$ exit'
|
||||||
....
|
....
|
||||||
|
|
||||||
|
|
||||||
== The cabal file
|
== The cabal file
|
||||||
|
|
||||||
It's time to write a Cabal file for this program.
|
It's time to write a Cabal file for this program.
|
||||||
This is just an ordinary Cabal file; we don't need to do anything special for Nix.
|
This is just an ordinary Cabal file; we don't need to do anything special for Nix.
|
||||||
|
|
||||||
////
|
////
|
||||||
$ curl https://codeberg.org/mhwombat/hello-flake-haskell/raw/branch/main/hello-flake-haskell.cabal --silent --output hello-flake-haskell.cabal
|
$ cp ../hello-flake-haskell.cabal .
|
||||||
////
|
////
|
||||||
|
|
||||||
[source,cabal,linenums]
|
[source,cabal,linenums]
|
||||||
|
|
@ -149,55 +140,77 @@ $ curl https://codeberg.org/mhwombat/hello-flake-haskell/raw/branch/main/hello-f
|
||||||
$# cat hello-flake-haskell.cabal
|
$# cat hello-flake-haskell.cabal
|
||||||
....
|
....
|
||||||
|
|
||||||
|
== Building the program manually (optional)
|
||||||
|
|
||||||
== (Optional) Building and running with cabal-install
|
[NOTE]
|
||||||
|
====
|
||||||
At this point, I would normally write `flake.nix` and use Nix to build the program.
|
In this section you will learn how to do some development tasks manually, the "hard" way.
|
||||||
I'll cover that in the next section.
|
This can help you understand the distinction between Nix's role and
|
||||||
However, it's useful to know how to build the package manually in a Nix environment,
|
the Haskell build system you've chosen.
|
||||||
without using a Nix flake.
|
Also, if you have a build problem but you're not sure if the fault is in
|
||||||
When you're new to Nix, this can help you differentiate between problems in your flake definition
|
your flake definition or some other configuration file,
|
||||||
and problems in your Cabal file.
|
these commands can help you narrow it down.
|
||||||
|
But you may wish to skip to the <<haskell-flake,next section>>
|
||||||
|
and come back here later.
|
||||||
|
====
|
||||||
|
|
||||||
|
We won't write `flake.nix` just yet.
|
||||||
|
First we'll try building the package manually.
|
||||||
|
(If you didn't run the `nix shell` command from <<haskell-nix-shell,earlier>>, do so now.)
|
||||||
....
|
....
|
||||||
$ cabal build
|
$ cabal build
|
||||||
....
|
....
|
||||||
|
|
||||||
Aha! We need `cabal-install` in our shell.
|
The `cabal` command is provided by the `cabal-install` package.
|
||||||
Rather than launch another shell-within-a-shell, let's exit create a new one.
|
The error happens because we don't have `cabal-install` available
|
||||||
|
in the temporary shell.
|
||||||
|
We can correct that.
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ exit'
|
$# echo '$ nix shell --impure --expr '"'"'with import <nixpkgs> {}; haskellPackages.ghcWithPackages (p: [ p.hostname p.cabal-install ])'"'"
|
||||||
$# echo '$ nix-shell -p "[ cabal-install (haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hostname ]))]"'
|
$# nix shell --impure --expr 'with import <nixpkgs> {}; haskellPackages.ghcWithPackages (p: [ p.hostname p.cabal-install ])' --command sh
|
||||||
$# nix-shell -p "[ cabal-install (haskellPackages.ghcWithPackages (pkgs: with pkgs; [ hostname ]))]" --command sh
|
|
||||||
$ cabal build
|
|
||||||
$ cabal run
|
|
||||||
$# echo '$ exit'
|
|
||||||
....
|
....
|
||||||
|
|
||||||
After some output messages, the build succeeds and the program runs.
|
Note that we're now inside a temporary shell inside the previous
|
||||||
|
temporary shell! To get back to the original shell, we have to `exit`
|
||||||
|
twice.
|
||||||
|
Alternatively, we could have done `exit` followed by the
|
||||||
|
second `nix-shell` command.
|
||||||
|
|
||||||
|
....
|
||||||
|
$# echo '$ cabal build'
|
||||||
|
$# echo ". . ."
|
||||||
|
$# cabal build |& tail -n 4
|
||||||
|
....
|
||||||
|
|
||||||
|
After a lot of output messages, the build succeeds.
|
||||||
|
|
||||||
|
[#haskell-flake]
|
||||||
== The Nix flake
|
== The Nix flake
|
||||||
|
|
||||||
Now we should write `flake.nix`. We already know how to write most of
|
Now we should write `flake.nix`.
|
||||||
the flake from the examples we did earlier. The two parts that would be
|
We already know how to write most of the flake from the examples we did earlier.
|
||||||
different are the development shell and the package builder.
|
The two parts that will be different are the development shell and the package builder.
|
||||||
|
|
||||||
However, there's a simpler way, using `haskell-flake`.
|
However, there's a _much_ simpler way, using `haskell-flake`.
|
||||||
|
The following command will create `flake.nix` based on their template.
|
||||||
|
|
||||||
////
|
....
|
||||||
$ curl https://codeberg.org/mhwombat/hello-flake-haskell/raw/branch/main/flake.nix --silent --output flake.nix
|
$ nix flake init -t github:srid/haskell-flake
|
||||||
////
|
....
|
||||||
|
|
||||||
[source,nix,linenums]
|
Examining the flake,
|
||||||
|
you'll notice that it is well-commented.
|
||||||
|
The only thing we need to change for now is the name in `packages.default`;
|
||||||
|
I've highlighted the change below.
|
||||||
|
|
||||||
|
[source,nix,linenums,highlight=55]
|
||||||
.flake.nix
|
.flake.nix
|
||||||
....
|
....
|
||||||
|
$# sed -i 's/example/hello-flake-haskell/' flake.nix
|
||||||
$# cat flake.nix
|
$# cat flake.nix
|
||||||
....
|
....
|
||||||
|
|
||||||
The above definition will work for most of your haskell projects;
|
|
||||||
simply change the `description` and the package name in `packages.default`.
|
|
||||||
|
|
||||||
We also need a `LICENSE` file.
|
We also need a `LICENSE` file.
|
||||||
For now, this can be empty.
|
For now, this can be empty.
|
||||||
|
|
||||||
|
|
@ -205,25 +218,37 @@ For now, this can be empty.
|
||||||
$ touch LICENSE
|
$ touch LICENSE
|
||||||
....
|
....
|
||||||
|
|
||||||
|
== Building the program
|
||||||
|
|
||||||
Let's try out the new flake.
|
Let's try out the new flake.
|
||||||
|
Nix flakes only "`see`" files that are
|
||||||
....
|
|
||||||
$ nix run
|
|
||||||
....
|
|
||||||
|
|
||||||
Why can't it find `flake.nix`? Nix flakes only "`see`" files that are
|
|
||||||
part of the repository. We need to add all of the important files to the
|
part of the repository. We need to add all of the important files to the
|
||||||
repo before building or running the flake.
|
repo before building or running the flake.
|
||||||
|
|
||||||
....
|
....
|
||||||
$ git add flake.nix hello-flake-haskell.cabal LICENSE Main.hs
|
$ git add flake.nix hello-flake-haskell.cabal LICENSE Main.hs
|
||||||
|
$ nix build
|
||||||
|
....
|
||||||
|
|
||||||
|
We'll deal with those warnings later.
|
||||||
|
The important thing for now is that the build succeeded.
|
||||||
|
|
||||||
|
== Running the program
|
||||||
|
|
||||||
|
Now we can run the program.
|
||||||
|
|
||||||
|
....
|
||||||
$ nix run
|
$ nix run
|
||||||
....
|
....
|
||||||
|
|
||||||
|
By the way, we didn't need to do `nix build` earlier.
|
||||||
|
The `nix run` command will first build the program for us if needed.
|
||||||
|
|
||||||
We'd like to share this package with others, but first we should do some
|
We'd like to share this package with others, but first we should do some
|
||||||
cleanup. When the package was built (automatically by the `nix run`
|
cleanup.
|
||||||
command), it created a `flake.lock` file. We need to add this to the
|
It's time to deal with those warnings.
|
||||||
repo, and commit all important files.
|
When the package was built, Nix created a `flake.lock` file.
|
||||||
|
We need to add this to the repo, and commit all important files.
|
||||||
|
|
||||||
....
|
....
|
||||||
$ git add flake.lock
|
$ git add flake.lock
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,20 @@ $ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/hello.py
|
||||||
$# cat hello.py
|
$# cat hello.py
|
||||||
....
|
....
|
||||||
|
|
||||||
|
== Running the program manually (optional)
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
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's role and
|
||||||
|
the Python build system you've chosen.
|
||||||
|
Also, if you have a build problem but you'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 <<_configuring_setuptools,next section>>
|
||||||
|
and come back here later.
|
||||||
|
====
|
||||||
|
|
||||||
Before we package the program, let's verify that it runs. We're going to
|
Before we package the program, let's verify that it runs. We're going to
|
||||||
need Python. By now you've probably figured out that we can write a
|
need Python. By now you've probably figured out that we can write a
|
||||||
`flake.nix` and define a development shell that includes Python. We'll
|
`flake.nix` and define a development shell that includes Python. We'll
|
||||||
|
|
@ -34,31 +48,22 @@ packages you need), and you want to experiment a bit first.
|
||||||
|
|
||||||
The command to enter a temporary shell is
|
The command to enter a temporary shell is
|
||||||
|
|
||||||
`nix-shell -p __packages__`
|
`nix shell -p __installables__`
|
||||||
|
|
||||||
If there are multiple packages, they should be separated by spaces.
|
Where __installables__ are flakes and other types of packages that you need.
|
||||||
|
(You can learn more about these in the
|
||||||
[NOTE]
|
https://nix.dev/manual/nix/stable/command-ref/new-cli/nix#installables[Nix manual].)
|
||||||
====
|
|
||||||
The command used here is `nix-shell` with a hyphen, not `nix shell`
|
|
||||||
with a space; those are two different commands. In fact there are
|
|
||||||
hyphenated and non-hyphenated versions of many Nix commands, and yes,
|
|
||||||
it's confusing. The non-hyphenated commands were introduced when support
|
|
||||||
for flakes was added to Nix. I predict that eventually all hyphenated
|
|
||||||
commands will be replaced with non-hyphenated versions. Until then, a
|
|
||||||
useful rule of thumb is that non-hyphenated commands are for for working
|
|
||||||
directly with flakes; hyphenated commands are for everything else.
|
|
||||||
====
|
|
||||||
|
|
||||||
Let's enter a shell with Python so we can test the program.
|
Let's enter a shell with Python so we can test the program.
|
||||||
|
|
||||||
|
[#python-nix-shell]
|
||||||
....
|
....
|
||||||
$# echo '$ nix-shell -p python3'
|
$# echo '$ nix shell nixpkgs#python3'
|
||||||
$# nix-shell -p python3 --command sh
|
$# nix shell nixpkgs#python3 --command sh
|
||||||
$ python hello.py
|
$ python hello.py
|
||||||
....
|
....
|
||||||
|
|
||||||
== A Python builder
|
== Configuring setuptools
|
||||||
|
|
||||||
Next, create a Python script to build the package. We'll use Python's
|
Next, create a Python script to build the package. We'll use Python's
|
||||||
setuptools, but you can use other build tools. For more information on
|
setuptools, but you can use other build tools. For more information on
|
||||||
|
|
@ -78,9 +83,23 @@ $ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/setup.py
|
||||||
$# cat setup.py
|
$# cat setup.py
|
||||||
....
|
....
|
||||||
|
|
||||||
We won't write `flake.nix` just yet. First we'll try building the
|
== Building the program manually (optional)
|
||||||
package manually.
|
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
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's role and
|
||||||
|
the Python build system you've chosen.
|
||||||
|
Also, if you have a build problem but you'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 <<python-flake,next section>>
|
||||||
|
and come back here later.
|
||||||
|
====
|
||||||
|
|
||||||
|
We won't write `flake.nix` just yet.
|
||||||
|
First we'll try building the package manually.
|
||||||
|
(If you didn't run the `nix shell` command from <<python-nix-shell,earlier>>, do so now.)
|
||||||
....
|
....
|
||||||
$ python -m build
|
$ python -m build
|
||||||
....
|
....
|
||||||
|
|
@ -99,8 +118,9 @@ $# nix-shell -p "python3.withPackages (ps: with ps; [ build ])" --command sh
|
||||||
|
|
||||||
Note that we're now inside a temporary shell inside the previous
|
Note that we're now inside a temporary shell inside the previous
|
||||||
temporary shell! To get back to the original shell, we have to `exit`
|
temporary shell! To get back to the original shell, we have to `exit`
|
||||||
twice. Alternatively, we could have done `exit` followed by the
|
twice.
|
||||||
`nix-shell` command.
|
Alternatively, we could have done `exit` followed by the
|
||||||
|
second `nix-shell` command.
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ python -m build'
|
$# echo '$ python -m build'
|
||||||
|
|
@ -109,11 +129,12 @@ $# python -m build > /dev/null 2>&1
|
||||||
|
|
||||||
After a lot of output messages, the build succeeds.
|
After a lot of output messages, the build succeeds.
|
||||||
|
|
||||||
|
[#python-flake]
|
||||||
== The Nix flake
|
== The Nix flake
|
||||||
|
|
||||||
Now we should write `flake.nix`. We already know how to write most of
|
Now we should write `flake.nix`.
|
||||||
the flake from the examples we did earlier. The two parts that will be
|
We already know how to write most of the flake from the examples we did earlier.
|
||||||
different are the development shell and the package builder.
|
The two parts that will be different are the development shell and the package builder.
|
||||||
|
|
||||||
Let's start with the development shell. It seems logical to write
|
Let's start with the development shell. It seems logical to write
|
||||||
something like the following.
|
something like the following.
|
||||||
|
|
@ -172,10 +193,12 @@ $ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/flake.ni
|
||||||
$# cat flake.nix
|
$# cat flake.nix
|
||||||
....
|
....
|
||||||
|
|
||||||
|
== Building the program
|
||||||
|
|
||||||
Let's try out the new flake.
|
Let's try out the new flake.
|
||||||
|
|
||||||
....
|
....
|
||||||
$ nix run
|
$ nix build
|
||||||
....
|
....
|
||||||
|
|
||||||
Why can't it find `flake.nix`? Nix flakes only "`see`" files that are
|
Why can't it find `flake.nix`? Nix flakes only "`see`" files that are
|
||||||
|
|
@ -184,13 +207,28 @@ repo before building or running the flake.
|
||||||
|
|
||||||
....
|
....
|
||||||
$ git add flake.nix setup.py hello.py
|
$ git add flake.nix setup.py hello.py
|
||||||
|
$ nix build
|
||||||
|
....
|
||||||
|
|
||||||
|
We'll deal with those warnings later.
|
||||||
|
The important thing for now is that the build succeeded.
|
||||||
|
|
||||||
|
== Running the program
|
||||||
|
|
||||||
|
Now we can run the program.
|
||||||
|
|
||||||
|
....
|
||||||
$ nix run
|
$ nix run
|
||||||
....
|
....
|
||||||
|
|
||||||
|
By the way, we didn't need to do `nix build` earlier.
|
||||||
|
The `nix run` command will first build the program for us if needed.
|
||||||
|
|
||||||
We'd like to share this package with others, but first we should do some
|
We'd like to share this package with others, but first we should do some
|
||||||
cleanup. When the package was built (automatically by the `nix run`
|
cleanup.
|
||||||
command), it created a `flake.lock` file. We need to add this to the
|
It's time to deal with those warnings.
|
||||||
repo, and commit all important files.
|
When the package was built, Nix created a `flake.lock` file.
|
||||||
|
We need to add this to the repo, and commit all important files.
|
||||||
|
|
||||||
....
|
....
|
||||||
$ git add flake.lock
|
$ git add flake.lock
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
= From the command line
|
= From the command line (flake style)
|
||||||
|
|
||||||
|
....
|
||||||
|
$# echo '$ nix shell nixpkgs#hello nixpkgs#cowsay --command bash'
|
||||||
|
$# nix shell nixpkgs#hello nixpkgs#cowsay --command bash <<EOL
|
||||||
|
$ hello
|
||||||
|
$ cowsay "moo"
|
||||||
|
$# EOL
|
||||||
|
....
|
||||||
|
|
||||||
|
= From the command line (non-flake style)
|
||||||
|
|
||||||
....
|
....
|
||||||
$# echo '$ nix-shell -p "[hello cowsay]"'
|
$# echo '$ nix-shell -p "[hello cowsay]"'
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,17 @@
|
||||||
= In a Bash script
|
= In a Bash script (flake style)
|
||||||
|
|
||||||
|
[source,bash,linenums]
|
||||||
|
.Script
|
||||||
|
....
|
||||||
|
include::my-flake-script.sh[]
|
||||||
|
....
|
||||||
|
|
||||||
|
.Output
|
||||||
|
....
|
||||||
|
$# ./my-flake-script.sh
|
||||||
|
....
|
||||||
|
|
||||||
|
= In a Bash script (non-flake style)
|
||||||
|
|
||||||
[source,bash,linenums]
|
[source,bash,linenums]
|
||||||
.Script
|
.Script
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
= In `flake.nix`
|
||||||
|
|
||||||
|
See the example in <<_introducing_a_dependency>>
|
||||||
|
where defined a development shell in <<hello-flake-dependency,flake.nix>>
|
||||||
|
with a dependency on `cowsay` ,
|
||||||
|
and tested the shell.
|
||||||
|
|
||||||
= In `shell.nix`
|
= In `shell.nix`
|
||||||
|
|
||||||
[source,nix,linenums]
|
[source,nix,linenums]
|
||||||
|
|
|
||||||
54
source/recipes/remote-git/flake/flake.nix
Normal file
54
source/recipes/remote-git/flake/flake.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
# See https://github.com/mhwombat/nix-for-numbskulls/blob/main/flakes.md
|
||||||
|
# for a brief overview of what each section in a flake should or can contain.
|
||||||
|
|
||||||
|
description = "a sample flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
hello-nix = {
|
||||||
|
url = "git+https://codeberg.org/mhwombat/hello-nix";
|
||||||
|
flake = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils, hello-nix }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells = rec {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
packages = [ hello-nix ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = rec {
|
||||||
|
hello = pkgs.stdenv.mkDerivation rec {
|
||||||
|
name = "hello-again";
|
||||||
|
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
unpackPhase = "true";
|
||||||
|
|
||||||
|
buildPhase = ":";
|
||||||
|
|
||||||
|
installPhase =
|
||||||
|
''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp $src/hello-again $out/bin/hello-again
|
||||||
|
chmod +x $out/bin/hello-again
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
default = hello;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps = rec {
|
||||||
|
hello = flake-utils.lib.mkApp { drv = self.packages.${system}.hello; };
|
||||||
|
default = hello;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
4
source/recipes/remote-git/flake/hello-again
Executable file
4
source/recipes/remote-git/flake/hello-again
Executable file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
echo "I'm a flake, but I'm running a command defined in a non-flake package."
|
||||||
|
hello-nix
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
= Access to a package defined in a remote git repo
|
= Access to a package defined in a remote git repo
|
||||||
|
|
||||||
Ex: Access a package called `hello-nix`,
|
Ex: Access a package (not a flake) called `hello-nix`,
|
||||||
which is defined in a remote git repo on codeberg.
|
which is defined in a remote git repo on codeberg.
|
||||||
To use a package from GitHub, GitLab, or any other public platform,
|
To use a package from GitHub, GitLab, or any other public platform,
|
||||||
modify the URL.
|
modify the URL.
|
||||||
|
|
|
||||||
69241
wombats-book-of-nix.pdf
69241
wombats-book-of-nix.pdf
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue