diff --git a/pills/01-why-you-should-give-it-try.md b/pills/01-why-you-should-give-it-try.md index feb3bc0..e6ce644 100644 --- a/pills/01-why-you-should-give-it-try.md +++ b/pills/01-why-you-should-give-it-try.md @@ -2,7 +2,7 @@ ## Introduction -Welcome to the first post of the \"[Nix](https://nixos.org/nix) in pills\" series. Nix is a purely functional package manager and deployment system for POSIX. +Welcome to the first post of the "[Nix](https://nixos.org/nix) in pills" series. Nix is a purely functional package manager and deployment system for POSIX. There's a lot of documentation that describes what Nix, [NixOS](https://nixos.org/nixos) and related projects are. But the purpose of this post is to convince you to give Nix a try. Installing NixOS is not required, but sometimes I may refer to NixOS as a real world example of Nix usage for building a whole operating system. diff --git a/pills/02-install-on-your-running.md b/pills/02-install-on-your-running.md index 014931e..e34a51c 100644 --- a/pills/02-install-on-your-running.md +++ b/pills/02-install-on-your-running.md @@ -64,7 +64,7 @@ building path(s) `/nix/store/a7p1w3z2h8pl00ywvw6icr3g5l9vm5r7-user-environmen created 7 symlinks in user environment -A profile in Nix is a general and convenient concept for realizing rollbacks. Profiles are used to compose components that are spread among multiple paths under a new unified path. Not only that, but profiles are made up of multiple \"generations\": they are versioned. Whenever you change a profile, a new generation is created. +A profile in Nix is a general and convenient concept for realizing rollbacks. Profiles are used to compose components that are spread among multiple paths under a new unified path. Not only that, but profiles are made up of multiple "generations": they are versioned. Whenever you change a profile, a new generation is created. Generations can be switched and rolled back atomically, which makes them convenient for managing changes to your system. @@ -78,7 +78,7 @@ manifest.nix -> /nix/store/q8b5238akq07lj9gfb3qb5ycq4dxxiwm-env-manifest.nix< share -> /nix/store/ig31y9gfpp8pf3szdd7d4sf29zr7igbr-nix-2.1.3/share -That nix-2.1.3 derivation in the Nix store is Nix itself, with binaries and libraries. The process of \"installing\" the derivation in the profile basically reproduces the hierarchy of the nix-2.1.3 store derivation in the profile by means of symbolic links. +That nix-2.1.3 derivation in the Nix store is Nix itself, with binaries and libraries. The process of "installing" the derivation in the profile basically reproduces the hierarchy of the nix-2.1.3 store derivation in the profile by means of symbolic links. The contents of this profile are special, because only one program has been installed in our profile, therefore e.g. the `bin` directory points to the only program which has been installed (Nix itself). @@ -86,7 +86,7 @@ But that's only the contents of the latest generation of our profile. In fact, ` In turn, that's a symlink to `default-1-link` in the same directory. Yes, that means it's the first generation of the `default` profile. -Finally, `default-1-link` is a symlink to the nix store \"user-environment\" derivation that you saw printed during the installation process. +Finally, `default-1-link` is a symlink to the nix store "user-environment" derivation that you saw printed during the installation process. We'll talk about `manifest.nix` more in the next article. diff --git a/pills/03-enter-environment.md b/pills/03-enter-environment.md index a9d7daa..993e6ac 100644 --- a/pills/03-enter-environment.md +++ b/pills/03-enter-environment.md @@ -171,7 +171,7 @@ So where are we getting packages from? We said something about this already in t $ nix-channel --list nixpkgs http://nixos.org/channels/nixpkgs-unstable -If you're using NixOS, you may not see any output from the above command (if you're using the default), or you may see a channel whose name begins with \"nixos-\" instead of \"nixpkgs\". +If you're using NixOS, you may not see any output from the above command (if you're using the default), or you may see a channel whose name begins with "nixos-" instead of "nixpkgs". That's essentially the contents of `~/.nix-channels`. diff --git a/pills/04-basics-of-language.md b/pills/04-basics-of-language.md index 21c4403..8878779 100644 --- a/pills/04-basics-of-language.md +++ b/pills/04-basics-of-language.md @@ -97,7 +97,7 @@ As said previously, you cannot mix integers and strings. You need to explicitly Using the syntax with two single quotes is useful for writing double quotes inside strings without needing to escape them: nix-repl> ''test " test'' - "test \" test" + "test " test" nix-repl> ''${foo}'' "strval" diff --git a/pills/05-functions-and-imports.md b/pills/05-functions-and-imports.md index 690a299..f1dd51b 100644 --- a/pills/05-functions-and-imports.md +++ b/pills/05-functions-and-imports.md @@ -8,7 +8,7 @@ I remind you how to enter the Nix environment: `source ~/.nix-profile/etc/profil ## Nameless and single parameter -Functions are anonymous (lambdas), and only have a single parameter. The syntax is extremely simple. Type the parameter name, then \"`:`\", then the body of the function. +Functions are anonymous (lambdas), and only have a single parameter. The syntax is extremely simple. Type the parameter name, then "`:`", then the body of the function. nix-repl> x: x*2 «lambda» @@ -105,7 +105,7 @@ Also you can allow passing more attributes (**variadic**) than the expected ones nix-repl> mul = { a, b, ... }: a*b nix-repl> mul { a = 3; b = 4; c = 2; } -However, in the function body you cannot access the \"c\" attribute. The solution is to give a name to the given set with the **@-pattern**: +However, in the function body you cannot access the "c" attribute. The solution is to give a name to the given set with the **@-pattern**: nix-repl> mul = s@{ a, b, ... }: a*b*s.c nix-repl> mul { a = 3; b = 4; c = 2; } diff --git a/pills/06-our-first-derivation.md b/pills/06-our-first-derivation.md index 542919e..4522643 100644 --- a/pills/06-our-first-derivation.md +++ b/pills/06-our-first-derivation.md @@ -87,7 +87,7 @@ Important: the hash of the out path is based solely on the input derivations in Many things are empty in that `.drv`, however I'll write a summary of the [.drv format](http://nixos.org/~eelco/pubs/phd-thesis.pdf) for you: -1. The output paths (there can be multiple ones). By default nix creates one out path called \"out\". +1. The output paths (there can be multiple ones). By default nix creates one out path called "out". 2. The list of input derivations. It's empty because we are not referring to any other derivation. Otherwise, there would be a list of other .drv files. @@ -174,7 +174,7 @@ Just like dependencies in other package managers, how do we refer to other packa nix-repl> builtins.toString d "/nix/store/40s0qmrfb45vlh6610rk29ym318dswdr-myname" -Nix does the \"set to string conversion\" as long as there is the `outPath` attribute (much like a toString method in other languages): +Nix does the "set to string conversion" as long as there is the `outPath` attribute (much like a toString method in other languages): nix-repl> builtins.toString { outPath = "foo"; } "foo" @@ -255,7 +255,7 @@ Aha! Nix added a dependency to our myname.drv, it's the coreutils.drv. Before do ## When is the derivation built -Nix does not build derivations **during evaluation** of Nix expressions. In fact, that's why we have to do \":b drv\" in `nix repl`, or use nix-store -r in the first place. +Nix does not build derivations **during evaluation** of Nix expressions. In fact, that's why we have to do ":b drv" in `nix repl`, or use nix-store -r in the first place. An important separation is made in Nix: @@ -275,8 +275,8 @@ We're walking through the fundamentals of Nix derivations, to understand how the With the derivation function we provide a set of information on how to build a package, and we get back the information about where the package was built. Nix converts a set to a string when there's an `outPath`; that's very convenient. With that, it's easy to refer to other derivations. -When Nix builds a derivation, it first creates a .drv file from a derivation expression, and uses it to build the output. It does so recursively for all the dependencies (inputs). It \"executes\" the .drv files like a machine. Not much magic after all. +When Nix builds a derivation, it first creates a .drv file from a derivation expression, and uses it to build the output. It does so recursively for all the dependencies (inputs). It "executes" the .drv files like a machine. Not much magic after all. ## Next pill -\...we will finally write our first **working** derivation. Yes, this post is about \"our first derivation\", but I never said it was a working one ;) +\...we will finally write our first **working** derivation. Yes, this post is about "our first derivation", but I never said it was a working one ;) diff --git a/pills/08-generic-builders.md b/pills/08-generic-builders.md index 447385e..ab99653 100644 --- a/pills/08-generic-builders.md +++ b/pills/08-generic-builders.md @@ -114,7 +114,7 @@ What do we do here? 6. Once we're set up, compile and install. -As you can see, there's no reference to \"hello\" in the builder anymore. It still makes several assumptions, but it's certainly more generic. +As you can see, there's no reference to "hello" in the builder anymore. It still makes several assumptions, but it's certainly more generic. Now let's rewrite `hello.nix`: @@ -226,7 +226,7 @@ Then we rewrite `hello.nix` as follows: Finally! We got a very simple description of a package! Below are a couple of remarks that you may find useful as you're continuing to understand the nix language: -- We assigned to pkgs the import that we did in the previous expressions in the \"with\". Don't be afraid, it's that straightforward. +- We assigned to pkgs the import that we did in the previous expressions in the "with". Don't be afraid, it's that straightforward. - The mkDerivation variable is a nice example of partial application, look at it as (`import ./autotools.nix`) `pkgs`. First we import the expression, then we apply the `pkgs` parameter. That will give us a function that accepts the attribute set `attrs`. @@ -248,4 +248,4 @@ In Nix you create derivations stored in the nix store, and then you compose them ## Next pill -\...we will talk a little about runtime dependencies. Is the GNU hello world package self-contained? What are its runtime dependencies? We only specified build dependencies by means of using other derivations in the \"hello\" derivation. +\...we will talk a little about runtime dependencies. Is the GNU hello world package self-contained? What are its runtime dependencies? We only specified build dependencies by means of using other derivations in the "hello" derivation. diff --git a/pills/09-automatic-runtime.md b/pills/09-automatic-runtime.md index 9cca4da..90a7b5c 100644 --- a/pills/09-automatic-runtime.md +++ b/pills/09-automatic-runtime.md @@ -30,7 +30,7 @@ Why are we looking at `.drv` files? Because the `hello.drv` file is the represen ## Digression about NAR files -The `NAR` format is the \"Nix ARchive\". This format was designed due to existing archive formats, such as `tar`, being insufficient. Nix benefits from deterministic build tools, but commonly used archivers lack this property: they add padding, they do not sort files, they add timestamps, and so on. This can result in directories containing bit-identical files turning into non-bit-identical archives, which leads to different hashes. +The `NAR` format is the "Nix ARchive". This format was designed due to existing archive formats, such as `tar`, being insufficient. Nix benefits from deterministic build tools, but commonly used archivers lack this property: they add padding, they do not sort files, they add timestamps, and so on. This can result in directories containing bit-identical files turning into non-bit-identical archives, which leads to different hashes. Thus the `NAR` format was developed as a simple, deterministic archive format. `NAR`s are used extensively within Nix, as we will see below. @@ -76,19 +76,19 @@ Even after reducing the rpath, the `hello` binary would still depend upon `gcc` We will add a new phase to our autotools builder. The builder has six phases already: -1. The \"environment setup\" phase +1. The "environment setup" phase -2. The \"unpack phase\": we unpack the sources in the current directory (remember, Nix changes to a temporary directory first) +2. The "unpack phase": we unpack the sources in the current directory (remember, Nix changes to a temporary directory first) -3. The \"change directory\" phase, where we change source root to the directory that has been unpacked +3. The "change directory" phase, where we change source root to the directory that has been unpacked -4. The \"configure\" phase: `./configure` +4. The "configure" phase: `./configure` -5. The \"build\" phase: `make` +5. The "build" phase: `make` -6. The \"install\" phase: `make install` +6. The "install" phase: `make install` -Now we will add a new phase after the installation phase, which we call the \"fixup\" phase. At the end of the `builder.sh`, we append: +Now we will add a new phase after the installation phase, which we call the "fixup" phase. At the end of the `builder.sh`, we append: find $out -type f -exec patchelf --shrink-rpath '{}' \; -exec strip '{}' \; 2>/dev/null diff --git a/pills/11-garbage-collector.md b/pills/11-garbage-collector.md index 0b4ab33..042c01e 100644 --- a/pills/11-garbage-collector.md +++ b/pills/11-garbage-collector.md @@ -2,11 +2,11 @@ Welcome to the 11th Nix pill. In the previous [10th pill](10-developing-with-nix-shell.md), we drew a parallel between the isolated build environment provided by `nix-build` and the isolated development shell provided by `nix-shell`. Using `nix-shell` allowed us to debug, modify, and manually build software using an environment that is almost identical to the one provided by `nix-build`. -Today, we will stop focusing on packaging and instead look at a critical component of Nix: the garbage collector. When we use Nix tools, we are often building derivations. This includes `.drv` files as well as out paths. These artifacts go in the Nix store and take up space in our storage. Eventually we may wish to free up some space by removing derivations we no longer need. This is the focus of the 11th pill. By default, Nix takes a relatively conservative approach when automatically deciding which derivations are \"needed\". In this pill, we will also see a technique to conduct more destructive upgrade and deletion operations. +Today, we will stop focusing on packaging and instead look at a critical component of Nix: the garbage collector. When we use Nix tools, we are often building derivations. This includes `.drv` files as well as out paths. These artifacts go in the Nix store and take up space in our storage. Eventually we may wish to free up some space by removing derivations we no longer need. This is the focus of the 11th pill. By default, Nix takes a relatively conservative approach when automatically deciding which derivations are "needed". In this pill, we will also see a technique to conduct more destructive upgrade and deletion operations. ## How does garbage collection work? -Programming languages with garbage collectors use the concept of a set of \"garbage collector (or 'GC') roots\" to keep track of \"live\" objects. A GC root is an object that is always considered \"live\" (unless explicitly removed as GC root). The garbage collection process starts from the GC roots and proceeds by recursively marking object references as \"live\". All other objects can be collected and deleted. +Programming languages with garbage collectors use the concept of a set of "garbage collector (or 'GC') roots" to keep track of "live" objects. A GC root is an object that is always considered "live" (unless explicitly removed as GC root). The garbage collection process starts from the GC roots and proceeds by recursively marking object references as "live". All other objects can be collected and deleted. Instead of objects, Nix's garbage collection operates on store paths, [with the GC roots themselves being store paths](https://nixos.org/manual/nix/stable/package-management/garbage-collector-roots.html). . This approach is much more principled than traditional package managers such as `dpkg` or `rpm`, which may leave around unused packages or dangling files. @@ -81,7 +81,7 @@ In fact, `nix-build` automatically adds the `result` symlink as a GC root. Note The name of the GC root symlink is not important to us at this time. What is important is that such a symlink exists and points to `/home/nix/result`. This is called an **indirect GC root**. A GC root is considered indirect if its specification is outside of `/nix/var/nix/gcroots`. In this case, this means that the target of the `result` symlink will not be garbage collected. -To remove a derivation considered \"live\" by an indirect GC root, there are two possibilities: +To remove a derivation considered "live" by an indirect GC root, there are two possibilities: - Remove the indirect GC root from `/nix/var/nix/gcroots/auto`. @@ -97,7 +97,7 @@ The main source of software duplication in the nix store comes from GC roots, du The same holds for profiles. Manipulating the `nix-env` profile will create further generations. Old generations refer to old software, thus increasing duplication in the nix store after an upgrade. -Other systems typically \"forget\" everything about their previous state after an upgrade. With Nix, we can perform this type of upgrade (having Nix remove all old derivations, including old generations), but we do so manually. There are four steps to doing this: +Other systems typically "forget" everything about their previous state after an upgrade. With Nix, we can perform this type of upgrade (having Nix remove all old derivations, including old generations), but we do so manually. There are four steps to doing this: - First, we download a new version of the nixpkgs channel, which holds the description of all the software. This is done via `nix-channel --update`. @@ -120,4 +120,4 @@ Garbage collection in Nix is a powerful mechanism to clean up your system. The ` ## Next pill -In the next pill, we will package another project and introduce the \"inputs\" design pattern. We've only played with a single derivation until now; however we'd like to start organizing a small repository of software. The \"inputs\" pattern is widely used in nixpkgs; it allows us to decouple derivations from the repository itself and increase customization opportunities. +In the next pill, we will package another project and introduce the "inputs" design pattern. We've only played with a single derivation until now; however we'd like to start organizing a small repository of software. The "inputs" pattern is widely used in nixpkgs; it allows us to decouple derivations from the repository itself and increase customization opportunities. diff --git a/pills/12-inputs-design-pattern.md b/pills/12-inputs-design-pattern.md index a8fbb03..e98af7f 100644 --- a/pills/12-inputs-design-pattern.md +++ b/pills/12-inputs-design-pattern.md @@ -14,7 +14,7 @@ Over time, the `nixpkgs` repository evolved a particular structure. This structu Different operating system distributions have different opinions about how package repositories should be organized. Systems like Debian scatter packages in several small repositories (which tends to make tracking interdependent changes more difficult, and hinders contributions to the repositories), while systems like Gentoo put all package descriptions in a single repository. -Nix follows the \"single repository\" pattern by placing all descriptions of all packages into [nixpkgs](https://github.com/NixOS/nixpkgs). This approach has proven natural and attractive for new contributions. +Nix follows the "single repository" pattern by placing all descriptions of all packages into [nixpkgs](https://github.com/NixOS/nixpkgs). This approach has proven natural and attractive for new contributions. For the rest of this pill, we will adopt the single repository pattern. The natural implementation in Nix is to create a top-level Nix expression, followed by one expression for each package. The top-level expression imports and combines all package expressions in an attribute set mapping names to packages. @@ -129,7 +129,7 @@ Taking a closer look at the above command, we see the following options: - The -f option is used to specify the expression to use. In this case, the expression is the `./default.nix` of the current directory. -- The -i option stands for \"installation\". +- The -i option stands for "installation". - The -A is the same as above for `nix-build`. @@ -147,7 +147,7 @@ The approach we've taken so far has a few problems: Until now, our approach to addressing the above problems has been inadequate and required changing the nix expression to match our needs. With the `inputs` pattern, we provide another answer: let the user change the `inputs` of the expression. -When we talk about \"the inputs of an expression\", we are referring to the set of derivations needed to build that expression. In this case: +When we talk about "the inputs of an expression", we are referring to the set of derivations needed to build that expression. In this case: - `mkDerivation` from `autotools`. Recall that `mkDerivation` has an implicit dependency on the toolchain. @@ -172,7 +172,7 @@ Our goal is to make package expressions independent of the repository. To achiev else []; } -Recall that \"`{...}: ...`\" is the syntax for defining functions accepting an attribute set as argument; the above snippet just defines a function. +Recall that "`{...}: ...`" is the syntax for defining functions accepting an attribute set as argument; the above snippet just defines a function. We made `gd` and its dependencies optional. If `gdSupport` is true (which it is by default), we will fill `buildInputs` and `graphviz` will be built with `gd` support. Otherwise, if an attribute set is passed with `gdSupport = false;`, the build will be completed without `gd` support. @@ -214,22 +214,22 @@ Let's talk a closer look at the snippet and dissect the syntax: - The entire expression in `default.nix` returns an attribute set with the keys `hello`, `graphviz`, and `graphvizCore`. -- With \"`let`\", we define some local variables. +- With "`let`", we define some local variables. -- We bring `pkgs` into the scope when defining the package set. This saves us from having to type `pkgs`\" repeatedly. +- We bring `pkgs` into the scope when defining the package set. This saves us from having to type `pkgs`" repeatedly. - We import `hello.nix` and `graphviz.nix`, which each return a function. We call the functions with a set of inputs to get back the derivation. -- The \"`inherit x`\" syntax is equivalent to \"`x = x`\". This means that the \"`inherit gd`\" here, combined with the above \"`with pkgs;`\", is equivalent to \"`gd = pkgs.gd`\". +- The "`inherit x`" syntax is equivalent to "`x = x`". This means that the "`inherit gd`" here, combined with the above "`with pkgs;`", is equivalent to "`gd = pkgs.gd`". The entire repository of this can be found at the [pill 12](https://gist.github.com/tfc/ca800a444b029e85a14e530c25f8e872) gist. ## Conclusion -The \"`inputs`\" pattern allows our expressions to be easily customizable through a set of arguments. These arguments could be flags, derivations, or any other customizations enabled by the nix language. Our package expressions are simply functions: there is no extra magic present. +The "`inputs`" pattern allows our expressions to be easily customizable through a set of arguments. These arguments could be flags, derivations, or any other customizations enabled by the nix language. Our package expressions are simply functions: there is no extra magic present. -The \"`inputs`\" pattern also makes the expressions independent of the repository. Given that we pass all needed information through arguments, it is possible to use these expressions in any other context. +The "`inputs`" pattern also makes the expressions independent of the repository. Given that we pass all needed information through arguments, it is possible to use these expressions in any other context. ## Next pill -In the next pill, we will talk about the \"`callPackage`\" design pattern. This removes the tedium of specifying the names of the inputs twice: once in the top-level `default.nix`, and once in the package expression. With `callPackage`, we will implicitly pass the necessary inputs from the top-level expression. +In the next pill, we will talk about the "`callPackage`" design pattern. This removes the tedium of specifying the names of the inputs twice: once in the top-level `default.nix`, and once in the package expression. With `callPackage`, we will implicitly pass the necessary inputs from the top-level expression. diff --git a/pills/13-callpackage-design-pattern.md b/pills/13-callpackage-design-pattern.md index 3fbd8a2..d2e29eb 100644 --- a/pills/13-callpackage-design-pattern.md +++ b/pills/13-callpackage-design-pattern.md @@ -41,7 +41,7 @@ We want `callPackage` to be a function of two arguments, with the following beha ## Implementing `callPackage` -In this section, we will build up the `callPackages` pattern from scratch. To start, we need a way to obtain the argument names of a function (in this case, the function that takes \"inputs\" and produces a package derivation) at runtime. This is because we want to automatically pass such arguments. +In this section, we will build up the `callPackages` pattern from scratch. To start, we need a way to obtain the argument names of a function (in this case, the function that takes "inputs" and produces a package derivation) at runtime. This is because we want to automatically pass such arguments. Nix provides a builtin function to do this: @@ -81,9 +81,9 @@ Let's dissect the above snippet: - We define a `callPackage` variable which is a function. -- The first parameter to the `callPackage` function is a set of name-value pairs that may appear in the argument set of the function we wish to \"autocall\". +- The first parameter to the `callPackage` function is a set of name-value pairs that may appear in the argument set of the function we wish to "autocall". -- The second parameter is the function to \"autocall\" +- The second parameter is the function to "autocall" - We take the argument names of the function and intersect with the set of all values. @@ -145,7 +145,7 @@ The reader should notice a magic thing happening. We're defining `pkgs` in terms ## Conclusion -The \"`callPackage`\" pattern has simplified our repository considerably. We were able to import packages that require named arguments and call them automatically, given the set of all packages sourced from `nixpkgs`. +The "`callPackage`" pattern has simplified our repository considerably. We were able to import packages that require named arguments and call them automatically, given the set of all packages sourced from `nixpkgs`. We've also introduced some useful builtin functions that allows us to introspect Nix functions and manipulate attributes. These builtin functions are not usually used when packaging software, but rather act as tools for packaging. They are documented in the [Nix manual](https://nixos.org/manual/nix/stable/expressions/builtins.html). @@ -153,4 +153,4 @@ Writing a repository in Nix is an evolution of writing convenient functions for ## Next pill -In the next pill, we will talk about the \"`override`\" design pattern. The `graphvizCore` seems straightforward. It starts from `graphviz.nix` and builds it without gd. In the next pill, we will consider another point of view: starting from `pkgs.graphviz` and disabling gd? +In the next pill, we will talk about the "`override`" design pattern. The `graphvizCore` seems straightforward. It starts from `graphviz.nix` and builds it without gd. In the next pill, we will consider another point of view: starting from `pkgs.graphviz` and disabling gd? diff --git a/pills/14-override-design-pattern.md b/pills/14-override-design-pattern.md index 4faa231..e7fb160 100644 --- a/pills/14-override-design-pattern.md +++ b/pills/14-override-design-pattern.md @@ -52,13 +52,13 @@ We would like to avoid specifying the nix expression again. Instead, we would li The difference is obvious, as well as the advantages of this approach. -Note: that `.override` is not a \"method\" in the OO sense as you may think. Nix is a functional language. The`.override` is simply an attribute of a set. +Note: that `.override` is not a "method" in the OO sense as you may think. Nix is a functional language. The`.override` is simply an attribute of a set. ## The override implementation -Recall that the graphviz attribute in the repository is the derivation returned by the function imported from `graphviz.nix`. We would like to add a further attribute named \"`override`\" to the returned set. +Recall that the graphviz attribute in the repository is the derivation returned by the function imported from `graphviz.nix`. We would like to add a further attribute named "`override`" to the returned set. -Let's start by first creating a function \"`makeOverridable`\". This function will take two arguments: a function (that must return a set) and the set of original arguments to be passed to the function. +Let's start by first creating a function "`makeOverridable`". This function will take two arguments: a function (that must return a set) and the set of original arguments to be passed to the function. We will put this function in a `lib.nix`: @@ -128,7 +128,7 @@ Now it would be nice if `callPackage` made our derivations overridable. This is ## Conclusion -The \"`override`\" pattern simplifies the way we customize packages starting from an existing set of packages. This opens a world of possibilities for using a central repository like `nixpkgs` and defining overrides on our local machine without modifying the original package. +The "`override`" pattern simplifies the way we customize packages starting from an existing set of packages. This opens a world of possibilities for using a central repository like `nixpkgs` and defining overrides on our local machine without modifying the original package. We can dream of a custom, isolated `nix-shell` environment for testing graphviz with a custom gd: @@ -140,4 +140,4 @@ The key in Nix is to find powerful yet simple abstractions in order to let the u ## Next pill -In the next pill, we will talk about Nix search paths. By \"search path\", we mean a place in the file system where Nix looks for expressions. This answers the question of where `` comes from. +In the next pill, we will talk about Nix search paths. By "search path", we mean a place in the file system where Nix looks for expressions. This answers the question of where `` comes from. diff --git a/pills/15-nix-search-paths.md b/pills/15-nix-search-paths.md index e1a3083..ec9a146 100644 --- a/pills/15-nix-search-paths.md +++ b/pills/15-nix-search-paths.md @@ -1,6 +1,6 @@ # Nix Search Paths -Welcome to the 15th Nix pill. In the previous [14th](14-override-design-pattern.md) pill we have introduced the \"override\" pattern, useful for writing variants of derivations by passing different inputs. +Welcome to the 15th Nix pill. In the previous [14th](14-override-design-pattern.md) pill we have introduced the "override" pattern, useful for writing variants of derivations by passing different inputs. Assuming you followed the previous posts, I hope you are now ready to understand `nixpkgs`. But we have to find `nixpkgs` in our system first! So this is the step: introducing some options and environment variables used by nix tools. @@ -14,7 +14,7 @@ In the shell for example, when you execute the command `ping`, it's being search In nix it's exactly the same, however the syntax is different. Instead of just typing `ping` you have to type ``. Yes, I know\... you are already thinking of ``. However, don't stop reading here, let's keep going. -What's `NIX_PATH` good for? Nix expressions may refer to an \"abstract\" path such as ``, and it's possible to override it from the command line. +What's `NIX_PATH` good for? Nix expressions may refer to an "abstract" path such as ``, and it's possible to override it from the command line. For ease we will use `nix-instantiate --eval` to do our tests. I remind you, [nix-instantiate](https://nixos.org/manual/nix/stable/command-ref/nix-instantiate.html) is used to evaluate nix expressions and generate the .drv files. Here we are not interested in building derivations, so evaluation is enough. It can be used for one-shot expressions. @@ -31,7 +31,7 @@ It's useless from a nix view point, but I think it's useful for your own underst Great. At first attempt nix obviously said could not be found anywhere in the search path. Note that the -I option accepts a single directory. Paths added with -I take precedence over `NIX_PATH`. -The `NIX_PATH` also accepts a different yet very handy syntax: \"`somename=somepath`\". That is, instead of searching inside a directory for a name, we specify exactly the value of that name. +The `NIX_PATH` also accepts a different yet very handy syntax: "`somename=somepath`". That is, instead of searching inside a directory for a name, we specify exactly the value of that name. $ NIX_PATH="ping=/bin/ping" nix-instantiate --eval -E '' /bin/ping @@ -82,14 +82,14 @@ In order to specify an alternative to `~/.nix-defexpr` it's possible to use the replacing old `graphviz' installing `graphviz' -Oh why did it say there's another derivation named graphviz? Because both `graphviz` and `graphvizCore` attributes in our repository have the name \"graphviz\" for the derivation: +Oh why did it say there's another derivation named graphviz? Because both `graphviz` and `graphvizCore` attributes in our repository have the name "graphviz" for the derivation: $ nix-env -f '' -qaP graphviz graphviz graphvizCore graphviz hello hello -By default `nix-env` parses all derivations and uses the derivation names to interpret the command line. So in this case \"graphviz\" matched two derivations. Alternatively, like for `nix-build`, one can use -A to specify an attribute name instead of a derivation name: +By default `nix-env` parses all derivations and uses the derivation names to interpret the command line. So in this case "graphviz" matched two derivations. Alternatively, like for `nix-build`, one can use -A to specify an attribute name instead of a derivation name: $ nix-env -f '' -i -A graphviz replacing old `graphviz' @@ -113,7 +113,7 @@ It may or may not make sense for you, or it's like that for historical reasons, ## Conclusion -The `NIX_PATH` variable is the search path used by nix when using the angular brackets syntax. It's possible to refer to \"abstract\" paths inside nix expressions and define the \"concrete\" path by means of `NIX_PATH`, or the usual -I flag in nix tools. +The `NIX_PATH` variable is the search path used by nix when using the angular brackets syntax. It's possible to refer to "abstract" paths inside nix expressions and define the "concrete" path by means of `NIX_PATH`, or the usual -I flag in nix tools. We've also explained some of the uncommon `nix-env` behaviors for newcomers. The `nix-env` tool does not use `NIX_PATH` to search for packages, but rather for `~/.nix-defexpr`. Beware of that! diff --git a/pills/20-basic-dependencies-and-hooks.md b/pills/20-basic-dependencies-and-hooks.md index 2f54fb0..7c50f94 100644 --- a/pills/20-basic-dependencies-and-hooks.md +++ b/pills/20-basic-dependencies-and-hooks.md @@ -192,9 +192,9 @@ This demonstrates an important point. For the *current* package alone, it doesn' ## Setup Hooks -As we mentioned above, sometimes dependencies need to influence the packages that use them in ways other than just *being* a dependency. [^1] `propagatedBuildInputs` can actually be seen as an example of this: packages using that are effectively \"injecting\" those dependencies as extra `buildInputs` in their downstream dependents. But in general, a dependency might affect the packages it depends on in arbitrary ways. *Arbitrary* is the key word here. We could teach `setup.sh` things about upstream packages like `pkg/nix-support/propagated-build-inputs`, but not arbitrary interactions. +As we mentioned above, sometimes dependencies need to influence the packages that use them in ways other than just *being* a dependency. [^1] `propagatedBuildInputs` can actually be seen as an example of this: packages using that are effectively "injecting" those dependencies as extra `buildInputs` in their downstream dependents. But in general, a dependency might affect the packages it depends on in arbitrary ways. *Arbitrary* is the key word here. We could teach `setup.sh` things about upstream packages like `pkg/nix-support/propagated-build-inputs`, but not arbitrary interactions. -Setup hooks are the basic building block we have for this. In nixpkgs, a \"hook\" is basically a bash callback, and a setup hook is no exception. Let's look at the last part of `findInputs` we haven't covered: +Setup hooks are the basic building block we have for this. In nixpkgs, a "hook" is basically a bash callback, and a setup hook is no exception. Let's look at the last part of `findInputs` we haven't covered: findInputs() { local pkg=$1 @@ -237,7 +237,7 @@ Functions listed in `envHooks` are applied to every package passed to `addToEnv` anEnvHook() { local pkg=$1 - echo "I'm depending on \"$pkg\"" + echo "I'm depending on "$pkg"" } envHooks+=(anEnvHook)