openSUSE:Package dependencies
tagline: From openSUSE
Build Service Tutorial · Tips & Tricks · Cross Distribution Howto · Packaging checks
Desktop menu categories · RPM Macros · Scriptlets · Init scripts · How to write good changes
Contents |
How to do distribution upgrades
There are two update modes which need different behaviour
- Bugfixes (Patches)
- Distribution upgrade
In the first mode, installed packages are patched in order to fix bugs or to introduce missing functionality. However, the package version usually stays since the pristine tarball is the same; only the package release number is changed.
Also, the build environment (compiler, libraries, etc.) only sees minimal changes.
Distribution upgrade lifts the complete system to a new level and the operating system version gets increased. (If the system is e.g. openSUSE 10.2, it will increase to openSUSE 10.3) The package changes allowed during distribution upgrade can be much more severe and include
- dropped packages
- new packages
- renamed packages
- merged packages
- splitted packages
Such changes are hard (or even impossible) to express by RPM dependencies. Thus, a more expressive form of package dependencies is needed so the system upgrade can be performed.
This Wiki page documents how to express dependencies for distribution upgrade.
If you are adding dependencies for seamless system upgrade, do not forget to specify the openSUSE version for which these are required. It will allow to recognize these lines as obsolete in future versions (most probably it would be openSUSE version + 1 and SLE version + 2).
Means to express dependencies
Each package can express dependencies on other packages by defining symbolic
names for Provides, Requires, and Conflicts.
These symbolic names are usually names of packages but can also be “abstract”
names not related to a package.
These symbolic names can be used to express capabilities which are unrelated to a specific package. For example, the capability MTA (mail transport agent) is provided by multiple packages, sendmail and postfix being the most prominent.
It is important to remember that all symbolic names (being package or abstract names) reside in the same namespace. When choosing an abstract name (e.g. for a capability), it must not conflict with another package name.
To express update dependencies in order to replace one (old) package with another (newer) package, the Obsoletes tag is used.
Facts for RPM dependencies
- Each package implicitly provides its name.
There is no need to provide the package name, but other packages can require (or conflict with) the package name. - A package can not conflict with a symbolic tag it provides.
Since the package name is provided implicitly, a package can not conflict with itself. - Obsolete works on real package names only.
One can not obsolete a symbolic tag. - Symbolic names, as used in Requires, Provides and Conflicts are case-sensitive.
Basic dependencies
Installing a new package
| pac.spec | |
|---|---|
| Name: | pac |
| Version: | 1.0 |
| Requires: | |
| Provides: | |
| Obsoletes: | |
| Conflicts: |
Updating a package
| pac.spec | |
|---|---|
| Name: | pac |
| Version: | 1.1 |
| Requires: | |
| Provides: | |
| Obsoletes: | |
| Conflicts: |
The matching name and the higher version make this an update for pac-1.0.
Renaming a package
| package.spec | ||
|---|---|---|
| Name: | package | |
| Version: | 1.1 | |
| Requires: | ||
| Provides: | pac = %version | |
| Obsoletes: | pac < %version | |
| Conflicts: |
Strictly speaking, giving the old package name in the Provides: field is only needed if another package requires the old package name. Please add the Version number to the field of the old package name, so a later re-renaming is possible. (For example: Provides: pac = 1.0). In 90% of the cases, you can just use %version as in the example above.
However, the Provides: entry triggers the selection of the new package during update. It is this field which tells that it is taking over for the old package. The Obsoletes: just says to delete the package. The Version: field is irrelevant here, but you should also add the old package version number to the Obsoletes: field (in this example: Obsoletes: pac <= 1.0) to enable "the way back" to the old package name with a higher version number. As shown in the example, you can use %version here aswell. Be sure to only use "<" in that case, otherwise you can not revert to the old name within the same version.
If you obsolete a subpackage with a different version number than the main package, you can not use %version in Provides/Obsoletes. Of course, you can use the same version string as in Version of the subpackage.
Please also add a simple comment to the specfile, e. g. “# pac was last used in openSUSE 12.3”. Without it, it will be hard to decide when it is possible to wipe these lines out. Otherwise, it may stay there forever.
Replace a package by another with the same functionality
| package.spec | |
|---|---|
| Name: | package |
| Version: | 1.1 |
| Requires: | |
| Provides: | |
| Obsoletes: | pac < %version |
| Conflicts: |
Instead of renaming a package, pac will be replaced by package, although package provides no files of pac. So package does not provide pac.
This only works if one package obsoletes pac only. If there are more packages, the solver will not do this update.
Splitting and Merging
Splitting off a sub-package
| pac.spec | pac-devel.spec | |||
|---|---|---|---|---|
| Name: | pac | Name: | pac-devel | |
| Version: | 1.1 | Version: | 1.1 | |
| Requires: | Requires: | |||
| Provides: | Provides: | pac:/file/from/pac | ||
| Obsoletes: | Obsoletes: | |||
| Conflicts: | Conflicts: |
Splitting a package into two
| firstpac.spec | secondpac.spec | |||
|---|---|---|---|---|
| Name: | firstpac | Name: | secondpac | |
| Version: | 1.1 | Version: | 1.1 | |
| Requires: | Requires: | |||
| Provides: | pac = 8.15 | Provides: | pac:/file/from/pac | |
| Obsoletes: | pac <= 8.15 | Obsoletes: | ||
| Conflicts: | Conflicts: |
The example shown lists separate spec files for pac and pac-devel. (Remember that RPM allows to define sub-packages from a “main” package with a single .spec file.
The dependency resolution (installing both new packages) is done by YaST with the split-alias mentioned in Provides: of pac-devel.
It is up to the package maintainer to decide about dependencies between pac and pac-devel. For example, if one wants to split a library package into a main, a -devel, and a -doc package, the main and the -doc package are independant, but the -devel package requires the main package.
During an update, the aformentioned split-alias tag is important. YaST only updates already installed packages, in this case only the main package. Without the split-alias, this would remove files needed for development which were part of the old main package but are not in the new main package.
The given Provides: for pac now triggers this update dependency as it tells YaST also to install pac-devel even though it was not installed before.
If a package is split in more than two packages, the split-alias tags must be mutually exclusive. It is the only way for YaST to correctly handle such update dependencies.
Important enhancement for the future
Splitting a library package into a main and a -devel package is always a good idea. But it does not make sense in every case — because sometimes, the -devel package would be too small or does not contain anything. In this case, just add a Provides: pac-devel = %version in the main package to do the trick that other packages can require this virtual -devel package.
Please also add a simple comment to the specfile, e. g. “# -devel splitted in openSUSE 12.3”. Without it, it will be hard to decide when it is possible to wipe these lines out. Otherwise it may stay there forever.
Merging a package
| package.spec | |
|---|---|
| Name: | package |
| Version: | 1.1 |
| Requires: | |
| Provides: | pac = 8.15 |
| Obsoletes: | pac <= 8.15 |
| Conflicts: |
This is comparable to a package rename. The new package must also incorporate the Provides and Obsoletes tags from the old package. This is needed to properly update from distribution before X.
Merging two packages into a new one
| package.spec | |
|---|---|
| Name: | package |
| Version: | 1.1 |
| Requires: | |
| Provides: | pac1 = 8.15, pac2 = 2.3 |
| Obsoletes: | pac1 <= 8.15, pac2 <= 2.3 |
| Conflicts: |
Handling alternatives
Non conflicting
| firstpac.spec | secondpac.spec | thirdpac.spec | |||||
|---|---|---|---|---|---|---|---|
| Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
| Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
| Requires: | Requires: | Requires: | |||||
| Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac 1.0 | ||
| Obsoletes: | Obsoletes: | Obsoletes: | |||||
| Conflicts: | Conflicts: | Conflicts: |
All three package provide the capability Pac and can be installed in parallel.
(The upper case letter in Pac is choosen on purpose to distinguish this tag from a package. Such capabilities must be agreed upon within the openSUSE community. Ask on the "opensuse-packaging" mailing list before inventing your own tag!).
Example: xdm and kdm provide capability "Display-Manager".
Partially conflicting
| firstpac.spec | secondpac.spec | thirdpac.spec | |||||
|---|---|---|---|---|---|---|---|
| Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
| Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
| Requires: | Requires: | Requires: | |||||
| Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | ||
| Obsoletes: | Obsoletes: | Obsoletes: | |||||
| Conflicts: | secondpac | Conflicts: | firstpac | Conflicts: |
The Conflicts express that only either firstpac or secondpac might be installed, but not both.
Mutually exclusive
| firstpac.spec | secondpac.spec | thirdpac.spec | |||||
|---|---|---|---|---|---|---|---|
| Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
| Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
| Requires: | Requires: | Requires: | |||||
| Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | ||
| Obsoletes: | Obsoletes: | Obsoletes: | |||||
| Conflicts: | secondpac thirdpac | Conflicts: | firstpac thirdpac | Conflicts: | firstpac secondpac |
Only one of firstpac, secondpac, or thirdpac might be installed.










