Go to main content

Packaging and Delivering Software With the Image Packaging System in Oracle® Solaris 11.4

Exit Print View

Updated: November 2020
 
 

Dependency Types

In IPS, a package cannot be installed unless all package dependencies are satisfied. IPS allows packages to be mutually dependent (to have circular dependencies). IPS also allows packages to have different kinds of dependencies on the same package at the same time.

Each section in this chapter contains an example depend action as it would appear in a manifest during package creation. Note that dependency specifications do not include the publisher name. See Avoiding Conflicting Package Content for a discussion of possible conflicts.

require Dependency

The most basic type of dependency is the require dependency. These dependencies are typically used to express functional dependencies such as libraries, or interpreters such as Python or Perl.

If a package pkg-a@1.0 contains a require dependency on package pkg-b@2, then if pkg-a@1.0 is installed, the pkg-b package at version 2 or higher must also be installed. This acceptance of higher versioned packages reflects the implicit expectation of binary compatibility in newer versions of existing packages.

If any version of the package named in the depend action is acceptable, you can omit the version portion of the specified FMRI.

An example require dependency is:

depend fmri=pkg:/system/library type=require

require-any Dependency

The require-any dependency is used if any one of multiple target packages as specified by multiple fmri attributes can satisfy the dependency. IPS chooses one of the packages to install if the dependency is not already satisfied.

For example, you could use a require-any dependency to ensure that at least one version of Perl is installed on the system. The versioning is handled in the same manner as for the require dependency.

The order in which packages are listed in a require-any dependency has no effect on which package will be selected to satisfy the dependency. For example, the first package listed is not preferred over any other. The exception is that a package that is already installed and that will not be removed by some other part of the pkg operation is preferred over any package that is not already installed.

An example require-any dependency is:

depend type=require-any fmri=pkg:/editor/gnu-emacs/gnu-emacs-gtk \
    fmri=pkg:/editor/gnu-emacs/gnu-emacs-no-x11 \
    fmri=pkg:/editor/gnu-emacs/gnu-emacs-x11

optional Dependency

The optional dependency specifies that if the given package is installed, it must be at the given version or greater.

This type of dependency is typically used to handle cases where packages transfer content. In this case, each version of the package post-transfer would contain an optional dependency on the post-transfer version of the other package, so that it would be impossible to install incompatible versions of the two packages. Omitting the version on an optional dependency makes the dependency meaningless, but is permitted.

An example optional dependency is:

depend fmri=pkg:/x11/server/xorg@1.9.99 type=optional

conditional Dependency

The conditional dependency has a predicate attribute and an fmri attribute. If the package specified in the value of the predicate attribute is present on the system at the specified or greater version, the conditional dependency is treated as a require dependency on the package in the fmri attribute. If the package specified in the predicate attribute is not present on the system or is present at a lower version, the conditional dependency is ignored.

The conditional dependency is most often used to install optional extensions to a package if the requisite base packages are present on the system.

For example, an editor package that has both X11 and terminal versions might place the X11 version in a separate package, and include a conditional dependency on the X11 version from the text version with the existence of the requisite X client library package as the predicate.

In the following example conditional dependency, package version numbers are not needed because the named packages are already sufficiently version constrained:

depend fmri=library/python/pycurl-35 predicate=runtime/python-35 type=conditional

group Dependency

The group dependency is used to construct groups of packages.

The group dependency ignores the version specified. Any version of the named package satisfies this dependency.

The named package is required unless the package has been the object of one of the following operations:

  • The package has been placed on the avoid list. See the pkg(1) man page for information about the avoid list.

  • No packages that match the fmri value are known.

  • The package has been rejected with pkg install --reject.

  • The package has been uninstalled with pkg uninstall.

These three options enable administrators to deselect packages that are the subject of a group dependency. If any of these three options has been used, IPS will not reinstall the package during an update unless the package was subsequently required by another dependency. If the new dependency is removed by another subsequent operation, then the package is uninstalled again.

Obsolete packages silently satisfy the group dependency, effectively ignoring the dependency.

A good example of how to use these dependencies is to construct packages containing group dependencies on packages that are needed for typical uses of a system. Some examples might be solaris-large-server, solaris-desktop, or developer-gnu. Oracle Solaris Group Packages shows a set of Oracle Solaris packages that deliver group dependencies.

Installing group packages provides confidence that over subsequent updates to newer versions of the OS, the appropriate packages will be added to the system.

An example group dependency is:

depend fmri=package/pkg type=group

group-any Dependency

The group-any dependency is used if any one of multiple target packages as specified by multiple fmri attributes can satisfy the dependency. IPS chooses one of the packages to install if the dependency is not already satisfied. The same rules apply to a group-any dependency that apply to a group dependency with the exception that non-obsolete package stems are preferred over obsolete package stems.

The order in which packages are listed in a group-any dependency has no effect on which package will be selected to satisfy the dependency. For example, the first package listed is not preferred over any other. The following selection preferences exist:

  • A package that is already installed and that will not be removed by some other part of the pkg operation is preferred over any package that is not already installed.

  • If some of the target packages are avoided, another target will be used to satisfy the dependency. If all target packages are avoided, the dependency is ignored.

  • If some of the target packages are obsolete, another target will be used to satisfy the dependency. If all target packages are obsolete, the dependency is ignored.

