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:hpcic25
and then set Spack up like this:
git clone --depth=2 --branch=releases/v1.0 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack repo update builtin --tag v2025.07.0
spack mirror add --unsigned tutorial /mirror
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
Warning
The spack tutorial -y command is intended for use in a container or VM.
Use with care in other environments since it replaces some configuration files in order to establish suitable settings for the tutorial.
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 yjgv7u3uwf m4 1.4.20 ypq2dyeslm
autoconf 2.72 5xgjgaemj5 m4 1.4.20 rpphs4iqga
autoconf 2.72 krgi7jfdrs macsio 1.1 jubkwpoou3
autoconf-archive 2023.02.20 u24n5okomp macsio 1.1 w4772cduse
automake 1.16.5 vorbe53mrr meson 1.7.0 hcseihgy2i
automake 1.16.5 jgeyxwqrov meson 1.7.0 tqc2ju3muw
axl 0.9.0 maau75ypfw mpc 1.3.1 mkqx7budcw
bc 1.07.1 vbae3vxecf mpfr 4.2.1 abjn4yec4c
berkeley-db 18.1.40 k5bepowzfo mpich 4.3.0 l2h74uyzoj
berkeley-db 18.1.40 ikx4n4c7ko mpich 4.3.0 3bsqfeynbf
bison 3.8.2 ecemgn6zeg munge 0.5.15 uwm6hk76ja
bison 3.8.2 acgafisyw7 ncurses 6.5 u7sn2jtlva
boost 1.72.0 x4ntqhhem4 ncurses 6.5 56rxnkfzlb
bzip2 1.0.8 vy2ggzhuzo netlib-lapack 3.12.1 xx23tbfq7n
bzip2 1.0.8 3kql5yq6uc netlib-scalapack 2.2.2 igwbxq4vt5
ca-certificates-mozilla 2025-05-20 s3bxsw4irc netlib-scalapack 2.2.2 tl5f6ke6ov
callpath 1.0.4 yokxcwu2j5 netlib-scalapack 2.2.2 hk7ftpc2qc
cmake 3.31.8 usc3vzrzie netlib-scalapack 2.2.2 nimjflq6w6
cmake 3.31.8 yxjigtdrlw nghttp2 1.65.0 hpkxq4qzia
compiler-wrapper 1.0 rwnqblirwn nghttp2 1.65.0 2v5o3rauqq
curl 8.11.1 7xf5wleip2 ninja 1.12.1 binn5bdm4u
curl 8.11.1 etcxzzkvyw ninja 1.12.1 pn35lwakeu
diffutils 3.10 pptkbjbkik numactl 2.0.18 74aq3kxwhm
diffutils 3.10 6lfrh36pe3 numactl 2.0.18 naapp6hxkq
dtcmp 1.1.5 pqglwfz6zw openblas 0.3.29 77haeboy74
dyninst 13.0.0 np3n5uf2ba openblas 0.3.29 z3ynokzpyv
ed 1.4 iktf6j2v5y openmpi 5.0.8 ezkzlw5tyu
elfutils 0.192 bqadq4z3np openmpi 5.0.8 qdunbuirtg
er 0.5.0 vmunrpqq4a openssh 9.9p1 2s7eddoqit
expat 2.7.1 ut2qx6nkwc openssh 9.9p1 sgecnstwdq
expat 2.7.1 lfwqiuwkit openssl 3.4.1 kphogwy3wl
findutils 4.10.0 ga3qiejil4 openssl 3.4.1 osxtmvl4zg
findutils 4.10.0 vhsfohm5zw pcre2 10.44 ayrshy3nkp
gawk 5.3.1 jxq6uva54u pdsh 2.31 b2w7bpkhnb
gcc 10.5.0 7w652unbwy perl 5.40.0 nsqyer7nqs
gcc 11.4.0 j7ykyvm5an perl 5.40.0 txcbw3fccp
gcc 12.5.0 fmxnit5ggu pigz 2.8 prsofdph5z
gcc-runtime 10.5.0 ekeebbiepo pigz 2.8 zia4xj2idu
gcc-runtime 11.4.0 3c5xh7dqud pkgconf 2.3.0 xoghzadcbb
gcc-runtime 12.5.0 zubbt4yxn3 pkgconf 2.3.0 qz3jy42ylz
gdbm 1.23 5yo63cnvgy pmix 5.0.5 msnkjumpg7
gdbm 1.23 cxbuzxk4lq pmix 5.0.5 wqd5fdu5gl
gettext 0.23.1 soasbhmurz py-beniget 0.4.1 yjbwas7zwz
gettext 0.23.1 goyejxw4nh py-cython 3.0.12 33ypsy5oip
glib 2.82.5 wpegaowgsf py-flit-core 3.12.0 bw467tx7wa
glibc 2.35 epwvtixhox py-gast 0.5.4 xwt2et7ii2
gmake 4.4.1 haeogmcedf py-meson-python 0.16.0 bi3kygbxso
gmake 4.4.1 5vb6e4beeo py-numpy 2.3.1 7cmuxbwfgn
gmake 4.4.1 xvxobm5cq3 py-packaging 25.0 4edf37ky2o
gmake 4.4.1 4gp5ttded7 py-pip 25.1.1 tsrheapc75
gmp 6.3.0 zx3x4nm3dj py-pip 25.1.1 nne5hgsvom
hdf5 1.14.6 53lfqwufrt py-ply 3.11 cg53hr3fds
hdf5 1.14.6 rewh52tlww py-pybind11 2.13.6 lgys3shnnr
hdf5 1.14.6 p3ly6asjcv py-pyproject-metadata 0.9.1 vlo72hfjof
hwloc 2.11.1 jhcvb6nk7g py-pythran 0.16.1 y2j3wh4mr4
hwloc 2.11.1 3e4kpzphqr py-scipy 1.16.0 qbiffx7j4v
intel-tbb 2022.0.0 3g2dqp5itv py-setuptools 80.9.0 73p4zkrqbb
json-c 0.18 tiufmaxqw6 py-setuptools 80.9.0 hjettfg7x2
json-cwx 0.12 5roxsj7npl py-wheel 0.45.1 daflthkr3y
kokkos 4.5.01 53vnflrbks py-wheel 0.45.1 wjtuyuom3i
kokkos-kernels 4.5.01 wudwbac7p6 python 3.13.5 dcljl7pmhi
krb5 1.21.3 zo73rgnlq3 python 3.13.5 musqpuq2h6
krb5 1.21.3 nm4trzqdaw python-venv 1.0 hzcm35kueh
kvtree 1.5.0 hztyggwuil python-venv 1.0 xmpetx7fsz
libbsd 0.12.2 bcrniixykr rankstr 0.4.0 khn5kuon4e
libbsd 0.12.2 es3e2le2oe re2c 3.1 zpoiduqoui
libdwarf 2.0.0 uirapsmqr5 re2c 3.1 cjnodvgptr
libedit 3.1-20240808 h766azt27z readline 8.2 skysn5ppma
libedit 3.1-20240808 wspzmodxgc readline 8.2 lxvqq5ood4
libevent 2.1.12 dvz3n3eojb redset 0.4.0 sn64td3ppz
libevent 2.1.12 alldwq4ypk scr 2.0.0 qdg5iykctd
libfabric 2.2.0 lublgehlip scr 3.1.0 jsy37gt736
libfabric 2.2.0 atjn3er45p shuffile 0.4.0 mo3jxy62lc
libffi 3.4.8 4466i2xl4j silo 4.11.1 axjmrnblx3
libffi 3.4.8 ddom6iure3 slurm 23-11-1-1 ycmepbpfi4
libgcrypt 1.11.1 ln55ajiiws spath 0.4.0 kmq4tumwh2
libgpg-error 1.55 xxu2l5erii sqlite 3.46.0 zjvsjg7we5
libiberty 2.41 cvva4qyqow sqlite 3.46.0 brglstmfyn
libiconv 1.18 kgw5nkswdp tar 1.35 ye5hcpfjk5
libiconv 1.18 m2sseeiara tar 1.35 4do6jx74ch
libmd 1.1.0 7x6ozmzda7 tcl 8.6.12 gbhibagbyj
libmd 1.1.0 bqguhkf6f3 tcl 8.6.12 6wkjgx5kzi
libpciaccess 0.17 w5iqeddpn6 texinfo 7.1 z47kihjvhl
libpciaccess 0.17 j336pb5rrn trilinos 16.1.0 5agd4kt5c4
libsigsegv 2.14 vefpsalwx4 trilinos 16.1.0 s2kwzuhecz
libsigsegv 2.14 ffctxurczj unzip 6.0 hvxekp5s26
libtool 2.4.7 l2jtwyuivf util-linux-uuid 2.41 o26ozsqsvc
libtool 2.4.7 7z4rzcr3e7 util-linux-uuid 2.41 v2nef6xnzn
libxcrypt 4.4.38 iundcaqxew util-macros 1.20.1 itmqxdmqzx
libxcrypt 4.4.38 qhnn6wrmss util-macros 1.20.1 kbleacprn5
libxml2 2.13.5 7mdlpguain xz 5.6.3 zeynpnjapl
libxml2 2.13.5 f2wxschdrk xz 5.6.3 3kvqodyyfe
libyogrt 1.35 7igkceogx7 yaksa 0.3 at3giizyfe
llvm 14.0.0 oc4qy2fa3e yaksa 0.3 5r6tuoocxu
lmod 8.7.18 gegst44iqq zlib-ng 2.0.7 yq5p6pli22
lua 5.4.6 cvp4vnchqf zlib-ng 2.2.4 g7ixtqygrf
lua-luafilesystem 1.8.0 clpxqjmecg zlib-ng 2.2.4 6xddq3ypcy
lua-luaposix 36.1 xtcb4fb255 zlib-ng 2.2.4 rdf7ff3uwe
lwgrp 1.0.6 aueg5csxqj zstd 1.5.7 bmaw6fn2i5
lz4 1.10.0 6ekevdfw2g zstd 1.5.7 2jhx5guzif
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.0.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.0 openblas@0.3.29 openmpi@5.0.8 scr@2.0.0 silo@4.11.1 trilinos@16.1.0
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@12.5.0 ------
mpich@4.3.0 openblas@0.3.29 openmpi@5.0.8 py-scipy@1.16.0 scr@3.1.0
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@11.4.0 --------------
adept-utils@1.0.1 elfutils@0.192 kokkos@4.5.01 macsio@1.1 tcl@8.6.12
berkeley-db@18.1.40 expat@2.7.1 krb5@1.21.3 ncurses@6.5 tcl@8.6.12
bison@3.8.2 gcc@12.5.0 libdwarf@2.0.0 nghttp2@1.65.0 texinfo@7.1
boost@1.72.0 gettext@0.23.1 libffi@3.4.8 ninja@1.12.1 unzip@6.0
callpath@1.0.4 glib@2.82.5 libiberty@2.41 openssh@9.9p1 zlib-ng@2.0.7
cmake@3.31.8 gmp@6.3.0 lua@5.4.6 openssl@3.4.1 zlib-ng@2.2.4
curl@8.11.1 hwloc@2.11.1 lz4@1.10.0 python@3.13.5 zstd@1.5.7
dyninst@13.0.0 intel-tbb@2022.0.0 m4@1.4.20 re2c@3.1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@12.5.0 --------------
axl@0.9.0 expat@2.7.1 m4@1.4.20 openssl@3.4.1 redset@0.4.0
berkeley-db@18.1.40 gettext@0.23.1 macsio@1.1 py-cython@3.0.12 shuffile@0.4.0
bison@3.8.2 hwloc@2.11.1 ncurses@6.5 py-numpy@2.3.1 spath@0.4.0
cmake@3.31.8 krb5@1.21.3 nghttp2@1.65.0 python@3.13.5 zlib-ng@2.2.4
curl@8.11.1 kvtree@1.5.0 ninja@1.12.1 rankstr@0.4.0 zstd@1.5.7
er@0.5.0 libffi@3.4.8 openssh@9.9p1 re2c@3.1
-- 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.5.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 json-c@0.18 libtool@2.4.7 pdsh@2.31
bc@1.07.1 json-cwx@0.12 libxcrypt@4.4.38 perl@5.40.0
bzip2@1.0.8 libbsd@0.12.2 libxml2@2.13.5 pigz@2.8
diffutils@3.10 libedit@3.1-20240808 lmod@8.7.18 pkgconf@2.3.0
dtcmp@1.1.5 libevent@2.1.12 lua-luafilesystem@1.8.0 pmix@5.0.5
ed@1.4 libfabric@2.2.0 lua-luaposix@36.1 readline@8.2
findutils@4.10.0 libgcrypt@1.11.1 lwgrp@1.0.6 slurm@23-11-1-1
gawk@5.3.1 libgpg-error@1.55 mpc@1.3.1 sqlite@3.46.0
gdbm@1.23 libiconv@1.18 mpfr@4.2.1 tar@1.35
gmake@4.4.1 libmd@1.1.0 munge@0.5.15 util-linux-uuid@2.41
hdf5@1.14.6 libpciaccess@0.17 numactl@2.0.18 xz@5.6.3
hdf5@1.14.6 libsigsegv@2.14 pcre2@10.44 yaksa@0.3
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@12.5.0 ------------------
automake@1.16.5 libevent@2.1.12 libxml2@2.13.5 sqlite@3.46.0
bzip2@1.0.8 libfabric@2.2.0 numactl@2.0.18 tar@1.35
diffutils@3.10 libiconv@1.18 perl@5.40.0 util-linux-uuid@2.41
findutils@4.10.0 libmd@1.1.0 pigz@2.8 xz@5.6.3
gdbm@1.23 libpciaccess@0.17 pkgconf@2.3.0 yaksa@0.3
gmake@4.4.1 libsigsegv@2.14 pmix@5.0.5
libbsd@0.12.2 libtool@2.4.7 py-meson-python@0.16.0
libedit@3.1-20240808 libxcrypt@4.4.38 readline@8.2
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@11.4.0 ----------------
kokkos-kernels@4.5.01
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@12.5.0 ----------------
py-pybind11@2.13.6 py-pythran@0.16.1
-- linux-ubuntu22.04-x86_64_v3 / no compilers -------------------
gcc-runtime@10.5.0 gcc-runtime@11.4.0 gcc-runtime@12.5.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.0 openblas@0.3.29 openmpi@5.0.8 scr@2.0.0 silo@4.11.1 trilinos@16.1.0
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx,fortran=gcc@12.5.0 ------
mpich@4.3.0 openblas@0.3.29 openmpi@5.0.8 py-scipy@1.16.0 scr@3.1.0
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@11.4.0 --------------
adept-utils@1.0.1 elfutils@0.192 kokkos@4.5.01 macsio@1.1 tcl@8.6.12
berkeley-db@18.1.40 expat@2.7.1 krb5@1.21.3 ncurses@6.5 tcl@8.6.12
bison@3.8.2 gcc@12.5.0 libdwarf@2.0.0 nghttp2@1.65.0 texinfo@7.1
boost@1.72.0 gettext@0.23.1 libffi@3.4.8 ninja@1.12.1 unzip@6.0
callpath@1.0.4 glib@2.82.5 libiberty@2.41 openssh@9.9p1 zlib-ng@2.0.7
cmake@3.31.8 gmp@6.3.0 lua@5.4.6 openssl@3.4.1 zlib-ng@2.2.4
curl@8.11.1 hwloc@2.11.1 lz4@1.10.0 python@3.13.5 zstd@1.5.7
dyninst@13.0.0 intel-tbb@2022.0.0 m4@1.4.20 re2c@3.1
-- linux-ubuntu22.04-x86_64_v3 / %c,cxx=gcc@12.5.0 --------------
axl@0.9.0 expat@2.7.1 m4@1.4.20 openssl@3.4.1 redset@0.4.0
berkeley-db@18.1.40 gettext@0.23.1 macsio@1.1 py-cython@3.0.12 shuffile@0.4.0
bison@3.8.2 hwloc@2.11.1 ncurses@6.5 py-numpy@2.3.1 spath@0.4.0
cmake@3.31.8 krb5@1.21.3 nghttp2@1.65.0 python@3.13.5 zlib-ng@2.2.4
curl@8.11.1 kvtree@1.5.0 ninja@1.12.1 rankstr@0.4.0 zstd@1.5.7
er@0.5.0 libffi@3.4.8 openssh@9.9p1 re2c@3.1
-- 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.5.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 json-c@0.18 libtool@2.4.7 pdsh@2.31
bc@1.07.1 json-cwx@0.12 libxcrypt@4.4.38 perl@5.40.0
bzip2@1.0.8 libbsd@0.12.2 libxml2@2.13.5 pigz@2.8
diffutils@3.10 libedit@3.1-20240808 lmod@8.7.18 pkgconf@2.3.0
dtcmp@1.1.5 libevent@2.1.12 lua-luafilesystem@1.8.0 pmix@5.0.5
ed@1.4 libfabric@2.2.0 lua-luaposix@36.1 readline@8.2
findutils@4.10.0 libgcrypt@1.11.1 lwgrp@1.0.6 slurm@23-11-1-1
gawk@5.3.1 libgpg-error@1.55 mpc@1.3.1 sqlite@3.46.0
gdbm@1.23 libiconv@1.18 mpfr@4.2.1 tar@1.35
gmake@4.4.1 libmd@1.1.0 munge@0.5.15 util-linux-uuid@2.41
hdf5@1.14.6 libpciaccess@0.17 numactl@2.0.18 xz@5.6.3
hdf5@1.14.6 libsigsegv@2.14 pcre2@10.44 yaksa@0.3
-- linux-ubuntu22.04-x86_64_v3 / %c=gcc@12.5.0 ------------------
automake@1.16.5 libevent@2.1.12 libxml2@2.13.5 sqlite@3.46.0
bzip2@1.0.8 libfabric@2.2.0 numactl@2.0.18 tar@1.35
diffutils@3.10 libiconv@1.18 perl@5.40.0 util-linux-uuid@2.41
findutils@4.10.0 libmd@1.1.0 pigz@2.8 xz@5.6.3
gdbm@1.23 libpciaccess@0.17 pkgconf@2.3.0 yaksa@0.3
gmake@4.4.1 libsigsegv@2.14 pmix@5.0.5
libbsd@0.12.2 libtool@2.4.7 py-meson-python@0.16.0
libedit@3.1-20240808 libxcrypt@4.4.38 readline@8.2
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@11.4.0 ----------------
kokkos-kernels@4.5.01
-- linux-ubuntu22.04-x86_64_v3 / %cxx=gcc@12.5.0 ----------------
py-pybind11@2.13.6 py-pythran@0.16.1
-- linux-ubuntu22.04-x86_64_v3 / no compilers -------------------
gcc-runtime@10.5.0 gcc-runtime@11.4.0 gcc-runtime@12.5.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.