Errors with installing a Solaris p5p
package
Say you’re packaging a package for Solaris yourself and you need to install it on a slightly older machine than where it was built.
When running a sudo pkg install -g myinstall.p5p myinstall
, you run into the following errors:
Reason: No version matching 'require' dependency shell/bash@5.1.16-11.4.45.0.1.119.0 can be installed
----------------------------------------
Reject: pkg://solaris/shell/bash@5.1.16-11.4.45.0.1.119.0
Reason: No version matching 'require' dependency library/ncurses@6.3-11.4.45.0.0.117.0 can be installed
----------------------------------------
Reject: pkg://solaris/library/ncurses@6.3-11.4.45.0.1.119.0
Reason: No version matching 'require' dependency shell/bash@5.1.16-11.4.45.0.0.117.0 can be installed
----------------------------------------
Reject: pkg://solaris/shell/bash@5.1.16-11.4.48.0.1.126.0
Reason: No version matching 'require' dependency system/library@11.4-11.4.48.0.0.124.0 can be installed
pkgdepend resolve
Per the documentation above, this command will “Transform dependencies on files into dependencies on the packages that deliver those files. Dependencies are first resolved against the manifests given on the command line and then against the packages installed on the system.”
This will result in package version specifications that are relative to the system being built. For example:
depend fmri=pkg:/shell/bash@5.1.16-11.4.45.0.1.119.0 type=require
depend fmri=pkg:/shell/ksh93@93.21.1.20120801-11.4.45.0.1.119.0 type=require
depend fmri=pkg:/system/core-os@11.4-11.4.45.0.1.119.3 type=require
depend fmri=pkg:/system/library/gcc/gcc-c-runtime@11.2.0-11.4.45.0.1.119.0 type=require
depend fmri=pkg:/system/library/libc@11.4-11.4.45.0.1.119.3 type=require
depend fmri=pkg:/system/library/math@11.4-11.4.0.1.0.17.0 type=require
depend fmri=pkg:/system/library/security/crypto@11.4-11.4.45.0.1.119.3 type=require
depend fmri=pkg:/system/library@11.4-11.4.45.0.1.119.3 type=require
depend fmri=pkg:/system/linker@11.4-11.4.45.0.1.119.3 type=require
Because of this, if your Solaris build system has a newer version (even patch level) than your target install system, you may have version dependencies that aren’t resolvable on the target install system (like those that caused our error).
So how do we resolve this problem? This forum post states
The recommended solution to this problem is to build your packages on the oldest release you’re supporting, so that the dependencies will be at that release or later in line with Solaris binary compatibility, Modifying them as you’re doing may work for your case, but it entirely depends on the nature of the dependencies. You can also use the pkgmogrify tool to use a basic manifest template and process it into the final form if needed.
https://forums.oracle.com/ords/apexds/post/while-packaging-is-there-a-way-to-circumvent-that-pkgdepend-6809
So, if you control the entire set of systems being targeted or can require minimum requirements down to the patch level, the first solution is fine. However, if you are a third party source for Solaris users, you probably don’t have as much control. That’s where pkgmogrify
can help.
pkgmogrify
pkgmogrify collects all its input files and then applies any directives found to the inputs. There are more directive available, but the one we’re interested in here is transform
with the edit
operation.
First, lets go back to the depend
directive in the package manifest to understand how we’re going to change it:
depend fmri=pkg:/shell/bash@5.1.16-11.4.45.0.1.119.0 type=require
depend
is the action we’re trying to matchfmri
andtype
(following by=
and a value) are attributes
Now, we’re going to jump to the transform directive to fix it:
<transform depend fmri=pkg:/shell/bash -> edit fmri '@.+' ''>
transform
is the transform directive. There is also aninclude
directive, but we won’t be using that here.depend
is going to be be matched as the action typefmri=pkg:/shell/bash
is going to be matched as anattribute=<value-regexp>
key pair. So the value after the=
is matched as a regex. Fortunately, no regex special characters here, so it just reduced to a substring match->
is the separator between the matching criteria on the left and then operation to be performed on the right.edit
signals that we want to change according to a regex match and substitution.add
,default
,delete
,drop
,emit
,exit
,print
, andset
are also available. Set the linked man page above for more on those.- the
fmri
afteredit
is the name of the attribute that we’re modifying. Yes, it does seem like this is redundant because the attribute name on the match side seems to be an exact match. '@.+'
is the match regex. For the valuepkg:/shell/bash@5.1.16-11.4.45.0.1.119.0
that will match on@5.1.16-11.4.45.0.1.119.0
as a greedy match.''
(this is two single quotes, not a double quote as it may appear in examples elsewhere) specifies the replacement value, which in this case is an empty string.
Based on the above directive, we’re truncating the @
and everything after it in the fmri
value. Note that type=require
is a completely different key/value attribute pair and is unaffected.
Our output from pkgmogrify manifest.res transform-doc
will look like the following (oversimplified to relevant inputs and outputs):
# manifest.res
depend fmri=pkg:/shell/bash@5.1.16-11.4.45.0.1.119.0 type=require
# transform-doc
<transform depend fmri=pkg:/shell/bash -> edit fmri '@.+' ''>
# output
depend fmri=pkg:/shell/bash type=require
The new depend
directive will match whatever version of bash is available.
Reducing the pkgmogrify
transforms
If you’re trying to be backwards-compatible, you’re probably dealing with more than one version conflict. In the case of something like our original set of dependencies mentioned earlier, you would need a transform that addressed each:
<transform depend fmri=pkg:/shell/bash -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/shell/ksh93 -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/core-os -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/library/libc -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/library/math -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/library/security/crypto -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/library -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system/linker -> edit fmri '@.+' ''>
But the match criteria are regular expressions, so you can do the following instead (or however short you want the match string to be):
<transform depend fmri=pkg:/shell -> edit fmri '@.+' ''>
<transform depend fmri=pkg:/system -> edit fmri '@.+' ''>
Keep in mind that this could be a blunt instrument that could impact more dependencies than you intended if you make the match criteria too generic.
Some other commands
Install a package from file
sudo pkg install -g some-package-file-or-uri.p5p package-name
The -g
option directs pkg install
to use a file path or uri to install the package. package-name
still has to match the package file given.
Information on the package
pkg info [-g some-package-file-or-uri.p5p] package-name
$ pkg info bash
Name: shell/bash
Summary: GNU Bourne-Again shell (bash)
Category: System/Shells
State: Installed
Publisher: solaris
Version: 5.1.8
Branch: 11.4.36.0.1.101.0
Packaging Date: July 16, 2021 at 2:42:47 AM
Last Install Time: November 11, 2023 at 12:42:14 AM
Size: 6.86 MB
FMRI: pkg://solaris/shell/bash@5.1.8-11.4.36.0.1.101.0:20210716T024247Z
Project URL: https://www.gnu.org/software/bash
Source URL: https://ftp.gnu.org/gnu/bash/bash-5.1.tar.gz
List all the files in the package
pkg contents [-g some-package-location.p5p] package-name
$ pkg contents bash
PATH
etc/bash/bash_completion.example
etc/bash/bashrc.example
etc/bash/inputrc.example
etc/skel/.bashrc
usr/bin/bash
usr/bin/bashbug
usr/bin/rbash
usr/gnu/bin/sh
usr/share/bash/alias
usr/share/bash/arith
usr/share/bash/arith_for
usr/share/bash/bg
usr/share/bash/bind
usr/share/bash/break
usr/share/bash/builtin
usr/share/bash/caller
usr/share/bash/case
Uninstall
sudo uninstall package_name