An example group dependency is:

depend type=group-any \
    fmri=runtime/python-26 \
    fmri=runtime/python-27

origin Dependency

The origin dependency exists to resolve upgrade issues that require intermediate transitions. The default behavior is to specify the minimum version of a package (if installed) that must be present on the image being updated. If the value of the root-image attribute is true, the package must be present on the image rooted at / in order to install this package.

For example, a typical use might be a database package version 5 that supports upgrade from version 3 or greater, but not earlier versions. In this case, version 5 would have an origin dependency on itself at version 3. Thus, if version 5 was being freshly installed, installation would proceed. However, if version 1 of the package was installed, the package could not be upgraded directly to version 5. In this case, pkg update database-package would not select version 5 but instead would select version 3 as the latest possible version to which to upgrade.

If the value of the root-image attribute is true, the dependency target must be at the specified version or greater if it is present in the running system, rather than on the image being updated. This form of the origin dependency is generally used for operating system issues such as dependencies on boot block installers.

An example origin dependency is:

depend fmri=pkg:/database/mydb@3.0 type=origin

Device Driver with Manually Maintained Firmware

Device drivers should manage their own firmware: Firmware should be delivered in the driver package and should be updated when the administrator uses the pkg update command to update the driver. See Firmware Compatibility in Writing Device Drivers in Oracle Solaris 11.4 for driver design information. Drivers also should continue to function with downrev firmware, even if some new features might not be supported.

A few drivers require manual intervention to update the device firmware, separate from running pkg update to update the driver. A few of these drivers with manually maintained firmware are not compatible with all older versions of the firmware and have a minimum version requirement for the firmware. The origin dependency can be used to prevent installation of a driver that is not compatible with the currently installed firmware, which can prevent a system upgrade that results in a system that is not fully functioning.

The origin dependency can be used to specify the minimum version of the device firmware that is compatible with the version of the driver that is being delivered. If the value of the root-image attribute is true and the value of the fmri attribute starts with pkg:/feature/firmware/, the remainder of the fmri value is treated as a command in /usr/lib/fwenum that evaluates the firmware dependency. When an administrator attempts to update a package that specifies this type of dependency and the firmware enumerator determines that the firmware dependency is not satisfied, an error message is displayed and the update is not performed: the system is not changed. The error message shows the firmware version that is required for devices managed by this driver. Once the firmware has been updated, the administrator can attempt the pkg update again.

The following is an example of an origin dependency with a minimum firmware version requirement:

depend fmri=pkg:/feature/firmware/mpt_sas minimum-version=1.0.0.0 \
root-image=true type=origin variant.opensolaris.zone=global

The pkg client invokes the firmware enumerator as shown in the following example:

/usr/lib/fwenum/mpt_sas minimum-version=1.0.0.0

The following sample message from the pkg client tells the administrator that two devices that are managed by the mpt_sas driver have firmware whose version does not satisfy the minimum requirement. The message also states that minimum required firmware version.

There are 2 instances of downrev firmware for the mpt_sas devices present on this system;
upgrade each to version 1.0.0.0 or greater to permit installation of this version of Solaris.

If a driver supports the same device from multiple vendors, the dependency can specify a vendor attribute in addition to the minimum-version attribute.

incorporate Dependency

The incorporate dependency specifies that if the given package is installed, it must be at the given version, to the given version accuracy. For example, if the dependent FMRI has a version of 1.4.3, then no version less than 1.4.3 or greater than or equal to 1.4.4 satisfies the dependency. Version 1.4.3.7 does satisfy this example dependency.

The common way to use incorporate dependencies is to put many of them in the same package to define a surface in the package version space that is compatible. Packages that contain such sets of incorporate dependencies are often called constraint packages. Constraint packages are typically used to define sets of software packages that are built together and are not separately versioned. The incorporate dependency is heavily used in Oracle Solaris to ensure that compatible versions of software are installed together.

An example incorporate dependency is:

depend type=incorporate \
    fmri=pkg:/driver/network/ethernet/e1000g@11.4-11.4.14.0.1.5.0

parent Dependency

The parent dependency is used for zones or other child images. In this case, the dependency is only checked in the child image, and specifies a package and version that must be present in the parent image or global zone. The version specified must match to the level of precision specified.

For example, if the parent dependency is on A@2.1, then any version of A beginning with 2.1 matches. This dependency is often used to require that packages are kept in sync between non-global zones and the global zone. As a shortcut, the special package name feature/package/dependency/self is used as a synonym for the exact version of the package that contains this dependency.

The parent dependency is used to keep key operating system components, such as libc.so.1, installed in the non-global zone synchronized with the kernel installed in the global zone. The parent dependency is also discussed in Handling Non-Global Zones.

An example parent dependency is:

depend type=parent fmri=feature/package/dependency/self \
    variant.opensolaris.zone=nonglobal

exclude Dependency

The package that contains the exclude dependency cannot be installed if the dependent package is installed in the image at the specified version level or greater.

If the version is omitted from the FMRI of an exclude dependency, then no version of the excluded package can be installed concurrently with the package specifying the dependency.

The exclude dependency is seldom used. These constraints can be frustrating to administrators, and should be avoided where possible.

An example exclude dependency is:

depend fmri=pkg:/x11/server/xorg@1.10.99 type=exclude