talk about data classes in docs
This commit is contained in:
parent
14b090e896
commit
8f9fb4d1fe
@ -2253,21 +2253,10 @@ RPATHs in Spack are handled in one of three ways:
|
|||||||
set in standard variables like ``CC``, ``CXX``, ``F77``, and ``FC``,
|
set in standard variables like ``CC``, ``CXX``, ``F77``, and ``FC``,
|
||||||
so most build systems (autotools and many gmake systems) pick them
|
so most build systems (autotools and many gmake systems) pick them
|
||||||
up and use them.
|
up and use them.
|
||||||
#. CMake also respects Spack's compiler wrappers, but many CMake
|
#. CMake also respects Spack's compiler wrappers during the build, but
|
||||||
builds have logic to overwrite RPATHs when binaries are
|
modifies them upon installation. If you inherit from ``CMakePackage``,
|
||||||
installed. Spack provides the ``std_cmake_args`` variable, which
|
Spack will set the default ``cmake`` defines to ensure that RPATHs
|
||||||
includes parameters necessary for CMake build use the right
|
are set correctly upon installation.
|
||||||
installation RPATH. It can be used like this when ``cmake`` is
|
|
||||||
invoked:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class MyPackage(Package):
|
|
||||||
...
|
|
||||||
def install(self, spec, prefix):
|
|
||||||
cmake("..", *std_cmake_args)
|
|
||||||
make()
|
|
||||||
make("install")
|
|
||||||
|
|
||||||
#. If you need to modify the build to add your own RPATHs, you can
|
#. If you need to modify the build to add your own RPATHs, you can
|
||||||
use the ``self.rpath`` property of your package, which will
|
use the ``self.rpath`` property of your package, which will
|
||||||
@ -2322,18 +2311,23 @@ commands, as ``libdwarf`` does:
|
|||||||
:emphasize-lines: 9, 12
|
:emphasize-lines: 9, 12
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
configure: Executable
|
||||||
|
make: Executable
|
||||||
|
|
||||||
class Libelf(Package):
|
class Libelf(Package):
|
||||||
|
data: Data
|
||||||
...
|
...
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
configure("--prefix=" + prefix,
|
self.data.configure("--prefix=" + prefix,
|
||||||
"--enable-shared",
|
"--enable-shared",
|
||||||
"--disable-dependency-tracking",
|
"--disable-dependency-tracking",
|
||||||
"--disable-debug")
|
"--disable-debug")
|
||||||
make()
|
self.data.make()
|
||||||
|
|
||||||
# The mkdir commands in libelf's install can fail in parallel
|
# The mkdir commands in libelf's install can fail in parallel
|
||||||
make("install", parallel=False)
|
self.data.make("install", parallel=False)
|
||||||
|
|
||||||
The first make will run in parallel here, but the second will not. If
|
The first make will run in parallel here, but the second will not. If
|
||||||
you set ``parallel`` to ``False`` at the package level, then each call
|
you set ``parallel`` to ``False`` at the package level, then each call
|
||||||
@ -2346,20 +2340,17 @@ can use the variable ``make_jobs`` to extract the number of jobs specified
|
|||||||
by the ``--jobs`` option:
|
by the ``--jobs`` option:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:emphasize-lines: 7, 11
|
:emphasize-lines: 2, 8
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
make_jobs: int
|
||||||
|
|
||||||
class Xios(Package):
|
class Xios(Package):
|
||||||
...
|
...
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
...
|
make_xios = Executable("./make_xios")
|
||||||
options = [
|
make_xios(..., "--jobs", str(self.pkg.make_jobs))
|
||||||
...
|
|
||||||
'--jobs', str(make_jobs),
|
|
||||||
]
|
|
||||||
...
|
|
||||||
make_xios = Executable("./make_xios")
|
|
||||||
make_xios(*options)
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Install-level build parallelism
|
Install-level build parallelism
|
||||||
@ -2949,14 +2940,45 @@ This means that the former should only be used if the environment variables depe
|
|||||||
package, whereas the latter should be used if the environment variables depend only on the package
|
package, whereas the latter should be used if the environment variables depend only on the package
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
--------------------------------
|
---------------------------------------------------------
|
||||||
Setting package module variables
|
Setting and requesting Python variables with data classes
|
||||||
--------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Apart from modifying environment variables of the dependent package, you can also define Python
|
Apart from environment variables, Spack also provides a way to set Python variables that are
|
||||||
variables to be used by the dependent. This is done by implementing
|
necessary for configuring or building a package. A package that requires certain Python variables
|
||||||
:meth:`setup_dependent_package <spack.package_base.PackageBase.setup_dependent_package>`. An
|
for its build can declare them using a data class and an annotation in the package class:
|
||||||
example of this can be found in the ``Python`` package:
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 1-2,5,10-11
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
make: Executable
|
||||||
|
|
||||||
|
class MyPackage(Package):
|
||||||
|
data: Data
|
||||||
|
|
||||||
|
depends_on("gmake", type="build")
|
||||||
|
|
||||||
|
def install(self, spec, prefix):
|
||||||
|
self.data.make("mytarget")
|
||||||
|
self.data.make("install", parallel=False)
|
||||||
|
|
||||||
|
The dependency ``gmake`` implements :meth:`setup_dependent_package <spack.package_base.PackageBase.setup_dependent_package>`
|
||||||
|
to set the ``make`` variable so it can be used by the dependent package:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
class Gmake(Package):
|
||||||
|
...
|
||||||
|
def setup_dependent_package(self, module, dependent_spec):
|
||||||
|
module.make = MakeExecutable(
|
||||||
|
self.spec.prefix.bin.make,
|
||||||
|
jobs=determine_number_of_jobs(dependent_spec),
|
||||||
|
)
|
||||||
|
|
||||||
|
Another example of this can be found in the ``Python`` package:
|
||||||
|
|
||||||
.. literalinclude:: _spack_root/var/spack/repos/spack_repo/builtin/packages/python/package.py
|
.. literalinclude:: _spack_root/var/spack/repos/spack_repo/builtin/packages/python/package.py
|
||||||
:pyobject: Python.setup_dependent_package
|
:pyobject: Python.setup_dependent_package
|
||||||
@ -2966,14 +2988,45 @@ This allows Python packages to directly use these variables:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
class Data:
|
||||||
...
|
python_platlib: str
|
||||||
install("script.py", python_platlib)
|
|
||||||
|
|
||||||
.. note::
|
class MyPythonPackage(Package):
|
||||||
|
data: Data
|
||||||
|
|
||||||
We recommend using ``setup_dependent_package`` sparingly, as it is not always clear where
|
extends("python")
|
||||||
global variables are coming from when editing a ``package.py`` file.
|
|
||||||
|
def install(self, spec, prefix):
|
||||||
|
...
|
||||||
|
install("script.py", self.data.python_platlib)
|
||||||
|
|
||||||
|
There are a few special variables that are set by Spack's build environment instead of by
|
||||||
|
dependencies. These can be request in the data class as well. Among those are ``make_jobs: int``,
|
||||||
|
``configure: Executable``, ``prefix: Prefix``, and ``dso_suffix: str``.
|
||||||
|
|
||||||
|
Notice that type hints in data classes are not required and not enforced at runtime. They are only
|
||||||
|
used for documentation purposes and to help IDEs with code completion.
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
Module level variables (legacy)
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
For packages that do not use the data class mechanism, Spack will still set global variables
|
||||||
|
in the package module. This is an artifact of the legacy package system and is not recommended
|
||||||
|
to be used in new packages.
|
||||||
|
|
||||||
|
If we omit the data class in the previous example, we can still use the ``make`` variable as
|
||||||
|
a global variable:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class MyPackage(Package):
|
||||||
|
def install(self, spec, prefix):
|
||||||
|
make("mytarget") # not recommended, use data class instead
|
||||||
|
make("install", parallel=False)
|
||||||
|
|
||||||
|
This is not recommended, because it is unclear where the ``make`` variable is set, and leads to
|
||||||
|
issues with editors and type checkers.
|
||||||
|
|
||||||
-----
|
-----
|
||||||
Views
|
Views
|
||||||
|
Loading…
Reference in New Issue
Block a user