Building from source using Meson

This is a short guide on how to build the Sage from source using Meson.

Walkthrough

Note

If you have previously build Sage in-place, you first have to delete the already compiled files, e.g. with shopt -s globstar followed by rm src/**/*.so or for f in src/**/*.so ; do mv "$f" "$f.old"; done. Moreover, remove the old generated files with find src/sage/ext/interpreters -type f ! -name 'meson.build' -delete. Also uninstall the ‘old’ sage packages with pip uninstall sage-conf sage-setup sagemath-standard.

Sage relies on a number of external libraries, which have to be installed before building. The easiest way to install them is to use Conda. Alternatively, you can install them via your system package manager. Both methods are described below.

Using Conda

  • If you haven’t already, download and install Miniforge for your platform following the Miniforge instructions. Other Conda distributions like Miniconda should work as well, but may require additional configuration (see Install from conda-forge).

  • Create and activate a new conda environment with the dependencies of Sage and a few additional developer tools:

    $ mamba env create --file environment-3.12-linux.yml --name sage-dev
    $ mamba activate sage-dev
    
    $ mamba env create --file environment-3.12-macos.yml --name sage-dev
    $ mamba activate sage-dev
    

    Note

    Windows support is very experimental and many features are not working yet.

    First you need to install the Microsoft Visual C++ compiler. You can download the Visual Studio Build Tools. Make sure to select “VC++ 2022 version xx.x build tools” and “Windows SDK”. If you prefer, you can also run the following command to install the necessary components:

    $ winget install Microsoft.VisualStudio.2022.BuildTools --force --override "--wait --passive --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.22621"
    

    Alternatively, you can use the compiler that comes bundled with Visual Studio.

    If you haven’t already, install the latest version of Conda from Miniforge. It is strongly recommended to choose the option to add Conda to the PATH during installation (because we will not use the Miniforge prompt).

    Open the “VS x64 Native Tools Command Prompt” (for 64bit) or “Developer Command Prompt for VS2022 (or 2019)” (for 32bit).

    $ mamba env create --file environment-3.12-win.yml --name sage-dev
    $ conda activate sage-dev
    $ set LIB=%CONDA_PREFIX%\Library\lib;%LIB%
    $ set INCLUDE=%CONDA_PREFIX%\Library\include;%INCLUDE%
    

    Windows support is experimental and not fully working yet. In fact, the Sage prompt is not working at all, but you can use the Python prompt to run certain commands. For example, the following should work after building Sage:

    >>> from sage.rings.integer import Integer
    >>> Integer(5)
    5
    >>> Integer(5) + 2.0
    7.0
    

    A different Python version can be selected by replacing 3.12 with the desired version.

  • To compile and install Sage in editable install, just use: .. code-block:: shell-session

    $ pip install –no-build-isolation –editable .

    This will install Sage in the current Conda environment. The --no-build-isolation flag is necessary to allow the build system to reuse the already installed build dependencies.

  • You can then start Sage from the command line with ./sage or run the tests with ./sage -t.

Using system package manager

You can also install the dependencies via your system package manager. Note, however, that not all dependencies may be available for your system, and that the versions may be outdated. In this case, Meson will try to build certain dependencies from source, or it will fail with an error message. In this case, you can either install the missing dependencies manually, or use Conda to install them.

Depending on your distribution, install the following packages:

Not yet supported.

