Der Bogen schließt sich: dein selbst gebautes Tool als Output und in der Shell.
packages.default-Output (per nix run startbar)
und stellt dasselbe Tool in der Dev-Shell bereit – die komplette toolbox.
callPackage: Dateien sauber einbinden
In Lektion 10 war toolbox.nix eine Funktion (sie nahm
{ buildGoModule, ... }). pkgs.callPackage ruft so eine Funktion auf und füllt
ihre Argumente automatisch aus pkgs – du musst nichts von Hand durchreichen:
toolbox = pkgs.callPackage ./toolbox.nix {};
# callPackage schaut in pkgs nach buildGoModule, lib, … und reicht sie ein
So sieht die flake.nix aus, wenn beides zusammenkommt:
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
toolbox = pkgs.callPackage ./toolbox.nix {}; # dein Paket
in {
# 1) als baubares/ausführbares Paket:
packages.${system}.default = toolbox;
# 2) und gleichzeitig in der Dev-Shell verfügbar:
devShells.${system}.default = pkgs.mkShell {
packages = [ pkgs.go pkgs.jq toolbox ]; # ← dein Tool neben den anderen
};
};
Damit kannst du:
$ nix build # baut toolbox → ./result/bin/toolbox
$ nix run # baut & startet toolbox direkt
$ nix develop # Shell, in der `toolbox` im PATH liegt
pkgs erweitern
Manchmal willst du dein Paket (oder eine gepatchte Version) so einbinden, als wäre es Teil von
Nixpkgs – damit andere Pakete es über pkgs.toolbox finden. Das macht ein
Overlay:
pkgs = import nixpkgs {
inherit system;
overlays = [
(final: prev: {
toolbox = final.callPackage ./toolbox.nix {};
})
];
};
# jetzt existiert pkgs.toolbox überall im Flake
Ein Overlay ist eine Funktion final: prev: { … }: prev ist das alte
pkgs, final das fertige (für gegenseitige Referenzen). Für eine einzelne
Dev-Shell reicht oft callPackage ohne Overlay – Overlays glänzen, wenn mehrere Pakete
aufeinander aufbauen.
callPackage vs. direkter Import
import ./toolbox.nix liefert nur die Funktion – die Argumente fehlen dann.
callPackage ./toolbox.nix {} ruft sie korrekt mit den pkgs-Argumenten auf.
„function called without required argument" heißt fast immer: import statt
callPackage benutzt.
pkgs neu auf und kostet Auswertungszeit. Für „ich will mein Tool in
einer Shell" ist die lokale let toolbox = … in-Variante schlanker.
nix run braucht $out/bin
nix run startet das Programm aus packages.default. Es muss also ein
ausführbares Binary in $out/bin liegen – genau das, was die Sprach-Builder automatisch tun.
Nicht spicken – Abrufen aus dem Gedächtnis ist genau die Übung, die hängen bleibt.
Was leistet pkgs.callPackage ./toolbox.nix {}?
callPackage nimmt die Funktion aus der Datei und füllt ihre Argumente
(buildGoModule, lib, …) automatisch aus pkgs.
Wie machst du dein Paket in der Dev-Shell verfügbar?
Dein gebautes Paket ist eine Derivation wie jede andere – es gehört einfach in die
packages-Liste neben pkgs.go & Co.
Wann lohnt sich ein Overlay statt callPackage allein?
Overlays machen dein Paket global als pkgs.toolbox sichtbar – nützlich, wenn andere
Pakete darauf aufbauen. Für eine einzelne Shell ist callPackage schlanker.
Ziel: Das toolbox-Paket aus Lektion 10 in dein Flake einhängen.
toolbox = pkgs.callPackage ./toolbox.nix {}; im let deines Flakes ein.packages.<system>.default = toolbox; und teste nix run.toolbox zur packages-Liste der Dev-Shell hinzu.nix develop, dann toolbox direkt aufrufen – es liegt im PATH.Tipp: git add toolbox.nix nicht vergessen, sonst sieht das Flake die Datei nicht.
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
toolbox = pkgs.callPackage ./toolbox.nix {};
in {
packages.${system}.default = toolbox;
devShells.${system}.default = pkgs.mkShell {
packages = [ pkgs.go toolbox ];
};
}
# nix run → startet toolbox; nix develop → toolbox im PATH
Glückwunsch: ein vollständiges Flake aus eigenem Paket + reproduzierbarer Dev-Shell.
callPackage
und Overlays.
Lies, wie callPackage Argumente auflöst und wie ein Overlay final/prev nutzt.
callPackage oder ein git add.
use flake, Profi-Kniffe)