Home Explore Blog Models CI



nixpkgs

24th chunk of `doc/stdenv/stdenv.chapter.md`
2e47d293c1c58d69bf917cb0881955f7ddc88a7772081b950000000100000fbc
The setup hook mechanism is a bit of a sledgehammer though: a powerful feature with a broad and indiscriminate area of effect. The combination of its power and implicit use may be expedient, but isn’t without costs. Nix itself is unchanged, but the spirit of added dependencies being effect-free is violated even if the latter isn’t. For example, if a derivation path is mentioned more than once, Nix itself doesn’t care and makes sure the dependency derivation is already built just the same—depending is just needing something to exist, and needing is idempotent. However, a dependency specified twice will have its setup hook run twice, and that could easily change the build environment (though a well-written setup hook will therefore strive to be idempotent so this is in fact not observable). More broadly, setup hooks are anti-modular in that multiple dependencies, whether the same or different, should not interfere and yet their setup hooks may well do so.

The most typical use of the setup hook is actually to add other hooks which are then run (i.e. after all the setup hooks) on each dependency. For example, the C compiler wrapper’s setup hook feeds itself flags for each dependency that contains relevant libraries and headers. This is done by defining a bash function, and appending its name to one of `envBuildBuildHooks`, `envBuildHostHooks`, `envBuildTargetHooks`, `envHostHostHooks`, `envHostTargetHooks`, or `envTargetTargetHooks`. These 6 bash variables correspond to the 6 sorts of dependencies by platform (there’s 12 total but we ignore the propagated/non-propagated axis).

Packages adding a hook should not hard code a specific hook, but rather choose a variable *relative* to how they are included. Returning to the C compiler wrapper example, if the wrapper itself is an `n` dependency, then it only wants to accumulate flags from `n + 1` dependencies, as only those ones match the compiler’s target platform. The `hostOffset` variable is defined with the current dependency’s host offset `targetOffset` with its target offset, before its setup hook is sourced. Additionally, since most environment hooks don’t care about the target platform, that means the setup hook can append to the right bash array by doing something like

```bash
addEnvHooks "$hostOffset" myBashFunction
```

The *existence* of setups hooks has long been documented and packages inside Nixpkgs are free to use this mechanism. Other packages, however, should not rely on these mechanisms not changing between Nixpkgs versions. Because of the existing issues with this system, there’s little benefit from mandating it be stable for any period of time.

First, let’s cover some setup hooks that are part of Nixpkgs default `stdenv`. This means that they are run for every package built using `stdenv.mkDerivation`, even with custom builders. Some of these are platform specific, so they may run on Linux but not Darwin or vice-versa.

### `move-docs.sh` {#move-docs.sh}

This setup hook moves any installed documentation to the `/share` subdirectory directory. This includes the man, doc and info directories. This is needed for legacy programs that do not know how to use the `share` subdirectory.

### `compress-man-pages.sh` {#compress-man-pages.sh}

This setup hook compresses any man pages that have been installed. The compression is done using the gzip program. This helps to reduce the installed size of packages.

### `strip.sh` {#strip.sh}

This runs the strip command on installed binaries and libraries. This removes unnecessary information like debug symbols when they are not needed. This also helps to reduce the installed size of packages.

### `patch-shebangs.sh` {#patch-shebangs.sh}

This setup hook patches installed scripts to add Nix store paths to their shebang interpreter as found in the build environment. The [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) line tells a Unix-like operating system which interpreter to use to execute the script's contents.

::: {.note}

Title: Nixpkgs Setup Hooks: Caveats, Customization, and Standard Tools
Summary
Nixpkgs' setup hook mechanism is a powerful yet indiscriminate 'sledgehammer' feature. It has drawbacks like violating effect-free dependencies, potential for non-idempotent behavior, and anti-modularity. Hooks primarily add *other* hooks dynamically by defining Bash functions and appending names to `env...Hooks` variables via `hostOffset`. Existing Nixpkgs hooks are stable, but custom ones shouldn't rely on this due to the system's issues. Default `stdenv` hooks include `move-docs.sh` (moves docs to `/share`), `compress-man-pages.sh` (gzippes man pages), `strip.sh` (removes debug symbols), and `patch-shebangs.sh` (updates script interpreters).