=== Usage The helpers can be imported directly from the Git repository archive: let beaker = import (fetchTarball https://git.sr.ht/~evhan/beaker/archive/master.tar.gz) {}; in doStuff { with beaker; ... } This library only includes three attributes, so it's also relatively harmless to pull into scope, for example: with import (fetchTarball https://git.sr.ht/~evhan/beaker/archive/e9a0d500.tar.gz) {}; eggProgram { name = "example"; src = ./.; eggCache = eggCache { eggs = ./example.egg.lock; hash = "sha256-rbTfihyt6XfHP8VhaLmA8xBAneuUj7oDJXZ/BxY1OZU="; }; } You can use a specific version of the Nix packages collection by setting the `pkgs` property of the library. By default, the `` path is used: with import (fetchTarball https://git.sr.ht/~evhan/beaker/archive/master.tar.gz) { pkgs = your.nixpkgs.collection; }; ==== Using Flakes To use this project with Nix flakes, add the archive URL as an input. The following example will pin a version of this project as an input and force it to use the same version of `nixpkgs` as the flake itself. The `beaker` library is be passed to the `outputs` builder, and you can access the helpers for a specific system via `beaker.lib.${system}`: { inputs = { beaker.url = "https://git.sr.ht/~evhan/beaker/archive/0.0.17.tar.gz"; beaker.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = { self, nixpkgs, beaker }: let system = "x86_64-linux"; in { packages.${system}.default = beaker.lib.${system}.eggProgram { name = "example-using-flakes"; src = ./.; }; }; } ==== Using Niv To use this project with [Niv](https://github.com/nmattia/niv), add it to your project sources: niv init niv add beaker -t https://git.sr.ht/~evhan/beaker/archive/0.0.17.tar.gz Then create a `default.nix` with the following contents: let pkgs = import {}; sources = import ./nix/sources.nix; beaker = import sources.beaker { inherit pkgs; }; in beaker.eggProgram { name = "example-using-niv"; src = ./.; } === Fetching Egg Dependencies [procedure] eggCache attrSet A fixed-output derivation that fetches a set of eggs for installation. The list of eggs to cache should be specified via `eggs`, which expects a path to a file in "override" format specifying a list of egg names and versions. This file can be generated via `chicken-status -list` (for all installed eggs) or `chicken-lock` (for a specific egg's dependencies). eggCache { name = "example-egg-cache"; hash = "sha256-XbwSzGUJfKgiKcrYuu9Y3gwRTYmoesM9KZlIhdII2AU="; eggs = ./eggs.lock; } Alternatively, you can specify the list of eggs directly: eggCache { name = "example-egg-cache"; hash = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo="; eggs = [ { name = "srfi-18"; version = "0.1"; } { name = "srfi-69"; version = "0.4"; } ]; } You can print the hash for a set of eggs using the `-command` flag to the `chicken-lock` program, to hash the resulting egg cache: # for the egg in the current directory chicken-lock -command nix hash path # for a few specific eggs and versions chicken-lock srfi-18:0.1 srfi-69:0.4 -command nix hash path # for the given override file chicken-lock -from-list ./eggs.lock -command nix hash path ==== Combining Multiple Egg Caches To merge multiple egg caches, you can use `symlinkJoin`: pkgs.symlinkJoin { name = "example-egg-caches"; paths = [ (eggCache { ... }) (eggCache { ... }) ]; } The result will be a single egg cache containing all of the specified eggs. Note that if any input paths contain different versions of the same egg, the first one listed takes precedence. === Building Eggs [procedure] eggRepository attrSet Builds any eggs in the given `src` directory, producing a compiled egg repository under `/lib/chicken/` and placing any resulting binaries under `/bin`. Apart from `eggCache`, this derivation accepts all the same attributes as `stdenv.mkDerivation`. If no `name` is given, the string `"eggs"` is used. The result is suitable for use in the `buildInputs` of an `eggProgram`, in order to satisfy its egg dependencies. Any dependencies not satisfied by a compiled `eggRepository` must be provided as sources via `eggCache` so that all inputs are known at build time. # create an extension repository from source eggRepository { src = ./.; eggCache = eggCache { ... }; } If any dependencies are missing from both the inputs and cache, the build will fail with the error message `"extension or version not found: "`. [procedure] eggProgram attrSet Builds any eggs in the given `src` directory, bundling all dependencies and placing the resulting binaries into `/bin`. The `name` attribute is required. Apart from that, this derivation accepts all the same attributes as `eggRepository`. # build a program entirely from source eggProgram { name = "example-program"; src = ./.; eggCache = eggCache { ... }; } Unlike `eggRepository`, this derivation only preserves shared object files in the repository path, and it does not expose the output repository to downstream derivations. This means that all `egg-info`, `inline`, `link` and `types` files are removed, and the result is unsuitable for use in the `builtInputs` of another `eggProgram`. It should only be used to produce executables, not extension repositories intended for reuse. Combining the `eggRepository` and `eggProgram` derivations is useful to stage build operations, for example to avoid rebuilding all egg dependencies whenever the current source directory changes. let # pre-compile egg dependencies compiledEggs = eggRepository { src = eggCache { ... }; }; in # build program from source eggProgram { name = "example-program"; src = ./.; buildInputs = [ compiledEggs ]; } ==== Linking With External Libraries When linking to external libraries, it's usually enough to use `buildInputs`. For eggs, this can either be done when compiling the egg itself, or when building a program that uses the cached egg from source. For example, to build a program using the openssl egg, you can either build the program and its dependencies (including the OpenSSL library) from source all at once, or you can compile the openssl egg first, then link to the result. In either case, the `openssl` package should be provided in `buildInputs` when building the egg: let opensslEggDependencies = [ pkgs.openssl pkgs.pkg-config ]; opensslEggSources = eggCache { hash = "sha256-RCjCBvKOFmz92RIP1lP0svxjAC00gAmOLdeAB9PxE+8="; eggs = [ { name = "openssl"; version = "2.2.4"; } { name = "srfi-18"; version = "0.1.6"; } { name = "address-info"; version = "1.0.5"; } { name = "srfi-1"; version = "0.5.1"; } { name = "srfi-14"; version = "0.2.1"; } { name = "srfi-13"; version = "0.3.3"; } ]; }; compiledOpensslEgg = eggRepository { src = opensslEggSources; buildInputs = opensslEggDependencies; }; in { # build a program using the openssl egg sources fromSourceEgg = eggProgram { name = "example-from-source"; src = ./.; eggCache = opensslEggSources; buildInputs = opensslEggDependencies; }; # build a program linking to the compiled openssl egg fromCompiledEgg = eggProgram { name = "example-from-compiled"; src = ./.; buildInputs = [ compiledOpensslEgg ]; }; } === Development Shell When using `eggProgram`, the `nix develop` command will start a development shell that causes CHICKEN to use an isolated build environment. In this shell, environment variables are set so that CHICKEN will install all files under a temporary build root, and the `chicken-install` program will work in offline mode, fetching dependencies only from the given `eggCache` and not from any network locations. === Examples These eggs provide examples of using these Nix functions: * [dust](https://git.sr.ht/~evhan/dust/tree/master/item/default.nix) * [sourcehut](https://git.sr.ht/~evhan/chicken-sourcehut/tree/master/item/default.nix) * [sq](https://hg.sr.ht/~evhan/sq/browse/default.nix?rev=tip) In each of these projects, the lock file that's used to populate the `eggCache` has been created by running `chicken-lock > ${name}.egg.lock`, and then checking that file in to source control.