summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHarmen Stoppels <me@harmenstoppels.nl>2023-10-13 14:59:44 +0200
committerGitHub <noreply@github.com>2023-10-13 14:59:44 +0200
commitc9677b24651270d1e9c7c3fe37329d460f5544b9 (patch)
tree3cfe50d39ff4d5482a34c21330c02dd9f4679bf3 /lib
parent3752fe9e4249e4467c8ab0badab876a81b186619 (diff)
downloadspack-c9677b24651270d1e9c7c3fe37329d460f5544b9.tar.gz
spack-c9677b24651270d1e9c7c3fe37329d460f5544b9.tar.bz2
spack-c9677b24651270d1e9c7c3fe37329d460f5544b9.tar.xz
spack-c9677b24651270d1e9c7c3fe37329d460f5544b9.zip
Expand multiple build systems section (#39589)
Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/packaging_guide.rst153
1 files changed, 102 insertions, 51 deletions
diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst
index d25009532a..acc79ea342 100644
--- a/lib/spack/docs/packaging_guide.rst
+++ b/lib/spack/docs/packaging_guide.rst
@@ -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
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
@@ -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.
-.. _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
^^^^^^^^^^^^^^^^^^
@@ -3741,6 +3692,106 @@ for instance:
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:
-----------------------