1{
2 stdenv,
3 lib,
4 fetchFromGitHub,
5 python3,
6 extraPythonPackages ? ps: [ ],
7 unstableGitUpdater,
8 makeWrapper,
9 writeShellScript,
10}:
11
12stdenv.mkDerivation rec {
13 pname = "klipper";
14 version = "0.13.0-unstable-2025-07-12";
15
16 src = fetchFromGitHub {
17 owner = "KevinOConnor";
18 repo = "klipper";
19 rev = "9323a5dfe28619a53c7f350c2e894d299c342bca";
20 sha256 = "sha256-m6A8a3lR8aeMudA/kz1wCynm+6jZY3w6v2Pag54lQd8=";
21 };
22
23 sourceRoot = "${src.name}/klippy";
24
25 # NB: This is needed for the postBuild step
26 nativeBuildInputs = [
27 (python3.withPackages (p: with p; [ cffi ]))
28 makeWrapper
29 ];
30
31 buildInputs = [
32 (python3.withPackages (
33 p:
34 with p;
35 [
36 python-can
37 cffi
38 pyserial
39 greenlet
40 jinja2
41 markupsafe
42 numpy
43 ]
44 ++ extraPythonPackages p
45 ))
46 ];
47
48 # we need to run this to prebuild the chelper.
49 postBuild = ''
50 python ./chelper/__init__.py
51 '';
52
53 # Python 3 is already supported but shebangs aren't updated yet
54 postPatch = ''
55 for file in klippy.py console.py parsedump.py; do
56 substituteInPlace $file \
57 --replace '/usr/bin/env python2' '/usr/bin/env python'
58 done
59
60 # needed for cross compilation
61 substituteInPlace ./chelper/__init__.py \
62 --replace 'GCC_CMD = "gcc"' 'GCC_CMD = "${stdenv.cc.targetPrefix}cc"'
63 '';
64
65 pythonInterpreter =
66 (python3.withPackages (
67 p: with p; [
68 numpy
69 matplotlib
70 ]
71 )).interpreter;
72
73 pythonScriptWrapper = writeShellScript pname ''
74 ${pythonInterpreter} "@out@/lib/scripts/@script@" "$@"
75 '';
76
77 # NB: We don't move the main entry point into `/bin`, or even symlink it,
78 # because it uses relative paths to find necessary modules. We could wrap but
79 # this is used 99% of the time as a service, so it's not worth the effort.
80 installPhase = ''
81 runHook preInstall
82 mkdir -p $out/lib/klipper
83 cp -r ./* $out/lib/klipper
84
85 # Moonraker expects `config_examples` and `docs` to be available
86 # under `klipper_path`
87 cp -r $src/docs $out/lib/docs
88 cp -r $src/config $out/lib/config
89 cp -r $src/scripts $out/lib/scripts
90 cp -r $src/klippy $out/lib/klippy
91
92 # Add version information. For the normal procedure see https://www.klipper3d.org/Packaging.html#versioning
93 # This is done like this because scripts/make_version.py is not available when sourceRoot is set to "${src.name}/klippy"
94 echo "${version}-NixOS" > $out/lib/klipper/.version
95
96 mkdir -p $out/bin
97 chmod 755 $out/lib/klipper/klippy.py
98 makeWrapper $out/lib/klipper/klippy.py $out/bin/klippy --chdir $out/lib/klipper
99
100 substitute "$pythonScriptWrapper" "$out/bin/klipper-calibrate-shaper" \
101 --subst-var "out" \
102 --subst-var-by "script" "calibrate_shaper.py"
103 chmod 755 "$out/bin/klipper-calibrate-shaper"
104
105 runHook postInstall
106 '';
107
108 passthru.updateScript = unstableGitUpdater {
109 url = meta.homepage;
110 tagPrefix = "v";
111 };
112
113 meta = with lib; {
114 description = "Klipper 3D printer firmware";
115 mainProgram = "klippy";
116 homepage = "https://github.com/KevinOConnor/klipper";
117 maintainers = with maintainers; [
118 lovesegfault
119 zhaofengli
120 cab404
121 ];
122 platforms = platforms.linux;
123 license = licenses.gpl3Only;
124 };
125}