build-pkg - A script to aid packaging
build-pkg [-hivlomPKFRNT] [-C config] [-w work_dir] [-I cmd] [-n file] [-c category] [-p name] [-u user] [-g group] [-y args] [-U src:dst[, ...]] [-G src:dst[, ...]] [-V version] [-O file] [cmd ...]
Supported options are:
pkginfo file if that is
required.
pkgmk is removed.
build
directory and not the defaults of root for the owner and bin for the
group.
This is useful if you are building a package where the software concerned makes use of setuid, setuid components, directories owned by non-root users, etc.
build
directory and do not play around with the permissions
This is useful if you are building a package where the software concerned makes use of setuid, setuid components, directories owned by non-root users, etc.
perl module, even if the blib
directory exists under the current working directory.
chroot-install that it should clean the build directory
before performing any work. See the -S option to chroot-install
for more details.
chroot-install that it should fix the file permissions it
finds. See the -F option to chroot-install for more details.
Note that if chroot-install is not called - i.e. the
InstallPackage/build directory is already built - then this option
instructs build-pkg to fix the directory permissions directly.
chroot-install, even if build-pkg thinks that it should
be run. This is most useful if you are attempting to build a package which
consists solely of package control scripts like postinstall, postremote,
etc.
template-control to process any package control script template
files.
pkginfo file for a new version of the software.
$HOME/.build-pkg
This file has a relatively simple format. Lines starting with a # or
which are blank (no characters or all spaces) are ignored. All other
lines have the format of:
key = value
Where valid keys are:
+-------------+-----------------------------------------+ | Key | Value should be... | +-------------+-----------------------------------------+ | PkgPrefix | Prefix to the package name | | BaseDir | The base directory | | PerlBaseDir | The base directory for perl modules | | Category | The category prefix | | Vendor | Vendor name | | Class | Class of package | | Email | EMail address of package builder | | Name | Name of the package builder | | WaitTime | Time to wait after an error has occured | +-------------+-----------------------------------------+
$PWD/InstallPackage
chroot-install command; this can be a
command name which is on the PATH. The default is chroot-install
%[pkginfo variable]%''.
eg %PKG%. The default is %PKG%-v%VERSION%-sol%OSVER%-%ARCH%.pkg.
application'' or ``system''. If neither is
present then the category of ``application'' is added.
/etc/passwd. Numeric UIDs can
not be given.
/etc/group. Numeric GIDs can not
be given.
chroot-install. This
allows you to pass specific arguements to chroot-install
like the -d and -l options. Remember that you'll have
have to surround such options with quotes so that
build-pkg does not view them as options to itself.
Note that this differs from the passing of a command with options
to be run by chroot-install as you can not pass options for
chroot-install itself in this way.
Thus if you wanted to copy the directory /foo/bar into the
chroot()ed area then you could use:
build-pkg -y '-d /foo/bar' make install
To get the required effect.
src
will be mapped to the username given in dst. Thus if you
specify:
-U root:bin,adm:nobody
Then any files owned by root will be shown as being owned by bin
and any files owned by adm will be shown as being owned by nobody.
src
will be mapped to the group given in dst. Thus if you
specify:
-U other:bin,sys:bin
Then any files in the groups other or sys will be placed in the group bin.
build-pkg. Please see the
section titled ``HANDLING OF SYSTEM DIRECTORIES AND USING OVERLAY FILES'' for
more details on this option.
chroot-install; i.e.:
build-pkg make install
Note that if you do not specify a command then you will be dropped into
a shell running within the chroot()ed environment.
This script is designed to help build a Solaris package using a combination of the Solaris packaging tools and chroot-install.
It works by performing the following:
perl module or not; they
are handled differently. It is assumed that we are dealing
with a perl module if the blib directory exists under the
current working directory.
Note that the -P option can be used to say that we are not
dealing with a perl module, even if the blib directory
does exist under the current working directory.
pkginfo file for the
package. This is done by asking the user a series of questions.
Each question relates directly to each required field in the
pkginfo file; as such direction is given on the correct values
to be entered and input validation is performed. Where appropriate
default answers are given.
This results in a pkginfo file with the following variables set
within it:
PKG ARCH VERSION BASEDIR NAME CATEGORY DESC VENDOR CLASSES PSTAMP EMAIL
Please see the pkginfo(4) manual page for a description of
the above variables.
build directory (under the work directory) is empty then
it is filled with the package contents. How this is performed
depends on whether we're dealing with a perl module or not.
If we're dealing with a perl module then we just pull in the
relevent files from the blib directory.
If we are not dealing with a perl module then we call on
chroot-install to perform the installation for us.
prototype file. This is performed by
scanning the build directory. Any control files in the
work directory (InstallPackage by default) will also be
taken into account.
Hand crafted prototype entries can be added by placing
them in a file called ExtraPrototype in the work
directory.
pkgmk
-l option
At the end of the above the package will be in the work directory as a single file. With the default options you will see, relative to the current working directory, the following file:
InstallPackage/%PKG%-v%VERSION%-%ARCH%.pkg
Where the values surrounded by % signs are macros set
for the current package. Thus if the package has a name
of SomePackage, with a version of 1.0.2 and was
built in the SPARC architecture then the name would be:
InstallPackage/SomePackage-v1.0.2-sparc.pkg
This package is suitable for adding to a system by using the following command line:
# pkgadd -d InstallPackage/SomePackage-v1.0.2-sparc.pkg
Note that to run pkgadd you have to be the root user.
Whilst it looks complex from the outside, build-pkg is relatively simple to use in day-to-day usage.
For example to create a package for gcc and friends (i.e.
gcc, g++, g77, etc) under Solaris 8 all I did was to:
gcc version 3.0.3
make installed from the Companion CD and that
it was available at /opt/sfw/bin/gmake. Note that you could always
use the -x option to chroot-install to copy GNU make into the
chroot environment.
% simple-proj
Whilst not an essential command, this will prepare an InstallPackage
directory and place a number of package script files within it. Currently
these are postinstall and postremove scripts which will re-build the manual
page windex in the /usr/local/man manual tree.
Doing this will ensure that any manual pages installed by the package will be available immediately after package installation.
% build-pkg -c gnu -p GNUgcc -F gmake install
In the top level directory of gcc. After answering questions relating
to the contents of the pkginfo file, build-pkg went away and built the
package for me.
The use of the -c option to add ``gnu'' to the package category and -p
to make the package name default to ``GNUgcc'' are due to specific settings
in my $HOME/.build-pkg file. However even if you do not have a
.build-pkg file it is useful to specify these on the command line
Note that the -F option to build-pkg is to ensure that all of the files
installed by gcc have the correct permissions; there are a number of
include files installed by gcc which end up with a file mode of 0600 even
when a file creation mask (aka the umask) of 022 is used.
# pkgadd -d InstallPackage/GNUgcc-v3.0.3-i386.pkg GNUgcc
And watched whilst the package was installed.
Sometimes even the installation of software will have strange dependancies;
for example perl 5.6.1 has a dependancy on the gcc specific file
float.h. Thus when the attempt to build the package was made using
just:
% build-pkg make install
The following was in the output returned by the make install run by
chroot-install:
chroot-install: chroot()ing to /home/software/compiled/perl-5.6.1/perl-5.6.1/InstallPackage/build make install.perl install.man STRIPFLAGS= make[1]: Entering directory `/home/software/compiled/perl-5.6.1/perl-5.6.1' make[1]: *** No rule to make target `/usr/local/lib/gcc-lib/i386-pc-solaris2.8/3.0.3/include/float.h', needed by `miniperlmain.o'. Stop. make[1]: Leaving directory `/home/software/compiled/perl-5.6.1/perl-5.6.1' make: *** [install] Error 2 chroot-install: Cleaning up random files
The solution to this was to mount /usr/local/lib/gcc-lib/ into the chroot()ed area.
This can be done by using the -y flag to build-pkg to pass chroot-install its
-l flag which is used to specify additional directories to mount via lofs. Thus
the command line used was:
% build-pkg -y '-l /usr/local/lib/gcc-lib/' make install
Which made make happen and thus allowed the installation to finish.
The packages which are produced by the process the above description lays out are quite simple; infact they are as about as simple as you can get with a Solaris package.
There are some additional features you can make use of within Solaris packages.
These are configured by a number of different files outlined below. You can just
place these files in the InstallPackage directory for them to be taken into
account when the package is built.
One
very useful feature is the setting dependancies, i.e. saying that package foo relies on
package bar; if when package foo is added to the system package bar has not
been installed yet then a warning message will be displayed. Likewise, if you have
installed both packages and you attempt to remove bar then a warning message
tells you that package foo depends on bar.
You configure such dependancies via the depend file. The format of this file
is fully described in the depend(4); however a simple example is shown below:
P perl Perl scripting language
P PMlwp LWP Perl module
1.0.1
The above depend file states that the package depends on the perl package
existing on the system and that version 1.0.1 of the PMlwp package
eixsts as well.
There are other files which can be used as well:
request script solicits data from the admin installing the package and
then sets or redefines environment variables used by other scripts.
checkinstall script examines the target system for needed data, patches
required, etc. It determines if the package installation is to proceed.
Note that a major problem with the checkinstall script is that it is run
as the user nobody. This means that the checkinstall script has to be
readable by the nobody user for it to work. For spool-based packages this
is relatively easy to ensure as you can physically examine the path. For
data stream packages of the type build-pkg creates things are a little more
complex as pkgadd will convert the data stream package into a spool-based
package for the addition by creating a directory under /tmp/. When it does
this it fails to mkdir() the directory used to a sensible permission to
take into account someone running with a reasonable umask (i.e. 077).
If you do use a checkinstall script it is recommended that you also inform
the people who will be pkgadding the package to their systems that they do
so by first setting their umask to 022; i.e.
# umask 022 # pkgadd -d PACKAGE
checkinstall script for checking to see if package
installation should occur as it is run as the root user. Its group it runs
in is other.
Note that no files should be installed by this script.
windex file. This is run as the root
user with a group of other.
root user and with a group of other.
Note that no files should be removed by this script.
windex file. This is run as the root user and
with a group of other.
prototype
file.
For example, additional space might be needed for files that are dynamically created at installation time.
Note that if you use installf to add items to the package database in the
any of the package control scripts (i.e. postinstall) and you do not
provide a space file then a warning message will be displayed to this effect
when you build the package.
All of the above scripts should be Bourne shell scripts calling /sbin/sh
If you are generating relocatable packages with the -R flag it is
recommended that the scripts use the variable $BASEDIR rather than
hardcode the base directory to /
The return code of the scripts is important as it controls what the packaging tools do after a script has finished. The table below summerises the
+----+-----------------------------------------------------------+ |Code| Meaning | +----+-----------------------------------------------------------+ | 0 | Successful completion of script | +----+-----------------------------------------------------------+ | 1 | Fatal error; installation process is halted at this point | +----+-----------------------------------------------------------+ | 2 | Warning or error condition; installation continues. A | | | warning message is displayed at the time of completion | +----+-----------------------------------------------------------+ | 3 | The pkgadd command is cleanly halted. Only the | | | checkinstall script returns this code | +----+-----------------------------------------------------------+ | 10 | System should be rebooted when installation of all | | | selected packages is completed. This value should be | | | added to one of the single digit return codes above. | +----+-----------------------------------------------------------+ | 20 | System should be rebooted immediately after the current | | | package has been installed. This value should be added to | | | one of the single digit return codes above. | +----+-----------------------------------------------------------+
More details are available in Sun's Application Packaging Developer's Guide.
To make use of the above files, you just need to place them into the work
directory, i.e. InstallPackage.
Certain system directories are handled in a special way; such
directories have their entries in the generated prototype file changed
so that the ownership and permissions of the directory under the
InstallPackage directory will not be imposed on the system which the
resulting package is installed on.
For example if the directory InstallPackage/build/usr had the permissions
of 0700 then the resulting prototype line would be:
d none /usr root bin 0700
This is not very useful as installing a package with the above line would
result in pkgadd complaining about an installed item not matching what
the package to be installed wants. If the package is still installed then
the result would be that the system would only work for the root user!
The line which is actually generated is:
d none /usr ? ? ?
Which is more useful. System directories which have this treatment are:
/usr /usr/bin /usr/lib /var /home /etc /etc/rc*.d /etc/init.d /var/run /usr/man /usr/include /usr/man/man* /var/log /usr/share /opt /tmp
/etc/rc*.d represents all of the startup directories like /etc/rcS.d et al.
/usr/man/man* represents all of the manual page directories like /usr/man/man1m et al.
It is also possible to specify an overlay file using the -O option which is used to over ride lines in the
prototype file generated by build-pkg. The file given to -O should
be in a similar format to a prototype file; the only difference are:
part field which is optional and is the first field on the line
should never be used.
ftype field are: b, c, d, f and p.
These represent block devices, character devices, directories, files and named
pipes respectively
ftype of f - are not specified in the
form path1=path2 where path1 is the final location of the file and
path2 is the source of that file.
Instead just the final destination of the file should be used instead. Thus
if the final prototype file has a line like:
f none /etc/some_file=.../InstallPackage/build/etc/some_file 0644 root bin
Where ... is the path running down to the InstallPackage the overlay
file should contain:
f none /etc/some_file ? ? ?
Note that the above would ensure that the file ownerships and modes would not
be changed by the package installation. It also means that pkgadd would not
complain about incorrect file modes of a pre-existing file.
Lines which do not conform to the above will be ignored and have a warning output to the standard error.
It is the responsibility of the caller to ensure that the entries in the provided overlay file are syntically correct.
System directories which are automatically ignored - see above for the list - are not affected by the contents of the overlay file.
This option has been added so that it is possible to build packages which
ignore the ownership and permissions of user-defined files and directories
in much the same way as the permissions for directories like /etc and
</home> are ignored automatically.
Trying to use this option to do more than this probably is not a good idea and has not been tested.
build-pkg keeps its various files and directories in the InstallPackage
directory (changable via the -w option) under the working directory build-pkg
was run in.
This directory can contain the following entries generated by build-pkg:
/etc/passwd and /etc/group files
within the chroot()ed environment. This file is written to by
chroot-install called with the -Y flag. It is used to track users and
groups added whilst within the chroot() environment.
pkginfo file - see pkginfo(4) for details.
prototype file - see prototype(4) for
details.
/usr/local/bin/waterbuffalo then the location of the file so that
build-pkg can see it would be:
$CWD/InstallPackage/build/usr/local/bin/waterbuffalo
InstallPackage directory.
By default the name of the file will be %PKG%-v%VERSION%-%ARCH%.pkg
where the %..% values are taken from the pkginfo file.
It should be noted that you can also place the other various package
configuration files supported by the Sun packaging system into the
InstallPackage directory as well. The current list of supported
package configuration files is:
o depend o request o checkinstall o preinstall o postinstall o preremove o postremove o copyright o space o compver
Finally, you can also place a file called ExtraPrototype into the
InstallPackage directory which can contain hand crafted lines for
the prototype file.
It is possible to use build-pkg without also using chroot-install
or working with a perl module; all you have to do is present build-pkg
with the directory structure it expects. This has the advantage of not
requiring root privilages to build the package.
Thus all you need to do is create the InstallPackage/build directory
mentioned in the previous section and populate it appropriately. build-pkg
will create everything else if required.
It should be noted that if you do this that you'll have to ensure that all
of the permissions on the files are correct as what you put into the
build directory will be mirrored in the resulting package.
It is also recommended that you do not use the -K option as this will
end up with chroot-install being invoked by build-pkg.
You can also install software based on GNU autoconf without using
chroot-install by using the following:
% ./configure % gmake install % simple-proj % umask 022 % mkdir -p InstallPackage/build/usr/local % gmake install prefix=`pwd`/InstallPackage/build/usr/local % build-pkg -c gnu -p GNUgcc
This works by telling the Makefile that the ${prefix} - from which
all pathnames within the Makefile are hopefully derived - is
actually under $PWD/InstallPackage/build/usr/local rather than the
/usr/local which the package was built with.
This works as build-pkg sees the directory $PWD/InstallPackage/build
as the root point for the package being built.
However this method does have problems. For starters it does not deal
with files installed outside of ${prefix} - for example configuration
files installed into /etc
For that reason it is recommended that you use chroot-install when
dealing with 3rd-party software.
If you specify a package name prefix (ie PkgPrefix in the $HOME/.build-pkg file) then you can not
remove this prefix when specifying the package name unless you
specify the package name directory with the -p option
We do not support classes within packages
Simon Burr <simes@bpfh.net>
Copyright (c) 2002, Simon Burr <simes@bpfh.net> All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.