···2233Sage is a pretty complex package that depends on many other complex packages and patches some of those. As a result, the sage nix package is also quite complex.
4455-Don't feel discouraged to fix, simplify or improve things though. Here's a quick overview over the functions of the individual files:
66-77-- `sage-src.nix`
88- Downloads the source code and applies patches. This makes sure that all the other files work with the same sage source. If you want to apply a patch to sage or update sage to a new version, this is the place to do it.
99-1010-- `env-locations.nix`
1111- Creates a bash file that sets a bunch of environment variables telling sage where to find various packages and files. The definitions of those environment variables can be found in the sage source in the `src/env.py` file. This bash file needs to be sourced before sage is started (done in `sage-env.nix` and `sagedoc.nix`).
1212-1313-- `sage-env.nix`
1414- Sets all environment variables sage needs to run. This includes the package locations defined in `env-locations.nix` as well as the location of sage itself and its various subdirectories.
1515-1616-- `sagelib.nix`
1717- Defines the main sage package (without setting the necessary environments or running any tests).
1818-1919-- `sage-with-env.nix`
2020- Wraps sage in the necessary environment.
2121-2222-- `sage.nix`
2323- Runs sages doctests.
2424-2525-- `sage-wrapper.nix`
2626- Optionally tells sage where do find the docs.
2727-2828-- `sagedoc.nix`
2929- Builds and tests the sage html documentation. Can be used for offline documentation viewing as well as the sage `browse_sage_doc` and `search_doc` functions.
3030-3131-- `sagenb.nix`
3232- The (semi deprecated) sage notebook.
3333-3434-- `default.nix`
3535- Introduces necessary overrides, defines new packages and ties everything together (returning the `sage` package).
3636-3737-- `flask-oldsessions.nix`, `flask-openid.nix`, `python-openid.nix`
3838- These are python packages that were rejected from the main nixpkgs tree because they appear unmaintained. They are needed for the (semi-deprecated) sage notebook. Since that notebook is still needed to run the sage doctests, these packages are included but not exposed to the rest of nixpkgs.
3939-4040-- `pybrial.nix`
4141- pybrial is a dependency of sage. However, pybrial itself also has sage as a dependency. Because of that circular dependency, pybrial is hidden from the rest of nixpkgs (just as the flask packages and python-openid.
4242-4343-- `openblas-pc.nix`
4444- This creates a `.pc` file to be read by `pkg-config` that allows openblas to take on different roles, like `cblas` or `lapack`.
55+Don't feel discouraged to fix, simplify or improve things though. The individual files have comments explaining their purpose. The most importent ones are `default.nix` linking everything together, `sage-src.nix` adding patches and `sagelib.nix` building the actual sage package.
456467## The sage build is broken
478
+73-50
pkgs/applications/science/math/sage/default.nix
···11-{ nixpkgs
11+{ pkgs
22, withDoc ? false
33}:
4455+# Here sage and its dependencies are put together. Some dependencies may be pinned
66+# as a last resort. Patching sage for compatibility with newer dependency versions
77+# is always preferred, see `sage-src.nix` for that.
88+59let
66- inherit (nixpkgs) fetchpatch fetchurl symlinkJoin callPackage nodePackages;
1010+ inherit (pkgs) fetchurl symlinkJoin callPackage nodePackages_8_x;
711812 # https://trac.sagemath.org/ticket/15980 for tracking of python3 support
99- python = nixpkgs.python2.override {
1313+ python = pkgs.python2.override {
1014 packageOverrides = self: super: {
1115 # python packages that appear unmaintained and were not accepted into the nixpkgs
1216 # tree because of that. These packages are only dependencies of the more-or-less
1317 # deprecated sagenb. However sagenb is still a default dependency and the doctests
1418 # depend on it.
1519 # See https://github.com/NixOS/nixpkgs/pull/38787 for a discussion.
2020+ # The dependency on the sage notebook (and therefore these packages) will be
2121+ # removed in the future:
2222+ # https://trac.sagemath.org/ticket/25837
1623 flask-oldsessions = self.callPackage ./flask-oldsessions.nix {};
1724 flask-openid = self.callPackage ./flask-openid.nix {};
1825 python-openid = self.callPackage ./python-openid.nix {};
2626+ sagenb = self.callPackage ./sagenb.nix {
2727+ mathjax = nodePackages_8_x.mathjax;
2828+ };
19293030+ # Package with a cyclic dependency with sage
2031 pybrial = self.callPackage ./pybrial.nix {};
21323333+ # `sagelib`, i.e. all of sage except some wrappers and runtime dependencies
2234 sagelib = self.callPackage ./sagelib.nix {
2335 inherit flint ecl arb;
2436 inherit sage-src openblas-blas-pc openblas-cblas-pc openblas-lapack-pc pynac singular;
2525- linbox = nixpkgs.linbox.override { withSage = true; };
3737+ linbox = pkgs.linbox.override { withSage = true; };
2638 };
3939+ };
4040+ };
27412828- sagenb = self.callPackage ./sagenb.nix {
2929- mathjax = nodePackages.mathjax;
3030- };
4242+ # A bash script setting various environment variables to tell sage where
4343+ # the files its looking fore are located. Also see `sage-env`.
4444+ env-locations = callPackage ./env-locations.nix {
4545+ inherit pari_data ecl;
4646+ inherit singular;
4747+ cysignals = python.pkgs.cysignals;
4848+ three = nodePackages_8_x.three;
4949+ mathjax = nodePackages_8_x.mathjax;
5050+ };
31513232- sagedoc = self.callPackage ./sagedoc.nix {
3333- inherit sage-src;
3434- };
5252+ # The shell file that gets sourced on every sage start. Will also source
5353+ # the env-locations file.
5454+ sage-env = callPackage ./sage-env.nix {
5555+ sagelib = python.pkgs.sagelib;
5656+ inherit env-locations;
5757+ inherit python rWrapper openblas-cblas-pc ecl singular palp flint pynac pythonEnv;
5858+ pkg-config = pkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
5959+ };
35603636- env-locations = self.callPackage ./env-locations.nix {
3737- inherit pari_data ecl;
3838- inherit singular;
3939- three = nodePackages.three;
4040- mathjax = nodePackages.mathjax;
4141- };
6161+ # The documentation for sage, building it takes a lot of ram.
6262+ sagedoc = callPackage ./sagedoc.nix {
6363+ inherit sage-with-env;
6464+ inherit python;
6565+ };
42664343- sage-env = self.callPackage ./sage-env.nix {
4444- inherit sage-src python rWrapper openblas-cblas-pc ecl singular palp flint pynac pythonEnv;
4545- pkg-config = nixpkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
4646- };
4747-4848- sage-with-env = self.callPackage ./sage-with-env.nix {
4949- inherit pythonEnv;
5050- inherit sage-src openblas-blas-pc openblas-cblas-pc openblas-lapack-pc pynac singular;
5151- pkg-config = nixpkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
5252- three = nodePackages.three;
5353- };
5454-5555- sage = self.callPackage ./sage.nix { };
6767+ # sagelib with added wrappers and a dependency on sage-tests to make sure thet tests were run.
6868+ sage-with-env = callPackage ./sage-with-env.nix {
6969+ inherit pythonEnv;
7070+ inherit sage-env;
7171+ inherit openblas-blas-pc openblas-cblas-pc openblas-lapack-pc pynac singular;
7272+ pkg-config = pkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
7373+ three = nodePackages_8_x.three;
7474+ };
56755757- sage-wrapper = self.callPackage ./sage-wrapper.nix {
5858- inherit sage-src withDoc;
5959- };
6060- };
7676+ # Doesn't actually build anything, just runs sages testsuite. This is a
7777+ # separate derivation to make it possible to re-run the tests without
7878+ # rebuilding sagelib (which takes ~30 minutes).
7979+ # Running the tests should take something in the order of 1h.
8080+ sage-tests = callPackage ./sage-tests.nix {
8181+ inherit sage-with-env;
6182 };
62838484+ # FIXME
6385 openblas-blas-pc = callPackage ./openblas-pc.nix { name = "blas"; };
6486 openblas-cblas-pc = callPackage ./openblas-pc.nix { name = "cblas"; };
6587 openblas-lapack-pc = callPackage ./openblas-pc.nix { name = "lapack"; };
···91113 } // { extraLibs = pythonRuntimeDeps; }; # make the libs accessible
9211493115 # needs to be rWrapper, standard "R" doesn't include default packages
9494- rWrapper = nixpkgs.rWrapper.override {
116116+ rWrapper = pkgs.rWrapper.override {
95117 # https://trac.sagemath.org/ticket/25674
9696- R = nixpkgs.R.overrideAttrs (attrs: rec {
118118+ R = pkgs.R.overrideAttrs (attrs: rec {
97119 name = "R-3.4.4";
98120 src = fetchurl {
99121 url = "http://cran.r-project.org/src/base/R-3/${name}.tar.gz";
···102124 });
103125 };
104126105105- arb = nixpkgs.arb.override { inherit flint; };
127127+ arb = pkgs.arb.override { inherit flint; };
106128107107- singular = nixpkgs.singular.override { inherit flint; };
129129+ singular = pkgs.singular.override { inherit flint; };
108130109131 # *not* to confuse with the python package "pynac"
110110- pynac = nixpkgs.pynac.override { inherit singular flint; };
132132+ pynac = pkgs.pynac.override { inherit singular flint; };
111133112134 # With openblas (64 bit), the tests fail the same way as when sage is build with
113135 # openblas instead of openblasCompat. Apparently other packages somehow use flints
114136 # blas when it is available. Alternative would be to override flint to use
115137 # openblasCompat.
116116- flint = nixpkgs.flint.override { withBlas = false; };
138138+ flint = pkgs.flint.override { withBlas = false; };
117139118140 # Multiple palp dimensions need to be available and sage expects them all to be
119141 # in the same folder.
120142 palp = symlinkJoin {
121121- name = "palp-${nixpkgs.palp.version}";
143143+ name = "palp-${pkgs.palp.version}";
122144 paths = [
123123- (nixpkgs.palp.override { dimensions = 4; doSymlink = false; })
124124- (nixpkgs.palp.override { dimensions = 5; doSymlink = false; })
125125- (nixpkgs.palp.override { dimensions = 6; doSymlink = true; })
126126- (nixpkgs.palp.override { dimensions = 11; doSymlink = false; })
145145+ (pkgs.palp.override { dimensions = 4; doSymlink = false; })
146146+ (pkgs.palp.override { dimensions = 5; doSymlink = false; })
147147+ (pkgs.palp.override { dimensions = 6; doSymlink = true; })
148148+ (pkgs.palp.override { dimensions = 11; doSymlink = false; })
127149 ];
128150 };
129151130152 # Sage expects those in the same directory.
131153 pari_data = symlinkJoin {
132154 name = "pari_data";
133133- paths = with nixpkgs; [
155155+ paths = with pkgs; [
134156 pari-galdata
135157 pari-seadata-small
136158 ];
137159 };
138160139161 # https://trac.sagemath.org/ticket/22191
140140- ecl = nixpkgs.ecl_16_1_2;
162162+ ecl = pkgs.ecl_16_1_2;
141163in
142142- python.pkgs.sage-wrapper // {
143143- doc = python.pkgs.sagedoc;
144144- lib = python.pkgs.sagelib;
145145- }
164164+# A wrapper around sage that makes sure sage finds its docs (if they were build).
165165+callPackage ./sage.nix {
166166+ inherit sage-tests sage-with-env sagedoc;
167167+ inherit withDoc;
168168+}
···1616, cysignals
1717}:
18181919+# A bash script setting various environment variables to tell sage where
2020+# the files its looking fore are located. Also see `sage-env`.
1921writeTextFile rec {
2022 name = "sage-env-locations";
2123 destination = "/${name}";
+11-6
pkgs/applications/science/math/sage/sage-env.nix
···22, lib
33, writeTextFile
44, python
55-, sage-src
65, sagelib
76, env-locations
87, gfortran
···4645, gsl
4746, ntl
4847}:
4848+4949+# This generates a `sage-env` shell file that will be sourced by sage on startup.
5050+# It sets up various environment variables, telling sage where to find its
5151+# dependencies.
49525053let
5154 runtimepath = (lib.makeBinPath ([
···103106 openblas-cblas-pc
104107 ])
105108 }'
106106- export SAGE_ROOT='${sage-src}'
109109+ export SAGE_ROOT='${sagelib.src}'
107110 export SAGE_LOCAL='@sage-local@'
108111 export SAGE_SHARE='${sagelib}/share'
109112 orig_path="$PATH"
110113 export PATH='${runtimepath}'
111114112115 # set dependent vars, like JUPYTER_CONFIG_DIR
113113- source "${sage-src}/src/bin/sage-env"
116116+ source "${sagelib.src}/src/bin/sage-env"
114117 export PATH="${runtimepath}:$orig_path" # sage-env messes with PATH
115118116119 export SAGE_LOGS="$TMPDIR/sage-logs"
117120 export SAGE_DOC="''${SAGE_DOC_OVERRIDE:-doc-placeholder}"
118118- export SAGE_DOC_SRC="''${SAGE_DOC_SRC_OVERRIDE:-${sage-src}/src/doc}"
121121+ export SAGE_DOC_SRC="''${SAGE_DOC_SRC_OVERRIDE:-${sagelib.src}/src/doc}"
119122120123 # set locations of dependencies
121124 . ${env-locations}/sage-env-locations
···154157155158 export SAGE_LIB='${sagelib}/${python.sitePackages}'
156159157157- export SAGE_EXTCODE='${sage-src}/src/ext'
160160+ export SAGE_EXTCODE='${sagelib.src}/src/ext'
158161159159- # for find_library
162162+ # for find_library
160163 export DYLD_LIBRARY_PATH="${lib.makeLibraryPath [stdenv.cc.libc singular]}:$DYLD_LIBRARY_PATH"
161164 '';
165165+} // {
166166+ lib = sagelib; # equivalent of `passthru`, which `writeTextFile` doesn't support
162167}
+19-5
pkgs/applications/science/math/sage/sage-src.nix
···22, fetchFromGitHub
33, fetchpatch
44}:
55+66+# This file is responsible for fetching the sage source and adding necessary patches.
77+# It does not actually build anything, it just copies the patched sources to $out.
88+# This is done because multiple derivations rely on these sources and they should
99+# all get the same sources with the same patches applied.
1010+511stdenv.mkDerivation rec {
612 version = "8.4";
713 name = "sage-src-${version}";
···1319 sha256 = "0gips1hagiz9m7s21bg5as8hrrm2x5k47h1bsq0pc46iplfwmv2d";
1420 };
15212222+ # Patches needed because of particularities of nix or the way this is packaged.
2323+ # The goal is to upstream all of them and get rid of this list.
1624 nixPatches = [
1725 # https://trac.sagemath.org/ticket/25358
1826 (fetchpatch {
···4048 ./patches/Only-test-py2-py3-optional-tests-when-all-of-sage-is.patch
4149 ];
42505151+ # Patches needed because of package updates. We could just pin the versions of
5252+ # dependencies, but that would lead to rebuilds, confusion and the burdons of
5353+ # maintaining multiple versions of dependencies. Instead we try to make sage
5454+ # compatible with never dependency versions when possible. All these changes
5555+ # should come from or be proposed to upstream. This list will probably never
5656+ # be empty since dependencies update all the time.
4357 packageUpgradePatches = let
4444- # fetch a diff between base and rev on sage's git server
4545- # used to fetch trac tickets by setting the base to the release and the
4646- # revision to the last commit that should be included
5858+ # Fetch a diff between `base` and `rev` on sage's git server.
5959+ # Used to fetch trac tickets by setting the `base` to the last release and the
6060+ # `rev` to the last commit of the ticket.
4761 fetchSageDiff = { base, rev, ...}@args: (
4862 fetchpatch ({
4963 url = "https://git.sagemath.org/sage.git/patch?id2=${base}&id=${rev}";
···6579 # https://trac.sagemath.org/ticket/25260
6680 ./patches/numpy-1.15.1.patch
67816868- # ntl upgrade
6969- # https://trac.sagemath.org/ticket/25532#comment:29
8282+ # needed for ntl update
8383+ # https://trac.sagemath.org/ticket/25532
7084 (fetchpatch {
7185 name = "lcalc-c++11.patch";
7286 url = "https://git.archlinux.org/svntogit/community.git/plain/trunk/sagemath-lcalc-c++11.patch?h=packages/sagemath&id=0e31ae526ab7c6b5c0bfacb3f8b1c4fd490035aa";
···5151, libbraiding
5252}:
53535454+# This is the core sage python package. Everything else is just wrappers gluing
5555+# stuff together. It is not very useful on its own though, since it will not
5656+# find many of its dependencies without `sage-env`, will not be tested without
5757+# `sage-tests` and will not have html docs without `sagedoc`.
5858+5459buildPythonPackage rec {
5560 format = "other";
5656- version = sage-src.version;
5757- pname = "sagelib";
5858-6161+ version = src.version;
6262+ name = "sagelib-${version}";
5963 src = sage-src;
60646165 nativeBuildInputs = [
+4-1
pkgs/applications/science/math/sage/sagenb.nix
···11-# Has a cyclic dependency with sage (not expressed here) and is not useful outside of sage
21{ stdenv
32, fetchpatch
43, python
···1211, flask-autoindex
1312, flask-babel
1413}:
1414+1515+# Has a cyclic dependency with sage (not expressed here) and is not useful outside of sage.
1616+# Deprecated, hopefully soon to be removed. See
1717+# https://trac.sagemath.org/ticket/25837
15181619buildPythonPackage rec {
1720 pname = "sagenb";