Docs: Update spec variant checks plus python quotes and string formatting (#40643)

This commit is contained in:
Tamara Dahlgren 2023-10-23 00:15:03 -07:00 committed by GitHub
parent d9167834c4
commit cfc5363053
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 176 additions and 164 deletions

View file

@ -127,9 +127,9 @@ check out a commit from the ``master`` branch, you would want to add:
.. code-block:: python .. code-block:: python
depends_on('autoconf', type='build', when='@master') depends_on("autoconf", type="build", when="@master")
depends_on('automake', type='build', when='@master') depends_on("automake", type="build", when="@master")
depends_on('libtool', type='build', when='@master') depends_on("libtool", type="build", when="@master")
It is typically redundant to list the ``m4`` macro processor package as a It is typically redundant to list the ``m4`` macro processor package as a
dependency, since ``autoconf`` already depends on it. dependency, since ``autoconf`` already depends on it.
@ -145,7 +145,7 @@ example, the ``bash`` shell is used to run the ``autogen.sh`` script.
.. code-block:: python .. code-block:: python
def autoreconf(self, spec, prefix): def autoreconf(self, spec, prefix):
which('bash')('autogen.sh') which("bash")("autogen.sh")
""""""""""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""""""""""
patching configure or Makefile.in files patching configure or Makefile.in files
@ -186,9 +186,9 @@ To opt out of this feature, use the following setting:
To enable it conditionally on different architectures, define a property and To enable it conditionally on different architectures, define a property and
make the package depend on ``gnuconfig`` as a build dependency: make the package depend on ``gnuconfig`` as a build dependency:
.. code-block .. code-block:: python
depends_on('gnuconfig', when='@1.0:') depends_on("gnuconfig", when="@1.0:")
@property @property
def patch_config_files(self): def patch_config_files(self):
@ -230,7 +230,7 @@ version, this can be done like so:
@property @property
def force_autoreconf(self): def force_autoreconf(self):
return self.version == Version('1.2.3') return self.version == Version("1.2.3")
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
Finding configure flags Finding configure flags
@ -278,13 +278,22 @@ function like so:
def configure_args(self): def configure_args(self):
args = [] args = []
if '+mpi' in self.spec: if self.spec.satisfies("+mpi"):
args.append('--enable-mpi') args.append("--enable-mpi")
else: else:
args.append('--disable-mpi') args.append("--disable-mpi")
return args return args
Alternatively, you can use the :ref:`enable_or_disable <autotools_enable_or_disable>` helper:
.. code-block:: python
def configure_args(self):
return [self.enable_or_disable("mpi")]
Note that we are explicitly disabling MPI support if it is not Note that we are explicitly disabling MPI support if it is not
requested. This is important, as many Autotools packages will enable requested. This is important, as many Autotools packages will enable
options by default if the dependencies are found, and disable them options by default if the dependencies are found, and disable them
@ -295,9 +304,11 @@ and `here <https://wiki.gentoo.org/wiki/Project:Quality_Assurance/Automagic_depe
for a rationale as to why these so-called "automagic" dependencies for a rationale as to why these so-called "automagic" dependencies
are a problem. are a problem.
By default, Autotools installs packages to ``/usr``. We don't want this, .. note::
so Spack automatically adds ``--prefix=/path/to/installation/prefix``
to your list of ``configure_args``. You don't need to add this yourself. By default, Autotools installs packages to ``/usr``. We don't want this,
so Spack automatically adds ``--prefix=/path/to/installation/prefix``
to your list of ``configure_args``. You don't need to add this yourself.
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
Helper functions Helper functions
@ -308,6 +319,8 @@ You may have noticed that most of the Autotools flags are of the form
``--without-baz``. Since these flags are so common, Spack provides a ``--without-baz``. Since these flags are so common, Spack provides a
couple of helper functions to make your life easier. couple of helper functions to make your life easier.
.. _autotools_enable_or_disable:
""""""""""""""""" """""""""""""""""
enable_or_disable enable_or_disable
""""""""""""""""" """""""""""""""""
@ -319,11 +332,11 @@ typically used to enable or disable some feature within the package.
.. code-block:: python .. code-block:: python
variant( variant(
'memchecker', "memchecker",
default=False, default=False,
description='Memchecker support for debugging [degrades performance]' description="Memchecker support for debugging [degrades performance]"
) )
config_args.extend(self.enable_or_disable('memchecker')) config_args.extend(self.enable_or_disable("memchecker"))
In this example, specifying the variant ``+memchecker`` will generate In this example, specifying the variant ``+memchecker`` will generate
the following configuration options: the following configuration options:
@ -343,15 +356,15 @@ the ``with_or_without`` method.
.. code-block:: python .. code-block:: python
variant( variant(
'schedulers', "schedulers",
values=disjoint_sets( values=disjoint_sets(
('auto',), ('alps', 'lsf', 'tm', 'slurm', 'sge', 'loadleveler') ("auto",), ("alps", "lsf", "tm", "slurm", "sge", "loadleveler")
).with_non_feature_values('auto', 'none'), ).with_non_feature_values("auto", "none"),
description="List of schedulers for which support is enabled; " description="List of schedulers for which support is enabled; "
"'auto' lets openmpi determine", "'auto' lets openmpi determine",
) )
if 'schedulers=auto' not in spec: if not spec.satisfies("schedulers=auto"):
config_args.extend(self.with_or_without('schedulers')) config_args.extend(self.with_or_without("schedulers"))
In this example, specifying the variant ``schedulers=slurm,sge`` will In this example, specifying the variant ``schedulers=slurm,sge`` will
generate the following configuration options: generate the following configuration options:
@ -376,16 +389,16 @@ generated, using the ``activation_value`` argument to
.. code-block:: python .. code-block:: python
variant( variant(
'fabrics', "fabrics",
values=disjoint_sets( values=disjoint_sets(
('auto',), ('psm', 'psm2', 'verbs', 'mxm', 'ucx', 'libfabric') ("auto",), ("psm", "psm2", "verbs", "mxm", "ucx", "libfabric")
).with_non_feature_values('auto', 'none'), ).with_non_feature_values("auto", "none"),
description="List of fabrics that are enabled; " description="List of fabrics that are enabled; "
"'auto' lets openmpi determine", "'auto' lets openmpi determine",
) )
if 'fabrics=auto' not in spec: if not spec.satisfies("fabrics=auto"):
config_args.extend(self.with_or_without('fabrics', config_args.extend(self.with_or_without("fabrics",
activation_value='prefix')) activation_value="prefix"))
``activation_value`` accepts a callable that generates the configure ``activation_value`` accepts a callable that generates the configure
parameter value given the variant value; but the special value parameter value given the variant value; but the special value
@ -409,16 +422,16 @@ When Spack variants and configure flags do not correspond one-to-one, the
.. code-block:: python .. code-block:: python
variant('debug_tools', default=False) variant("debug_tools", default=False)
config_args += self.enable_or_disable('debug-tools', variant='debug_tools') config_args += self.enable_or_disable("debug-tools", variant="debug_tools")
Or when one variant controls multiple flags: Or when one variant controls multiple flags:
.. code-block:: python .. code-block:: python
variant('debug_tools', default=False) variant("debug_tools", default=False)
config_args += self.with_or_without('memchecker', variant='debug_tools') config_args += self.with_or_without("memchecker", variant="debug_tools")
config_args += self.with_or_without('profiler', variant='debug_tools') config_args += self.with_or_without("profiler", variant="debug_tools")
"""""""""""""""""""" """"""""""""""""""""
@ -432,8 +445,8 @@ For example:
.. code-block:: python .. code-block:: python
variant('profiler', when='@2.0:') variant("profiler", when="@2.0:")
config_args += self.with_or_without('profiler') config_args += self.with_or_without("profiler")
will neither add ``--with-profiler`` nor ``--without-profiler`` when the version is will neither add ``--with-profiler`` nor ``--without-profiler`` when the version is
below ``2.0``. below ``2.0``.
@ -452,10 +465,10 @@ the variant values require atypical behavior.
def with_or_without_verbs(self, activated): def with_or_without_verbs(self, activated):
# Up through version 1.6, this option was named --with-openib. # Up through version 1.6, this option was named --with-openib.
# In version 1.7, it was renamed to be --with-verbs. # In version 1.7, it was renamed to be --with-verbs.
opt = 'verbs' if self.spec.satisfies('@1.7:') else 'openib' opt = "verbs" if self.spec.satisfies("@1.7:") else "openib"
if not activated: if not activated:
return '--without-{0}'.format(opt) return f"--without-{opt}"
return '--with-{0}={1}'.format(opt, self.spec['rdma-core'].prefix) return f"--with-{opt}={self.spec['rdma-core'].prefix}"
Defining ``with_or_without_verbs`` overrides the behavior of a Defining ``with_or_without_verbs`` overrides the behavior of a
``fabrics=verbs`` variant, changing the configure-time option to ``fabrics=verbs`` variant, changing the configure-time option to
@ -479,7 +492,7 @@ do this like so:
.. code-block:: python .. code-block:: python
configure_directory = 'src' configure_directory = "src"
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
Building out of source Building out of source
@ -491,7 +504,7 @@ This can be done using the ``build_directory`` variable:
.. code-block:: python .. code-block:: python
build_directory = 'spack-build' build_directory = "spack-build"
By default, Spack will build the package in the same directory that By default, Spack will build the package in the same directory that
contains the ``configure`` script contains the ``configure`` script
@ -514,8 +527,8 @@ library or build the documentation, you can add these like so:
.. code-block:: python .. code-block:: python
build_targets = ['all', 'docs'] build_targets = ["all", "docs"]
install_targets = ['install', 'docs'] install_targets = ["install", "docs"]
^^^^^^^ ^^^^^^^
Testing Testing

View file

@ -87,7 +87,7 @@ A typical usage of these methods may look something like this:
.. code-block:: python .. code-block:: python
def initconfig_mpi_entries(self) def initconfig_mpi_entries(self):
# Get existing MPI configurations # Get existing MPI configurations
entries = super(self, Foo).initconfig_mpi_entries() entries = super(self, Foo).initconfig_mpi_entries()
@ -95,25 +95,25 @@ A typical usage of these methods may look something like this:
# This spec has an MPI variant, and we need to enable MPI when it is on. # This spec has an MPI variant, and we need to enable MPI when it is on.
# This hypothetical package controls MPI with the ``FOO_MPI`` option to # This hypothetical package controls MPI with the ``FOO_MPI`` option to
# cmake. # cmake.
if '+mpi' in self.spec: if self.spec.satisfies("+mpi"):
entries.append(cmake_cache_option('FOO_MPI', True, "enable mpi")) entries.append(cmake_cache_option("FOO_MPI", True, "enable mpi"))
else: else:
entries.append(cmake_cache_option('FOO_MPI', False, "disable mpi")) entries.append(cmake_cache_option("FOO_MPI", False, "disable mpi"))
def initconfig_package_entries(self): def initconfig_package_entries(self):
# Package specific options # Package specific options
entries = [] entries = []
entries.append('#Entries for build options') entries.append("#Entries for build options")
bar_on = '+bar' in self.spec bar_on = self.spec.satisfies("+bar")
entries.append(cmake_cache_option('FOO_BAR', bar_on, 'toggle bar')) entries.append(cmake_cache_option("FOO_BAR", bar_on, "toggle bar"))
entries.append('#Entries for dependencies') entries.append("#Entries for dependencies")
if self.spec['blas'].name == 'baz': # baz is our blas provider if self.spec["blas"].name == "baz": # baz is our blas provider
entries.append(cmake_cache_string('FOO_BLAS', 'baz', 'Use baz')) entries.append(cmake_cache_string("FOO_BLAS", "baz", "Use baz"))
entries.append(cmake_cache_path('BAZ_PREFIX', self.spec['baz'].prefix)) entries.append(cmake_cache_path("BAZ_PREFIX", self.spec["baz"].prefix))
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
External documentation External documentation

View file

@ -54,8 +54,8 @@ to terminate such build attempts with a suitable message:
.. code-block:: python .. code-block:: python
conflicts('cuda_arch=none', when='+cuda', conflicts("cuda_arch=none", when="+cuda",
msg='CUDA architecture is required') msg="CUDA architecture is required")
Similarly, if your software does not support all versions of the property, Similarly, if your software does not support all versions of the property,
you could add ``conflicts`` to your package for those versions. For example, you could add ``conflicts`` to your package for those versions. For example,
@ -66,13 +66,13 @@ custom message should a user attempt such a build:
.. code-block:: python .. code-block:: python
unsupported_cuda_archs = [ unsupported_cuda_archs = [
'10', '11', '12', '13', "10", "11", "12", "13",
'20', '21', "20", "21",
'30', '32', '35', '37' "30", "32", "35", "37"
] ]
for value in unsupported_cuda_archs: for value in unsupported_cuda_archs:
conflicts('cuda_arch={0}'.format(value), when='+cuda', conflicts(f"cuda_arch={value}", when="+cuda",
msg='CUDA architecture {0} is not supported'.format(value)) msg=f"CUDA architecture {value} is not supported")
^^^^^^^ ^^^^^^^
Methods Methods
@ -107,16 +107,16 @@ class of your package. For example, you can add it to your
spec = self.spec spec = self.spec
args = [] args = []
... ...
if '+cuda' in spec: if spec.satisfies("+cuda"):
# Set up the cuda macros needed by the build # Set up the cuda macros needed by the build
args.append('-DWITH_CUDA=ON') args.append("-DWITH_CUDA=ON")
cuda_arch_list = spec.variants['cuda_arch'].value cuda_arch_list = spec.variants["cuda_arch"].value
cuda_arch = cuda_arch_list[0] cuda_arch = cuda_arch_list[0]
if cuda_arch != 'none': if cuda_arch != "none":
args.append('-DCUDA_FLAGS=-arch=sm_{0}'.format(cuda_arch)) args.append(f"-DCUDA_FLAGS=-arch=sm_{cuda_arch}")
else: else:
# Ensure build with cuda is disabled # Ensure build with cuda is disabled
args.append('-DWITH_CUDA=OFF') args.append("-DWITH_CUDA=OFF")
... ...
return args return args
@ -125,7 +125,7 @@ You will need to customize options as needed for your build.
This example also illustrates how to check for the ``cuda`` variant using This example also illustrates how to check for the ``cuda`` variant using
``self.spec`` and how to retrieve the ``cuda_arch`` variant's value, which ``self.spec`` and how to retrieve the ``cuda_arch`` variant's value, which
is a list, using ``self.spec.variants['cuda_arch'].value``. is a list, using ``self.spec.variants["cuda_arch"].value``.
With over 70 packages using ``CudaPackage`` as of January 2021 there are With over 70 packages using ``CudaPackage`` as of January 2021 there are
lots of examples to choose from to get more ideas for using this package. lots of examples to choose from to get more ideas for using this package.

View file

@ -57,13 +57,13 @@ If you look at the ``perl`` package, you'll see:
.. code-block:: python .. code-block:: python
phases = ['configure', 'build', 'install'] phases = ["configure", "build", "install"]
Similarly, ``cmake`` defines: Similarly, ``cmake`` defines:
.. code-block:: python .. code-block:: python
phases = ['bootstrap', 'build', 'install'] phases = ["bootstrap", "build", "install"]
If we look at the ``cmake`` example, this tells Spack's ``PackageBase`` If we look at the ``cmake`` example, this tells Spack's ``PackageBase``
class to run the ``bootstrap``, ``build``, and ``install`` functions class to run the ``bootstrap``, ``build``, and ``install`` functions
@ -78,7 +78,7 @@ If we look at ``perl``, we see that it defines a ``configure`` method:
.. code-block:: python .. code-block:: python
def configure(self, spec, prefix): def configure(self, spec, prefix):
configure = Executable('./Configure') configure = Executable("./Configure")
configure(*self.configure_args()) configure(*self.configure_args())
There is also a corresponding ``configure_args`` function that handles There is also a corresponding ``configure_args`` function that handles
@ -92,7 +92,7 @@ phases are pretty simple:
make() make()
def install(self, spec, prefix): def install(self, spec, prefix):
make('install') make("install")
The ``cmake`` package looks very similar, but with a ``bootstrap`` The ``cmake`` package looks very similar, but with a ``bootstrap``
function instead of ``configure``: function instead of ``configure``:
@ -100,14 +100,14 @@ function instead of ``configure``:
.. code-block:: python .. code-block:: python
def bootstrap(self, spec, prefix): def bootstrap(self, spec, prefix):
bootstrap = Executable('./bootstrap') bootstrap = Executable("./bootstrap")
bootstrap(*self.bootstrap_args()) bootstrap(*self.bootstrap_args())
def build(self, spec, prefix): def build(self, spec, prefix):
make() make()
def install(self, spec, prefix): def install(self, spec, prefix):
make('install') make("install")
Again, there is a ``boostrap_args`` function that determines the Again, there is a ``boostrap_args`` function that determines the
correct bootstrap flags to use. correct bootstrap flags to use.
@ -128,16 +128,16 @@ before or after a particular phase. For example, in ``perl``, we see:
.. code-block:: python .. code-block:: python
@run_after('install') @run_after("install")
def install_cpanm(self): def install_cpanm(self):
spec = self.spec spec = self.spec
if '+cpanm' in spec: if spec.satisfies("+cpanm"):
with working_dir(join_path('cpanm', 'cpanm')): with working_dir(join_path("cpanm", "cpanm")):
perl = spec['perl'].command perl = spec["perl"].command
perl('Makefile.PL') perl("Makefile.PL")
make() make()
make('install') make("install")
This extra step automatically installs ``cpanm`` in addition to the This extra step automatically installs ``cpanm`` in addition to the
base Perl installation. base Perl installation.
@ -174,10 +174,10 @@ In the ``perl`` package, we can see:
.. code-block:: python .. code-block:: python
@run_after('build') @run_after("build")
@on_package_attributes(run_tests=True) @on_package_attributes(run_tests=True)
def test(self): def test(self):
make('test') make("test")
As you can guess, this runs ``make test`` *after* building the package, As you can guess, this runs ``make test`` *after* building the package,
if and only if testing is requested. Again, this is not specific to if and only if testing is requested. Again, this is not specific to
@ -189,7 +189,7 @@ custom build systems, it can be added to existing build systems as well.
.. code-block:: python .. code-block:: python
@run_after('install') @run_after("install")
@on_package_attributes(run_tests=True) @on_package_attributes(run_tests=True)
works as expected. However, if you reverse the ordering: works as expected. However, if you reverse the ordering:
@ -197,7 +197,7 @@ custom build systems, it can be added to existing build systems as well.
.. code-block:: python .. code-block:: python
@on_package_attributes(run_tests=True) @on_package_attributes(run_tests=True)
@run_after('install') @run_after("install")
the tests will always be run regardless of whether or not the tests will always be run regardless of whether or not
``--test=root`` is requested. See https://github.com/spack/spack/issues/3833 ``--test=root`` is requested. See https://github.com/spack/spack/issues/3833

View file

@ -59,7 +59,7 @@ using GNU Make, you should add a dependency on ``gmake``:
.. code-block:: python .. code-block:: python
depends_on('gmake', type='build') depends_on("gmake", type="build")
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -93,8 +93,8 @@ there are any other variables you need to set, you can do this in the
.. code-block:: python .. code-block:: python
def edit(self, spec, prefix): def edit(self, spec, prefix):
env['PREFIX'] = prefix env["PREFIX"] = prefix
env['BLASLIB'] = spec['blas'].libs.ld_flags env["BLASLIB"] = spec["blas"].libs.ld_flags
`cbench <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/cbench/package.py>`_ `cbench <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/cbench/package.py>`_
@ -113,7 +113,7 @@ you can do this like so:
.. code-block:: python .. code-block:: python
build_targets = ['CC=cc'] build_targets = ["CC=cc"]
If you do need access to the spec, you can create a property like so: If you do need access to the spec, you can create a property like so:
@ -125,8 +125,8 @@ If you do need access to the spec, you can create a property like so:
spec = self.spec spec = self.spec
return [ return [
'CC=cc', "CC=cc",
'BLASLIB={0}'.format(spec['blas'].libs.ld_flags), f"BLASLIB={spec['blas'].libs.ld_flags}",
] ]
@ -145,12 +145,12 @@ and a ``filter_file`` method to help with this. For example:
.. code-block:: python .. code-block:: python
def edit(self, spec, prefix): def edit(self, spec, prefix):
makefile = FileFilter('Makefile') makefile = FileFilter("Makefile")
makefile.filter(r'^\s*CC\s*=.*', 'CC = ' + spack_cc) makefile.filter(r"^\s*CC\s*=.*", f"CC = {spack_cc}")
makefile.filter(r'^\s*CXX\s*=.*', 'CXX = ' + spack_cxx) makefile.filter(r"^\s*CXX\s*=.*", f"CXX = {spack_cxx}")
makefile.filter(r'^\s*F77\s*=.*', 'F77 = ' + spack_f77) makefile.filter(r"^\s*F77\s*=.*", f"F77 = {spack_f77}")
makefile.filter(r'^\s*FC\s*=.*', 'FC = ' + spack_fc) makefile.filter(r"^\s*FC\s*=.*", f"FC = {spack_fc}")
`stream <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/stream/package.py>`_ `stream <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/stream/package.py>`_
@ -181,16 +181,16 @@ well for storing variables:
def edit(self, spec, prefix): def edit(self, spec, prefix):
config = { config = {
'CC': 'cc', "CC": "cc",
'MAKE': 'make', "MAKE": "make",
} }
if '+blas' in spec: if spec.satisfies("+blas"):
config['BLAS_LIBS'] = spec['blas'].libs.joined() config["BLAS_LIBS"] = spec["blas"].libs.joined()
with open('make.inc', 'w') as inc: with open("make.inc", "w") as inc:
for key in config: for key in config:
inc.write('{0} = {1}\n'.format(key, config[key])) inc.write(f"{key} = {config[key]}\n")
`elk <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/elk/package.py>`_ `elk <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/elk/package.py>`_
@ -204,14 +204,14 @@ them in a list:
def edit(self, spec, prefix): def edit(self, spec, prefix):
config = [ config = [
'INSTALL_DIR = {0}'.format(prefix), f"INSTALL_DIR = {prefix}",
'INCLUDE_DIR = $(INSTALL_DIR)/include', "INCLUDE_DIR = $(INSTALL_DIR)/include",
'LIBRARY_DIR = $(INSTALL_DIR)/lib', "LIBRARY_DIR = $(INSTALL_DIR)/lib",
] ]
with open('make.inc', 'w') as inc: with open("make.inc", "w") as inc:
for var in config: for var in config:
inc.write('{0}\n'.format(var)) inc.write(f"{var}\n")
`hpl <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/hpl/package.py>`_ `hpl <https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/hpl/package.py>`_
@ -284,7 +284,7 @@ can tell Spack where to locate it like so:
.. code-block:: python .. code-block:: python
build_directory = 'src' build_directory = "src"
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
@ -299,8 +299,8 @@ install the package:
def install(self, spec, prefix): def install(self, spec, prefix):
mkdir(prefix.bin) mkdir(prefix.bin)
install('foo', prefix.bin) install("foo", prefix.bin)
install_tree('lib', prefix.lib) install_tree("lib", prefix.lib)
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -152,16 +152,16 @@ set. Once set, ``pypi`` will be used to define the ``homepage``,
.. code-block:: python .. code-block:: python
homepage = 'https://pypi.org/project/setuptools/' homepage = "https://pypi.org/project/setuptools/"
url = 'https://pypi.org/packages/source/s/setuptools/setuptools-49.2.0.zip' url = "https://pypi.org/packages/source/s/setuptools/setuptools-49.2.0.zip"
list_url = 'https://pypi.org/simple/setuptools/' list_url = "https://pypi.org/simple/setuptools/"
is equivalent to: is equivalent to:
.. code-block:: python .. code-block:: python
pypi = 'setuptools/setuptools-49.2.0.zip' pypi = "setuptools/setuptools-49.2.0.zip"
If a package has a different homepage listed on PyPI, you can If a package has a different homepage listed on PyPI, you can
@ -208,7 +208,7 @@ dependencies to your package:
.. code-block:: python .. code-block:: python
depends_on('py-setuptools@42:', type='build') depends_on("py-setuptools@42:", type="build")
Note that ``py-wheel`` is already listed as a build dependency in the Note that ``py-wheel`` is already listed as a build dependency in the
@ -232,7 +232,7 @@ Look for dependencies under the following keys:
* ``dependencies`` under ``[project]`` * ``dependencies`` under ``[project]``
These packages are required for building and installation. You can These packages are required for building and installation. You can
add them with ``type=('build', 'run')``. add them with ``type=("build", "run")``.
* ``[project.optional-dependencies]`` * ``[project.optional-dependencies]``
@ -279,12 +279,12 @@ distutils library, and has almost the exact same API. In addition to
* ``setup_requires`` * ``setup_requires``
These packages are usually only needed at build-time, so you can These packages are usually only needed at build-time, so you can
add them with ``type='build'``. add them with ``type="build"``.
* ``install_requires`` * ``install_requires``
These packages are required for building and installation. You can These packages are required for building and installation. You can
add them with ``type=('build', 'run')``. add them with ``type=("build", "run")``.
* ``extras_require`` * ``extras_require``
@ -296,7 +296,7 @@ distutils library, and has almost the exact same API. In addition to
These are packages that are required to run the unit tests for the These are packages that are required to run the unit tests for the
package. These dependencies can be specified using the package. These dependencies can be specified using the
``type='test'`` dependency type. However, the PyPI tarballs rarely ``type="test"`` dependency type. However, the PyPI tarballs rarely
contain unit tests, so there is usually no reason to add these. contain unit tests, so there is usually no reason to add these.
See https://setuptools.pypa.io/en/latest/userguide/dependency_management.html See https://setuptools.pypa.io/en/latest/userguide/dependency_management.html
@ -321,7 +321,7 @@ older versions of flit may use the following keys:
* ``requires`` under ``[tool.flit.metadata]`` * ``requires`` under ``[tool.flit.metadata]``
These packages are required for building and installation. You can These packages are required for building and installation. You can
add them with ``type=('build', 'run')``. add them with ``type=("build", "run")``.
* ``[tool.flit.metadata.requires-extra]`` * ``[tool.flit.metadata.requires-extra]``
@ -434,12 +434,12 @@ the BLAS/LAPACK library you want pkg-config to search for:
.. code-block:: python .. code-block:: python
depends_on('py-pip@22.1:', type='build') depends_on("py-pip@22.1:", type="build")
def config_settings(self, spec, prefix): def config_settings(self, spec, prefix):
return { return {
'blas': spec['blas'].libs.names[0], "blas": spec["blas"].libs.names[0],
'lapack': spec['lapack'].libs.names[0], "lapack": spec["lapack"].libs.names[0],
} }
@ -463,10 +463,10 @@ has an optional dependency on ``libyaml`` that can be enabled like so:
def global_options(self, spec, prefix): def global_options(self, spec, prefix):
options = [] options = []
if '+libyaml' in spec: if spec.satisfies("+libyaml"):
options.append('--with-libyaml') options.append("--with-libyaml")
else: else:
options.append('--without-libyaml') options.append("--without-libyaml")
return options return options
@ -492,10 +492,10 @@ allows you to specify the directories to search for ``libyaml``:
def install_options(self, spec, prefix): def install_options(self, spec, prefix):
options = [] options = []
if '+libyaml' in spec: if spec.satisfies("+libyaml"):
options.extend([ options.extend([
spec['libyaml'].libs.search_flags, spec["libyaml"].libs.search_flags,
spec['libyaml'].headers.include_flags, spec["libyaml"].headers.include_flags,
]) ])
return options return options
@ -556,7 +556,7 @@ detected are wrong, you can provide the names yourself by overriding
.. code-block:: python .. code-block:: python
import_modules = ['six'] import_modules = ["six"]
Sometimes the list of module names to import depends on how the Sometimes the list of module names to import depends on how the
@ -571,9 +571,9 @@ This can be expressed like so:
@property @property
def import_modules(self): def import_modules(self):
modules = ['yaml'] modules = ["yaml"]
if '+libyaml' in self.spec: if self.spec.satisfies("+libyaml"):
modules.append('yaml.cyaml') modules.append("yaml.cyaml")
return modules return modules
@ -586,14 +586,14 @@ Instead of defining the ``import_modules`` explicitly, only the subset
of module names to be skipped can be defined by using ``skip_modules``. of module names to be skipped can be defined by using ``skip_modules``.
If a defined module has submodules, they are skipped as well, e.g., If a defined module has submodules, they are skipped as well, e.g.,
in case the ``plotting`` modules should be excluded from the in case the ``plotting`` modules should be excluded from the
automatically detected ``import_modules`` ``['nilearn', 'nilearn.surface', automatically detected ``import_modules`` ``["nilearn", "nilearn.surface",
'nilearn.plotting', 'nilearn.plotting.data']`` set: "nilearn.plotting", "nilearn.plotting.data"]`` set:
.. code-block:: python .. code-block:: python
skip_modules = ['nilearn.plotting'] skip_modules = ["nilearn.plotting"]
This will set ``import_modules`` to ``['nilearn', 'nilearn.surface']`` This will set ``import_modules`` to ``["nilearn", "nilearn.surface"]``
Import tests can be run during the installation using ``spack install Import tests can be run during the installation using ``spack install
--test=root`` or at any time after the installation using --test=root`` or at any time after the installation using
@ -612,11 +612,11 @@ after the ``install`` phase:
.. code-block:: python .. code-block:: python
@run_after('install') @run_after("install")
@on_package_attributes(run_tests=True) @on_package_attributes(run_tests=True)
def install_test(self): def install_test(self):
with working_dir('spack-test', create=True): with working_dir("spack-test", create=True):
python('-c', 'import numpy; numpy.test("full", verbose=2)') python("-c", "import numpy; numpy.test('full', verbose=2)")
when testing is enabled during the installation (i.e., ``spack install when testing is enabled during the installation (i.e., ``spack install
@ -638,7 +638,7 @@ provides Python bindings in a ``python`` directory, you can use:
.. code-block:: python .. code-block:: python
build_directory = 'python' build_directory = "python"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -81,28 +81,27 @@ class of your package. For example, you can add it to your
class MyRocmPackage(CMakePackage, ROCmPackage): class MyRocmPackage(CMakePackage, ROCmPackage):
... ...
# Ensure +rocm and amdgpu_targets are passed to dependencies # Ensure +rocm and amdgpu_targets are passed to dependencies
depends_on('mydeppackage', when='+rocm') depends_on("mydeppackage", when="+rocm")
for val in ROCmPackage.amdgpu_targets: for val in ROCmPackage.amdgpu_targets:
depends_on('mydeppackage amdgpu_target={0}'.format(val), depends_on(f"mydeppackage amdgpu_target={val}",
when='amdgpu_target={0}'.format(val)) when=f"amdgpu_target={val}")
... ...
def cmake_args(self): def cmake_args(self):
spec = self.spec spec = self.spec
args = [] args = []
... ...
if '+rocm' in spec: if spec.satisfies("+rocm"):
# Set up the hip macros needed by the build # Set up the hip macros needed by the build
args.extend([ args.extend([
'-DENABLE_HIP=ON', "-DENABLE_HIP=ON",
'-DHIP_ROOT_DIR={0}'.format(spec['hip'].prefix)]) f"-DHIP_ROOT_DIR={spec['hip'].prefix}"])
rocm_archs = spec.variants['amdgpu_target'].value rocm_archs = spec.variants["amdgpu_target"].value
if 'none' not in rocm_archs: if "none" not in rocm_archs:
args.append('-DHIP_HIPCC_FLAGS=--amdgpu-target={0}' args.append(f"-DHIP_HIPCC_FLAGS=--amdgpu-target={','.join(rocm_archs}")
.format(",".join(rocm_archs)))
else: else:
# Ensure build with hip is disabled # Ensure build with hip is disabled
args.append('-DENABLE_HIP=OFF') args.append("-DENABLE_HIP=OFF")
... ...
return args return args
... ...
@ -114,7 +113,7 @@ build.
This example also illustrates how to check for the ``rocm`` variant using This example also illustrates how to check for the ``rocm`` variant using
``self.spec`` and how to retrieve the ``amdgpu_target`` variant's value ``self.spec`` and how to retrieve the ``amdgpu_target`` variant's value
using ``self.spec.variants['amdgpu_target'].value``. using ``self.spec.variants["amdgpu_target"].value``.
All five packages using ``ROCmPackage`` as of January 2021 also use the All five packages using ``ROCmPackage`` as of January 2021 also use the
:ref:`CudaPackage <cudapackage>`. So it is worth looking at those packages :ref:`CudaPackage <cudapackage>`. So it is worth looking at those packages

View file

@ -57,7 +57,7 @@ overridden like so:
.. code-block:: python .. code-block:: python
def test(self): def test(self):
scons('check') scons("check")
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
@ -88,7 +88,7 @@ base class already contains:
.. code-block:: python .. code-block:: python
depends_on('scons', type='build') depends_on("scons", type="build")
If you want to specify a particular version requirement, you can override If you want to specify a particular version requirement, you can override
@ -96,7 +96,7 @@ this in your package:
.. code-block:: python .. code-block:: python
depends_on('scons@2.3.0:', type='build') depends_on("scons@2.3.0:", type="build")
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
@ -238,14 +238,14 @@ the package build phase. This is done by overriding ``build_args`` like so:
def build_args(self, spec, prefix): def build_args(self, spec, prefix):
args = [ args = [
'PREFIX={0}'.format(prefix), f"PREFIX={prefix}",
'ZLIB={0}'.format(spec['zlib'].prefix), f"ZLIB={spec['zlib'].prefix}",
] ]
if '+debug' in spec: if spec.satisfies("+debug"):
args.append('DEBUG=yes') args.append("DEBUG=yes")
else: else:
args.append('DEBUG=no') args.append("DEBUG=no")
return args return args
@ -275,8 +275,8 @@ environment variables. For example, cantera has the following option:
* env_vars: [ string ] * env_vars: [ string ]
Environment variables to propagate through to SCons. Either the Environment variables to propagate through to SCons. Either the
string "all" or a comma separated list of variable names, e.g. string "all" or a comma separated list of variable names, e.g.
'LD_LIBRARY_PATH,HOME'. "LD_LIBRARY_PATH,HOME".
- default: 'LD_LIBRARY_PATH,PYTHONPATH' - default: "LD_LIBRARY_PATH,PYTHONPATH"
In the case of cantera, using ``env_vars=all`` allows us to use In the case of cantera, using ``env_vars=all`` allows us to use

View file

@ -1549,7 +1549,7 @@ its value:
def configure_args(self): def configure_args(self):
... ...
if "+shared" in self.spec: if self.spec.satisfies("+shared"):
extra_args.append("--enable-shared") extra_args.append("--enable-shared")
else: else:
extra_args.append("--disable-shared") extra_args.append("--disable-shared")
@ -1636,7 +1636,7 @@ Within a package recipe a multi-valued variant is tested using a ``key=value`` s
.. code-block:: python .. code-block:: python
if "languages=jit" in spec: if spec.satisfies("languages=jit"):
options.append("--enable-host-shared") options.append("--enable-host-shared")
""""""""""""""""""""""""""""""""""""""""""" """""""""""""""""""""""""""""""""""""""""""
@ -3528,7 +3528,7 @@ need to override methods like ``configure_args``:
def configure_args(self): def configure_args(self):
args = ["--enable-cxx"] + self.enable_or_disable("libs") args = ["--enable-cxx"] + self.enable_or_disable("libs")
if "libs=static" in self.spec: if self.spec.satisfies("libs=static"):
args.append("--with-pic") args.append("--with-pic")
return args return args
@ -4391,7 +4391,7 @@ for supported features, for instance:
.. code-block:: python .. code-block:: python
if "avx512" in spec.target: if spec.satisfies("target=avx512"):
args.append("--with-avx512") args.append("--with-avx512")
The snippet above will append the ``--with-avx512`` item to a list of arguments only if the corresponding The snippet above will append the ``--with-avx512`` item to a list of arguments only if the corresponding