summary refs log tree commit diff
path: root/pkgs/applications/science/math/sage/default.nix
blob: b74bcc3d63772426e449e1b0f78650d8fe6d64a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# TODO
# - consider writing a script to convert spkgs to nix packages, similar to vim
#   or cabal2nix. This would allow a more efficient and "cleaner" build, greater
#   flexibility and the possibility to select which dependencies to add and which
#   to remove. It would also allow to use system packages for some dependencies
#   and recompile others (optimized for the system) without recompiling everything.
# - add optdeps:
#   - imagemagick
#   - texlive full for documentation
#   - ...
# - further seperate build outputs. Also maybe run `make doc`.
#   Configure flags like --bindir and --libdir oculd also be used for that, see
#   ./configure --help`.

# Other resources:
# - https://wiki.debian.org/DebianScience/Sage
# - https://github.com/cschwan/sage-on-gentoo
# - https://git.archlinux.org/svntogit/community.git/tree/trunk?h=packages/sagemath

{ stdenv
, bash
, fetchurl
, perl
, gfortran6
, python
, autoreconfHook
, gettext
, which
, texlive
, texinfo
, hevea
, buildDocs ? false
, optimize ? false # optimize sage to the current system (obviously impure)
}:

stdenv.mkDerivation rec {
  version = "8.1";
  name = "sage-${version}";

  # Modified version of patchShebangs that patches to the sage-internal version if possible
  # and falls back to the system version if not.
  patchSageShebangs = ./patchSageShebangs.sh;
  src = fetchurl {
    # Note that the source is *not* fetched from github, since that doesn't
    # the upstream folder with all the source tarballs of the spkgs.
    # If those are not present they are fetched at build time, which breaks
    # when building in a sandbox (and probably only works if you install the
    # latest sage version).
    urls = [
      "http://mirrors.mit.edu/sage/src/sage-${version}.tar.gz"
      "ftp://ftp.fu-berlin.de/unix/misc/sage/src/sage-${version}.tar.gz"
      "http://sagemath.polytechnic.edu.na/src/sage-${version}.tar.gz"
      "ftp://ftp.sun.ac.za/pub/mirrors/www.sagemath.org/src/sage-${version}.tar.gz"
      "http://sagemath.mirror.ac.za/src/sage-${version}.tar.gz"
      "http://ftp.leg.uct.ac.za/pub/packages/sage/src/sage-${version}.tar.gz"
      "http://mirror.ufs.ac.za/sagemath/src/sage-${version}.tar.gz"
      "http://mirrors-usa.go-parts.com/sage/sagemath/src/sage-${version}.tar.gz"
      "http://www.cecm.sfu.ca/sage/src/sage-${version}.tar.gz"
      "http://files.sagemath.org/src/sage-${version}.tar.gz"
      "http://mirrors.xmission.com/sage/src/sage-${version}.tar.gz"
      "http://sagemath.c3sl.ufpr.br/src/sage-${version}.tar.gz"
      "http://linorg.usp.br/sage/src/sage-${version}.tar.gz"
      "http://mirror.hust.edu.cn/sagemath/src/sage-${version}.tar.gz"
      "http://ftp.iitm.ac.in/sage/src/sage-${version}.tar.gz"
      "http://ftp.kaist.ac.kr/sage/src/sage-${version}.tar.gz"
      "http://ftp.riken.jp/sagemath/src/sage-${version}.tar.gz"
      "http://mirrors.tuna.tsinghua.edu.cn/sagemath/src/sage-${version}.tar.gz"
      "http://mirrors.ustc.edu.cn/sagemath/src/sage-${version}.tar.gz"
      "http://ftp.tsukuba.wide.ad.jp/software/sage/src/sage-${version}.tar.gz"
      "http://ftp.yz.yamagata-u.ac.jp/pub/math/sage/src/sage-${version}.tar.gz"
      "http://mirror.yandex.ru/mirrors/sage.math.washington.edu/src/sage-${version}.tar.gz"
      "http://mirror.aarnet.edu.au/pub/sage/src/sage-${version}.tar.gz"
      "http://sage.mirror.garr.it/mirrors/sage/src/sage-${version}.tar.gz"
      "http://www.mirrorservice.org/sites/www.sagemath.org/src/sage-${version}.tar.gz"
      "http://mirror.switch.ch/mirror/sagemath/src/sage-${version}.tar.gz"
      "https://mirrors.up.pt/pub/sage/src/sage-${version}.tar.gz"
      "http://www-ftp.lip6.fr/pub/math/sagemath/src/sage-${version}.tar.gz"
      "http://ftp.ntua.gr/pub/sagemath/src/sage-${version}.tar.gz"
    ];
    sha256 = "1cpcs1mr0yii64s152xmxyd450bfzjb22jjj0zh9y3n6g9alzpyq";
  };

  postPatch = ''
    substituteAllInPlace src/bin/sage-env
    bash=${bash} substituteAllInPlace build/bin/sage-spkg
  '';

  installPhase = ''
    # Sage installs during first `make`, `make install` is no-op and just takes time.
  '';

  outputs = [ "out" ] ++ stdenv.lib.optionals (buildDocs) [ "doc" ];

  buildInputs = [
    bash # needed for the build
    perl # needed for the build
    python # needed for the build
    gfortran6 # needed to build giac, openblas
    autoreconfHook # needed to configure sage with prefix
    gettext # needed to build the singular spkg
    which # needed in configure of mpir
    texinfo # needed to build maxima
  ] ++ stdenv.lib.optionals(buildDocs) [
    hevea # needed to build the docs of the giac spkg
    (texlive.combine { inherit (texlive)
      scheme-basic
      collection-pstricks # needed by giac
      times # font needed by giac
      stmaryrd # needed by giac
      babel-greek # optional for giac, otherwise throws a bunch of latex command not founds
      ;
    })
  ];

  nativeBuildInputs = [ gfortran6 perl which ];

  patches = [
    # fix usages of /bin/rm
    ./spkg-singular.patch
    # help python find the crypt library
    # patches python3 and indirectly python2, since those installation files are symlinked
    ./spkg-python.patch
    # fix usages of /usr/bin/perl
    ./spkg-git.patch
    # fix usages of /bin/cp and add necessary argument to function call
    ./spkg-giac.patch
    # environment
    ./env.patch
    # adjust wrapper shebang and patch shebangs after each spkg build
    ./shebangs.patch
  ];

  enableParallelBuilding = true;

  hardeningDisable = [
    "format" # needed to build palp, for lines like `printf(ctime(&_NFL->TIME))`
    # TODO could be patched with `sed s|printf(ctime(\(.*\)))|%s... or fixed upstream
  ];

  configureFlags = stdenv.lib.optionals(buildDocs) [ "--docdir=$(doc)" ];
  preConfigure = ''
    export SAGE_NUM_THREADS="$NIX_BUILD_CORES"

    export HOME=/tmp/sage-home
    export SAGE_ROOT="$PWD"
    export SAGE_SRC="$PWD"

    mkdir -p "$HOME"
    mkdir -p "$out"

    # we need to keep the source around
    dir="$PWD"
    cd ..
    mv "$dir" "$out/sage-root"

    export SAGE_SPKG_INSTALL_DOCS='no'
    cd "$out/sage-root" # build in target dir, since `make` is also `make install`
  ''
  + stdenv.lib.optionalString (buildDocs) ''
    mkdir -p "$doc"
    export SAGE_DOC="$doc"
    export SAGE_DOCBUILD_OPTS="--no-pdf-links -k"
  ''
  + stdenv.lib.optionalString (!optimize) ''
    export SAGE_FAT_BINARY=yes
  '';

  buildFlags = if (buildDocs) then "doc" else "build";

  # for reference: http://doc.sagemath.org/html/en/installation/source.html
  preBuild = ''
    # symlink python to make sure the shebangs are patched to the sage path
    # while still being able to use python before building it
    # (this is important because otherwise sage will try to install python
    # packages globally later on)
    ln -s "${python}/bin/python2" $out/bin/python2
    ln -s "$out/bin/python2" $out/bin/python
    touch $out/bin/python3
    bash $patchSageShebangs .
  '';

  postBuild = ''
    # Clean up
    rm -r "$out/sage-root/upstream" # don't keep the sources of all the spkgs
    rm -rf "$out/sage-root/src/build"
    rm -rf "$out/sage-root/src/autom4te.cache"
    rm -rf "$out/sage-root/src/config"
    rm -rf "$out/sage-root/src/m4"
    rm -rf "$out/sage-root/.git"
    rm -r "$out/sage-root/logs"
    rm -r "$out"/lib/python*/test
    # Fix dependency cycle between out and doc
    rm -f "$out/sage-root/config.log"
    rm -f "$out/sage-root/config.status"
    rm -f "$out/sage-root/build/make/Makefile-auto"
    rm -f "$out/sage-home/.sage/gap/libgap-workspace-"*
    # Make sure unnessessary packages don't end up in the build closure
    find "$out" \
        -iname 'config.log' \
        -delete \
        -or -iname 'Makefile' \
        -delete
    rm -f "$out/lib/R/etc/Renviron"
    # Make sure all shebangs are properly patched
    bash $patchSageShebangs $out
  '';

  # TODO there are some doctest failures, which seem harmless.
  # We should figure out a way to fix the failures or ignore only those tests.
  doCheck = false;

  checkTarget = "ptestalllong"; # all long tests in parallell
  preCheck = ''
    export SAGE_TIMEOUT=0 # no timeout
    export SAGE_TIMEOUT_LONG=0 # no timeout
  '';

  meta = {
    homepage = http://www.sagemath.org;
    description = "A free open source mathematics software system";
    # taken from the homepage
    longDescription = ''
      SageMath is a free open-source mathematics software system licensed under the GPL. It builds on top of many existing open-source packages: NumPy, SciPy, matplotlib, Sympy, Maxima, GAP, FLINT, R and many more. Access their combined power through a common, Python-based language or directly via interfaces or wrappers.
      Mission: Creating a viable free open source alternative to Magma, Maple, Mathematica and Matlab.
    '';
    license = stdenv.lib.licenses.gpl2Plus;
    platforms = ["x86_64-linux" "i686-linux"];
    maintainers = with stdenv.lib.maintainers; [ timokau ];
  };
}