At least Fedora 41 is required.

  $ sudo dnf install L-function L-function-devel Singular Singular-devel \
        binutils boost-devel brial brial-devel bzip2 bzip2-devel cddlib \
        cddlib-devel cliquer cliquer-devel cmake curl diffutils ecl eclib \
        eclib-devel fflas-ffpack-devel findutils flex flint flint-devel gap \
        gap-core gap-devel gap-libs gap-pkg-ace gap-pkg-aclib gap-pkg-alnuth \
        gap-pkg-anupq gap-pkg-atlasrep gap-pkg-autodoc gap-pkg-automata \
        gap-pkg-autpgrp gap-pkg-browse gap-pkg-caratinterface gap-pkg-circle \
        gap-pkg-congruence gap-pkg-crisp gap-pkg-crypting gap-pkg-crystcat \
        gap-pkg-curlinterface gap-pkg-cvec gap-pkg-datastructures \
        gap-pkg-digraphs gap-pkg-edim gap-pkg-ferret gap-pkg-fga \
        gap-pkg-fining gap-pkg-float gap-pkg-format gap-pkg-forms \
        gap-pkg-fplsa gap-pkg-fr gap-pkg-francy gap-pkg-genss \
        gap-pkg-groupoids gap-pkg-grpconst gap-pkg-images gap-pkg-io \
        gap-pkg-irredsol gap-pkg-json gap-pkg-jupyterviz gap-pkg-lpres \
        gap-pkg-nq gap-pkg-openmath gap-pkg-orb gap-pkg-permut gap-pkg-polenta \
        gap-pkg-polycyclic gap-pkg-primgrp gap-pkg-profiling gap-pkg-radiroot \
        gap-pkg-recog gap-pkg-resclasses gap-pkg-scscp gap-pkg-semigroups \
        gap-pkg-singular gap-pkg-smallgrp gap-pkg-smallsemi gap-pkg-sophus \
        gap-pkg-spinsym gap-pkg-standardff gap-pkg-tomlib gap-pkg-transgrp \
        gap-pkg-transgrp-data gap-pkg-utils gap-pkg-uuid gap-pkg-xmod \
        gap-pkg-zeromqinterface gc gc-devel gcc gcc-c++ gcc-gfortran gd \
        gd-devel gengetopt gf2x gf2x-devel gfan givaro givaro-devel glpk \
        glpk-devel glpk-utils gmp gmp-devel gmp-ecm gmp-ecm-devel gsl \
        gsl-devel iml iml-devel info libatomic_ops libatomic_ops-devel \
        libbraiding-devel libcurl-devel libffi libffi-devel libfplll \
        libfplll-devel libgap libhomfly-devel libmpc libmpc-devel linbox \
        linbox-devel lrcalc-devel m4 m4ri-devel m4rie-devel make mathjax3 \
        maxima maxima-runtime-ecl meson mpfi-devel mpfr-devel nauty \
        ncurses-devel ninja-build ntl-devel openblas-devel openssl \
        openssl-devel palp pari-devel pari-elldata pari-galdata pari-galpol \
        pari-gp pari-seadata patch patchelf perl perl-ExtUtils-MakeMaker \
        perl-IPC-Cmd pkg-config planarity planarity-devel ppl ppl-devel \
        primecount primecount-devel primesieve primesieve-devel python3 \
        python3-devel python3-setuptools python3-virtualenv qhull qhull-devel \
        readline-devel rw-devel sqlite sqlite-devel suitesparse \
        suitesparse-devel symmetrica-devel sympow tachyon tachyon-devel tar \
        texinfo tox which xgap xz xz-devel zeromq zeromq-devel zlib-devel
  $ sudo pacman -S bc binutils boost brial bzip2 cblas cddlib cliquer cmake \
        ecl eclib fflas-ffpack fplll gap gc gcc gcc-fortran gd gf2x gfan glpk \
        gsl iml lapack lcalc libatomic_ops libbraiding libhomfly linbox lrcalc \
        m4 m4ri m4rie make maxima-fas meson nauty ninja openblas openssl palp \
        pari pari-elldata pari-galdata pari-galpol pari-seadata patch perl \
        pkgconf planarity ppl primecount primesieve python python-tox qhull \
        rankwidth readline singular sqlite3 suitesparse symmetrica sympow \
        tachyon tar which zeromq
  $ sudo xbps-install SuiteSparse-devel bash bc binutils boost-devel \
        brial-devel bzip2-devel cddlib-devel cliquer-devel cmake curl \
        diffutils ecl eclib-devel ecm-devel fflas-ffpack flintlib-devel \
        fplll-devel freetype-devel gc-devel gcc gcc-fortran gd-devel gengetopt \
        gf2x-devel gfan givaro-devel glpk-devel gmp-devel gmpxx-devel \
        gsl-devel gzip iml-devel lcalc-devel libatomic_ops-devel \
        libbraiding-devel libcurl-devel libffi-devel libgomp-devel \
        libhomfly-devel liblzma-devel libmpc-devel libpng-devel libqhull-devel \
        libxcrypt-devel linbox-devel lrcalc-devel m4 m4ri-devel m4rie-devel \
        make mathjax maxima-ecl mpfi-devel mpfr-devel nauty ncurses-devel \
        ninja ntl-devel openblas-devel openssl-devel palp pari pari-devel \
        pari-elldata-small pari-galdata pari-galpol-small pari-seadata patch \
        patchelf perl pkgconf planarity-devel ppl-devel primecount-devel \
        primesieve-devel python3 python3-appdirs python3-devel python3-distlib \
        python3-filelock python3-setuptools python3-virtualenv qhull \
        rankwidth-devel readline-devel singular sqlite-devel symmetrica-devel \
        sympow tachyon tar texinfo tox which xz zeromq-devel zlib-devel

