
- remove the old LGPL license headers from all files in Spack - add SPDX headers to all files - core and most packages are (Apache-2.0 OR MIT) - a very small number of remaining packages are LGPL-2.1-only
1611 lines
68 KiB
ReStructuredText
1611 lines
68 KiB
ReStructuredText
.. Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
|
|
Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
|
|
SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
.. _modules-tutorial:
|
|
|
|
============
|
|
Module Files
|
|
============
|
|
|
|
In this tutorial, we'll introduce a few concepts that are fundamental
|
|
to the generation of module files with Spack, and we'll guide you through
|
|
the customization of both module files content and their layout on disk. In the end you
|
|
should have a clear understanding of:
|
|
|
|
* What are module files and how they work
|
|
* How Spack generates them
|
|
* Which commands are available to ease their maintenance
|
|
* How it is possible to customize them in all aspects
|
|
|
|
.. _module_file_tutorial_overview:
|
|
|
|
-------------------
|
|
Modules at a glance
|
|
-------------------
|
|
|
|
Let's start by summarizing what module files are and how you can use
|
|
them to modify your environment. The idea is to give enough information so that
|
|
people without any previous exposure to them will be able to follow the tutorial
|
|
later on. We'll also give a high-level view of how module files are generated
|
|
in Spack. If you are already familiar with these topics you can quickly skim
|
|
through this section or move directly to :ref:`module_file_tutorial_prerequisites`.
|
|
|
|
.. _module_file_tutorial_what_are_modules:
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
What are module files?
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Module files are an easy way to modify your environment in a controlled manner
|
|
during a shell session. In general, they contain the information needed to run an
|
|
application or use a library, and they work in conjunction with a tool that
|
|
interprets them.
|
|
Typical module files instruct this tool to modify the environment variables when a
|
|
module file is loaded:
|
|
|
|
.. code-block:: console
|
|
|
|
$ module show zlib
|
|
-------------------------------------------------------------------
|
|
/home/mculpo/PycharmProjects/spack/share/spack/modules/linux-ubuntu14.04-x86_64/zlib/1.2.11-gcc-7.2.0-linux-ubuntu14.04-x86_64-co2px3k:
|
|
|
|
module-whatis A free, general-purpose, legally unencumbered lossless data-compression library.
|
|
prepend-path MANPATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/share/man
|
|
prepend-path LIBRARY_PATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/lib
|
|
prepend-path LD_LIBRARY_PATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/lib
|
|
prepend-path CPATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/include
|
|
prepend-path PKG_CONFIG_PATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/lib/pkgconfig
|
|
prepend-path CMAKE_PREFIX_PATH /home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/
|
|
-------------------------------------------------------------------
|
|
|
|
$ echo $LD_LIBRARY_PATH
|
|
|
|
$ module load zlib
|
|
$ echo $LD_LIBRARY_PATH
|
|
/home/mculpo/PycharmProjects/spack/opt/spack/linux-ubuntu14.04-x86_64/gcc-7.2.0/zlib-1.2.11-co2px3k53m76lm6tofylh2mur2hnicux/lib
|
|
|
|
and to undo the modifications when the same module file is unloaded:
|
|
|
|
.. code-block:: console
|
|
|
|
$ module unload zlib
|
|
$ echo $LD_LIBRARY_PATH
|
|
|
|
$
|
|
|
|
Different formats exist for module files, and different tools
|
|
provide various levels of support for them. Spack can natively generate:
|
|
|
|
1. Non-hierarchical module files written in TCL
|
|
2. Hierarchical module files written in Lua
|
|
|
|
and can build `environment-modules <http://modules.sourceforge.net/>`_
|
|
and `lmod <http://lmod.readthedocs.io/en/latest>`_ as support tools.
|
|
Which of the formats or tools best suits one's needs depends on each particular
|
|
use-case. For the sake of illustration, we'll be working on
|
|
both formats using ``lmod``.
|
|
|
|
.. seealso::
|
|
Environment modules
|
|
This is the original tool that provided modules support. Its first
|
|
version was coded in C in the early '90s and was later substituted by a version
|
|
completely coded in TCL - the one Spack is distributing. More details on
|
|
its features are given in the `homepage of the project <http://modules.sourceforge.net/>`_
|
|
or in its `github page <https://github.com/cea-hpc/modules>`_. The tool is able to
|
|
interpret the non-hierarchical TCL modulefiles written by Spack.
|
|
|
|
Lmod
|
|
Lmod is a module system written in Lua, designed to easily handle hierarchies of
|
|
module files. It's a drop-in replacement of Environment Modules and works with
|
|
both of the module file formats generated by Spack.
|
|
Despite being fully compatible with Environment Modules there are many features that
|
|
are unique to Lmod. These features are either
|
|
`targeted towards safety <http://lmod.readthedocs.io/en/latest/010_user.html#safety-features>`_
|
|
or meant to
|
|
`extend the module system functionality <http://lmod.readthedocs.io/en/latest/010_user.html#module-hierarchy>`_.
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
How do we generate module files?
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Before we dive into the hands-on sections it's worth spending a couple of words to explain how
|
|
module files are generated by Spack. The following diagram provides a high-level view
|
|
of the process:
|
|
|
|
|
|
.. image:: module_file_generation.*
|
|
|
|
The red dashed line above represents Spack's boundaries, the blue one Spack's dependencies [#f1]_.
|
|
Module files are generated by combining:
|
|
|
|
* the configuration details in ``config.yaml`` and ``modules.yaml``
|
|
* the information contained in Spack packages (and processed by the module subpackage)
|
|
* a set of template files
|
|
|
|
with `Jinja2 <http://jinja.pocoo.org/docs/2.9/>`_, an external template engine
|
|
that stamps out each particular module file. As Spack serves very diverse needs
|
|
this process has many points of customization, and we'll explore most of
|
|
them in the next sections.
|
|
|
|
.. [#f1] Spack vendors its dependencies! This means that Spack comes with a copy of
|
|
each one of its dependencies, including ``Jinja2``, and is already configured to use them.
|
|
|
|
.. _module_file_tutorial_prerequisites:
|
|
|
|
----------------------
|
|
Setup for the tutorial
|
|
----------------------
|
|
|
|
In order to showcase the capabilities of Spack's module file generation, we need
|
|
a representative set of software to work with. This set must include different
|
|
flavors of the same packages installed alongside each other and some
|
|
:ref:`external packages <sec-external-packages>`.
|
|
|
|
The purpose of this setup is not to make our life harder but to demonstrate
|
|
how Spack can help with similar situations, as they will happen on real HPC clusters.
|
|
For instance, it's often preferable for Spack to use vendor-provided MPI
|
|
implementations than to build one itself.
|
|
|
|
The best way to follow along is to use a Docker image, which comes
|
|
with Spack and all the software used in the following parts already
|
|
pre-installed. If you want to proceed this way, read :ref:`module_file_tutorial_use_docker`.
|
|
|
|
If you don't have Docker installed or for any other reason you
|
|
prefer to work locally, follow instead :ref:`module_file_tutorial_work_locally`
|
|
to know how to clone Spack and install the software.
|
|
Be aware that the set-up will take longer and that the details of the snippets
|
|
below assume the Docker image and may need changes to work in your particular
|
|
environment.
|
|
|
|
.. _module_file_tutorial_use_docker:
|
|
|
|
^^^^^^^^^^^^^^^^^^
|
|
Use a Docker image
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
The fastest way to set-up your environment is to :ref:`use a Docker image <workflow_create_docker_image>`:
|
|
|
|
.. code-block:: console
|
|
|
|
$ docker pull spack/module-tutorial:latest
|
|
$ docker run --rm -h module-file-tutorial -it spack/module-tutorial:latest
|
|
root@module-file-tutorial:/#
|
|
|
|
If you arrived at this point you should be ready to start, as all the software needed is
|
|
pre-installed in the image:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# which spack
|
|
/usr/local/bin/spack
|
|
root@module-file-tutorial:/# spack find
|
|
==> 43 installed packages.
|
|
-- linux-ubuntu16.04-x86_64 / gcc@5.4.0 -------------------------
|
|
autoconf@2.69 gdbm@1.14.1 isl@0.19 lmod@7.7.29 lua-luaposix@33.4.0 mpfr@4.0.1 pkgconf@1.4.2 zlib@1.2.11
|
|
automake@1.16.1 git@2.9.4 libsigsegv@2.11 lua@5.3.4 m4@1.4.18 ncurses@6.1 readline@7.0
|
|
gcc@7.2.0 gmp@6.1.2 libtool@2.4.6 lua-luafilesystem@1_6_3 mpc@1.1.0 perl@5.26.2 tcl@8.6.8
|
|
|
|
-- linux-ubuntu16.04-x86_64 / gcc@7.2.0 -------------------------
|
|
bzip2@1.0.6 mpich@3.2.1 netlib-scalapack@2.0.2 netlib-scalapack@2.0.2 openssl@1.0.2o py-scipy@1.1.0 readline@7.0
|
|
cmake@3.12.0 ncurses@6.1 netlib-scalapack@2.0.2 openblas@0.3.0 pkgconf@1.4.2 py-setuptools@39.2.0 sqlite@3.23.1
|
|
gdbm@1.14.1 netlib-lapack@3.8.0 netlib-scalapack@2.0.2 openmpi@1.10.2 py-numpy@1.14.3 python@2.7.15 zlib@1.2.11
|
|
|
|
Go to :ref:`module_file_tutorial_non_hierarchical` to proceed with the tutorial.
|
|
|
|
.. note::
|
|
Dockerfile for this image
|
|
Those of you that want to build a similar container themselves can find the
|
|
``Dockerfile`` and the other resources in Spack's ``share/spack/docs/docker``
|
|
folder.
|
|
|
|
.. _module_file_tutorial_work_locally:
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
Work in a local folder
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
If you don't feel like using a container, you can set-up your environment
|
|
locally. Let's start by cloning the Spack repository and moving to the directory
|
|
where it was checked out:
|
|
|
|
.. code-block:: console
|
|
|
|
$ git clone https://github.com/spack/spack.git
|
|
$ cd spack
|
|
|
|
From here we'll be building the required stack of software.
|
|
|
|
"""""""""""""""""""
|
|
Build a module tool
|
|
"""""""""""""""""""
|
|
|
|
The first thing that we need is the module tool. In this case we
|
|
choose ``lmod`` as it can work with both hierarchical and non-hierarchical
|
|
module file layouts.
|
|
|
|
.. code-block:: console
|
|
|
|
$ bin/spack install lmod
|
|
|
|
Once the module tool is installed we need to have it available in the
|
|
current shell. As the installation directories are definitely not easy
|
|
to remember, we'll employ the command ``spack location`` to retrieve the
|
|
``lmod`` prefix directly from Spack:
|
|
|
|
.. code-block:: console
|
|
|
|
$ . $(spack location -i lmod)/lmod/lmod/init/bash
|
|
|
|
Now we can source the setup file and activate the :ref:`shell support <shell-support>`:
|
|
|
|
.. code-block:: console
|
|
|
|
$ . share/spack/setup_env.sh
|
|
|
|
.. FIXME: this needs bootstrap support for ``lmod``
|
|
|
|
.. FIXME: check the docs here, update them if necessary
|
|
If you need to install Lmod or Environment module you can refer
|
|
to the documentation :ref:`here <InstallEnvironmentModules>`.
|
|
|
|
|
|
""""""""""""""""""
|
|
Add a new compiler
|
|
""""""""""""""""""
|
|
|
|
The second step is to build a recent compiler. On first use, Spack
|
|
scans the environment and automatically locates the
|
|
compiler(s) already available on the system. This is what you'll see
|
|
on Ubuntu 14.04:
|
|
|
|
.. code-block:: console
|
|
|
|
$ uname -a
|
|
Linux nuvolari 4.4.0-45-generic #66~14.04.1-Ubuntu SMP Wed Oct 19 15:05:38 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
|
|
|
|
$ spack compilers
|
|
==> Available compilers
|
|
-- gcc ----------------------------------------------------------
|
|
gcc@4.8
|
|
|
|
Let's bootstrap a more recent compiler with the one that was automatically detected:
|
|
|
|
.. code-block:: console
|
|
|
|
$ spack install gcc@7.2.0
|
|
...
|
|
Wait a long time
|
|
...
|
|
|
|
Once ``gcc`` is installed we can use shell support to load it and make
|
|
it readily available:
|
|
|
|
.. code-block:: console
|
|
|
|
$ spack load gcc@7.2.0
|
|
|
|
It may not be apparent, but the last command employed the module files
|
|
generated automatically by Spack. What happens under the hood when you use
|
|
the ``spack load`` command is:
|
|
|
|
1. the spec passed as argument is translated into a module file name
|
|
2. the current module tool is used to load that module file
|
|
|
|
You can use this command to double check:
|
|
|
|
.. code-block:: console
|
|
|
|
$ module list
|
|
Currently Loaded Modules:
|
|
1) lmod-7.7-gcc-4.8-okcwjgw 2) gcc-7.2.0-gcc-4.8-twd5nqg
|
|
|
|
Note that the 7-digit hash at the end of the generated module may vary depending
|
|
on architecture or package version. Now that we have ``gcc@7.2.0`` in ``PATH`` we
|
|
can finally add it to the list of compilers known to Spack:
|
|
|
|
.. code-block:: console
|
|
|
|
$ spack compiler add
|
|
==> Added 1 new compiler to ~/.spack/linux/compilers.yaml
|
|
gcc@7.2.0
|
|
|
|
$ spack compilers
|
|
==> Available compilers
|
|
-- gcc ----------------------------------------------------------
|
|
gcc@7.2.0 gcc@4.8
|
|
|
|
|
|
""""""""""""""""""""""""""""""""""""""""""""""""""""
|
|
Build the software that will be used in the tutorial
|
|
""""""""""""""""""""""""""""""""""""""""""""""""""""
|
|
|
|
The last step is to install the software stack needed later on. To mimic
|
|
an external installation of an MPI provider we'll install ``openmpi`` on
|
|
the system we are working on. On Ubuntu 14.04 it boils down to:
|
|
|
|
.. code-block:: console
|
|
|
|
$ sudo apt-get install openmpi-bin openmpi-common libopenmpi-dev
|
|
...
|
|
|
|
but the exact command varies according to your OS. Then we need to prepare
|
|
a ``packages.yaml`` file that instructs Spack to use an externally provided MPI:
|
|
|
|
.. code-block:: yaml
|
|
|
|
packages:
|
|
openmpi:
|
|
buildable: False
|
|
paths:
|
|
openmpi@1.6: /usr
|
|
|
|
Finally, we should use Spack to install the packages used in the examples:
|
|
|
|
.. code-block:: console
|
|
|
|
$ spack install netlib-scalapack ^openmpi ^openblas
|
|
$ spack install netlib-scalapack ^mpich ^openblas
|
|
$ spack install netlib-scalapack ^openmpi ^netlib-lapack
|
|
$ spack install netlib-scalapack ^mpich ^netlib-lapack
|
|
$ spack install py-scipy ^openblas
|
|
|
|
|
|
.. _module_file_tutorial_non_hierarchical:
|
|
|
|
-----------------------------
|
|
Non-hierarchical module files
|
|
-----------------------------
|
|
|
|
If you arrived to this point you should have an environment that looks similar to:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
autoconf-2.69-gcc-5.4.0-cbvv5rj lua-luaposix-33.4.0-gcc-5.4.0-i7w7ynf perl-5.26.2-gcc-5.4.0-n2k4mza
|
|
automake-1.16.1-gcc-5.4.0-lykrrr4 m4-1.4.18-gcc-5.4.0-3z33ecf pkgconf-1.4.2-gcc-5.4.0-fovrh7a
|
|
bzip2-1.0.6-gcc-7.2.0-mwamumj mpc-1.1.0-gcc-5.4.0-56lbd3h pkgconf-1.4.2-gcc-7.2.0-yoxwmgb
|
|
cmake-3.12.0-gcc-7.2.0-6ovorxs mpfr-4.0.1-gcc-5.4.0-dy5r7hi py-numpy-1.14.3-gcc-7.2.0-t3loxvu
|
|
gcc-7.2.0-gcc-5.4.0-wwhgyej mpich-3.2.1-gcc-7.2.0-vt5xcat py-scipy-1.1.0-gcc-7.2.0-fdiryak
|
|
gdbm-1.14.1-gcc-5.4.0-q4fpyuo ncurses-6.1-gcc-5.4.0-3o765ou py-setuptools-39.2.0-gcc-7.2.0-jqhycal
|
|
gdbm-1.14.1-gcc-7.2.0-zk5lhob ncurses-6.1-gcc-7.2.0-xcgzqdv python-2.7.15-gcc-7.2.0-c7pnzul
|
|
git-2.9.4-gcc-5.4.0-mkaoyhz netlib-lapack-3.8.0-gcc-7.2.0-7apabqu readline-7.0-gcc-5.4.0-nxhwrg7
|
|
gmp-6.1.2-gcc-5.4.0-qc4qcfz netlib-scalapack-2.0.2-gcc-7.2.0-3bz5rxx readline-7.0-gcc-7.2.0-ccruj2i
|
|
isl-0.19-gcc-5.4.0-hsl7f52 netlib-scalapack-2.0.2-gcc-7.2.0-6i5qsqx sqlite-3.23.1-gcc-7.2.0-5ltus3a
|
|
libsigsegv-2.11-gcc-5.4.0-fypapcp netlib-scalapack-2.0.2-gcc-7.2.0-uhzmwog tcl-8.6.8-gcc-5.4.0-qhwyccy
|
|
libtool-2.4.6-gcc-5.4.0-o2pfwjf netlib-scalapack-2.0.2-gcc-7.2.0-z52ltyy zlib-1.2.11-gcc-5.4.0-5nus6kn
|
|
lmod-7.7.29-gcc-5.4.0-wl6mywv openblas-0.3.0-gcc-7.2.0-pdatzbi zlib-1.2.11-gcc-7.2.0-ezuwp4p
|
|
lua-5.3.4-gcc-5.4.0-izvaota openmpi-1.10.2-gcc-7.2.0-6oewzwj
|
|
lua-luafilesystem-1_6_3-gcc-5.4.0-ywlmaou openssl-1.0.2o-gcc-7.2.0-cvldq3v
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
The non-hierarchical module files that have been generated so far
|
|
follow :ref:`the default rules for module generation <modules-yaml>`.
|
|
Taking a look at the ``gcc`` module you'll see, for example:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module show gcc-7.2.0-gcc-5.4.0-wwhgyej
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
/usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/gcc-7.2.0-gcc-5.4.0-wwhgyej:
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
whatis("The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages. ")
|
|
prepend_path("PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin")
|
|
prepend_path("MANPATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/share/man")
|
|
prepend_path("LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib")
|
|
prepend_path("LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib64")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib64")
|
|
prepend_path("CPATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/include")
|
|
prepend_path("CMAKE_PREFIX_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/")
|
|
setenv("CC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gcc")
|
|
setenv("CXX","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/g++")
|
|
setenv("FC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F77","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F90","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
help([[The GNU Compiler Collection includes front ends for C, C++, Objective-C,
|
|
Fortran, Ada, and Go, as well as libraries for these languages.
|
|
]])
|
|
|
|
As expected, a few environment variables representing paths will be modified
|
|
by the module file according to the default prefix inspection rules.
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Filter unwanted modifications to the environment
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Now consider the case that your site has decided that ``CPATH`` and
|
|
``LIBRARY_PATH`` modifications should not be present in module files. What you can
|
|
do to abide by the rules is to create a configuration file ``~/.spack/modules.yaml``
|
|
with the following content:
|
|
|
|
.. code-block:: yaml
|
|
|
|
modules:
|
|
tcl:
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
|
|
Next you should regenerate all the module files:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh
|
|
==> You are about to regenerate tcl module files for:
|
|
|
|
-- linux-ubuntu16.04-x86_64 / gcc@5.4.0 -------------------------
|
|
cbvv5rj autoconf@2.69 qc4qcfz gmp@6.1.2 izvaota lua@5.3.4 dy5r7hi mpfr@4.0.1 qhwyccy tcl@8.6.8
|
|
lykrrr4 automake@1.16.1 hsl7f52 isl@0.19 ywlmaou lua-luafilesystem@1_6_3 3o765ou ncurses@6.1 5nus6kn zlib@1.2.11
|
|
wwhgyej gcc@7.2.0 fypapcp libsigsegv@2.11 i7w7ynf lua-luaposix@33.4.0 n2k4mza perl@5.26.2
|
|
q4fpyuo gdbm@1.14.1 o2pfwjf libtool@2.4.6 3z33ecf m4@1.4.18 fovrh7a pkgconf@1.4.2
|
|
mkaoyhz git@2.9.4 wl6mywv lmod@7.7.29 56lbd3h mpc@1.1.0 nxhwrg7 readline@7.0
|
|
|
|
-- linux-ubuntu16.04-x86_64 / gcc@7.2.0 -------------------------
|
|
mwamumj bzip2@1.0.6 7apabqu netlib-lapack@3.8.0 pdatzbi openblas@0.3.0 fdiryak py-scipy@1.1.0 ezuwp4p zlib@1.2.11
|
|
6ovorxs cmake@3.12.0 6i5qsqx netlib-scalapack@2.0.2 6oewzwj openmpi@1.10.2 jqhycal py-setuptools@39.2.0
|
|
zk5lhob gdbm@1.14.1 uhzmwog netlib-scalapack@2.0.2 cvldq3v openssl@1.0.2o c7pnzul python@2.7.15
|
|
vt5xcat mpich@3.2.1 3bz5rxx netlib-scalapack@2.0.2 yoxwmgb pkgconf@1.4.2 ccruj2i readline@7.0
|
|
xcgzqdv ncurses@6.1 z52ltyy netlib-scalapack@2.0.2 t3loxvu py-numpy@1.14.3 5ltus3a sqlite@3.23.1
|
|
|
|
==> Do you want to proceed? [y/n] y
|
|
==> Regenerating tcl module files
|
|
|
|
If you take a look now at the module for ``gcc`` you'll see that the unwanted
|
|
paths have disappeared:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module show gcc-7.2.0-gcc-5.4.0-wwhgyej
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
/usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/gcc-7.2.0-gcc-5.4.0-wwhgyej:
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
whatis("The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages. ")
|
|
prepend_path("PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin")
|
|
prepend_path("MANPATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/share/man")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib64")
|
|
prepend_path("CMAKE_PREFIX_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/")
|
|
setenv("CC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gcc")
|
|
setenv("CXX","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/g++")
|
|
setenv("FC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F77","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F90","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
help([[The GNU Compiler Collection includes front ends for C, C++, Objective-C,
|
|
Fortran, Ada, and Go, as well as libraries for these languages.
|
|
]])
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Prevent some module files from being generated
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Another common request at many sites is to avoid exposing software that
|
|
is only needed as an intermediate step when building a newer stack.
|
|
Let's try to prevent the generation of
|
|
module files for anything that is compiled with ``gcc@5.4.0`` (the OS provided compiler).
|
|
|
|
To do this you should add a ``blacklist`` keyword to ``~/.spack/modules.yaml``:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 3,4
|
|
|
|
modules:
|
|
tcl:
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
|
|
and regenerate the module files:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh --delete-tree
|
|
==> You are about to regenerate tcl module files for:
|
|
|
|
-- linux-ubuntu16.04-x86_64 / gcc@5.4.0 -------------------------
|
|
cbvv5rj autoconf@2.69 qc4qcfz gmp@6.1.2 izvaota lua@5.3.4 dy5r7hi mpfr@4.0.1 qhwyccy tcl@8.6.8
|
|
lykrrr4 automake@1.16.1 hsl7f52 isl@0.19 ywlmaou lua-luafilesystem@1_6_3 3o765ou ncurses@6.1 5nus6kn zlib@1.2.11
|
|
wwhgyej gcc@7.2.0 fypapcp libsigsegv@2.11 i7w7ynf lua-luaposix@33.4.0 n2k4mza perl@5.26.2
|
|
q4fpyuo gdbm@1.14.1 o2pfwjf libtool@2.4.6 3z33ecf m4@1.4.18 fovrh7a pkgconf@1.4.2
|
|
mkaoyhz git@2.9.4 wl6mywv lmod@7.7.29 56lbd3h mpc@1.1.0 nxhwrg7 readline@7.0
|
|
|
|
-- linux-ubuntu16.04-x86_64 / gcc@7.2.0 -------------------------
|
|
mwamumj bzip2@1.0.6 7apabqu netlib-lapack@3.8.0 pdatzbi openblas@0.3.0 fdiryak py-scipy@1.1.0 ezuwp4p zlib@1.2.11
|
|
6ovorxs cmake@3.12.0 6i5qsqx netlib-scalapack@2.0.2 6oewzwj openmpi@1.10.2 jqhycal py-setuptools@39.2.0
|
|
zk5lhob gdbm@1.14.1 uhzmwog netlib-scalapack@2.0.2 cvldq3v openssl@1.0.2o c7pnzul python@2.7.15
|
|
vt5xcat mpich@3.2.1 3bz5rxx netlib-scalapack@2.0.2 yoxwmgb pkgconf@1.4.2 ccruj2i readline@7.0
|
|
xcgzqdv ncurses@6.1 z52ltyy netlib-scalapack@2.0.2 t3loxvu py-numpy@1.14.3 5ltus3a sqlite@3.23.1
|
|
|
|
==> Do you want to proceed? [y/n] y
|
|
==> Regenerating tcl module files
|
|
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
bzip2-1.0.6-gcc-7.2.0-mwamumj netlib-scalapack-2.0.2-gcc-7.2.0-6i5qsqx py-numpy-1.14.3-gcc-7.2.0-t3loxvu
|
|
cmake-3.12.0-gcc-7.2.0-6ovorxs netlib-scalapack-2.0.2-gcc-7.2.0-uhzmwog py-scipy-1.1.0-gcc-7.2.0-fdiryak
|
|
gdbm-1.14.1-gcc-7.2.0-zk5lhob netlib-scalapack-2.0.2-gcc-7.2.0-z52ltyy py-setuptools-39.2.0-gcc-7.2.0-jqhycal
|
|
mpich-3.2.1-gcc-7.2.0-vt5xcat openblas-0.3.0-gcc-7.2.0-pdatzbi python-2.7.15-gcc-7.2.0-c7pnzul
|
|
ncurses-6.1-gcc-7.2.0-xcgzqdv openmpi-1.10.2-gcc-7.2.0-6oewzwj readline-7.0-gcc-7.2.0-ccruj2i
|
|
netlib-lapack-3.8.0-gcc-7.2.0-7apabqu openssl-1.0.2o-gcc-7.2.0-cvldq3v sqlite-3.23.1-gcc-7.2.0-5ltus3a
|
|
netlib-scalapack-2.0.2-gcc-7.2.0-3bz5rxx pkgconf-1.4.2-gcc-7.2.0-yoxwmgb zlib-1.2.11-gcc-7.2.0-ezuwp4p
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
This time it is convenient to pass the option ``--delete-tree`` to the command that
|
|
regenerates the module files to instruct it to delete the existing tree and regenerate
|
|
a new one instead of overwriting the files in the existing directory.
|
|
|
|
If you look closely you'll see though that we went too far in blacklisting modules:
|
|
the module for ``gcc@7.2.0`` disappeared as it was bootstrapped with ``gcc@5.4.0``. To specify
|
|
exceptions to the blacklist rules you can use ``whitelist``:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 3,4
|
|
|
|
modules:
|
|
tcl:
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
|
|
``whitelist`` rules always have precedence over ``blacklist`` rules. If you regenerate the modules again:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh -y
|
|
==> Regenerating tcl module files
|
|
|
|
|
|
you'll see that now the module for ``gcc@7.2.0`` has reappeared:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module av gcc-7.2.0-gcc-5.4.0-wwhgyej
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
gcc-7.2.0-gcc-5.4.0-wwhgyej
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
|
|
An additional possibility that you can leverage to unclutter the environment
|
|
is that of preventing the generation of module files for implicitly installed
|
|
packages. In this case all one needs to do is to add the following line:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 3
|
|
|
|
modules:
|
|
tcl:
|
|
blacklist_implicits: true
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
|
|
to ``modules.yaml`` and regenerate the module file tree as above.
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Change module file naming
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The next step in making module files more user-friendly is to
|
|
improve their naming scheme.
|
|
To reduce the length of the hash or remove it altogether you can
|
|
use the ``hash_length`` keyword in the configuration file:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 3
|
|
|
|
modules:
|
|
tcl:
|
|
hash_length: 0
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
|
|
If you try to regenerate the module files now you will get an error:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh --delete-tree -y
|
|
==> Error: Name clashes detected in module files:
|
|
|
|
file: /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/netlib-scalapack-2.0.2-gcc-7.2.0
|
|
spec: netlib-scalapack@2.0.2%gcc@7.2.0 build_type=RelWithDebInfo ~pic+shared arch=linux-ubuntu16.04-x86_64
|
|
spec: netlib-scalapack@2.0.2%gcc@7.2.0 build_type=RelWithDebInfo ~pic+shared arch=linux-ubuntu16.04-x86_64
|
|
spec: netlib-scalapack@2.0.2%gcc@7.2.0 build_type=RelWithDebInfo ~pic+shared arch=linux-ubuntu16.04-x86_64
|
|
spec: netlib-scalapack@2.0.2%gcc@7.2.0 build_type=RelWithDebInfo ~pic+shared arch=linux-ubuntu16.04-x86_64
|
|
|
|
==> Error: Operation aborted
|
|
|
|
.. note::
|
|
We try to check for errors upfront!
|
|
In Spack we check for errors upfront whenever possible, so don't worry about your module files:
|
|
as a name clash was detected nothing has been changed on disk.
|
|
|
|
The problem here is that without
|
|
the hashes the four different flavors of ``netlib-scalapack`` map to the same module file
|
|
name. We can add suffixes to differentiate them:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 9-11,14-17
|
|
|
|
modules:
|
|
tcl:
|
|
hash_length: 0
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
netlib-scalapack:
|
|
suffixes:
|
|
'^openmpi': openmpi
|
|
'^mpich': mpich
|
|
|
|
As you can see it is possible to specify rules that apply only to a
|
|
restricted set of packages using :ref:`anonymous specs <anonymous_specs>`.
|
|
Regenerating module files now we obtain:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh --delete-tree -y
|
|
==> Regenerating tcl module files
|
|
|
|
root@module-file-tutorial:/# module av
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
bzip2-1.0.6-gcc-7.2.0 netlib-lapack-3.8.0-gcc-7.2.0 openmpi-1.10.2-gcc-7.2.0 python-2.7.15-gcc-7.2.0
|
|
cmake-3.12.0-gcc-7.2.0 netlib-scalapack-2.0.2-gcc-7.2.0-netlib-mpich openssl-1.0.2o-gcc-7.2.0 readline-7.0-gcc-7.2.0
|
|
gcc-7.2.0-gcc-5.4.0 netlib-scalapack-2.0.2-gcc-7.2.0-netlib-openmpi pkgconf-1.4.2-gcc-7.2.0 sqlite-3.23.1-gcc-7.2.0
|
|
gdbm-1.14.1-gcc-7.2.0 netlib-scalapack-2.0.2-gcc-7.2.0-openblas-mpich py-numpy-1.14.3-gcc-7.2.0-openblas zlib-1.2.11-gcc-7.2.0
|
|
mpich-3.2.1-gcc-7.2.0 netlib-scalapack-2.0.2-gcc-7.2.0-openblas-openmpi py-scipy-1.1.0-gcc-7.2.0-openblas
|
|
ncurses-6.1-gcc-7.2.0 openblas-0.3.0-gcc-7.2.0 py-setuptools-39.2.0-gcc-7.2.0
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
Finally we can set a ``naming_scheme`` to prevent users from loading
|
|
modules that refer to different flavors of the same library/application:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 4,10,11
|
|
|
|
modules:
|
|
tcl:
|
|
hash_length: 0
|
|
naming_scheme: '${PACKAGE}/${VERSION}-${COMPILERNAME}-${COMPILERVER}'
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
conflict:
|
|
- '${PACKAGE}'
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
netlib-scalapack:
|
|
suffixes:
|
|
'^openmpi': openmpi
|
|
'^mpich': mpich
|
|
|
|
The final result should look like:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh --delete-tree -y
|
|
==> Regenerating tcl module files
|
|
root@module-file-tutorial:/# module av
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
bzip2/1.0.6-gcc-7.2.0 netlib-scalapack/2.0.2-gcc-7.2.0-netlib-openmpi py-scipy/1.1.0-gcc-7.2.0-openblas
|
|
cmake/3.12.0-gcc-7.2.0 netlib-scalapack/2.0.2-gcc-7.2.0-openblas-mpich py-setuptools/39.2.0-gcc-7.2.0
|
|
gcc/7.2.0-gcc-5.4.0 netlib-scalapack/2.0.2-gcc-7.2.0-openblas-openmpi (D) python/2.7.15-gcc-7.2.0
|
|
gdbm/1.14.1-gcc-7.2.0 openblas/0.3.0-gcc-7.2.0 readline/7.0-gcc-7.2.0
|
|
mpich/3.2.1-gcc-7.2.0 openmpi/1.10.2-gcc-7.2.0 sqlite/3.23.1-gcc-7.2.0
|
|
ncurses/6.1-gcc-7.2.0 openssl/1.0.2o-gcc-7.2.0 zlib/1.2.11-gcc-7.2.0
|
|
netlib-lapack/3.8.0-gcc-7.2.0 pkgconf/1.4.2-gcc-7.2.0
|
|
netlib-scalapack/2.0.2-gcc-7.2.0-netlib-mpich py-numpy/1.14.3-gcc-7.2.0-openblas
|
|
|
|
Where:
|
|
D: Default Module
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
.. note::
|
|
TCL specific directive
|
|
The directives ``naming_scheme`` and ``conflict`` are TCL specific and
|
|
can't be used in the ``lmod`` section of the configuration file.
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Add custom environment modifications
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
At many sites it is customary to set an environment variable in a
|
|
package's module file that points to the folder in which the package
|
|
is installed. You can achieve this with Spack by adding an
|
|
``environment`` directive to the configuration file:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 17-19
|
|
|
|
modules:
|
|
tcl:
|
|
hash_length: 0
|
|
naming_scheme: '${PACKAGE}/${VERSION}-${COMPILERNAME}-${COMPILERVER}'
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
conflict:
|
|
- '${PACKAGE}'
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
netlib-scalapack:
|
|
suffixes:
|
|
'^openmpi': openmpi
|
|
'^mpich': mpich
|
|
|
|
Under the hood Spack uses the :meth:`~spack.spec.Spec.format` API to substitute
|
|
tokens in either environment variable names or values. There are two caveats though:
|
|
|
|
- The set of allowed tokens in variable names is restricted to ``PACKAGE``,
|
|
``VERSION``, ``COMPILER``, ``COMPILERNAME``, ``COMPILERVER``, ``ARCHITECTURE``
|
|
- Any token expanded in a variable name is made uppercase, but other than that
|
|
case sensitivity is preserved
|
|
|
|
Regenerating the module files results in something like:
|
|
|
|
.. code-block:: console
|
|
:emphasize-lines: 15
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh -y
|
|
==> Regenerating tcl module files
|
|
|
|
root@module-file-tutorial:/# module show gcc
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
/usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/gcc/7.2.0-gcc-5.4.0:
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
whatis("The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages. ")
|
|
conflict("gcc")
|
|
prepend_path("PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin")
|
|
prepend_path("MANPATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/share/man")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib64")
|
|
prepend_path("CMAKE_PREFIX_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/")
|
|
setenv("CC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gcc")
|
|
setenv("CXX","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/g++")
|
|
setenv("FC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F77","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F90","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("GCC_ROOT","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o")
|
|
help([[The GNU Compiler Collection includes front ends for C, C++, Objective-C,
|
|
Fortran, Ada, and Go, as well as libraries for these languages.
|
|
]])
|
|
|
|
As you can see, the ``gcc`` module has the environment variable ``GCC_ROOT`` set.
|
|
|
|
Sometimes it's also useful to apply environment modifications selectively and target
|
|
only certain packages. You can, for instance set the common variables ``CC``, ``CXX``,
|
|
etc. in the ``gcc`` module file and apply other custom modifications to the
|
|
``openmpi`` modules as follows:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 20-32
|
|
|
|
modules:
|
|
tcl:
|
|
hash_length: 0
|
|
naming_scheme: '${PACKAGE}/${VERSION}-${COMPILERNAME}-${COMPILERVER}'
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
conflict:
|
|
- '${PACKAGE}'
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
gcc:
|
|
environment:
|
|
set:
|
|
CC: gcc
|
|
CXX: g++
|
|
FC: gfortran
|
|
F90: gfortran
|
|
F77: gfortran
|
|
openmpi:
|
|
environment:
|
|
set:
|
|
SLURM_MPI_TYPE: pmi2
|
|
OMPI_MCA_btl_openib_warn_default_gid_prefix: '0'
|
|
netlib-scalapack:
|
|
suffixes:
|
|
'^openmpi': openmpi
|
|
'^mpich': mpich
|
|
|
|
This time we will be more selective and regenerate only the ``gcc`` and
|
|
``openmpi`` module files:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh -y gcc
|
|
==> Regenerating tcl module files
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh -y openmpi
|
|
==> Regenerating tcl module files
|
|
|
|
root@module-file-tutorial:/# module show gcc
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
/usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/gcc/7.2.0-gcc-5.4.0:
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
whatis("The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, and Go, as well as libraries for these languages. ")
|
|
conflict("gcc")
|
|
prepend_path("PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin")
|
|
prepend_path("MANPATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/share/man")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib")
|
|
prepend_path("LD_LIBRARY_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/lib64")
|
|
prepend_path("CMAKE_PREFIX_PATH","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/")
|
|
setenv("CC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gcc")
|
|
setenv("CXX","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/g++")
|
|
setenv("FC","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F77","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("F90","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o/bin/gfortran")
|
|
setenv("GCC_ROOT","/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/gcc-7.2.0-wwhgyejrjfjtdsgga3hn246bc64jtr6o")
|
|
setenv("CC","gcc")
|
|
setenv("CXX","g++")
|
|
setenv("FC","gfortran")
|
|
setenv("F90","gfortran")
|
|
setenv("F77","gfortran")
|
|
help([[The GNU Compiler Collection includes front ends for C, C++, Objective-C,
|
|
Fortran, Ada, and Go, as well as libraries for these languages.
|
|
]])
|
|
|
|
root@module-file-tutorial:/# module show openmpi
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
/usr/local/share/spack/modules/linux-ubuntu16.04-x86_64/openmpi/1.10.2-gcc-7.2.0:
|
|
----------------------------------------------------------------------------------------------------------------------------------------------
|
|
whatis("An open source Message Passing Interface implementation. ")
|
|
conflict("openmpi")
|
|
prepend_path("MANPATH","/usr/share/man")
|
|
prepend_path("ACLOCAL_PATH","/usr/share/aclocal")
|
|
prepend_path("PKG_CONFIG_PATH","/usr/lib/pkgconfig")
|
|
setenv("OPENMPI_ROOT","/usr")
|
|
setenv("SLURM_MPI_TYPE","pmi2")
|
|
setenv("OMPI_MCA_btl_openib_warn_default_gid_prefix","0")
|
|
help([[An open source Message Passing Interface implementation. The Open MPI
|
|
Project is an open source Message Passing Interface implementation that
|
|
is developed and maintained by a consortium of academic, research, and
|
|
industry partners. Open MPI is therefore able to combine the expertise,
|
|
technologies, and resources from all across the High Performance
|
|
Computing community in order to build the best MPI library available.
|
|
Open MPI offers advantages for system and software vendors, application
|
|
developers and computer science researchers.
|
|
]])
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
Autoload dependencies
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Spack can also generate module files that contain code to load the
|
|
dependencies automatically. You can, for instance generate python
|
|
modules that load their dependencies by adding the ``autoload``
|
|
directive and assigning it the value ``direct``:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 3,38,39
|
|
|
|
modules:
|
|
tcl:
|
|
verbose: True
|
|
hash_length: 0
|
|
naming_scheme: '${PACKAGE}/${VERSION}-${COMPILERNAME}-${COMPILERVER}'
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
conflict:
|
|
- '${PACKAGE}'
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
gcc:
|
|
environment:
|
|
set:
|
|
CC: gcc
|
|
CXX: g++
|
|
FC: gfortran
|
|
F90: gfortran
|
|
F77: gfortran
|
|
openmpi:
|
|
environment:
|
|
set:
|
|
SLURM_MPI_TYPE: pmi2
|
|
OMPI_MCA_btl_openib_warn_default_gid_prefix: '0'
|
|
netlib-scalapack:
|
|
suffixes:
|
|
'^openmpi': openmpi
|
|
'^mpich': mpich
|
|
^python:
|
|
autoload: 'direct'
|
|
|
|
and regenerating the module files for every package that depends on ``python``:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module tcl refresh -y ^python
|
|
==> Regenerating tcl module files
|
|
|
|
Now the ``py-scipy`` module will be:
|
|
|
|
.. code-block:: tcl
|
|
|
|
#%Module1.0
|
|
## Module file created by spack (https://github.com/spack/spack) on 2018-07-10 15:15:09.308128
|
|
##
|
|
## py-scipy@1.1.0%gcc@7.2.0 arch=linux-ubuntu16.04-x86_64 /fdiryak
|
|
##
|
|
|
|
|
|
module-whatis "SciPy (pronounced 'Sigh Pie') is a Scientific Library for Python. It provides many user-friendly and efficient numerical routines such as routines for numerical integration and optimization."
|
|
|
|
proc ModulesHelp { } {
|
|
puts stderr "SciPy (pronounced "Sigh Pie") is a Scientific Library for Python. It"
|
|
puts stderr "provides many user-friendly and efficient numerical routines such as"
|
|
puts stderr "routines for numerical integration and optimization."
|
|
}
|
|
|
|
if ![ is-loaded python/2.7.15-gcc-7.2.0 ] {
|
|
puts stderr "Autoloading python/2.7.15-gcc-7.2.0"
|
|
module load python/2.7.15-gcc-7.2.0
|
|
}
|
|
if ![ is-loaded openblas/0.3.0-gcc-7.2.0 ] {
|
|
puts stderr "Autoloading openblas/0.3.0-gcc-7.2.0"
|
|
module load openblas/0.3.0-gcc-7.2.0
|
|
}
|
|
if ![ is-loaded py-numpy/1.14.3-gcc-7.2.0-openblas ] {
|
|
puts stderr "Autoloading py-numpy/1.14.3-gcc-7.2.0-openblas"
|
|
module load py-numpy/1.14.3-gcc-7.2.0-openblas
|
|
}
|
|
conflict py-scipy
|
|
|
|
prepend-path LD_LIBRARY_PATH "/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-7.2.0/py-scipy-1.1.0-fdiryak4ywv2krvqo7uzogfcc6uckkdp/lib"
|
|
prepend-path CMAKE_PREFIX_PATH "/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-7.2.0/py-scipy-1.1.0-fdiryak4ywv2krvqo7uzogfcc6uckkdp/"
|
|
prepend-path PYTHONPATH "/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-7.2.0/py-scipy-1.1.0-fdiryak4ywv2krvqo7uzogfcc6uckkdp/lib/python2.7/site-packages"
|
|
setenv PY_SCIPY_ROOT "/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-7.2.0/py-scipy-1.1.0-fdiryak4ywv2krvqo7uzogfcc6uckkdp"
|
|
|
|
and will contain code to autoload all the dependencies:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load py-scipy
|
|
Autoloading python/2.7.15-gcc-7.2.0
|
|
Autoloading openblas/0.3.0-gcc-7.2.0
|
|
Autoloading py-numpy/1.14.3-gcc-7.2.0-openblas
|
|
|
|
In case messages are unwanted during the autoload procedure, it will be
|
|
sufficient to omit the line setting ``verbose: True`` in the configuration file above.
|
|
|
|
-------------------------
|
|
Hierarchical module files
|
|
-------------------------
|
|
|
|
So far we worked with non-hierarchical module files, i.e. with module files
|
|
that are all generated in the same root directory and don't attempt to
|
|
dynamically modify the ``MODULEPATH``. This results in a flat module structure where
|
|
all the software is visible at the same time:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
-------------------------------------------- /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64 ---------------------------------------------
|
|
bzip2/1.0.6-gcc-7.2.0 openblas/0.3.0-gcc-7.2.0 (L)
|
|
cmake/3.11.4-gcc-7.2.0 openmpi/1.10.2-gcc-7.2.0
|
|
gcc/7.2.0-gcc-5.4.0 openssl/1.0.2o-gcc-7.2.0
|
|
gdbm/1.14.1-gcc-7.2.0 pkgconf/1.4.2-gcc-7.2.0
|
|
mpich/3.2.1-gcc-7.2.0 py-numpy/1.14.3-gcc-7.2.0-openblas (L)
|
|
ncurses/6.1-gcc-7.2.0 py-scipy/1.1.0-gcc-7.2.0-openblas (L)
|
|
netlib-lapack/3.8.0-gcc-7.2.0 py-setuptools/39.2.0-gcc-7.2.0
|
|
netlib-scalapack/2.0.2-gcc-7.2.0-netlib-mpich python/2.7.15-gcc-7.2.0 (L)
|
|
netlib-scalapack/2.0.2-gcc-7.2.0-netlib-openmpi readline/7.0-gcc-7.2.0
|
|
netlib-scalapack/2.0.2-gcc-7.2.0-openblas-mpich sqlite/3.23.1-gcc-7.2.0
|
|
netlib-scalapack/2.0.2-gcc-7.2.0-openblas-openmpi (D) zlib/1.2.11-gcc-7.2.0
|
|
|
|
Where:
|
|
L: Module is loaded
|
|
D: Default Module
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
This layout is quite simple to deploy, but you can see from the above snippet
|
|
that nothing prevents users from loading incompatible sets of modules:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module purge
|
|
root@module-file-tutorial:/# module load netlib-lapack/3.8.0-gcc-7.2.0 openblas/0.3.0-gcc-7.2.0
|
|
root@module-file-tutorial:/# module list
|
|
|
|
Currently Loaded Modules:
|
|
1) netlib-lapack/3.8.0-gcc-7.2.0 2) openblas/0.3.0-gcc-7.2.0
|
|
|
|
Even if ``conflicts`` directives are carefully placed in module files, they:
|
|
|
|
- won't enforce a consistent environment, but will just report an error
|
|
- need constant updates, for instance as soon as a new compiler or MPI library is installed
|
|
|
|
`Hierarchical module files <http://lmod.readthedocs.io/en/latest/080_hierarchy.html>`_ try to
|
|
overcome these shortcomings by showing at start-up only a restricted view of what is
|
|
available on the system: more specifically only the software that has been installed with
|
|
OS provided compilers. Among this software there will be other - usually more recent - compilers
|
|
that, once loaded, will prepend new directories to ``MODULEPATH`` unlocking all the software
|
|
that was compiled with them. This "unlocking" idea can then be extended arbitrarily to
|
|
virtual dependencies, as we'll see in the following section.
|
|
|
|
^^^^^^^^^^^^^^^^^
|
|
Core/Compiler/MPI
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
The most widely used hierarchy is the so called ``Core/Compiler/MPI`` where, on top
|
|
of the compilers, different MPI libraries also unlock software linked to them.
|
|
There are just a few steps needed to adapt the ``modules.yaml`` file we used previously:
|
|
|
|
#. enable the ``lmod`` file generator
|
|
#. change the ``tcl`` tag to ``lmod``
|
|
#. remove ``tcl`` specific directives (``naming_scheme`` and ``conflict``)
|
|
#. declare which compilers are considered ``core_compilers``
|
|
#. remove the ``mpi`` related suffixes (as they will be substituted by hierarchies)
|
|
|
|
After these modifications your configuration file should look like:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 2-8
|
|
|
|
modules:
|
|
enable::
|
|
- lmod
|
|
lmod:
|
|
core_compilers:
|
|
- 'gcc@5.4.0'
|
|
hierarchy:
|
|
- mpi
|
|
hash_length: 0
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
suffixes:
|
|
'^openblas': openblas
|
|
'^netlib-lapack': netlib
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
gcc:
|
|
environment:
|
|
set:
|
|
CC: gcc
|
|
CXX: g++
|
|
FC: gfortran
|
|
F90: gfortran
|
|
F77: gfortran
|
|
openmpi:
|
|
environment:
|
|
set:
|
|
SLURM_MPI_TYPE: pmi2
|
|
OMPI_MCA_btl_openib_warn_default_gid_prefix: '0'
|
|
|
|
|
|
.. note::
|
|
Double colon in configuration files
|
|
The double colon after ``enable`` is intentional and it serves the
|
|
purpose of overriding the default list of enabled generators so
|
|
that only ``lmod`` will be active (see :ref:`config-overrides` for more
|
|
details).
|
|
|
|
The directive ``core_compilers`` accepts a list of compilers. Everything built
|
|
using these compilers will create a module in the ``Core`` part of the hierarchy,
|
|
which is the entry point for hierarchical module files. It is
|
|
common practice to put the OS provided compilers in the list and only build common utilities
|
|
and other compilers with them.
|
|
|
|
If we now regenerate the module files:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module lmod refresh --delete-tree -y
|
|
==> Regenerating lmod module files
|
|
|
|
and update ``MODULEPATH`` to point to the ``Core``:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module purge
|
|
root@module-file-tutorial:/# module unuse /usr/local/share/spack/modules/linux-ubuntu16.04-x86_64
|
|
root@module-file-tutorial:/# module use /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core
|
|
|
|
asking for the available modules will return:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
------------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core --------------------------------------------
|
|
gcc/7.2.0
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
Unsurprisingly, the only visible module is ``gcc``. Loading that we'll unlock
|
|
the ``Compiler`` part of the hierarchy:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load gcc
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
----------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/gcc/7.2.0 -----------------------------------------
|
|
bzip2/1.0.6 mpich/3.2.1 openblas/0.3.0 pkgconf/1.4.2 py-setuptools/39.2.0 sqlite/3.23.1
|
|
cmake/3.12.0 ncurses/6.1 openmpi/1.10.2 py-numpy/1.14.3-openblas python/2.7.15 zlib/1.2.11
|
|
gdbm/1.14.1 netlib-lapack/3.8.0 openssl/1.0.2o py-scipy/1.1.0-openblas readline/7.0
|
|
|
|
------------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core --------------------------------------------
|
|
gcc/7.2.0 (L)
|
|
|
|
Where:
|
|
L: Module is loaded
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
The same holds true also for the ``MPI`` part, that you can enable by loading
|
|
either ``mpich`` or ``openmpi``. Let's start by loading ``mpich``:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load mpich
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/mpich/3.2.1-vt5xcat/gcc/7.2.0 -------------------------------
|
|
netlib-scalapack/2.0.2-netlib netlib-scalapack/2.0.2-openblas (D)
|
|
|
|
----------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/gcc/7.2.0 -----------------------------------------
|
|
bzip2/1.0.6 mpich/3.2.1 (L) openblas/0.3.0 pkgconf/1.4.2 py-setuptools/39.2.0 sqlite/3.23.1
|
|
cmake/3.12.0 ncurses/6.1 openmpi/1.10.2 py-numpy/1.14.3-openblas python/2.7.15 zlib/1.2.11
|
|
gdbm/1.14.1 netlib-lapack/3.8.0 openssl/1.0.2o py-scipy/1.1.0-openblas readline/7.0
|
|
|
|
------------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core --------------------------------------------
|
|
gcc/7.2.0 (L)
|
|
|
|
Where:
|
|
L: Module is loaded
|
|
D: Default Module
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
|
|
root@module-file-tutorial:/# module load openblas netlib-scalapack/2.0.2-openblas
|
|
root@module-file-tutorial:/# module list
|
|
|
|
Currently Loaded Modules:
|
|
1) gcc/7.2.0 2) mpich/3.2.1 3) openblas/0.3.0 4) netlib-scalapack/2.0.2-openblas
|
|
|
|
At this point we can showcase the improved consistency that a hierarchical layout provides
|
|
over a non-hierarchical one:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load openmpi
|
|
|
|
Lmod is automatically replacing "mpich/3.2.1" with "openmpi/1.10.2".
|
|
|
|
Due to MODULEPATH changes, the following have been reloaded:
|
|
1) netlib-scalapack/2.0.2-openblas
|
|
|
|
``Lmod`` took care of swapping the MPI provider for us, and it also substituted the
|
|
``netlib-scalapack`` module to conform to the change in the MPI.
|
|
In this way we can't accidentally pull-in two different MPI providers at the
|
|
same time or load a module file for a package linked to ``openmpi`` when ``mpich`` is also loaded.
|
|
Consistency for compilers and MPI is ensured by the tool.
|
|
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Add LAPACK to the hierarchy
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The hierarchy just shown is already a great improvement over non-hierarchical layouts,
|
|
but it still has an asymmetry: ``LAPACK`` providers cover the same semantic role
|
|
as ``MPI`` providers, but yet they are not part of the hierarchy.
|
|
|
|
To be more practical, this means that although we have gained an improved consistency in
|
|
our environment when it comes to ``MPI``, we still have the same problems as we had before
|
|
for ``LAPACK`` implementations:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module list
|
|
|
|
Currently Loaded Modules:
|
|
1) gcc/7.2.0 2) openblas/0.3.0 3) openmpi/1.10.2 4) netlib-scalapack/2.0.2-openblas
|
|
|
|
root@module-file-tutorial:/# module load netlib-scalapack/2.0.2-netlib
|
|
|
|
The following have been reloaded with a version change:
|
|
1) netlib-scalapack/2.0.2-openblas => netlib-scalapack/2.0.2-netlib
|
|
|
|
root@module-file-tutorial:/# module list
|
|
|
|
Currently Loaded Modules:
|
|
1) gcc/7.2.0 2) openblas/0.3.0 3) openmpi/1.10.2 4) netlib-scalapack/2.0.2-netlib
|
|
|
|
Hierarchies that are deeper than ``Core``/``Compiler``/``MPI`` are
|
|
probably still considered "unusual" or "impractical" at many sites, mainly because
|
|
module files are written manually and keeping track of the combinations
|
|
among multiple providers quickly becomes quite involved.
|
|
|
|
For instance, having both ``MPI`` and ``LAPACK`` in the hierarchy
|
|
means we must classify software into one of four categories:
|
|
|
|
#. Software that doesn't depend on ``MPI`` or ``LAPACK``
|
|
#. Software that depends only on ``MPI``
|
|
#. Software that depends only on ``LAPACK``
|
|
#. Software that depends on both
|
|
|
|
to decide when to show it to the user. The situation becomes more involved as the number of virtual
|
|
dependencies in the hierarchy increases.
|
|
|
|
We can take advantage of the DAG that Spack maintains for the installed software and solve
|
|
this combinatorial problem in a clean and automated way.
|
|
In some sense Spack's ability to manage this combinatorial complexity makes deeper
|
|
hierarchies feasible.
|
|
|
|
Coming back to our example, let's add ``lapack`` to the hierarchy and remove any remaining suffix:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 9
|
|
|
|
modules:
|
|
enable::
|
|
- lmod
|
|
lmod:
|
|
core_compilers:
|
|
- 'gcc@5.4.0'
|
|
hierarchy:
|
|
- mpi
|
|
- lapack
|
|
hash_length: 0
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
gcc:
|
|
environment:
|
|
set:
|
|
CC: gcc
|
|
CXX: g++
|
|
FC: gfortran
|
|
F90: gfortran
|
|
F77: gfortran
|
|
openmpi:
|
|
environment:
|
|
set:
|
|
SLURM_MPI_TYPE: pmi2
|
|
OMPI_MCA_btl_openib_warn_default_gid_prefix: '0'
|
|
|
|
After module files have been regenerated as usual:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module purge
|
|
|
|
root@module-file-tutorial:/# spack module lmod refresh --delete-tree -y
|
|
==> Regenerating lmod module files
|
|
|
|
we can see that now we have additional components in the hierarchy:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load gcc
|
|
root@module-file-tutorial:/# module load openblas
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
----------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/openblas/0.3.0-pdatzbi/gcc/7.2.0 ------------------------------
|
|
py-numpy/1.14.3 py-scipy/1.1.0
|
|
|
|
----------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/gcc/7.2.0 -----------------------------------------
|
|
bzip2/1.0.6 mpich/3.2.1 openblas/0.3.0 (L) pkgconf/1.4.2 readline/7.0
|
|
cmake/3.12.0 ncurses/6.1 openmpi/1.10.2 py-setuptools/39.2.0 sqlite/3.23.1
|
|
gdbm/1.14.1 netlib-lapack/3.8.0 openssl/1.0.2o python/2.7.15 zlib/1.2.11
|
|
|
|
------------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core --------------------------------------------
|
|
gcc/7.2.0 (L)
|
|
|
|
Where:
|
|
L: Module is loaded
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
|
|
root@module-file-tutorial:/# module load openmpi
|
|
root@module-file-tutorial:/# module avail
|
|
|
|
------------------ /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/openmpi/1.10.2-6oewzwj/openblas/0.3.0-pdatzbi/gcc/7.2.0 ------------------
|
|
netlib-scalapack/2.0.2
|
|
|
|
----------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/openblas/0.3.0-pdatzbi/gcc/7.2.0 ------------------------------
|
|
py-numpy/1.14.3 py-scipy/1.1.0
|
|
|
|
----------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/gcc/7.2.0 -----------------------------------------
|
|
bzip2/1.0.6 mpich/3.2.1 openblas/0.3.0 (L) pkgconf/1.4.2 readline/7.0
|
|
cmake/3.11.4 ncurses/6.1 openmpi/1.10.2 (L) py-setuptools/39.2.0 sqlite/3.23.1
|
|
gdbm/1.14.1 netlib-lapack/3.8.0 openssl/1.0.2o python/2.7.15 zlib/1.2.11
|
|
|
|
------------------------------------------- /usr/local/share/spack/lmod/linux-ubuntu16.04-x86_64/Core --------------------------------------------
|
|
gcc/7.2.0 (L)
|
|
|
|
Where:
|
|
L: Module is loaded
|
|
|
|
Use "module spider" to find all possible modules.
|
|
Use "module keyword key1 key2 ..." to search for all possible modules matching any of the "keys".
|
|
|
|
Both ``MPI`` and ``LAPACK`` providers will now benefit from the same safety features:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# module load py-numpy netlib-scalapack
|
|
root@module-file-tutorial:/# module load mpich
|
|
|
|
Lmod is automatically replacing "openmpi/1.10.2" with "mpich/3.2.1".
|
|
|
|
|
|
Due to MODULEPATH changes, the following have been reloaded:
|
|
1) netlib-scalapack/2.0.2
|
|
|
|
root@module-file-tutorial:/# module load mpich
|
|
|
|
Lmod is automatically replacing "openmpi/1.10.2" with "mpich/3.2.1".
|
|
|
|
|
|
Due to MODULEPATH changes, the following have been reloaded:
|
|
1) netlib-scalapack/2.0.2
|
|
|
|
Because we only compiled ``py-numpy`` with ``openblas`` the module
|
|
is made inactive when we switch the ``LAPACK`` provider. The user
|
|
environment is now consistent by design!
|
|
|
|
----------------------
|
|
Working with templates
|
|
----------------------
|
|
|
|
As briefly mentioned in the introduction, Spack uses `Jinja2 <http://jinja.pocoo.org/docs/2.9/>`_
|
|
to generate each individual module file.
|
|
This means that you have all of its flexibility and power when it comes to
|
|
customizing what gets generated!
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
Module file templates
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The templates that Spack uses to generate module files are stored in the
|
|
``share/spack/templates/module`` directory within the Spack prefix, and
|
|
they all share the same common structure. Usually, they start with a
|
|
header that identifies the type of module being generated. In the case of
|
|
hierarchical module files it's:
|
|
|
|
.. literalinclude:: ../../../share/spack/templates/modules/modulefile.lua
|
|
:language: jinja
|
|
:lines: 1-6
|
|
|
|
The statements within double curly brackets ``{{ ... }}`` denote
|
|
`expressions <http://jinja.pocoo.org/docs/2.9/templates/#expressions>`_
|
|
that will be evaluated and substituted at module generation time.
|
|
The rest of the file is then divided into
|
|
`blocks <http://jinja.pocoo.org/docs/2.9/templates/#template-inheritance>`_
|
|
that can be overridden or extended by users, if need be.
|
|
`Control structures <http://jinja.pocoo.org/docs/2.9/templates/#list-of-control-structures>`_
|
|
, delimited by ``{% ... %}``,
|
|
are also permitted in the template language:
|
|
|
|
.. literalinclude:: ../../../share/spack/templates/modules/modulefile.lua
|
|
:language: jinja
|
|
:lines: 73-88
|
|
|
|
The locations where Spack looks for templates are specified
|
|
in ``config.yaml``:
|
|
|
|
.. literalinclude:: ../../../etc/spack/defaults/config.yaml
|
|
:language: yaml
|
|
:lines: 21-24
|
|
|
|
and can be extended by users to employ custom templates, as we'll see next.
|
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
Extend the default templates
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Let's assume one of our software is protected by group membership:
|
|
allowed users belong to the same linux group, and access is granted at group level.
|
|
Wouldn't it be nice if people that are not
|
|
yet entitled to use it could receive a helpful message at module load time
|
|
that tells them who to contact in your organization to be inserted in the group?
|
|
|
|
To automate the generation of module files with such site-specific behavior
|
|
we'll start by extending the list of locations where Spack looks for module
|
|
files. Let's create the file ``~/.spack/config.yaml`` with the content:
|
|
|
|
.. code-block:: yaml
|
|
|
|
config:
|
|
template_dirs:
|
|
- $HOME/.spack/templates
|
|
|
|
This tells Spack to also search another location when looking for template files.
|
|
Next, we need to create our custom template extension in the folder listed above:
|
|
|
|
.. code-block:: jinja
|
|
|
|
{% extends "modules/modulefile.lua" %}
|
|
{% block footer %}
|
|
-- Access is granted only to specific groups
|
|
if not isDir("{{ spec.prefix }}") then
|
|
LmodError (
|
|
"You don't have the necessary rights to run \"{{ spec.name }}\".\n\n",
|
|
"\tPlease write an e-mail to 1234@foo.com if you need further information on how to get access to it.\n"
|
|
)
|
|
end
|
|
{% endblock %}
|
|
|
|
Let's name this file ``group-restricted.lua``. The line:
|
|
|
|
.. code-block:: jinja
|
|
|
|
{% extends "modules/modulefile.lua" %}
|
|
|
|
tells Jinja2 that we are reusing the standard template for hierarchical module files.
|
|
The section:
|
|
|
|
.. code-block:: jinja
|
|
|
|
{% block footer %}
|
|
-- Access is granted only to specific groups
|
|
if not isDir("{{ spec.prefix }}") then
|
|
LmodError (
|
|
"You don't have the necessary rights to run \"{{ spec.name }}\".\n\n",
|
|
"\tPlease write an e-mail to 1234@foo.com if you need further information on how to get access to it.\n"
|
|
)
|
|
end
|
|
{% endblock %}
|
|
|
|
overrides the ``footer`` block.
|
|
Finally, we need to add a couple of lines in ``modules.yaml`` to tell Spack which specs
|
|
need to use the new custom template. For the sake of illustration let's assume
|
|
it's ``netlib-scalapack``:
|
|
|
|
.. code-block:: yaml
|
|
:emphasize-lines: 35-36
|
|
|
|
modules:
|
|
enable::
|
|
- lmod
|
|
lmod:
|
|
core_compilers:
|
|
- 'gcc@5.4.0'
|
|
hierarchy:
|
|
- mpi
|
|
- lapack
|
|
hash_length: 0
|
|
whitelist:
|
|
- gcc
|
|
blacklist:
|
|
- '%gcc@5.4.0'
|
|
- readline
|
|
all:
|
|
filter:
|
|
environment_blacklist: ['CPATH', 'LIBRARY_PATH']
|
|
environment:
|
|
set:
|
|
'${PACKAGE}_ROOT': '${PREFIX}'
|
|
gcc:
|
|
environment:
|
|
set:
|
|
CC: gcc
|
|
CXX: g++
|
|
FC: gfortran
|
|
F90: gfortran
|
|
F77: gfortran
|
|
openmpi:
|
|
environment:
|
|
set:
|
|
SLURM_MPI_TYPE: pmi2
|
|
OMPI_MCA_btl_openib_warn_default_gid_prefix: '0'
|
|
netlib-scalapack:
|
|
template: 'group-restricted.lua'
|
|
|
|
If we regenerate the module files one last time:
|
|
|
|
.. code-block:: console
|
|
|
|
root@module-file-tutorial:/# spack module lmod refresh -y netlib-scalapack
|
|
==> Regenerating lmod module files
|
|
|
|
we'll find the following at the end of each ``netlib-scalapack`` module file:
|
|
|
|
.. code-block:: lua
|
|
|
|
-- Access is granted only to specific groups
|
|
if not isDir("/usr/local/opt/spack/linux-ubuntu16.04-x86_64/gcc-7.2.0/netlib-scalapack-2.0.2-d3lertflood3twaor44eam2kcr4l72ag") then
|
|
LmodError (
|
|
"You don't have the necessary rights to run \"netlib-scalapack\".\n\n",
|
|
"\tPlease write an e-mail to 1234@foo.com if you need further information on how to get access to it.\n"
|
|
)
|
|
end
|
|
|
|
and every user that doesn't have access to the software will now be redirected to
|
|
the right e-mail address where to ask for it!
|