Tutorial setup
If you have not done the prior sections, you’ll need to set Spack up like this:
git clone https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack tutorial
See the Basic Installation Tutorial for full details on setup. For more
help join us in the #tutorial
channel on Slack – get an
invitation at spackpm.herokuapp.com
Scripting with Spack¶
This tutorial introduces advanced Spack features related to scripting.
Specifically, we will show you how to write scripts using spack find
and spack python
.
Earlier sections of the tutorial demonstrated using spack find
to
list and search installed packages.
The spack python
command gives you access to all of Spack’s internal
APIs, allowing
you to write more complex queries, for example.
Since Spack has an extensive API, we’ll only scratch the surface here. We’ll give you enough information to start writing your own scripts and to find what you need, with a little digging.
Setting up the tutorial¶
Before proceeding, let’s ensure the outputs for this segment are reasonable. Since you may have a lot of packages installed from earlier sections of the tutorial, we want to perform a little cleanup.
Let’s remove gcc@8.3.0
and re-install hdf5
and zlib@clang
using the following commands:
$ spack uninstall -ay
==> Successfully uninstalled gcc@8.3.0%gcc@7.5.0~binutils~bootstrap~nvptx~piclibs~strip languages=c,c++,fortran patches=49341f7807b12a89750c010a20707598f83121da9829150d4049ed3a1a140564,dc1ca240b7fb70112ae6cc47cd86925adf78d29ed9d0c26b0c51d52e40ceca0e arch=linux-ubuntu18.04-x86_64/7mh4po7
==> Successfully uninstalled automake@1.16.2%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/d2krmb5
==> Successfully uninstalled pkgconf@1.7.3%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/4sh6pym
==> Successfully uninstalled libtool@2.4.6%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/jdxbjft
==> Successfully uninstalled diffutils@3.7%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/otkkten
==> Successfully uninstalled autoconf@2.69%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/mm33a3o
==> Successfully uninstalled patchelf@0.10%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/2nj3vxx
==> Successfully uninstalled m4@1.4.18%gcc@7.5.0+sigsegv patches=3877ab548f88597ab2327a2230ee048d2d07ace1062efe81fc92e91b7f39cd00,fc9b61654a3ba1a8d6cd78ce087e7c96366c290bc8d2c299f09828d793b853c8 arch=linux-ubuntu18.04-x86_64/mkc3u4x
==> Successfully uninstalled isl@0.18%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/4lkvfkv
==> Successfully uninstalled mpc@1.1.0%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/uur2dd6
==> Successfully uninstalled libiconv@1.16%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/jearpk4
==> Successfully uninstalled zlib@1.2.11%gcc@7.5.0+optimize+pic+shared arch=linux-ubuntu18.04-x86_64/smoyzzo
==> Successfully uninstalled perl@5.32.0%gcc@7.5.0+cpanm+shared+threads arch=linux-ubuntu18.04-x86_64/zfdvt2j
==> Successfully uninstalled mpfr@3.1.6%gcc@7.5.0 patches=7a6dd71bcda4803d6b89612706a17b8816e1acd5dd9bf1bec29cf748f3b60008 arch=linux-ubuntu18.04-x86_64/nwsubsw
==> Successfully uninstalled berkeley-db@18.1.40%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/4ihuiaz
==> Successfully uninstalled libsigsegv@2.12%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/lbrx7ln
==> Successfully uninstalled gdbm@1.18.1%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/4av4gyw
==> Successfully uninstalled readline@8.0%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/t54jzdy
==> Successfully uninstalled gmp@6.1.2%gcc@7.5.0 arch=linux-ubuntu18.04-x86_64/3ol3tld
==> Successfully uninstalled ncurses@6.2%gcc@7.5.0~symlinks+termlib arch=linux-ubuntu18.04-x86_64/crhlefo
$ spack compiler rm gcc@8.3.0
==> Removed compiler gcc@8.3.0
$ spack install hdf5
==> Installing libsigsegv-2.12-lbrx7lnfz46ukewxbhxnucmx76g23c6q
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/libsigsegv-2.12/linux-ubuntu18.04-x86_64-gcc-7.5.0-libsigsegv-2.12-lbrx7lnfz46ukewxbhxnucmx76g23c6q.spack
###################################################################################################################################################################### 100.0%
==> Extracting libsigsegv-2.12-lbrx7lnfz46ukewxbhxnucmx76g23c6q from binary cache
gpgconf: socketdir is '/home/spack/.gnupg'
gpgconf: no /run/user dir
gpgconf: using homedir as fallback
==> Installing patchelf-0.10-2nj3vxxz5lwexpp5srseegxt7v6n4whp
==> No binary for patchelf-0.10-2nj3vxxz5lwexpp5srseegxt7v6n4whp found: installing from source
==> Using cached archive: /home/spack/spack/var/spack/cache/_source-cache/archive/b2/b2deabce05c34ce98558c0efb965f209de592197b2c88e930298d740ead09019.tar.gz
==> patchelf: Executing phase: 'autoreconf'
==> patchelf: Executing phase: 'configure'
==> patchelf: Executing phase: 'build'
==> patchelf: Executing phase: 'install'
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/patchelf-0.10-2nj3vxxz5lwexpp5srseegxt7v6n4whp
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/libsigsegv-2.12-lbrx7lnfz46ukewxbhxnucmx76g23c6q
==> Installing pkgconf-1.7.3-4sh6pymrm2ms4auu3ajbjjr6fiuhz5g7
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/pkgconf-1.7.3/linux-ubuntu18.04-x86_64-gcc-7.5.0-pkgconf-1.7.3-4sh6pymrm2ms4auu3ajbjjr6fiuhz5g7.spack
###################################################################################################################################################################### 100.0%
==> Extracting pkgconf-1.7.3-4sh6pymrm2ms4auu3ajbjjr6fiuhz5g7 from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/pkgconf-1.7.3-4sh6pymrm2ms4auu3ajbjjr6fiuhz5g7
==> Installing util-macros-1.19.1-gs6ag7ktdoiirb62t7bcagjw62szrrg2
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/util-macros-1.19.1/linux-ubuntu18.04-x86_64-gcc-7.5.0-util-macros-1.19.1-gs6ag7ktdoiirb62t7bcagjw62szrrg2.spack
###################################################################################################################################################################### 100.0%
==> Extracting util-macros-1.19.1-gs6ag7ktdoiirb62t7bcagjw62szrrg2 from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/util-macros-1.19.1-gs6ag7ktdoiirb62t7bcagjw62szrrg2
==> Installing libiconv-1.16-jearpk4xci4zc7dkrza4fufaqfkq7rfl
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/libiconv-1.16/linux-ubuntu18.04-x86_64-gcc-7.5.0-libiconv-1.16-jearpk4xci4zc7dkrza4fufaqfkq7rfl.spack
###################################################################################################################################################################### 100.0%
==> Extracting libiconv-1.16-jearpk4xci4zc7dkrza4fufaqfkq7rfl from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/libiconv-1.16-jearpk4xci4zc7dkrza4fufaqfkq7rfl
==> Installing xz-5.2.5-komekkmyciga3kl24edjmredhj3uyt7v
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/xz-5.2.5/linux-ubuntu18.04-x86_64-gcc-7.5.0-xz-5.2.5-komekkmyciga3kl24edjmredhj3uyt7v.spack
###################################################################################################################################################################### 100.0%
==> Extracting xz-5.2.5-komekkmyciga3kl24edjmredhj3uyt7v from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/xz-5.2.5-komekkmyciga3kl24edjmredhj3uyt7v
==> Installing zlib-1.2.11-smoyzzo2qhzpn6mg6rd3l2p7b23enshg
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/zlib-1.2.11/linux-ubuntu18.04-x86_64-gcc-7.5.0-zlib-1.2.11-smoyzzo2qhzpn6mg6rd3l2p7b23enshg.spack
###################################################################################################################################################################### 100.0%
==> Extracting zlib-1.2.11-smoyzzo2qhzpn6mg6rd3l2p7b23enshg from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/zlib-1.2.11-smoyzzo2qhzpn6mg6rd3l2p7b23enshg
==> Installing berkeley-db-18.1.40-4ihuiazsglf22f3pntq5hc4kyszqzexn
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/berkeley-db-18.1.40/linux-ubuntu18.04-x86_64-gcc-7.5.0-berkeley-db-18.1.40-4ihuiazsglf22f3pntq5hc4kyszqzexn.spack
###################################################################################################################################################################### 100.0%
==> Extracting berkeley-db-18.1.40-4ihuiazsglf22f3pntq5hc4kyszqzexn from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/berkeley-db-18.1.40-4ihuiazsglf22f3pntq5hc4kyszqzexn
==> Installing m4-1.4.18-mkc3u4x2p2wie6jfhuku7g5rkovcrxps
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/m4-1.4.18/linux-ubuntu18.04-x86_64-gcc-7.5.0-m4-1.4.18-mkc3u4x2p2wie6jfhuku7g5rkovcrxps.spack
###################################################################################################################################################################### 100.0%
==> Extracting m4-1.4.18-mkc3u4x2p2wie6jfhuku7g5rkovcrxps from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/m4-1.4.18-mkc3u4x2p2wie6jfhuku7g5rkovcrxps
==> Installing ncurses-6.2-crhlefo3dv7lmsv5pf4icsy4gepkdorm
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/ncurses-6.2/linux-ubuntu18.04-x86_64-gcc-7.5.0-ncurses-6.2-crhlefo3dv7lmsv5pf4icsy4gepkdorm.spack
###################################################################################################################################################################### 100.0%
==> Extracting ncurses-6.2-crhlefo3dv7lmsv5pf4icsy4gepkdorm from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/ncurses-6.2-crhlefo3dv7lmsv5pf4icsy4gepkdorm
==> Installing libxml2-2.9.10-yn2r3wfhiilelyulh5toteicdtxjhw7d
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/libxml2-2.9.10/linux-ubuntu18.04-x86_64-gcc-7.5.0-libxml2-2.9.10-yn2r3wfhiilelyulh5toteicdtxjhw7d.spack
###################################################################################################################################################################### 100.0%
==> Extracting libxml2-2.9.10-yn2r3wfhiilelyulh5toteicdtxjhw7d from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/libxml2-2.9.10-yn2r3wfhiilelyulh5toteicdtxjhw7d
==> Installing libtool-2.4.6-jdxbjftheiotj6solpomva7dowrhlerl
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/libtool-2.4.6/linux-ubuntu18.04-x86_64-gcc-7.5.0-libtool-2.4.6-jdxbjftheiotj6solpomva7dowrhlerl.spack
###################################################################################################################################################################### 100.0%
==> Extracting libtool-2.4.6-jdxbjftheiotj6solpomva7dowrhlerl from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/libtool-2.4.6-jdxbjftheiotj6solpomva7dowrhlerl
==> Installing readline-8.0-t54jzdy2jj4snltjazlm3br2urcilc6v
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/readline-8.0/linux-ubuntu18.04-x86_64-gcc-7.5.0-readline-8.0-t54jzdy2jj4snltjazlm3br2urcilc6v.spack
###################################################################################################################################################################### 100.0%
==> Extracting readline-8.0-t54jzdy2jj4snltjazlm3br2urcilc6v from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/readline-8.0-t54jzdy2jj4snltjazlm3br2urcilc6v
==> Installing libpciaccess-0.16-bob4o5m3uku6vtdil5imasprgy775zg7
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/libpciaccess-0.16/linux-ubuntu18.04-x86_64-gcc-7.5.0-libpciaccess-0.16-bob4o5m3uku6vtdil5imasprgy775zg7.spack
###################################################################################################################################################################### 100.0%
==> Extracting libpciaccess-0.16-bob4o5m3uku6vtdil5imasprgy775zg7 from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/libpciaccess-0.16-bob4o5m3uku6vtdil5imasprgy775zg7
==> Installing gdbm-1.18.1-4av4gywgpaspkhy3dvbb62nulqogtzbb
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/gdbm-1.18.1/linux-ubuntu18.04-x86_64-gcc-7.5.0-gdbm-1.18.1-4av4gywgpaspkhy3dvbb62nulqogtzbb.spack
###################################################################################################################################################################### 100.0%
==> Extracting gdbm-1.18.1-4av4gywgpaspkhy3dvbb62nulqogtzbb from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/gdbm-1.18.1-4av4gywgpaspkhy3dvbb62nulqogtzbb
==> Installing perl-5.32.0-zfdvt2jjuaees43ffrrtphqs2ky3o22t
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/perl-5.32.0/linux-ubuntu18.04-x86_64-gcc-7.5.0-perl-5.32.0-zfdvt2jjuaees43ffrrtphqs2ky3o22t.spack
###################################################################################################################################################################### 100.0%
==> Extracting perl-5.32.0-zfdvt2jjuaees43ffrrtphqs2ky3o22t from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/perl-5.32.0-zfdvt2jjuaees43ffrrtphqs2ky3o22t
==> Installing autoconf-2.69-mm33a3ocsv3jsh2tfxc4mlab4xsurtdd
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/autoconf-2.69/linux-ubuntu18.04-x86_64-gcc-7.5.0-autoconf-2.69-mm33a3ocsv3jsh2tfxc4mlab4xsurtdd.spack
###################################################################################################################################################################### 100.0%
==> Extracting autoconf-2.69-mm33a3ocsv3jsh2tfxc4mlab4xsurtdd from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/autoconf-2.69-mm33a3ocsv3jsh2tfxc4mlab4xsurtdd
==> Installing automake-1.16.2-d2krmb5gweivlnztcymhklzsqbrpatt6
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/automake-1.16.2/linux-ubuntu18.04-x86_64-gcc-7.5.0-automake-1.16.2-d2krmb5gweivlnztcymhklzsqbrpatt6.spack
###################################################################################################################################################################### 100.0%
==> Extracting automake-1.16.2-d2krmb5gweivlnztcymhklzsqbrpatt6 from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/automake-1.16.2-d2krmb5gweivlnztcymhklzsqbrpatt6
==> Installing numactl-2.0.14-wbqbc5vw5sxzwhvu56p6x5nd5n4abrvh
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/numactl-2.0.14/linux-ubuntu18.04-x86_64-gcc-7.5.0-numactl-2.0.14-wbqbc5vw5sxzwhvu56p6x5nd5n4abrvh.spack
###################################################################################################################################################################### 100.0%
==> Extracting numactl-2.0.14-wbqbc5vw5sxzwhvu56p6x5nd5n4abrvh from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/numactl-2.0.14-wbqbc5vw5sxzwhvu56p6x5nd5n4abrvh
==> Installing hwloc-1.11.11-zqwfzhw5k2ollygh6nrjpsi7u4d4g6lu
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/hwloc-1.11.11/linux-ubuntu18.04-x86_64-gcc-7.5.0-hwloc-1.11.11-zqwfzhw5k2ollygh6nrjpsi7u4d4g6lu.spack
###################################################################################################################################################################### 100.0%
==> Extracting hwloc-1.11.11-zqwfzhw5k2ollygh6nrjpsi7u4d4g6lu from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/hwloc-1.11.11-zqwfzhw5k2ollygh6nrjpsi7u4d4g6lu
==> Installing openmpi-3.1.6-pmsyupw6w3gql4loaor25gfumlmvkl25
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/openmpi-3.1.6/linux-ubuntu18.04-x86_64-gcc-7.5.0-openmpi-3.1.6-pmsyupw6w3gql4loaor25gfumlmvkl25.spack
###################################################################################################################################################################### 100.0%
==> Extracting openmpi-3.1.6-pmsyupw6w3gql4loaor25gfumlmvkl25 from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/openmpi-3.1.6-pmsyupw6w3gql4loaor25gfumlmvkl25
==> Installing hdf5-1.10.7-vedchc5aoqyu3ydbp346qrbpe6kg46rq
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/gcc-7.5.0/hdf5-1.10.7/linux-ubuntu18.04-x86_64-gcc-7.5.0-hdf5-1.10.7-vedchc5aoqyu3ydbp346qrbpe6kg46rq.spack
###################################################################################################################################################################### 100.0%
==> Extracting hdf5-1.10.7-vedchc5aoqyu3ydbp346qrbpe6kg46rq from binary cache
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/gcc-7.5.0/hdf5-1.10.7-vedchc5aoqyu3ydbp346qrbpe6kg46rq
$ spack install zlib%clang
==> Installing zlib-1.2.11-5qffmms6gwykcikh6aag4h3z4scrfdla
==> Fetching file:///mirror/build_cache/linux-ubuntu18.04-x86_64/clang-6.0.0/zlib-1.2.11/linux-ubuntu18.04-x86_64-clang-6.0.0-zlib-1.2.11-5qffmms6gwykcikh6aag4h3z4scrfdla.spack
###################################################################################################################################################################### 100.0%
==> Extracting zlib-1.2.11-5qffmms6gwykcikh6aag4h3z4scrfdla from binary cache
gpgconf: socketdir is '/home/spack/.gnupg'
gpgconf: no /run/user dir
gpgconf: using homedir as fallback
[+] /home/spack/spack/opt/spack/linux-ubuntu18.04-x86_64/clang-6.0.0/zlib-1.2.11-5qffmms6gwykcikh6aag4h3z4scrfdla
Now we are ready to use the Spack’s find
and python
subcommands
to query the installed packages.
Scripting with spack find
¶
So far, the output we’ve seen from spack find
has been for human
consumption. But you can take advantage of some advanced options of
the command to generate machine-readable output suitable for piping
to a script.
spack find --format
¶
The main job of spack find
is to show the user a bunch of concrete
specs that correspond to installed packages. By default, we display them
with some default attributes, like the @version
suffix you’re used to
seeing in the output.
The --format
argument allows you to display the specs however you
choose, using custom format strings. Format strings let you specify the
names of particular parts of the specs you want displayed. Let’s see
the first option in action.
Suppose you only want to display the name, version, and first ten (10) characters of the hash for every package installed in your Spack instance. You can generate that output with the following command:
$ spack find --format "{name} {version} {hash:10}"
autoconf 2.69 mm33a3ocsv hdf5 1.10.7 vedchc5aoq libsigsegv 2.12 lbrx7lnfz4 ncurses 6.2 crhlefo3dv perl 5.32.0 zfdvt2jjua xz 5.2.5 komekkmyci
automake 1.16.2 d2krmb5gwe hwloc 1.11.11 zqwfzhw5k2 libtool 2.4.6 jdxbjfthei numactl 2.0.14 wbqbc5vw5s pkgconf 1.7.3 4sh6pymrm2 zlib 1.2.11 5qffmms6gw
berkeley-db 18.1.40 4ihuiazsgl libiconv 1.16 jearpk4xci libxml2 2.9.10 yn2r3wfhii openmpi 3.1.6 pmsyupw6w3 readline 8.0 t54jzdy2jj zlib 1.2.11 smoyzzo2qh
gdbm 1.18.1 4av4gywgpa libpciaccess 0.16 bob4o5m3uk m4 1.4.18 mkc3u4x2p2 patchelf 0.10 2nj3vxxz5l util-macros 1.19.1 gs6ag7ktdo
Note that name
, version
, and hash
are attributes of Spack’s
internal Spec
object and enclosing them in braces ensures they are
output according to your format string.
Using spack find --format
allows you to retrieve just the information
you need to do things like pipe the output to typical UNIX command-line
tools like sort
or uniq
.
spack find --json
¶
Alternatively, you can get a serialized version of Spec objects in
the JSON format using the --json
option. For example, you can
get attributes for all installations of zlib
by entering:
$ spack find --json zlib
[
{
"name": "zlib",
"hash": "5qffmms6gwykcikh6aag4h3z4scrfdla",
"version": "1.2.11",
"arch": {
"platform": "linux",
"platform_os": "ubuntu18.04",
"target": "x86_64"
},
"compiler": {
"name": "clang",
"version": "6.0.0"
},
"namespace": "builtin",
"parameters": {
"optimize": true,
"pic": true,
"shared": true,
"cflags": [],
"cppflags": [],
"cxxflags": [],
"fflags": [],
"ldflags": [],
"ldlibs": []
}
},
{
"name": "zlib",
"hash": "smoyzzo2qhzpn6mg6rd3l2p7b23enshg",
"version": "1.2.11",
"arch": {
"platform": "linux",
"platform_os": "ubuntu18.04",
"target": "x86_64"
},
"compiler": {
"name": "gcc",
"version": "7.5.0"
},
"namespace": "builtin",
"parameters": {
"optimize": true,
"pic": true,
"shared": true,
"cflags": [],
"cppflags": [],
"cxxflags": [],
"fflags": [],
"ldflags": [],
"ldlibs": []
}
}
The spack find --json
command gives you everything we know about
the specs in a structured format. You can pipe its output to
JSON filtering tools like jq
to extract just the parts you want.
Check out the basic usage docs for more examples.
Introducing the spack python
command¶
What if we need to perform more advanced queries?
Spack provides the spack python
command to launch a python interpreter
with Spack’s python modules available to import. It uses the underlying
python for the rest of its commands. So you can write scripts to:
run Spack commands;
explore abstract and concretized specs; and
directly access other internal components of Spack.
Let’s launch a Spack-aware python interpreter by entering:
$ spack python
exit()
Spack version 0.16.1
Python 3.6.9, Linux x86_64
>>> exit()
Since we are in a python interpreter, use exit()
to end
the session and return to the terminal.
Accessing the Spec
object¶
Now let’s take a look at the internal representation of the Spack Spec
.
As you already know, specs can be either abstract or concrete. The
specs you’ve seen in package.py
files (e.g., in the install()
method) have been concrete, or fully specified. The specs you’ve typed
on the command line have been abstract. Understanding the differences
between the two types is key to using Spack’s internal API.
Let’s open another python interpreter with spack python
, instantiate
the zlib
spec, and check a few properties of an abstract spec:
>>> from spack.spec import Spec
>>> s = Spec('zlib target=ivybridge')
>>> s.concrete
False
>>> s.version
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/spack/spack/lib/spack/spack/spec.py", line 3166, in version
raise SpecError("Spec version is not concrete: " + str(self))
SpecError: Spec version is not concrete: zlib arch=linux-None-ivybridge
>>> s.versions
[:]
>>> s.architecture
linux-None-ivybridge
Notice that there are Spec
properties and methods that are not
accessible to abstract specs; specifically:
an exception –
SpecError
– is raised if we try to access itsversion
;there are no associated
versions
; andthe spec’s operating system is
None
.
Now, without exiting the interpreter, let’s concretize the spec and try again:
>>> s.concretize()
>>> s.concrete
True
>>> s.version
Version('1.2.11')
>>> s.versions
[Version('1.2.11')]
>>> s.architecture
linux-ubuntu18.04-ivybridge
Notice that the concretized spec now:
has a
version
;has a single entry in its
versions
list; andthe operating system is now
ubuntu18.04
.
It is not necessary to store the intermediate abstract spec – you can
use the .concretized()
method as shorthand:
>>> t = Spec('zlib target=ivybridge').concretized()
>>> s == t
True
Querying the Spack database¶
Even more powerful queries are available when we look at the information
stored in the Spack database. The Database
object in Spack is in the
spack.store.db
variable. We’ll interact with it mainly through the
query()
method. Let’s see the documentation available for query()
using python’s built-in help()
function:
>>> import spack.store
>>> help(spack.store.db.query)
Help on method query in module spack.database:
query(*args, **kwargs) method of spack.database.Database instance
Query the Spack database including all upstream databases.
Args:
query_spec: queries iterate through specs in the database and
return those that satisfy the supplied ``query_spec``. If
query_spec is `any`, This will match all specs in the
database. If it is a spec, we'll evaluate
``spec.satisfies(query_spec)``
known (bool or any, optional): Specs that are "known" are those
for which Spack can locate a ``package.py`` file -- i.e.,
Spack "knows" how to install them. Specs that are unknown may
represent packages that existed in a previous version of
Spack, but have since either changed their name or
been removed
installed (bool or any, or InstallStatus or iterable of
InstallStatus, optional): if ``True``, includes only installed
specs in the search; if ``False`` only missing specs, and if
``any``, all specs in database. If an InstallStatus or iterable
of InstallStatus, returns specs whose install status
(installed, deprecated, or missing) matches (one of) the
InstallStatus. (default: True)
explicit (bool or any, optional): A spec that was installed
following a specific user request is marked as explicit. If
instead it was pulled-in as a dependency of a user requested
spec it's considered implicit.
start_date (datetime, optional): filters the query discarding
specs that have been installed before ``start_date``.
end_date (datetime, optional): filters the query discarding
specs that have been installed after ``end_date``.
hashes (container): list or set of hashes that we can use to
restrict the search
Returns:
list of specs that match the query
(END)
We will primarily make use of the query_spec
argument.
Recall that queries using the spack find
command are limited to
queries of attributes with matching values, not values they do not
have. In other words, we cannot use the spack find
command for
all packages that do not satisfy a certain criterion.
We can use the python interface to write these types of queries.
For example, let’s find all packages that were compiled with gcc
but
do not depend on mpich
. We can do this by using custom python code
and Spack database queries. We will use the spack.cmd.display_specs
for output to achieve the same printing functionality as the spack
find
command:
>>> gcc_query_spec = Spec('%gcc')
>>> gcc_specs = spack.store.db.query(gcc_query_spec)
>>> result = filter(lambda spec: not spec.satisfies('^mpich'), gcc_specs)
>>> import spack.cmd
>>> spack.cmd.display_specs(result)
-- linux-ubuntu18.04-x86_64 / gcc@7.5.0 -------------------------
autoconf@2.69 libiconv@1.16 m4@1.4.18 perl@5.30.3 zlib@1.2.11
automake@1.16.2 libpciaccess@0.13.5 ncurses@6.2 pkgconf@1.7.3
gdbm@1.18.1 libsigsegv@2.12 numactl@2.0.12 readline@8.0
hdf5@1.10.6 libtool@2.4.6 openmpi@3.1.6 util-macros@1.19.1
hwloc@1.11.11 libxml2@2.9.10 patchelf@0.10 xz@5.2.5
Now we have a powerful query not available through spack find
.
Let’s exit the interpreter to take us back to the command line:
>>> exit()
before generalizing the functionality for re-use.
Using scripts¶
Now let’s parameterize our script to accept arguments on the command line. With a few generalizations to use the include and exclude specs as arguments, we can create a powerful, general-purpose query script.
Open a file called find_exclude.py
in your preferred editor
and add the following code:
from spack.spec import Spec
import spack.store
import spack.cmd
import sys
include_spec = Spec(sys.argv[1])
exclude_spec = Spec(sys.argv[2])
all_included = spack.store.db.query(include_spec)
result = filter(lambda spec: not spec.satisfies(exclude_spec), all_included)
spack.cmd.display_specs(result)
Notice we added importing and using the system package (sys
)
to access the first and second command line arguments.
Now we can run our new script by entering the following:
$ spack python find_exclude.py %gcc ^mpich
-- linux-ubuntu18.04-x86_64 / gcc@7.5.0 -------------------------
autoconf@2.69 gdbm@1.18.1 libiconv@1.16 libtool@2.4.6 ncurses@6.2 patchelf@0.10 readline@8.0 zlib@1.2.11
automake@1.16.2 hdf5@1.10.7 libpciaccess@0.16 libxml2@2.9.10 numactl@2.0.14 perl@5.32.0 util-macros@1.19.1
berkeley-db@18.1.40 hwloc@1.11.11 libsigsegv@2.12 m4@1.4.18 openmpi@3.1.6 pkgconf@1.7.3 xz@5.2.5
This is great for us, as long as we remember to use Spack’s
python
command to run it.
Using the spack-python
executable¶
What if we want to make our script available for others to use without
the hassle of having to remember to use spack python
?
We can take advantage of the shebang line typically added as the first line of python executable files. But there is a catch, as we will soon see.
Open the find_exclude.py
script we created above in your preferred
editor and add the shebang line with spack python
as the arguments
to env
:
#!/usr/bin/env spack python
from spack.spec import Spec
import spack.store
import spack.cmd
import sys
include_spec = Spec(sys.argv[1])
exclude_spec = Spec(sys.argv[2])
all_included = spack.store.db.query(include_spec)
result = filter(lambda spec: not spec.satisfies(exclude_spec), all_included)
spack.cmd.display_specs(result)
Then exit our editor and add execute permissions to the script before running it as follows:
$ chmod u+x find_exclude.py
$ ./find_exclude.py %gcc ^mpich
/usr/bin/env: 'spack python': No such file or directory
If you are lucky, it worked on your system, but there is no guarantee.
Some systems only support a single argument on the shebang line (see
here).
spack-python
, which is a wrapper script for spack python
, solves
this issue.
Bring up the file in your editor again and change the env
argument
to spack-python
as follows:
#!/usr/bin/env spack-python
from spack.spec import Spec
import spack.store
import spack.cmd
import sys
include_spec = Spec(sys.argv[1])
exclude_spec = Spec(sys.argv[2])
all_included = spack.store.db.query(include_spec)
result = filter(lambda spec: not spec.satisfies(exclude_spec), all_included)
spack.cmd.display_specs(result)
Exit your editor and let’s run the script again:
$ ./find_exclude.py %gcc ^mpich
-- linux-ubuntu18.04-x86_64 / gcc@7.5.0 -------------------------
autoconf@2.69 gdbm@1.18.1 libiconv@1.16 libtool@2.4.6 ncurses@6.2 patchelf@0.10 readline@8.0 zlib@1.2.11
automake@1.16.2 hdf5@1.10.7 libpciaccess@0.16 libxml2@2.9.10 numactl@2.0.14 perl@5.32.0 util-macros@1.19.1
berkeley-db@18.1.40 hwloc@1.11.11 libsigsegv@2.12 m4@1.4.18 openmpi@3.1.6 pkgconf@1.7.3 xz@5.2.5
Congratulations! It will now work on any system with Spack installed.
You now have the basic tools to create your own custom Spack queries and prototype ideas. We hope one day you’ll contribute them back to Spack.