In the case that you want to install some dependencies manually, set the correct environment variables to point to the installed libraries:

$ export C_INCLUDE_PATH=$C_INCLUDE_PATH:/your/path/to/include
$ export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/your/path/to/include
$ export LIBRARY_PATH=$LIBRARY_PATH:/your/path/to/lib

We also recommend to install the Python package manager uv.

To compile and install Sage in editable install, then just use:

$ uv venv
$ uv pip install \
    meson-python \
    "cypari2 >=2.2.1" \
    "cython >=3.0, != 3.0.3, != 3.1.0" \
    "cython >=3.0, != 3.0.3" \
    "gmpy2 ~=2.1.b999" \
    memory_allocator \
    "numpy >=1.25" \
    jinja2 \
    setuptools
$ uv sync --frozen --inexact --no-build-isolation

You can then start Sage from the command line with ./sage or run the tests with ./sage -t.

Remarks

Note

By using pip install --editable in the above steps, the Sage library is installed in editable mode. This means that when you only edit source files, there is no need to rebuild the library; it suffices to restart Sage. Note that this even works when you edit Cython files (they will be recompiled automatically), so you no longer need to manually compile after editing Cython files.

Note

Note that make is not used at all, nor is configure. This means that any Sage-the-distribution commands such as sage -i will not work.

Note

By default, Meson will automatically determine the number of jobs to run in parallel based on the number of CPU available. This can be adjusted by passing --config-settings=compile-args=-jN to pip install.

--verbose can be passed to pip install, then the meson commands internally used by pip will be printed out.

Note

To build the documentation, use:

$ pip install --no-build-isolation -v -v --editable ./pkgs/sage-docbuild
$ sage --docbuild all html

Note

You can update the conda lock files by running tools/update-conda.py. In order to update the conda environment afterwards use:

$ mamba env update --file environment-3.12-linux.yml --name sage-dev

Background information

Under the hood, pip invokes meson to configure and build the project. We can also use meson directly as follows.

To configure the project, we need to run the following command:

$ meson setup builddir

This will create a build directory builddir that will hold the build artifacts.

If pip is used as above with --editable, builddir is set to be build/cp[Python major version][Python minor version], such as build/cp311.

To compile the project, run the following command:

$ meson compile -C builddir

On Windows, you may encounter a linker error related to a missing python_d.lib file. This typically indicates that your Python interpreter is not a debug build. To resolve this, it is recommended to use a release build by adding -Dbuildtype=release to the meson setup command, or alternatively, use a debug build of the Python interpreter.

Installing is done with the following command:

$ meson install -C builddir

This will install the project to currently active Python environment, or to the system Python environment if no environment is active. When editable install is used, it is not necessary to reinstall after each compilation.

Note

If you want to install the project to a different directory, you can specify the --prefix option when running the meson setup command:

$ meson setup builddir --prefix=/desired/install/path -Dpython.install_env=prefix

This will then install in the directory specified by --prefix, in particular the root folder will be be installed to /desired/install/path/lib/python3.12/site-packages/sage. Usually, this directory is not on your Python path, so you have to use:

$ PYTHONPATH=/desired/install/path ./sage

Alternatively, we can still use pip to install:

$ pip install --no-build-isolation --config-settings=builddir=builddir --editable .

Tip

Package maintainers may want to specify further build options or need to install to a different directory than the install prefix. Both are supported naturally by Meson:

$ meson setup builddir --prefix=/usr --libdir=... -Dcpp_args=...
$ meson compile -C builddir
$ DESTDIR=/path/to/staging/root meson install -C builddir

With the default prefix being /usr/local, it may then install to $DESTDIR/usr/local/lib/python3.12/site-packages/sage.

See Meson’s quick guide and Meson’s install guide for more information.

Miscellaneous tips

The environment variable MESONPY_EDITABLE_VERBOSE=1 can be set while running ./sage, so that when Cython files are recompiled a message is printed out. See https://mesonbuild.com/meson-python/how-to-guides/editable-installs.html#verbose-mode.

If a new .pyx file is added, it need to be added to meson.build file in the containing directory.

Unlike the make-based build system which relies on header comments # distutils: language = c++ to determine whether C++ should be used, Meson-based build system requires specifying override_options: ['cython_language=cpp'] in the meson.build file. Similarly, dependencies need to be specified by dependencies: [...].