.. highlight:: rest .. _sec-compiling: Compiling and Installing SLUG ============================== Compilation is only necessary if you are installing SLUG from source, as described in :ref:`sec-getting`. If you are installing from PyPI or a container, you can skip this section. There are two ways to build a source checkout. The first, described in :ref:`sec-building` below, is to build it in place with CMake. This has no separate installation step: it produces the ``slug`` command-line executable directly in the build directory, and the compiled Python extension module lands directly inside the ``slugpy`` package in the source tree, alongside its pure-Python code. This is the most flexible option, and the one to use if you plan to modify SLUG. The second, described in :ref:`sec-pip-install-source` below, is to build and install it into a Python environment with ``pip``, exactly as a PyPI installation would, but compiled on your own system. .. _sec-dependencies: Dependencies ------------- Required ~~~~~~~~~ * `CMake `_, version 3.15 or later. * A C++23-capable compiler. The following compilers are known to work: * GCC 13 or later * Clang 17 or later (paired with a libc++ of the same version or newer) * Intel's LLVM-based ``icpx``/oneAPI 2024.2.0+ (requires the flag ``-fp-model=strict`` for correct behavior) * Other C++23-capable compilers have not been tested. * The `GNU Scientific Library `_ (GSL). * `HDF5 `_ (only its C library is needed; HDF5's optional C++ component is not required). Bundled (no action needed) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ These are vendored as git submodules under ``src/extern`` and built automatically as part of the normal build -- just make sure they were fetched (see :ref:`sec-getting` on cloning with submodules; if you forgot, ``git submodule update --init --recursive`` from the repository root fetches them after the fact too): * `pybind11 `_, used to build the Python bindings (see below). * A reference implementation of C++23's ```` (from the `Kokkos mdspan `_ project), used as a last resort if neither the compiler's own standard library nor an externally installed ``mdspan`` package provides one. Whether a given compiler provides ```` natively depends on the *exact* standard-library snapshot it was built against, not just its nominal major version -- e.g. Homebrew's own ``gcc@16`` build on macOS bundles a libstdc++ new enough to have it, while the ``gcc-16`` package from Ubuntu's ``ppa:ubuntu-toolchain-r/test`` (as used in CI) does not, as of when this was last checked, and Apple's own system Clang/libc++ has no native ```` at all. None of this matters in practice: ``cmake/Mdspan.cmake`` detects native support with a real compile check (not a version guess) and falls back automatically, in the order listed above, to an externally-installed ``mdspan`` package and then this bundled submodule -- see that file's own comments, or AGENTS.md, for the full detail. Application code always just does ``#include `` regardless of which provider actually supplied it. One further wrinkle specific to this bundled fallback: its own ``config.hpp`` deliberately disables its multi-index ``operator[]`` on Clang versions before 17, as a workaround for a documented upstream Clang bug with parameter packs in bracket operators -- so a build that falls back to this submodule under Clang 16 or earlier fails with "no viable overloaded operator[]" errors on every ``mdspan`` indexing expression, even though Clang itself supports the multidimensional ``operator[]`` language feature from an earlier version (see :ref:`sec-dependencies` above). This is why Clang's own effective minimum version is 17, one version above where the language feature itself first appears. Optional ~~~~~~~~~ * `OpenMP `_, for multi-threaded execution. If no OpenMP implementation is found, the build falls back to a single-threaded binary automatically, with a warning at configure time. * An MPI implementation (e.g. `OpenMPI `_ or `MPICH `_), for multi-process execution across more than one machine -- see :ref:`sec-running-mpi`. If none is found, the build falls back to a single-process binary automatically, with a warning at configure time, the same way OpenMP does above; the two are independent of each other, so a build can have either, both, or neither. MPI support only applies to the ``slug`` command-line executable itself, not the Python bindings. * `Ninja `_, as the CMake generator. Not required -- CMake falls back to its own platform default (Unix Makefiles on Linux/macOS) -- but Ninja parallelizes the build automatically and matches what SLUG's own CI uses, so local builds behave the same way and incremental rebuilds are noticeably faster. * `Doxygen `_ (install separately, e.g. via your system package manager or Homebrew), plus the Python packages `Sphinx `_, `Breathe `_, and `Exhale `_: .. code-block:: bash pip install sphinx breathe exhale sphinx_rtd_theme to build this documentation site itself as part of the normal build -- see :ref:`sec-building-docs` below. Entirely optional: every other part of the build is unaffected if these aren't installed. Python ~~~~~~~ SLUG's Python frontend, ``slugpy`` (see :ref:`sec-slugpy`), requires Python 3.12 or later, plus `astropy `_, `h5py `_, `NumPy `_, `platformdirs `_, `SciPy `_, `tomlkit `_, `tqdm `_, and `urllib3 `_: .. code-block:: bash pip install astropy h5py numpy platformdirs scipy tomlkit tqdm urllib3 CMake builds the compiled ``_slug`` extension module against whichever Python interpreter it finds (or the one given explicitly via ``-DPython_EXECUTABLE``, see below), and that same interpreter needs the packages above installed for ``import slugpy`` to work afterwards. ``pyproject.toml`` lists these same packages (and the optional ones just below) under ``[project.dependencies]``/``[project.optional-dependencies]``. If you instead install a source checkout with ``pip`` (see :ref:`sec-pip-install-source`), ``pip`` installs them automatically. A further three tools are needed only for specific development tasks, not for using ``slugpy`` itself: `pytest `_ to run the test suite, `pyright `_ to type-check ``slugpy`` locally, and `ruff `_ to lint it: .. code-block:: bash pip install pytest pyright ruff .. _sec-building: Configuring and Building -------------------------- SLUG uses an out-of-source CMake build. From the repository root: .. code-block:: bash cmake -S . -B build -G Ninja cmake --build build (omit ``-G Ninja`` to use CMake's own default generator instead, if Ninja isn't installed -- see :ref:`sec-dependencies` above). This produces the ``slug`` command-line executable at ``build/slug``, and builds the compiled Python extension module directly into the ``slugpy`` package in the source tree (so ``import slugpy`` works from the repository root immediately afterward, with no separate install step). A few configure-time options worth knowing about: ``-DPython_EXECUTABLE=/path/to/python3`` Build the Python bindings against a specific Python interpreter, rather than whichever one CMake finds automatically. Needed if you use a virtual environment, conda environment, or other non-default interpreter for ``slugpy`` -- see :ref:`sec-dependencies` above for what that interpreter needs installed. ``-DSLUG_MDSPAN_PROVIDER=AUTO|NATIVE|PACKAGE|SUBMODULE`` Override the automatic ```` provider selection described above -- e.g. to require a specific provider and get a hard error if it isn't available, rather than a silent fallback. Defaults to ``AUTO``. ``-DCMAKE_BUILD_TYPE=Debug|Release|RelWithDebInfo`` The usual CMake build-type switch. If it is not given, SLUG defaults to ``Release``, an optimized build with assertions disabled; use ``Debug`` to turn on SLUG's internal assertion checks, e.g. when developing or debugging the code. Some of SLUG's own performance- sensitive targets (e.g. the Python extension module) are always built with optimizations enabled regardless of this setting, since they drive the same interpolation-heavy code any analysis using ``slugpy`` depends on. Setting the Data Path --------------------- Once SLUG is built, it is recommended but not required to set the environment variable ``SLUG_DIR`` to the repository root directory. This simplifies finding the data files that SLUG needs to run by providing an automatic search path that will be used when parsing the inputs -- see :ref:`sec-parameters` for details. For example, if you cloned the repository into ``/home/user/slug3``, you can do: .. code-block:: bash export SLUG_DIR=/home/user/slug3 This step is not necessary if you installed SLUG from PyPI or a container, or if you have :ref:`built and installed with pip `, since those installation methods automatically set up the data path for you. Verifying the Build --------------------- Once the build finishes, ``ctest`` (run from the build directory) executes SLUG's own test suite:: cd build ctest -L quick The ``quick`` label selects tests that run in a few seconds each and need no large data files beyond what's already committed to the repository; some further, slower end-to-end tests exist but require data files too large to distribute this way (see :ref:`sec-tests` for the full detail). .. _sec-pip-install-source: Installing a Source Checkout with pip -------------------------------------- Instead of building in place, you can build and install a source checkout into the active Python environment by running, from the repository root: .. code-block:: bash pip install . This uses the same CMake build, driven by `scikit-build-core `_, to compile SLUG, and then installs the slugpy package, the ``slug`` command-line executable, and the small data files distributed with the source code into the environment, exactly as installing from PyPI does (see :ref:`sec-getting`); the Python dependencies listed above are installed automatically. You still need a C++ compiler, CMake, GSL, and HDF5, as described in :ref:`sec-dependencies`. As with a PyPI installation, the large data files are not installed this way; download them with ``python -m slugpy.download_data``, or point the ``SLUG_DIR`` environment variable at an existing copy of them (e.g., the repository root of a checkout into which you have already downloaded them). The installed ``slug`` executable is built without MPI support by default, so that it does not depend on any particular MPI library. To build it with MPI support, pass the corresponding CMake option through ``pip``: .. code-block:: bash CMAKE_ARGS="-DSLUG_ENABLE_MPI=ON" pip install . Other CMake options described above can be passed the same way. .. _sec-building-docs: Building this Documentation ------------------------------ If Doxygen and the Python packages Sphinx, Breathe, and Exhale (see :ref:`sec-dependencies` above) are all found at configure time, ``cmake --build build`` (with no explicit ``--target``) builds this documentation site too, into ``doc/html``, alongside everything else -- if they aren't found, that step is simply skipped, with a note printed at configure time, and every other target is unaffected. To build just the documentation without touching anything else: .. code-block:: bash cmake --build build --target docs or, from ``doc/sphinx`` directly, without going through CMake at all -- though in this case ``slugPython`` must already have been built (``cmake --build build --target docs`` above builds it automatically first; this page's own autodoc-generated content, e.g. :ref:`sec-slugpy-full`, imports ``slugpy``, which fails without it): .. code-block:: bash cmake --build build --target slugPython cd doc/sphinx make html