Tutorial setup
If you have not done the prior sections, you’ll need to start the docker image:
docker run -it ghcr.io/spack/tutorial:sc25
and then set Spack up like this:
git clone --depth=2 --branch=releases/v1.1 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack repo update builtin --tag v2025.11.0
spack tutorial -y
spack bootstrap now
spack compiler find
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 slack.spack.io
Scripting with Spack¶
This tutorial introduces advanced scripting features available in Spack, using the spack find and spack python commands.
We’ve already seen how to list and search installed packages with spack find.
The spack python command allows us to write more complex queries, as it gives access to all of Spack’s internal APIs.
Since Spack has an extensive API, we’ll only scratch the surface here.
Scripting with spack find¶
The output we’ve seen from spack find has been for human consumption.
We can take advantage of the command’s advanced features to generate machine-readable output suitable for piping to a script.
spack find --format¶
The main function of spack find is to display concrete specs that correspond to installed packages.
By default, they are shown with default attributes, like the @version suffix.
The --format argument allows us to display the specs using custom format strings.
Suppose we only want to see the name, version, and first ten (10) characters of the hash for every package installed in the Spack instance. This output can be generated with the following command:
$ spack find --format "{name} {version} {hash:10}"
adept-utils 1.0.1 bkfrcjldbo m4 1.4.20 lxvpwtivih
autoconf 2.72 nzbffupyig macsio 1.1 3uiweakny3
autoconf 2.72 fgsf5ijzhn macsio 1.1 2qq3umgema
autoconf 2.72 r3ant5t3pr mbedtls 2.28.9 bz3ghzheol
autoconf-archive 2023.02.20 7p7gq7uzoa meson 1.8.5 muzyskyvwm
automake 1.16.5 pzmnwzmdyf meson 1.8.5 c5mkho7hg3
automake 1.16.5 6ib4pvm3dv mpc 1.3.1 sczvrkuwv7
automake 1.16.5 zmzk4bb3og mpfr 4.2.1 m3nwaltjkw
bc 1.07.1 s3qhnq46lg mpich 4.3.2 amwozyio5q
berkeley-db 18.1.40 vdgigswy4f mpich 4.3.2 uaioo2homc
bison 3.8.2 n7yzkylf4g munge 0.5.15 itsnhnf3jn
boost 1.72.0 3bt6bi5q4j ncurses 6.5-20250705 ncdxq3juvb
bzip2 1.0.8 x7t4najic2 ncurses 6.5-20250705 ytk4y2kvs7
bzip2 1.0.8 zom5sydb4b netlib-lapack 3.12.1 rhz3ueke3w
ca-certificates-mozilla 2025-08-12 etqlnw5hd6 netlib-scalapack 2.2.2 pglf7pu6w2
callpath 1.0.4 p4i3pshhj3 netlib-scalapack 2.2.2 3t7cajdej6
cmake 3.31.9 dmmnd4uqwk netlib-scalapack 2.2.2 apaz22ojhz
cmake 3.31.9 4a7thjgehx netlib-scalapack 2.2.2 yxweja4r47
cmake 3.31.9 ivvor7vdsq nghttp2 1.48.0 ft5kpbdiz6
compiler-wrapper 1.0 ntccuj2fi3 ninja 1.13.0 2stmhpcux6
curl 8.15.0 jtps3jq4as numactl 2.0.18 yzbm5q6nbl
curl 8.15.0 zianoaa5jz numactl 2.0.18 t2nikrtxvu
curl 8.15.0 isdtvvdzii openblas 0.3.30 dwjd7g2k2x
diffutils 3.12 cih4xrzw7y openblas 0.3.30 qz3ay7bvee
diffutils 3.12 msusunhi5v openmpi 5.0.8 tqxbnvoiw3
dtcmp 1.1.5 2kcmd2x76s openmpi 5.0.8 p2gmhau5ko
dyninst 13.0.0 jiygq6syjs openssh 9.9p1 cxdcxo5pdx
ed 1.4 4cbvnhde46 openssh 9.9p1 lip7jtpgco
elfutils 0.193 brbwl6lkh3 openssl 3.6.0 gv7wpik32u
expat 2.7.3 7yr5v6w2xu openssl 3.6.0 oa4vrqqj43
expat 2.7.3 ikeoatlzkk openssl 3.6.0 q4fenforzt
findutils 4.10.0 irvrytslml pcre2 10.44 z5vjj7qwop
flex 2.6.3 gmhq65uhcn pdsh 2.31 eicmuq5waz
gawk 5.3.1 irhvzcha2s perl 5.42.0 62kt5y4kl7
gcc 10.5.0 ntkvysydhi perl 5.42.0 cvuukniuti
gcc 11.4.0 rpw3bukias perl 5.42.0 jpuw66splu
gcc 11.4.0 ml7cem5pfe pigz 2.8 kaz756eya6
gcc 12.3.0 fmnvqo44pc pigz 2.8 zjrnsfoh55
gcc-runtime 10.5.0 ahapkrsgqx pigz 2.8 bs2taxmcal
gcc-runtime 11.4.0 qmbrryiepg pkgconf 2.5.1 f4qiprwjcd
gcc-runtime 11.4.0 nokfxvaa4a pmix 6.0.0 yqlblh6p4u
gcc-runtime 12.3.0 pgwnyw7ukf pmix 6.0.0 76oyav4s3n
gdbm 1.25 aq7qwy6yez prrte 4.0.0 buin62mint
gdbm 1.25 y5bsvao3cx prrte 4.0.0 zalt7csrls
gettext 0.23.1 cakgj4ntln py-beniget 0.4.2.post1 g6mqwbrfiy
gettext 0.23.1 xxxc56npfd py-calver 2025.4.17 gnnyu6h5kx
gettext 0.23.1 3f5v73yqnf py-cython 3.1.3 apuchub6dg
git 2.48.1 aim32246be py-flit-core 3.12.0 55omqj2ucv
glib 2.86.1 arsxi4dynj py-gast 0.6.0 xrd6sez3xn
glib-bootstrap 2.86.1 dcark7n2gm py-hatch-vcs 0.5.0 44uhp2gd53
glibc 2.35 vjnqll7uhr py-hatchling 1.27.0 qb7x6jyrjb
glibc 2.35 qg7qyazcn2 py-meson-python 0.18.0 o6u3um7xjp
gmake 4.4.1 ufbescpw7r py-numpy 2.3.4 ucqh5kunp6
gmake 4.4.1 vsq3oi374t py-packaging 25.0 j3t7cjg7qd
gmake 4.4.1 4obn7cgqfw py-pathspec 0.12.1 wvr3fheyxt
gmp 6.3.0 mj4re3lp3b py-pip 25.1.1 hjc6yfd2ld
gobject-introspection 1.86.0 zktpj7scqi py-pip 25.1.1 qwew5rgzuu
hdf5 1.14.6 7mm6knnnjx py-pluggy 1.6.0 2c2amjcima
hdf5 1.14.6 vllfzb7aaz py-ply 3.11 xgx3hu4hlc
hdf5 1.14.6 gdk3ghc3gh py-pybind11 3.0.1 b7sx7ll7um
hwloc 2.12.2 4hos3725ny py-pyproject-metadata 0.9.1 sypchiv5ka
hwloc 2.12.2 pmdeyoykxz py-pythran 0.18.0 w4fhoiyknp
hwloc 2.12.2 wkj6z6mxka py-scikit-build-core 0.11.5 5r47zypnbt
intel-tbb 2022.3.0 rbf737wu37 py-scipy 1.16.3 igjijidvsq
json-c 0.18 5viqezvbwe py-setuptools 80.9.0 lnndrgestz
json-cwx 0.12 xb3rsbkkz6 py-setuptools 80.9.0 urwrpfosir
kokkos 4.5.01 k2pkvic65l py-setuptools-scm 8.2.1 xcq4maxl4u
kokkos-kernels 4.5.01 qknxuyj5vb py-trove-classifiers 2025.9.11.17 cwn5qw7ibd
krb5 1.21.3 hnmy4fwwly py-wheel 0.45.1 hpfn7k7fkr
krb5 1.21.3 onmo4bvd2j py-wheel 0.45.1 vs4xbx3m62
libbsd 0.12.2 ucrhsywwal python 3.11.14 rbf2x4id5w
libbsd 0.12.2 zb37a5t5np python 3.14.0 pazbuxsobo
libdwarf 2.1.0 l4t7fu7gmh python 3.14.0 yvs3szqzvv
libedit 3.1-20240808 hdzcfgipuk python-venv 1.0 essoyki3al
libedit 3.1-20240808 c5o6gvvaov python-venv 1.0 nrdm37joni
libevent 2.1.12 lprginh6np re2c 3.1 axmwicsvae
libevent 2.1.12 fn26hildna readline 8.3 c6d2zljdkl
libfabric 2.3.1 n2l4ckstgt readline 8.3 eyfbskp7ur
libfabric 2.3.1 7imejdfjny scr 2.0.0 xuzclql7mx
libffi 3.5.2 zgro4twqg3 scr 2.0.0 f57s4noxfk
libffi 3.5.2 s56v4gfjyu silo 4.11.1 vsguusygbz
libgcrypt 1.11.2 4j7zjzsf5h slurm 25-05-1-1 tc55ttmeph
libgpg-error 1.55 jerwahojdg sqlite 3.50.4 elvodybm3e
libiberty 2.41 wz2npe3qsm sqlite 3.50.4 a4zeurpolt
libiconv 1.18 qtepnkrdvq sqlite 3.50.4 plzt2ndvbq
libiconv 1.18 g3zxoz6huo tar 1.35 lfgvgvawnp
libidn2 2.3.7 gntupl34gn tar 1.35 e3ajmyqkyi
libmd 1.1.0 gth3ii5boe tar 1.35 wfarfthvpw
libmd 1.1.0 cq4lpjpcxc tcl 8.6.17 x74vmgrwo7
libpciaccess 0.17 txbwcin227 tcl 8.6.17 tsq4fjjw2p
libpciaccess 0.17 p7g23cjqjl texinfo 7.2 k6ygirswvb
libsigsegv 2.14 bs5ujst3rr trilinos 16.1.0 tj433utqwn
libssh2 1.11.1 txa2olxuox trilinos 16.1.0 k3ozjlurkc
libtool 2.4.7 yt7ajy4c3z unzip 6.0 5gxay2amcy
libunistring 1.2 x5b7oeto7b util-linux-uuid 2.41 n45otd3wy4
libxcrypt 4.4.38 yiij42powr util-linux-uuid 2.41 b4npzn6ixc
libxcrypt 4.4.38 drjmmlw4cw util-macros 1.20.1 hwxnwvmn44
libxml2 2.13.5 5trxrsws5d xz 5.6.3 yzaocbs7ge
libxml2 2.13.5 lguldtjks3 xz 5.6.3 643vviqh75
libxml2 2.13.5 idam6zhjw4 yaksa 0.4 zuutzfx4db
libyogrt 1.35 ylblit5vwt yaksa 0.4 7jn3vivsnj
llvm 14.0.0 qr2e4rdcbj zlib-ng 2.0.7 qlavhjbsgq
lmod 8.7.18 gbpxgjwwyp zlib-ng 2.2.4 zk6keshnph
lua 5.4.6 hdxlqejf6f zlib-ng 2.2.4 4tglvhvqq7
lua-luafilesystem 1.8.0 nsymk62hqa zlib-ng 2.2.4 ct2r7xmldp
lua-luaposix 36.1 bubs6lunhi zstd 1.5.7 foiizhdg2m
lwgrp 1.0.6 bms4pwx7wh zstd 1.5.7 fj5u5hmzff
lz4 1.10.0 7m7ijnovaf
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 the format string.
spack find --format can be combined with typical command line tools like sort or uniq to retrieve information relevant to specific workflows.
spack find --json¶
Alternatively, we can get a serialized version of Spec objects in the JSON format using the --json option.
For example, to get attributes for all installations of zlib-ng:
$ spack find --json zlib-ng
This command provides complete information about any spec of interest in a structured format.
The output of spack find --json can be piped to JSON filtering tools like jq to extract specific information.
Visit 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 an interpreter with Spack’s Python modules available to import.
The underlying Python instance is used for all other commands.
We can write scripts to:
run Spack commands
explore abstract and concretized specs
directly access other internal components of Spack
Let’s launch a Spack-aware Python interpreter by entering:
$ spack python
exit()
Spack version 1.1.0
Python 3.11.11, Linux x86_64
>>> exit()
As we are in a Python interpreter, use exit() to end the session and return to the terminal.
Accessing the Spec object¶
Let’s take a look at the internal representation of the Spack Spec.
As previously mentioned, specs can be either abstract or concrete.
The specs we’ve seen in package.py files (e.g., in the install() method) have been concrete, or fully specified.
Specs 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
>>> zlib = Spec('zlib target=x86_64_v3')
>>> zlib.concrete
False
>>> zlib.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=None-None-x86_64_v3
>>> zlib.versions
[:]
>>> str(zlib.architecture)
None-None-x86_64_v3
Notice that there are Spec properties and methods not accessible to abstract specs; specifically:
an exception –
SpecError– is raised if we try to access itsversionthere are no associated
versionsthe spec’s operating system is
None
Without exiting the interpreter, let’s concretize the spec and try again:
>>> from spack.concretize import concretize_one
>>> zlib_concrete = spack.concretize.concretize_one(zlib)
>>> zlib_concrete.concrete
True
>>> zlib_concrete.version
Version('1.3.1')
>>> zlib_concrete.versions
[Version('1.3.1')]
>>> str(zlib_concrete.architecture)
linux-ubuntu22.04-x86_64_v3
Notice that the concretized spec now:
has a
versionhas a single entry in its
versionslistthe operating system is now
ubuntu22.04
Querying the Spack database¶
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.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.STORE.db.query)
Help on method query in module spack.database:
query(query_spec: Union[str, ForwardRef('spack.spec.Spec'), NoneType] = None, *, predicate_fn: Optional[Callable[[spack.database.InstallRecord], bool]] = None, installed: Union[bool, spack.enums.InstallRecordStatus] = True, explicit: Optional[bool] = None, start_date: Optional[datetime.datetime] = None, end_date: Optional[datetime.datetime] = None, in_buildcache: Optional[bool] = None, hashes: Optional[List[str]] = None, origin: Optional[str] = None, install_tree: str = 'all') -> List[ForwardRef('spack.spec.Spec')] method of spack.database.Database instance
Queries the Spack database including all upstream databases.
Args:
query_spec: if query_spec is ``None``, match all specs in the database.
If it is a spec, return all specs matching ``spec.satisfies(query_spec)``.
predicate_fn: optional predicate taking an InstallRecord as argument, and returning
whether that record is selected for the query. It can be used to craft criteria
that need some data for selection not provided by the Database itself.
installed: 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 matches at least
one of the InstallStatus.
explicit: 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: if set considers only specs installed from the starting date.
end_date: if set considers only specs installed until the ending date.
in_buildcache: specs that are marked in this database as part of an associated binary
cache are ``in_buildcache``. All other specs are not. This field is used for
querying mirror indices. By default, it does not check this status.
hashes: list of hashes used to restrict the search
install_tree: query 'all' (default), 'local', 'upstream', or upstream path
origin: origin of the spec
(END)
We’ll primarily make use of the query_spec argument.
Recall that spack find is limited to queries of attributes with matching values.
It cannot be used to find packages that do not meet a specific condition.
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.STORE.db.query(gcc_query_spec)
>>> result = [spec for spec in gcc_specs if not spec.satisfies('^mpich')]
>>> import spack.cmd
>>> spack.cmd.display_specs(result)
-- linux-ubuntu22.04-x86_64_v3 / gcc@11.4.0 -------------------------
autoconf@2.72 gdbm@1.23 libsigsegv@2.14 perl@5.38.0
automake@1.16.5 gettext@0.22.5 libtool@2.4.7 pigz@2.8
berkeley-db@18.1.40 glibc@2.35 libxcrypt@4.4.35 pkgconf@2.2.0
bison@3.8.2 gmake@4.4.1 libxml2@2.10.3 pmix@5.0.1
bzip2@1.0.8 hdf5@1.14.3 m4@1.4.19 readline@8.2
ca-certificates-mozilla@2023-05-30 hwloc@2.9.1 ncurses@6.5 tar@1.34
cmake@3.27.9 krb5@1.20.1 nghttp2@1.57.0 util-macros@1.19.3
curl@8.7.1 libedit@3.1-20230828 numactl@2.0.14 xz@5.4.6
diffutils@3.10 libevent@2.1.12 openmpi@5.0.3 zlib-ng@2.1.6
findutils@4.9.0 libiconv@1.17 openssh@9.7p1 zstd@1.5.6
gcc-runtime@11.4.0 libpciaccess@0.17 openssl@3.3.0
Now we have a powerful query not available through spack find.
Exit the interpreter to return to the command line:
>>> exit()
before generalizing the functionality for reuse.
Using scripts¶
Next, the script can be updated to accept arguments from the command line. By generalizing the script to take include and exclude specs as arguments, it becomes a flexible, general-purpose query tool.
Open a file called find_exclude.py in a text 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.STORE.db.query(include_spec)
result = [spec for spec in all_included if not spec.satisfies(exclude_spec)]
spack.cmd.display_specs(result)
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-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@11.4.0 ------
mpich@4.3.2 openmpi@5.0.8 scr@2.0.0 trilinos@16.1.0
openblas@0.3.30 scr@2.0.0 silo@4.11.1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@12.3.0 ------
mpich@4.3.2 openblas@0.3.30 openmpi@5.0.8 py-scikit-build-core@0.11.5 py-scipy@1.16.3
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@11.4.0 --------------
adept-utils@1.0.1 expat@2.7.3 libdwarf@2.1.0 openssl@3.6.0
berkeley-db@18.1.40 flex@2.6.3 libffi@3.5.2 openssl@3.6.0
bison@3.8.2 gcc@12.3.0 libiberty@2.41 python@3.11.14
boost@1.72.0 gettext@0.23.1 lua@5.4.6 python@3.14.0
callpath@1.0.4 gettext@0.23.1 lz4@1.10.0 re2c@3.1
cmake@3.31.9 glib@2.86.1 m4@1.4.20 tcl@8.6.17
cmake@3.31.9 glib-bootstrap@2.86.1 macsio@1.1 tcl@8.6.17
curl@8.15.0 gmp@6.3.0 macsio@1.1 texinfo@7.2
curl@8.15.0 hwloc@2.12.2 ncurses@6.5-20250705 zlib-ng@2.0.7
dyninst@13.0.0 hwloc@2.12.2 nghttp2@1.48.0 zlib-ng@2.2.4
ed@1.4 intel-tbb@2022.3.0 ninja@1.13.0 zstd@1.5.7
elfutils@0.193 krb5@1.21.3 openssh@9.9p1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@12.3.0 --------------
cmake@3.31.9 gettext@0.23.1 libffi@3.5.2 openssl@3.6.0 python@3.14.0
curl@8.15.0 hwloc@2.12.2 ncurses@6.5-20250705 py-cython@3.1.3 zlib-ng@2.2.4
expat@2.7.3 krb5@1.21.3 openssh@9.9p1 py-numpy@2.3.4 zstd@1.5.7
-- linux-ubuntu22.04-x86_64_v3 / %c,fortran=gcc@11.4.0 ----------
libyogrt@1.35
-- linux-ubuntu22.04-x86_64_v3 / %c,fortran=gcc@12.3.0 ----------
netlib-lapack@3.12.1 netlib-scalapack@2.2.2 netlib-scalapack@2.2.2
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@10.5.0 ------------------
gmake@4.4.1
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@11.4.0 ------------------
automake@1.16.5 libgcrypt@1.11.2 pcre2@10.44
automake@1.16.5 libgpg-error@1.55 pdsh@2.31
bc@1.07.1 libiconv@1.18 perl@5.42.0
bzip2@1.0.8 libmd@1.1.0 perl@5.42.0
diffutils@3.12 libpciaccess@0.17 pigz@2.8
dtcmp@1.1.5 libsigsegv@2.14 pigz@2.8
findutils@4.10.0 libssh2@1.11.1 pkgconf@2.5.1
gawk@5.3.1 libtool@2.4.7 pmix@6.0.0
gdbm@1.25 libxcrypt@4.4.38 prrte@4.0.0
gmake@4.4.1 libxml2@2.13.5 readline@8.3
gmake@4.4.1 libxml2@2.13.5 slurm@25-05-1-1
gobject-introspection@1.86.0 lmod@8.7.18 sqlite@3.50.4
hdf5@1.14.6 lua-luafilesystem@1.8.0 sqlite@3.50.4
hdf5@1.14.6 lua-luaposix@36.1 tar@1.35
json-c@0.18 lwgrp@1.0.6 tar@1.35
json-cwx@0.12 mbedtls@2.28.9 unzip@6.0
libbsd@0.12.2 mpc@1.3.1 util-linux-uuid@2.41
libedit@3.1-20240808 mpfr@4.2.1 xz@5.6.3
libevent@2.1.12 munge@0.5.15 yaksa@0.4
libfabric@2.3.1 numactl@2.0.18
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@12.3.0 ------------------
automake@1.16.5 libevent@2.1.12 libxcrypt@4.4.38 py-meson-python@0.18.0
bzip2@1.0.8 libfabric@2.3.1 libxml2@2.13.5 readline@8.3
diffutils@3.12 libiconv@1.18 numactl@2.0.18 sqlite@3.50.4
gdbm@1.25 libidn2@2.3.7 perl@5.42.0 tar@1.35
git@2.48.1 libmd@1.1.0 pigz@2.8 util-linux-uuid@2.41
libbsd@0.12.2 libpciaccess@0.17 pmix@6.0.0 xz@5.6.3
libedit@3.1-20240808 libunistring@1.2 prrte@4.0.0 yaksa@0.4
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@11.4.0 ----------------
kokkos@4.5.01 kokkos-kernels@4.5.01
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@12.3.0 ----------------
py-pybind11@3.0.1 py-pythran@0.18.0
-- linux-ubuntu22.04-x86_64_v3 / no compilers -------------------
gcc-runtime@10.5.0 gcc-runtime@11.4.0 gcc-runtime@11.4.0 gcc-runtime@12.3.0
This works well, as long as we remember to use Spack’s python command to run it.
Using the spack-python executable¶
What if the script needs to be shared with others, without requiring them to remember to use spack python?
This can be done by adding a shebang line as the first line of the Python script, which allows it to be run as an executable. However, there is an important limitation to be aware of, as shown in the next example.
Open the find_exclude.py script we created above 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.STORE.db.query(include_spec)
result = [spec for spec in all_included if not spec.satisfies(exclude_spec)]
spack.cmd.display_specs(result)
Exit the 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’: Permission denied
If we’re lucky, it ran successfully, but there’s no guarantee this will work for every system.
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 the 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.STORE.db.query(include_spec)
result = [spec for spec in all_included if not spec.satisfies(exclude_spec)]
spack.cmd.display_specs(result)
Exit the editor and run the script again:
$ ./find_exclude.py %gcc ^mpich
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@11.4.0 ------
mpich@4.3.2 openmpi@5.0.8 scr@2.0.0 trilinos@16.1.0
openblas@0.3.30 scr@2.0.0 silo@4.11.1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@12.3.0 ------
mpich@4.3.2 openblas@0.3.30 openmpi@5.0.8 py-scikit-build-core@0.11.5 py-scipy@1.16.3
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@11.4.0 --------------
adept-utils@1.0.1 expat@2.7.3 libdwarf@2.1.0 openssl@3.6.0
berkeley-db@18.1.40 flex@2.6.3 libffi@3.5.2 openssl@3.6.0
bison@3.8.2 gcc@12.3.0 libiberty@2.41 python@3.11.14
boost@1.72.0 gettext@0.23.1 lua@5.4.6 python@3.14.0
callpath@1.0.4 gettext@0.23.1 lz4@1.10.0 re2c@3.1
cmake@3.31.9 glib@2.86.1 m4@1.4.20 tcl@8.6.17
cmake@3.31.9 glib-bootstrap@2.86.1 macsio@1.1 tcl@8.6.17
curl@8.15.0 gmp@6.3.0 macsio@1.1 texinfo@7.2
curl@8.15.0 hwloc@2.12.2 ncurses@6.5-20250705 zlib-ng@2.0.7
dyninst@13.0.0 hwloc@2.12.2 nghttp2@1.48.0 zlib-ng@2.2.4
ed@1.4 intel-tbb@2022.3.0 ninja@1.13.0 zstd@1.5.7
elfutils@0.193 krb5@1.21.3 openssh@9.9p1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@12.3.0 --------------
cmake@3.31.9 gettext@0.23.1 libffi@3.5.2 openssl@3.6.0 python@3.14.0
curl@8.15.0 hwloc@2.12.2 ncurses@6.5-20250705 py-cython@3.1.3 zlib-ng@2.2.4
expat@2.7.3 krb5@1.21.3 openssh@9.9p1 py-numpy@2.3.4 zstd@1.5.7
-- linux-ubuntu22.04-x86_64_v3 / %c,fortran=gcc@11.4.0 ----------
libyogrt@1.35
-- linux-ubuntu22.04-x86_64_v3 / %c,fortran=gcc@12.3.0 ----------
netlib-lapack@3.12.1 netlib-scalapack@2.2.2 netlib-scalapack@2.2.2
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@10.5.0 ------------------
gmake@4.4.1
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@11.4.0 ------------------
automake@1.16.5 libgcrypt@1.11.2 pcre2@10.44
automake@1.16.5 libgpg-error@1.55 pdsh@2.31
bc@1.07.1 libiconv@1.18 perl@5.42.0
bzip2@1.0.8 libmd@1.1.0 perl@5.42.0
diffutils@3.12 libpciaccess@0.17 pigz@2.8
dtcmp@1.1.5 libsigsegv@2.14 pigz@2.8
findutils@4.10.0 libssh2@1.11.1 pkgconf@2.5.1
gawk@5.3.1 libtool@2.4.7 pmix@6.0.0
gdbm@1.25 libxcrypt@4.4.38 prrte@4.0.0
gmake@4.4.1 libxml2@2.13.5 readline@8.3
gmake@4.4.1 libxml2@2.13.5 slurm@25-05-1-1
gobject-introspection@1.86.0 lmod@8.7.18 sqlite@3.50.4
hdf5@1.14.6 lua-luafilesystem@1.8.0 sqlite@3.50.4
hdf5@1.14.6 lua-luaposix@36.1 tar@1.35
json-c@0.18 lwgrp@1.0.6 tar@1.35
json-cwx@0.12 mbedtls@2.28.9 unzip@6.0
libbsd@0.12.2 mpc@1.3.1 util-linux-uuid@2.41
libedit@3.1-20240808 mpfr@4.2.1 xz@5.6.3
libevent@2.1.12 munge@0.5.15 yaksa@0.4
libfabric@2.3.1 numactl@2.0.18
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@12.3.0 ------------------
automake@1.16.5 libevent@2.1.12 libxcrypt@4.4.38 py-meson-python@0.18.0
bzip2@1.0.8 libfabric@2.3.1 libxml2@2.13.5 readline@8.3
diffutils@3.12 libiconv@1.18 numactl@2.0.18 sqlite@3.50.4
gdbm@1.25 libidn2@2.3.7 perl@5.42.0 tar@1.35
git@2.48.1 libmd@1.1.0 pigz@2.8 util-linux-uuid@2.41
libbsd@0.12.2 libpciaccess@0.17 pmix@6.0.0 xz@5.6.3
libedit@3.1-20240808 libunistring@1.2 prrte@4.0.0 yaksa@0.4
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@11.4.0 ----------------
kokkos@4.5.01 kokkos-kernels@4.5.01
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@12.3.0 ----------------
py-pybind11@3.0.1 py-pythran@0.18.0
-- linux-ubuntu22.04-x86_64_v3 / no compilers -------------------
gcc-runtime@10.5.0 gcc-runtime@11.4.0 gcc-runtime@11.4.0 gcc-runtime@12.3.0
It will now work on any system with Spack installed.
With these tools, we can create custom Spack queries and prototype new ideas. Contributions that improve or extend common Spack workflows are always welcome in the community.