diff options
author | Harmen Stoppels <me@harmenstoppels.nl> | 2024-11-04 13:52:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-04 13:52:05 +0100 |
commit | 8d0856d1cc3f8d097b8f4a7e5a18ad662b8434c5 (patch) | |
tree | c4d150a1189ac05738e7dda3f8c7feed6f18e217 /lib | |
parent | 10f7014addebfe1a104f558f9cf1901fd1702452 (diff) | |
download | spack-8d0856d1cc3f8d097b8f4a7e5a18ad662b8434c5.tar.gz spack-8d0856d1cc3f8d097b8f4a7e5a18ad662b8434c5.tar.bz2 spack-8d0856d1cc3f8d097b8f4a7e5a18ad662b8434c5.tar.xz spack-8d0856d1cc3f8d097b8f4a7e5a18ad662b8434c5.zip |
packaging_guide.rst: explain forward and backward compat before the less common cases (#47402)
The idea is to go from most to least used: backward compat -> forward compat -> pinning on major or major.minor version -> pinning specific, concrete versions.
Further, the following
```python
# backward compatibility with Python
depends_on("python@3.8:")
depends_on("python@3.9:", when="@1.2:")
depends_on("python@3.10:", when="@1.4:")
# forward compatibility with Python
depends_on("python@:3.12", when="@:1.10")
depends_on("python@:3.13", when="@:1.12")
depends_on("python@:3.14")
```
is better than disjoint when ranges causing repetition of the rules on dependencies, and requiring frequent editing of existing lines after new releases are done:
```python
depends_on("python@3.8:3.12", when="@:1.1")
depends_on("python@3.9:3.12", when="@1.2:1.3")
depends_on("python@3.10:3.12", when="@1.4:1.10")
depends_on("python@3.10:3.13", when="@1.11:1.12")
depends_on("python@3.10:3.14", when="@1.13:")
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/docs/packaging_guide.rst | 91 |
1 files changed, 63 insertions, 28 deletions
diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index a736ff8c79..d9a37175b6 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -2503,15 +2503,14 @@ with. For example, suppose that in the ``libdwarf`` package you write: depends_on("libelf@0.8") -Now ``libdwarf`` will require ``libelf`` at *exactly* version ``0.8``. -You can also specify a requirement for a particular variant or for -specific compiler flags: +Now ``libdwarf`` will require ``libelf`` in the range ``0.8``, which +includes patch versions ``0.8.1``, ``0.8.2``, etc. Apart from version +restrictions, you can also specify variants if this package requires +optional features of the dependency. .. code-block:: python - depends_on("libelf@0.8+debug") - depends_on("libelf debug=True") - depends_on("libelf cppflags='-fPIC'") + depends_on("libelf@0.8 +parser +pic") Both users *and* package authors can use the same spec syntax to refer to different package configurations. Users use the spec syntax on the @@ -2519,46 +2518,82 @@ command line to find installed packages or to install packages with particular constraints, and package authors can use specs to describe relationships between packages. -^^^^^^^^^^^^^^ -Version ranges -^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Specifying backward and forward compatibility +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Packages are often compatible with a range of versions of their +dependencies. This is typically referred to as backward and forward +compatibility. Spack allows you to specify this in the ``depends_on`` +directive using version ranges. -Although some packages require a specific version for their dependencies, -most can be built with a range of versions. For example, if you are -writing a package for a legacy Python module that only works with Python -2.4 through 2.6, this would look like: +**Backwards compatibility** means that the package requires at least a +certain version of its dependency: .. code-block:: python - depends_on("python@2.4:2.6") + depends_on("python@3.10:") -Version ranges in Spack are *inclusive*, so ``2.4:2.6`` means any version -greater than or equal to ``2.4`` and up to and including any ``2.6.x``. If -you want to specify that a package works with any version of Python 3 (or -higher), this would look like: +In this case, the package requires Python 3.10 or newer. + +Commonly, packages drop support for older versions of a dependency as +they release new versions. In Spack you can conveniently add every +backward compatibility rule as a separate line: .. code-block:: python - depends_on("python@3:") + # backward compatibility with Python + depends_on("python@3.8:") + depends_on("python@3.9:", when="@1.2:") + depends_on("python@3.10:", when="@1.4:") + +This means that in general we need Python 3.8 or newer; from version +1.2 onwards we need Python 3.9 or newer; from version 1.4 onwards we +need Python 3.10 or newer. Notice that it's fine to have overlapping +ranges in the ``when`` clauses. -Here we leave out the upper bound. If you want to say that a package -requires Python 2, you can similarly leave out the lower bound: +**Forward compatibility** means that the package requires at most a +certain version of its dependency. Forward compatibility rules are +necessary when there are breaking changes in the dependency that the +package cannot handle. In Spack we often add forward compatibility +bounds only at the time a new, breaking version of a dependency is +released. As with backward compatibility, it is typical to see a list +of forward compatibility bounds in a package file as seperate lines: .. code-block:: python - depends_on("python@:2") + # forward compatibility with Python + depends_on("python@:3.12", when="@:1.10") + depends_on("python@:3.13", when="@:1.12") + +Notice how the ``:`` now appears before the version number both in the +dependency and in the ``when`` clause. This tells Spack that in general +we need Python 3.13 or older up to version ``1.12.x``, and up to version +``1.10.x`` we need Python 3.12 or older. Said differently, forward compatibility +with Python 3.13 was added in version 1.11, while version 1.13 added forward +compatibility with Python 3.14. + +Notice that a version range ``@:3.12`` includes *any* patch version +number ``3.12.x``, which is often useful when specifying forward compatibility +bounds. + +So far we have seen open-ended version ranges, which is by far the most +common use case. It is also possible to specify both a lower and an upper bound +on the version of a dependency, like this: + +.. code-block:: python -Notice that we didn't use ``@:3``. Version ranges are *inclusive*, so -``@:3`` means "up to and including any 3.x version". + depends_on("python@3.10:3.12") -You can also simply write +There is short syntax to specify that a package is compatible with say any +``3.x`` version: .. code-block:: python - depends_on("python@2.7") + depends_on("python@3") -to tell Spack that the package needs Python 2.7.x. This is equivalent to -``@2.7:2.7``. +The above is equivalent to ``depends_on("python@3:3")``, which means at least +Python version 3 and at most any version ``3.x.y``. In very rare cases, you may need to specify an exact version, for example if you need to distinguish between ``3.2`` and ``3.2.1``: |