1{
2 lib,
3 stdenv,
4 fetchPypi,
5 writeText,
6 buildPythonPackage,
7 isPyPy,
8 pythonOlder,
9
10 # build-system
11 certifi,
12 pkg-config,
13 pybind11,
14 setuptools,
15 setuptools-scm,
16
17 # native libraries
18 ffmpeg-headless,
19 freetype,
20 qhull,
21
22 # propagates
23 contourpy,
24 cycler,
25 fonttools,
26 kiwisolver,
27 numpy,
28 packaging,
29 pillow,
30 pyparsing,
31 python-dateutil,
32
33 # optional
34 importlib-resources,
35
36 # GTK3
37 enableGtk3 ? false,
38 cairo,
39 gobject-introspection,
40 gtk3,
41 pycairo,
42 pygobject3,
43
44 # Tk
45 # Darwin has its own "MacOSX" backend, PyPy has tkagg backend and does not support tkinter
46 enableTk ? (!stdenv.isDarwin && !isPyPy),
47 tcl,
48 tk,
49 tkinter,
50
51 # Ghostscript
52 enableGhostscript ? true,
53 ghostscript,
54
55 # Qt
56 enableQt ? false,
57 pyqt5,
58
59 # Webagg
60 enableWebagg ? false,
61 tornado,
62
63 # nbagg
64 enableNbagg ? false,
65 ipykernel,
66
67 # darwin
68 Cocoa,
69
70 # required for headless detection
71 libX11,
72 wayland,
73
74 # Reverse dependency
75 sage,
76}:
77
78let
79 interactive = enableTk || enableGtk3 || enableQt;
80in
81
82buildPythonPackage rec {
83 version = "3.8.4";
84 pname = "matplotlib";
85 pyproject = true;
86
87 disabled = pythonOlder "3.8";
88
89 src = fetchPypi {
90 inherit pname version;
91 hash = "sha256-iqw5fV6ewViWDjHDgcX/xS3dUr2aR3F+KmlAOBZ9/+o=";
92 };
93
94 env.XDG_RUNTIME_DIR = "/tmp";
95
96 # Matplotlib tries to find Tcl/Tk by opening a Tk window and asking the
97 # corresponding interpreter object for its library paths. This fails if
98 # `$DISPLAY` is not set. The fallback option assumes that Tcl/Tk are both
99 # installed under the same path which is not true in Nix.
100 # With the following patch we just hard-code these paths into the install
101 # script.
102 postPatch =
103 let
104 tcl_tk_cache = ''"${tk}/lib", "${tcl}/lib", "${lib.strings.substring 0 3 tk.version}"'';
105 in
106 ''
107 substituteInPlace pyproject.toml \
108 --replace-fail '"numpy>=2.0.0rc1,<2.3",' ""
109 ''
110 + lib.optionalString enableTk ''
111 sed -i '/self.tcl_tk_cache = None/s|None|${tcl_tk_cache}|' setupext.py
112 ''
113 + lib.optionalString (stdenv.isLinux && interactive) ''
114 # fix paths to libraries in dlopen calls (headless detection)
115 substituteInPlace src/_c_internal_utils.c \
116 --replace libX11.so.6 ${libX11}/lib/libX11.so.6 \
117 --replace libwayland-client.so.0 ${wayland}/lib/libwayland-client.so.0
118 '';
119
120 nativeBuildInputs = [ pkg-config ] ++ lib.optionals enableGtk3 [ gobject-introspection ];
121
122 buildInputs =
123 [
124 ffmpeg-headless
125 freetype
126 qhull
127 ]
128 ++ lib.optionals enableGhostscript [ ghostscript ]
129 ++ lib.optionals enableGtk3 [
130 cairo
131 gtk3
132 ]
133 ++ lib.optionals enableTk [
134 libX11
135 tcl
136 tk
137 ]
138 ++ lib.optionals stdenv.isDarwin [ Cocoa ];
139
140 # clang-11: error: argument unused during compilation: '-fno-strict-overflow' [-Werror,-Wunused-command-line-argument]
141 hardeningDisable = lib.optionals stdenv.isDarwin [ "strictoverflow" ];
142
143 build-system = [
144 certifi
145 numpy
146 pybind11
147 setuptools
148 setuptools-scm
149 ];
150
151 dependencies =
152 [
153 # explicit
154 contourpy
155 cycler
156 fonttools
157 kiwisolver
158 numpy
159 packaging
160 pillow
161 pyparsing
162 python-dateutil
163 ]
164 ++ lib.optionals (pythonOlder "3.10") [ importlib-resources ]
165 ++ lib.optionals enableGtk3 [
166 pycairo
167 pygobject3
168 ]
169 ++ lib.optionals enableQt [ pyqt5 ]
170 ++ lib.optionals enableWebagg [ tornado ]
171 ++ lib.optionals enableNbagg [ ipykernel ]
172 ++ lib.optionals enableTk [ tkinter ];
173
174 passthru.config = {
175 directories = {
176 basedirlist = ".";
177 };
178 libs = {
179 system_freetype = true;
180 system_qhull = true;
181 # LTO not working in darwin stdenv, see #19312
182 enable_lto = !stdenv.isDarwin;
183 };
184 };
185
186 passthru.tests = {
187 inherit sage;
188 };
189
190 env.MPLSETUPCFG = writeText "mplsetup.cfg" (lib.generators.toINI { } passthru.config);
191
192 # Encountering a ModuleNotFoundError, as describved and investigated at:
193 # https://github.com/NixOS/nixpkgs/issues/255262 . It could be that some of
194 # which may fail due to a freetype version that doesn't match the freetype
195 # version used by upstream.
196 doCheck = false;
197
198 meta = with lib; {
199 description = "Python plotting library, making publication quality plots";
200 homepage = "https://matplotlib.org/";
201 changelog = "https://github.com/matplotlib/matplotlib/releases/tag/v${version}";
202 license = with licenses; [
203 psfl
204 bsd0
205 ];
206 maintainers = with maintainers; [
207 lovek323
208 veprbl
209 ];
210 };
211}