Expand multiple build systems section (#39589)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
This commit is contained in:
parent
3752fe9e42
commit
c9677b2465
@ -3635,7 +3635,8 @@ regardless of the build system. The arguments for the phase are:
|
|||||||
The arguments ``spec`` and ``prefix`` are passed only for convenience, as they always
|
The arguments ``spec`` and ``prefix`` are passed only for convenience, as they always
|
||||||
correspond to ``self.spec`` and ``self.spec.prefix`` respectively.
|
correspond to ``self.spec`` and ``self.spec.prefix`` respectively.
|
||||||
|
|
||||||
If the ``package.py`` encodes builders explicitly, the signature for a phase changes slightly:
|
If the ``package.py`` has build instructions in a separate
|
||||||
|
:ref:`builder class <multiple_build_systems>`, the signature for a phase changes slightly:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -3645,56 +3646,6 @@ If the ``package.py`` encodes builders explicitly, the signature for a phase cha
|
|||||||
|
|
||||||
In this case the package is passed as the second argument, and ``self`` is the builder instance.
|
In this case the package is passed as the second argument, and ``self`` is the builder instance.
|
||||||
|
|
||||||
.. _multiple_build_systems:
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
Multiple build systems
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
There are cases where a software actively supports two build systems, or changes build systems
|
|
||||||
as it evolves, or needs different build systems on different platforms. Spack allows dealing with
|
|
||||||
these cases natively, if a recipe is written using builders explicitly.
|
|
||||||
|
|
||||||
For instance, software that supports two build systems unconditionally should derive from
|
|
||||||
both ``*Package`` base classes, and declare the possible use of multiple build systems using
|
|
||||||
a directive:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class ArpackNg(CMakePackage, AutotoolsPackage):
|
|
||||||
|
|
||||||
build_system("cmake", "autotools", default="cmake")
|
|
||||||
|
|
||||||
In this case the software can be built with both ``autotools`` and ``cmake``. Since the package
|
|
||||||
supports multiple build systems, it is necessary to declare which one is the default. The ``package.py``
|
|
||||||
will likely contain some overriding of default builder methods:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
|
||||||
def cmake_args(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
|
||||||
def configure_args(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
In more complex cases it might happen that the build system changes according to certain conditions,
|
|
||||||
for instance across versions. That can be expressed with conditional variant values:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class ArpackNg(CMakePackage, AutotoolsPackage):
|
|
||||||
|
|
||||||
build_system(
|
|
||||||
conditional("cmake", when="@0.64:"),
|
|
||||||
conditional("autotools", when="@:0.63"),
|
|
||||||
default="cmake",
|
|
||||||
)
|
|
||||||
|
|
||||||
In the example the directive impose a change from ``Autotools`` to ``CMake`` going
|
|
||||||
from ``v0.63`` to ``v0.64``.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
Mixin base classes
|
Mixin base classes
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
@ -3741,6 +3692,106 @@ for instance:
|
|||||||
|
|
||||||
In the example above ``Cp2k`` inherits all the conflicts and variants that ``CudaPackage`` defines.
|
In the example above ``Cp2k`` inherits all the conflicts and variants that ``CudaPackage`` defines.
|
||||||
|
|
||||||
|
.. _multiple_build_systems:
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
Multiple build systems
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
There are cases where a package actively supports two build systems, or changes build systems
|
||||||
|
as it evolves, or needs different build systems on different platforms. Spack allows dealing with
|
||||||
|
these cases by splitting the build instructions into separate builder classes.
|
||||||
|
|
||||||
|
For instance, software that supports two build systems unconditionally should derive from
|
||||||
|
both ``*Package`` base classes, and declare the possible use of multiple build systems using
|
||||||
|
a directive:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Example(CMakePackage, AutotoolsPackage):
|
||||||
|
|
||||||
|
variant("my_feature", default=True)
|
||||||
|
|
||||||
|
build_system("cmake", "autotools", default="cmake")
|
||||||
|
|
||||||
|
In this case the software can be built with both ``autotools`` and ``cmake``. Since the package
|
||||||
|
supports multiple build systems, it is necessary to declare which one is the default.
|
||||||
|
|
||||||
|
Additional build instructions are split into separate builder classes:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
||||||
|
def cmake_args(self):
|
||||||
|
return [
|
||||||
|
self.define_from_variant("MY_FEATURE", "my_feature")
|
||||||
|
]
|
||||||
|
|
||||||
|
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
||||||
|
def configure_args(self):
|
||||||
|
return self.with_or_without("my-feature", variant="my_feature")
|
||||||
|
|
||||||
|
In this example, ``spack install example +feature build_sytem=cmake`` will
|
||||||
|
pick the ``CMakeBuilder`` and invoke ``cmake -DMY_FEATURE:BOOL=ON``.
|
||||||
|
|
||||||
|
Similarly, ``spack install example +feature build_system=autotools`` will pick
|
||||||
|
the ``AutotoolsBuilder`` and invoke ``./configure --with-my-feature``.
|
||||||
|
|
||||||
|
Dependencies are always specified in the package class. When some dependencies
|
||||||
|
depend on the choice of the build system, it is possible to use when conditions as
|
||||||
|
usual:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Example(CMakePackage, AutotoolsPackage):
|
||||||
|
|
||||||
|
build_system("cmake", "autotools", default="cmake")
|
||||||
|
|
||||||
|
# Runtime dependencies
|
||||||
|
depends_on("ncurses")
|
||||||
|
depends_on("libxml2")
|
||||||
|
|
||||||
|
# Lowerbounds for cmake only apply when using cmake as the build system
|
||||||
|
with when("build_system=cmake"):
|
||||||
|
depends_on("cmake@3.18:", when="@2.0:", type="build")
|
||||||
|
depends_on("cmake@3:", type="build")
|
||||||
|
|
||||||
|
# Specify extra build dependencies used only in the configure script
|
||||||
|
with when("build_system=autotools"):
|
||||||
|
depends_on("perl", type="build")
|
||||||
|
depends_on("pkgconfig", type="build")
|
||||||
|
|
||||||
|
Very often projects switch from one build system to another, or add support
|
||||||
|
for a new build system from a certain version, which means that the choice
|
||||||
|
of the build system typically depends on a version range. Those situations can
|
||||||
|
be handled by using conditional values in the ``build_system`` directive:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Example(CMakePackage, AutotoolsPackage):
|
||||||
|
|
||||||
|
build_system(
|
||||||
|
conditional("cmake", when="@0.64:"),
|
||||||
|
conditional("autotools", when="@:0.63"),
|
||||||
|
default="cmake",
|
||||||
|
)
|
||||||
|
|
||||||
|
In the example the directive impose a change from ``Autotools`` to ``CMake`` going
|
||||||
|
from ``v0.63`` to ``v0.64``.
|
||||||
|
|
||||||
|
The ``build_system`` can be used as an ordinary variant, which also means that it can
|
||||||
|
be used in ``depends_on`` statements. This can be useful when a package *requires* that
|
||||||
|
its dependency has a CMake config file, meaning that the dependent can only build when the
|
||||||
|
dependency is built with CMake, and not Autotools. In that case, you can force the choice
|
||||||
|
of the build system in the dependent:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Dependent(CMakePackage):
|
||||||
|
|
||||||
|
depends_on("example build_system=cmake")
|
||||||
|
|
||||||
|
|
||||||
.. _install-environment:
|
.. _install-environment:
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user