1{
2 pkgs,
3 withDoc ? false,
4 requireSageTests ? true,
5 extraPythonPackages ? ps: [ ],
6}:
7
8# Here sage and its dependencies are put together. Some dependencies may be pinned
9# as a last resort. Patching sage for compatibility with newer dependency versions
10# is always preferred, see `sage-src.nix` for that.
11
12let
13 inherit (pkgs) symlinkJoin callPackage nodePackages;
14
15 python3 = pkgs.python3 // {
16 pkgs = pkgs.python3.pkgs.overrideScope (
17 self: super: {
18 # `sagelib`, i.e. all of sage except some wrappers and runtime dependencies
19 sagelib = self.callPackage ./sagelib.nix {
20 inherit flint3;
21 inherit sage-src env-locations singular;
22 inherit (maxima) lisp-compiler;
23 linbox = pkgs.linbox;
24 pkg-config = pkgs.pkg-config; # not to confuse with pythonPackages.pkg-config
25 };
26
27 sage-docbuild = self.callPackage ./python-modules/sage-docbuild.nix {
28 inherit sage-src;
29 };
30
31 sage-setup = self.callPackage ./python-modules/sage-setup.nix {
32 inherit sage-src;
33 };
34 }
35 );
36 };
37
38 # matches src/sage/repl/ipython_kernel/install.py:kernel_spec
39 jupyter-kernel-definition = {
40 displayName = "SageMath ${sage-src.version}";
41 argv = [
42 "${sage-with-env}/bin/sage" # FIXME which sage
43 "--python"
44 "-m"
45 "sage.repl.ipython_kernel"
46 "-f"
47 "{connection_file}"
48 ];
49 language = "sage";
50 logo32 = "${sage-src}/src/sage/ext_data/notebook-ipython/logo-64x64.png";
51 logo64 = "${sage-src}/src/sage/ext_data/notebook-ipython/logo-64x64.png";
52 };
53
54 jupyter-kernel-specs = pkgs.jupyter-kernel.create {
55 definitions = pkgs.jupyter-kernel.default // {
56 sagemath = jupyter-kernel-definition;
57 };
58 };
59
60 three = callPackage ./threejs-sage.nix { };
61
62 # A bash script setting various environment variables to tell sage where
63 # the files its looking fore are located. Also see `sage-env`.
64 env-locations = callPackage ./env-locations.nix {
65 inherit pari_data;
66 inherit singular maxima;
67 inherit three;
68 cysignals = python3.pkgs.cysignals;
69 mathjax = nodePackages.mathjax;
70 };
71
72 # The shell file that gets sourced on every sage start. Will also source
73 # the env-locations file.
74 sage-env = callPackage ./sage-env.nix {
75 sagelib = python3.pkgs.sagelib;
76 sage-docbuild = python3.pkgs.sage-docbuild;
77 inherit env-locations;
78 inherit
79 python3
80 singular
81 palp
82 flint3
83 pythonEnv
84 maxima
85 ;
86 pkg-config = pkgs.pkg-config; # not to confuse with pythonPackages.pkg-config
87 };
88
89 # The documentation for sage, building it takes a lot of ram.
90 sagedoc = callPackage ./sagedoc.nix {
91 inherit sage-with-env jupyter-kernel-specs;
92 };
93
94 # sagelib with added wrappers and a dependency on sage-tests to make sure thet tests were run.
95 sage-with-env = callPackage ./sage-with-env.nix {
96 inherit python3 pythonEnv;
97 inherit sage-env;
98 inherit singular maxima;
99 inherit three;
100 pkg-config = pkgs.pkg-config; # not to confuse with pythonPackages.pkg-config
101 };
102
103 # Doesn't actually build anything, just runs sages testsuite. This is a
104 # separate derivation to make it possible to re-run the tests without
105 # rebuilding sagelib (which takes ~30 minutes).
106 # Running the tests should take something in the order of 1h.
107 sage-tests = callPackage ./sage-tests.nix {
108 inherit sage-with-env;
109 pytest = python3.pkgs.pytest;
110 };
111
112 sage-src = callPackage ./sage-src.nix { };
113
114 pythonRuntimeDeps =
115 with python3.pkgs;
116 [
117 sagelib
118 sage-docbuild
119 cvxopt
120 networkx
121 service-identity
122 psutil
123 sympy
124 fpylll
125 matplotlib
126 tkinter # optional, as a matplotlib backend (use with `%matplotlib tk`)
127 scipy
128 ipywidgets
129 notebook # for "sage -n"
130 rpy2
131 sphinx
132 pillow
133 ]
134 ++ extraPythonPackages python3.pkgs;
135
136 pythonEnv =
137 python3.buildEnv.override {
138 extraLibs = pythonRuntimeDeps;
139 ignoreCollisions = true;
140 }
141 // {
142 extraLibs = pythonRuntimeDeps;
143 }; # make the libs accessible
144
145 singular = pkgs.singular.override { inherit flint3; };
146
147 maxima = pkgs.maxima-ecl.override {
148 lisp-compiler = pkgs.ecl.override {
149 # "echo syntax error | ecl > /dev/full 2>&1" segfaults in
150 # ECL. We apply a patch to fix it (write_error.patch), but it
151 # only works if threads are disabled. sage 9.2 tests this
152 # (src/sage/interfaces/tests.py) and ships ecl like so.
153 # https://gitlab.com/embeddable-common-lisp/ecl/-/merge_requests/1#note_1657275
154 threadSupport = false;
155
156 # if we don't use the system boehmgc, sending a SIGINT to ecl
157 # can segfault if we it happens during memory allocation.
158 # src/sage/libs/ecl.pyx would intermittently fail in this case.
159 useBoehmgc = true;
160 };
161 };
162
163 # With openblas (64 bit), the tests fail the same way as when sage is build with
164 # openblas instead of openblasCompat. Apparently other packages somehow use flints
165 # blas when it is available. Alternative would be to override flint to use
166 # openblasCompat.
167 flint3 = pkgs.flint3.override { withBlas = false; };
168
169 # Multiple palp dimensions need to be available and sage expects them all to be
170 # in the same folder.
171 palp = symlinkJoin {
172 name = "palp-${pkgs.palp.version}";
173 paths = [
174 (pkgs.palp.override {
175 dimensions = 4;
176 doSymlink = false;
177 })
178 (pkgs.palp.override {
179 dimensions = 5;
180 doSymlink = false;
181 })
182 (pkgs.palp.override {
183 dimensions = 6;
184 doSymlink = true;
185 })
186 (pkgs.palp.override {
187 dimensions = 11;
188 doSymlink = false;
189 })
190 ];
191 };
192
193 # Sage expects those in the same directory.
194 pari_data = symlinkJoin {
195 name = "pari_data";
196 paths = with pkgs; [
197 pari-galdata
198 pari-seadata-small
199 ];
200 };
201in
202# A wrapper around sage that makes sure sage finds its docs (if they were build).
203callPackage ./sage.nix {
204 inherit
205 sage-tests
206 sage-with-env
207 sagedoc
208 jupyter-kernel-definition
209 jupyter-kernel-specs
210 ;
211 inherit withDoc requireSageTests;
212}