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:sc24
and then set Spack up like this:
git clone --depth=100 --branch=releases/v0.23 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
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 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.
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}"
adept-utils 1.0.1 q5xl3h77oc gmp 6.3.0 5webgyazi3 macsio 1.1 o4zotmuc52 py-pythran 0.16.1 3bcgcevke7
autoconf 2.72 vgucajy3lk hdf5 1.14.5 ckoh67fpzb meson 1.5.1 xfqgelb63r py-scipy 1.14.1 g53zrs6vom
autoconf 2.72 yfxrc66azg hdf5 1.14.5 6ddnwvambf meson 1.5.1 tp5miymsew py-setuptools 69.2.0 snvbpkxkqt
autoconf-archive 2023.02.20 6s34ic3cja hdf5 1.14.5 tgtmflo4s6 mpc 1.3.1 qoauga4bfx py-setuptools 69.2.0 wbbopiponk
automake 1.16.5 awgfaon3ds hwloc 2.11.1 fwtuzgpmp2 mpfr 4.2.1 mdfsfjykvy py-wheel 0.41.2 pxniiekemg
automake 1.16.5 e4u6ql7bme hwloc 2.11.1 2fvcggi3gq mpich 4.2.3 cqazuix44i py-wheel 0.41.2 gho4mpquga
axl 0.9.0 z6q2ovzd5u intel-tbb 2021.12.0 u5vh5hcz3r mpich 4.2.3 ezes42nge7 python 3.11.9 ct26uvgbvv
bc 1.07.1 jasonjuuhs json-c 0.16 jiezkp3kmw munge 0.5.15 7ccb5fignq python 3.11.9 67g7nw4psf
berkeley-db 18.1.40 cexliohp6a json-cwx 0.12 pvkmxcbrrq ncurses 6.5 rvg7j6bmer python 3.13.0 gfyestlsao
berkeley-db 18.1.40 4mqvw3uqym kokkos 4.3.01 nxt5zthcpf ncurses 6.5 uajmsrcnww python 3.13.0 wxt7apsxjg
bison 3.8.2 sllhx5naxi krb5 1.21.3 pq3as37xno netlib-lapack 3.11.0 nn52q3bloz python-venv 1.0 wylyhqnxcx
bison 3.8.2 fky4vihmla krb5 1.21.3 frb66wnvsa netlib-scalapack 2.2.0 me353pomgl python-venv 1.0 pt3p7pdrin
boost 1.72.0 bzwzix4qau kvtree 1.5.0 5ubm4uy3f5 netlib-scalapack 2.2.0 wpymlkhhvz rankstr 0.4.0 r6xbtxcwl3
bzip2 1.0.8 ewqc7cx44b libbsd 0.12.2 hwya6i63fv netlib-scalapack 2.2.0 5fvq6fgjha re2c 3.1 tpzsx34tj4
bzip2 1.0.8 j3fd4z5i2t libbsd 0.12.2 3oqufcrjxa netlib-scalapack 2.2.0 bx3g36nfqn re2c 3.1 qgh7e7n6c3
ca-certificates-mozilla 2023-05-30 t2brqssuwb libdwarf 0.11.0 hz7ptvgac3 nghttp2 1.63.0 t2qkug7u7i readline 8.2 aylebxvheu
ca-certificates-mozilla 2023-05-30 xilbvuysbu libedit 3.1-20240808 nhrbcomj5l nghttp2 1.63.0 ippbbwuh3a readline 8.2 tb7zvufjv2
callpath 1.0.4 7hjlu6ddwm libedit 3.1-20240808 ht5niwqary ninja 1.12.1 xasrhuxnm5 redset 0.4.0 wn6bxs77ba
cmake 3.30.5 d2nwbxlz2q libevent 2.1.12 xbwxobi4cj ninja 1.12.1 myjhsx2n7x scr 2.0.0 inxkq6ww6n
cmake 3.30.5 yempnazpum libevent 2.1.12 nftqerg373 numactl 2.0.18 euqyy3hu6d scr 3.1.0 z6ndebu7r4
curl 8.10.1 fpywomo74r libfabric 1.22.0 lr77ky6sw7 numactl 2.0.18 n4nt7lopsr shuffile 0.4.0 6gdnjhlovk
curl 8.10.1 wsmx6spfnt libfabric 1.22.0 pvefo63faf openblas 0.3.28 w2fghghowf silo 4.11.1 tf6qseltlk
diffutils 3.10 lljulvxt5h libffi 3.4.6 ltl5sqyu2f openblas 0.3.28 aliqr5t6k2 slurm 23-11-1-1 wtptlf72di
diffutils 3.10 ioferp7x7e libffi 3.4.6 4ga47g7tj4 openmpi 5.0.5 jvwxvxe7dg spath 0.4.0 phgpwllzdk
dtcmp 1.1.5 m2vb6sgvtv libgcrypt 1.11.0 tau3vgrmq6 openmpi 5.0.5 suepxfzmhy sqlite 3.46.0 ogdosm6dqm
dyninst 13.0.0 idhmtve2yu libgpg-error 1.50 3g7e2nwelj openssh 9.9p1 wz7w27t54u sqlite 3.46.0 b63y5mxrvt
ed 1.4 p72c4zcdrx libiberty 2.41 ojjef3cyse openssh 9.9p1 3jdzvdmyxc tar 1.34 mmv6i4naeg
elfutils 0.191 zw2tlkv425 libiconv 1.17 bsga3novxp openssl 3.4.0 5gigqgwld4 tar 1.34 j5dljnv4mc
er 0.5.0 vcbjtu7365 libiconv 1.17 gdtmvyudyk openssl 3.4.0 i5fmca4xdy tcl 8.6.12 imrm45j44x
expat 2.6.4 hj6jtyrxtq libmd 1.0.4 qcfzttdxov pcre2 10.44 pim2bkxw3c tcl 8.6.12 w4gwr4ezme
expat 2.6.4 vlatljjv2t libmd 1.0.4 cpmq5mdiri pdsh 2.31 oe5lfjf4gn texinfo 7.1 ljsbwjcqdl
findutils 4.9.0 2sbkhchnzz libpciaccess 0.17 omw5cc44g5 perl 5.40.0 cwpt5ec6gc trilinos 16.0.0 ney6hmmpuf
findutils 4.9.0 wqmzrkeupx libpciaccess 0.17 ybxtd2t7kr perl 5.40.0 tt4vkz363s trilinos 16.0.0 63sfm7p6ve
gawk 5.3.1 x6mwj3lnzl libsigsegv 2.14 ea6qziv7ob pigz 2.8 pcwnu2wfae unzip 6.0 akxwy4wvo4
gcc 12.3.0 jjgfqpdmih libsigsegv 2.14 u2gofvqdvw pigz 2.8 zgwe2uay3t util-linux-uuid 2.40.2 xesify5chx
gcc-runtime 10.5.0 g7dc4oue6r libtool 2.4.7 tt3byemikn pkgconf 2.2.0 oplsmxryrc util-linux-uuid 2.40.2 64aencak6b
gcc-runtime 11.4.0 hshzy762rn libtool 2.4.7 xfe5xhomit pkgconf 2.2.0 gutpiwqutu util-macros 1.20.1 vdnwjqe534
gcc-runtime 12.3.0 w5nlv2kp2n libxcrypt 4.4.35 v64tnmrjg7 pmix 5.0.3 5wqqmswtib util-macros 1.20.1 vau55h7rdi
gdbm 1.23 jj2atvsdpr libxcrypt 4.4.35 apxktfacu5 pmix 5.0.3 t7gzekhpro xz 5.4.6 2fvrfr67ah
gdbm 1.23 ttyuhau65q libxml2 2.13.4 wozcmyn2bi py-beniget 0.4.1 oyzng5hw6k xz 5.4.6 ifvv7czmux
gettext 0.22.5 bexdfw2vfc libxml2 2.13.4 4fawd6mhag py-cython 3.0.11 efpxrfoxiv yaksa 0.3 eogugqp4p6
gettext 0.22.5 jbitwptksu libyogrt 1.35 gswz3l2d2q py-flit-core 3.9.0 ltdymw47r2 yaksa 0.3 ferxascsq3
glib 2.78.3 rf4t3xsios lmod 8.7.18 saucmo6quz py-gast 0.5.4 rbt72pqun5 zlib-ng 2.0.7 ocxrmffc7q
glibc 2.35 xvsfmyvk5j lua 5.4.6 qcxkktpc5l py-meson-python 0.16.0 jgr2tnqohn zlib-ng 2.0.7 umrbkwvnyd
glibc 2.35 tcngwuvjec lua-luafilesystem 1.8.0 4lpeywju4b py-numpy 2.1.2 ckezggl7xc zlib-ng 2.2.1 jjykcjtfyo
glibc 2.35 a7drdl4tlx lua-luaposix 36.1 hdnpce3ade py-packaging 24.1 i5hagd3pwt zlib-ng 2.2.1 fhud6vqkh7
glibc 2.35 gkoh6axllp lwgrp 1.0.6 euguteoau5 py-pip 23.1.2 vdyo63uzwk zlib-ng 2.2.1 i4mwsvmsv2
gmake 4.4.1 gcbcod5uik lz4 1.10.0 itxj6zzegx py-pip 23.1.2 3eaudob5lk zstd 1.5.6 t7h6imj35r
gmake 4.4.1 he2qdcb6bg m4 1.4.19 qaspjyq5yq py-ply 3.11 ohaizhq76a zstd 1.5.6 yk3lkd4xdu
gmake 4.4.1 srkzfjru5z m4 1.4.19 grpnckwm3e py-pybind11 2.13.5 bdx5tpnvwz
gmake 4.4.1 zoiouaigyc macsio 1.1 523dspnnce py-pyproject-metadata 0.7.1 p27mstg5gu
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-ng
by entering:
$ spack find --json zlib-ng
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.23.0
Python 3.10.12, 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=x86_64_v3')
>>> 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=None-None-x86_64_v3
>>> s.versions
[:]
>>> str(s.architecture)
None-None-x86_64_v3
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.3.1')
>>> s.versions
[Version('1.3.1')]
>>> str(s.architecture)
linux-ubuntu22.04-x86_64_v3
Notice that the concretized spec now:
has a
version
;has a single entry in its
versions
list; andthe operating system is now
ubuntu22.04
.
It is not necessary to store the intermediate abstract spec – you can
use the .concretized()
method as shorthand:
>>> t = Spec('zlib target=x86_64_v3').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.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(*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.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-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
.
Let’s exit the interpreter to take us back to the command line:
>>> exit()
before generalizing the functionality for reuse.
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.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-ubuntu22.04-x86_64_v3 / gcc@10.5.0 ---------------------
gcc-runtime@10.5.0 glibc@2.35 gmake@4.4.1
-- linux-ubuntu22.04-x86_64_v3 / gcc@11.4.0 ---------------------
adept-utils@1.0.1 dtcmp@1.1.5 gmp@6.3.0 libffi@3.4.6 lua-luaposix@36.1 openblas@0.3.28 python-venv@1.0 texinfo@7.1
autoconf@2.72 dyninst@13.0.0 hdf5@1.14.5 libgcrypt@1.11.0 lwgrp@1.0.6 openmpi@5.0.5 rankstr@0.4.0 trilinos@16.0.0
autoconf-archive@2023.02.20 ed@1.4 hdf5@1.14.5 libgpg-error@1.50 lz4@1.10.0 openssh@9.9p1 re2c@3.1 unzip@6.0
automake@1.16.5 elfutils@0.191 hwloc@2.11.1 libiberty@2.41 m4@1.4.19 openssl@3.4.0 readline@8.2 util-linux-uuid@2.40.2
axl@0.9.0 er@0.5.0 intel-tbb@2021.12.0 libiconv@1.17 macsio@1.1 pcre2@10.44 redset@0.4.0 util-macros@1.20.1
bc@1.07.1 expat@2.6.4 json-c@0.16 libmd@1.0.4 macsio@1.1 pdsh@2.31 scr@2.0.0 xz@5.4.6
berkeley-db@18.1.40 findutils@4.9.0 json-cwx@0.12 libpciaccess@0.17 meson@1.5.1 perl@5.40.0 scr@3.1.0 yaksa@0.3
bison@3.8.2 gawk@5.3.1 kokkos@4.3.01 libsigsegv@2.14 mpc@1.3.1 pigz@2.8 shuffile@0.4.0 zlib-ng@2.0.7
boost@1.72.0 gcc@12.3.0 krb5@1.21.3 libtool@2.4.7 mpfr@4.2.1 pkgconf@2.2.0 silo@4.11.1 zlib-ng@2.0.7
bzip2@1.0.8 gcc-runtime@11.4.0 kvtree@1.5.0 libxcrypt@4.4.35 mpich@4.2.3 pmix@5.0.3 slurm@23-11-1-1 zlib-ng@2.2.1
ca-certificates-mozilla@2023-05-30 gdbm@1.23 libbsd@0.12.2 libxml2@2.13.4 munge@0.5.15 py-pip@23.1.2 spath@0.4.0 zstd@1.5.6
callpath@1.0.4 gettext@0.22.5 libdwarf@0.11.0 libyogrt@1.35 ncurses@6.5 py-setuptools@69.2.0 sqlite@3.46.0
cmake@3.30.5 glib@2.78.3 libedit@3.1-20240808 lmod@8.7.18 nghttp2@1.63.0 py-wheel@0.41.2 tar@1.34
curl@8.10.1 glibc@2.35 libevent@2.1.12 lua@5.4.6 ninja@1.12.1 python@3.11.9 tcl@8.6.12
diffutils@3.10 gmake@4.4.1 libfabric@1.22.0 lua-luafilesystem@1.8.0 numactl@2.0.18 python@3.13.0 tcl@8.6.12
-- linux-ubuntu22.04-x86_64_v3 / gcc@12.3.0 ---------------------
autoconf@2.72 gcc-runtime@12.3.0 libffi@3.4.6 ncurses@6.5 perl@5.40.0 py-pip@23.1.2 re2c@3.1
automake@1.16.5 gdbm@1.23 libiconv@1.17 netlib-lapack@3.11.0 pigz@2.8 py-ply@3.11 readline@8.2
berkeley-db@18.1.40 gettext@0.22.5 libmd@1.0.4 netlib-scalapack@2.2.0 pkgconf@2.2.0 py-pybind11@2.13.5 sqlite@3.46.0
bison@3.8.2 glibc@2.35 libpciaccess@0.17 netlib-scalapack@2.2.0 pmix@5.0.3 py-pyproject-metadata@0.7.1 tar@1.34
bzip2@1.0.8 gmake@4.4.1 libsigsegv@2.14 nghttp2@1.63.0 py-beniget@0.4.1 py-pythran@0.16.1 util-linux-uuid@2.40.2
ca-certificates-mozilla@2023-05-30 hwloc@2.11.1 libtool@2.4.7 ninja@1.12.1 py-cython@3.0.11 py-scipy@1.14.1 util-macros@1.20.1
cmake@3.30.5 krb5@1.21.3 libxcrypt@4.4.35 numactl@2.0.18 py-flit-core@3.9.0 py-setuptools@69.2.0 xz@5.4.6
curl@8.10.1 libbsd@0.12.2 libxml2@2.13.4 openblas@0.3.28 py-gast@0.5.4 py-wheel@0.41.2 yaksa@0.3
diffutils@3.10 libedit@3.1-20240808 m4@1.4.19 openmpi@5.0.5 py-meson-python@0.16.0 python@3.11.9 zlib-ng@2.2.1
expat@2.6.4 libevent@2.1.12 meson@1.5.1 openssh@9.9p1 py-numpy@2.1.2 python@3.13.0 zstd@1.5.6
findutils@4.9.0 libfabric@1.22.0 mpich@4.2.3 openssl@3.4.0 py-packaging@24.1 python-venv@1.0
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.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
/usr/bin/env: use -[v]S to pass options in shebang lines
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.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-ubuntu22.04-x86_64_v3 / gcc@10.5.0 ---------------------
gcc-runtime@10.5.0 glibc@2.35 gmake@4.4.1
-- linux-ubuntu22.04-x86_64_v3 / gcc@11.4.0 ---------------------
adept-utils@1.0.1 dtcmp@1.1.5 gmp@6.3.0 libffi@3.4.6 lua-luaposix@36.1 openblas@0.3.28 python-venv@1.0 texinfo@7.1
autoconf@2.72 dyninst@13.0.0 hdf5@1.14.5 libgcrypt@1.11.0 lwgrp@1.0.6 openmpi@5.0.5 rankstr@0.4.0 trilinos@16.0.0
autoconf-archive@2023.02.20 ed@1.4 hdf5@1.14.5 libgpg-error@1.50 lz4@1.10.0 openssh@9.9p1 re2c@3.1 unzip@6.0
automake@1.16.5 elfutils@0.191 hwloc@2.11.1 libiberty@2.41 m4@1.4.19 openssl@3.4.0 readline@8.2 util-linux-uuid@2.40.2
axl@0.9.0 er@0.5.0 intel-tbb@2021.12.0 libiconv@1.17 macsio@1.1 pcre2@10.44 redset@0.4.0 util-macros@1.20.1
bc@1.07.1 expat@2.6.4 json-c@0.16 libmd@1.0.4 macsio@1.1 pdsh@2.31 scr@2.0.0 xz@5.4.6
berkeley-db@18.1.40 findutils@4.9.0 json-cwx@0.12 libpciaccess@0.17 meson@1.5.1 perl@5.40.0 scr@3.1.0 yaksa@0.3
bison@3.8.2 gawk@5.3.1 kokkos@4.3.01 libsigsegv@2.14 mpc@1.3.1 pigz@2.8 shuffile@0.4.0 zlib-ng@2.0.7
boost@1.72.0 gcc@12.3.0 krb5@1.21.3 libtool@2.4.7 mpfr@4.2.1 pkgconf@2.2.0 silo@4.11.1 zlib-ng@2.0.7
bzip2@1.0.8 gcc-runtime@11.4.0 kvtree@1.5.0 libxcrypt@4.4.35 mpich@4.2.3 pmix@5.0.3 slurm@23-11-1-1 zlib-ng@2.2.1
ca-certificates-mozilla@2023-05-30 gdbm@1.23 libbsd@0.12.2 libxml2@2.13.4 munge@0.5.15 py-pip@23.1.2 spath@0.4.0 zstd@1.5.6
callpath@1.0.4 gettext@0.22.5 libdwarf@0.11.0 libyogrt@1.35 ncurses@6.5 py-setuptools@69.2.0 sqlite@3.46.0
cmake@3.30.5 glib@2.78.3 libedit@3.1-20240808 lmod@8.7.18 nghttp2@1.63.0 py-wheel@0.41.2 tar@1.34
curl@8.10.1 glibc@2.35 libevent@2.1.12 lua@5.4.6 ninja@1.12.1 python@3.11.9 tcl@8.6.12
diffutils@3.10 gmake@4.4.1 libfabric@1.22.0 lua-luafilesystem@1.8.0 numactl@2.0.18 python@3.13.0 tcl@8.6.12
-- linux-ubuntu22.04-x86_64_v3 / gcc@12.3.0 ---------------------
autoconf@2.72 gcc-runtime@12.3.0 libffi@3.4.6 ncurses@6.5 perl@5.40.0 py-pip@23.1.2 re2c@3.1
automake@1.16.5 gdbm@1.23 libiconv@1.17 netlib-lapack@3.11.0 pigz@2.8 py-ply@3.11 readline@8.2
berkeley-db@18.1.40 gettext@0.22.5 libmd@1.0.4 netlib-scalapack@2.2.0 pkgconf@2.2.0 py-pybind11@2.13.5 sqlite@3.46.0
bison@3.8.2 glibc@2.35 libpciaccess@0.17 netlib-scalapack@2.2.0 pmix@5.0.3 py-pyproject-metadata@0.7.1 tar@1.34
bzip2@1.0.8 gmake@4.4.1 libsigsegv@2.14 nghttp2@1.63.0 py-beniget@0.4.1 py-pythran@0.16.1 util-linux-uuid@2.40.2
ca-certificates-mozilla@2023-05-30 hwloc@2.11.1 libtool@2.4.7 ninja@1.12.1 py-cython@3.0.11 py-scipy@1.14.1 util-macros@1.20.1
cmake@3.30.5 krb5@1.21.3 libxcrypt@4.4.35 numactl@2.0.18 py-flit-core@3.9.0 py-setuptools@69.2.0 xz@5.4.6
curl@8.10.1 libbsd@0.12.2 libxml2@2.13.4 openblas@0.3.28 py-gast@0.5.4 py-wheel@0.41.2 yaksa@0.3
diffutils@3.10 libedit@3.1-20240808 m4@1.4.19 openmpi@5.0.5 py-meson-python@0.16.0 python@3.11.9 zlib-ng@2.2.1
expat@2.6.4 libevent@2.1.12 meson@1.5.1 openssh@9.9p1 py-numpy@2.1.2 python@3.13.0 zstd@1.5.6
findutils@4.9.0 libfabric@1.22.0 mpich@4.2.3 openssl@3.4.0 py-packaging@24.1 python-venv@1.0
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.