Difference between revisions of "Construct ipkg packages (for developers)"

From NAS-Central Buffalo - The Linkstation Wiki
Jump to: navigation, search
(Build with tool-generated <code>prototype</code> File)
m
 
(One intermediate revision by one user not shown)
Line 21: Line 21:
 
=== ipkg-utils ===
 
=== ipkg-utils ===
  
''.ipk'' packages can be built using the tools contained in <tt>ipkg-utils</tt>. You may download <tt>ipkg-utils</tt> from the [http://downloads.linkstationwiki.net downloads area] or from the [ftp://ftp.handhelds.org/packages/ipkg-utils/ <tt>ipkg-utils</tt> home page]. To ensure compatibility, packages which are to be submitted to the official LinkStationWiki ipkg feed should be built using the version of <tt>ipkg-utils</tt> available from the [http://downloads.linkstationwiki.net downloads area].
+
''.ipk'' packages can be built using the tools contained in <tt>ipkg-utils</tt>. You may download <tt>ipkg-utils</tt> from the [http://downloads.nas-central.org downloads area] or from the [ftp://ftp.handhelds.org/packages/ipkg-utils/ <tt>ipkg-utils</tt> home page]. To ensure compatibility, packages which are to be submitted to the official LinkStationWiki ipkg feed should be built using the version of <tt>ipkg-utils</tt> available from the [http://downloads.nas-central.org downloads area].
  
 
Most of the tools contained in <tt>ipkg-utils</tt>, such as <tt>ipkg-build</tt>, are shell scripts. Please note, however, that some of the tools require Python. Non of them comes with any documentation. From studying the source code it has been concluded that <tt>ipkg-utils</tt> contains the following tools:
 
Most of the tools contained in <tt>ipkg-utils</tt>, such as <tt>ipkg-build</tt>, are shell scripts. Please note, however, that some of the tools require Python. Non of them comes with any documentation. From studying the source code it has been concluded that <tt>ipkg-utils</tt> contains the following tools:
Line 67: Line 67:
 
# The owner, group, and access permissions of the input files must be configured as they should appear when installed
 
# The owner, group, and access permissions of the input files must be configured as they should appear when installed
  
Build System | In other context a ''build system'' is the software system, e.g. a Makefile system, for building some software. Here we use the term to identify the computer and environment where the software and packages are constructed.
+
{{Postit|Build System|The term ''build system'' has two meanings
 +
#A software system, e.g. a Makefile system, for building some software from source code.
 +
#The computer and environment where a software and packages are constructed.
 +
The actual meaning should be clear from the context.}}
  
 
We will call this directory structure the ''prototype'' structure for the purpose of this document. The system (LinkStation) on which you want to install packages will be called the ''target system''. The system on which you build the software and the package will be called the ''build system''.   
 
We will call this directory structure the ''prototype'' structure for the purpose of this document. The system (LinkStation) on which you want to install packages will be called the ''target system''. The system on which you build the software and the package will be called the ''build system''.   
Line 78: Line 81:
  
 
[[#Building an .ipk - using ipkg-mk on top of ipkg-build|ipkg-mk]] (described below) is a tool to gain more control over the building of a package, than  with ipkg-build. However, ipkg-mk can't fix the problem of having to have ''root'' access to build non-trivial packages. It also does not fix the problem of missing user or group definitions on the build system.
 
[[#Building an .ipk - using ipkg-mk on top of ipkg-build|ipkg-mk]] (described below) is a tool to gain more control over the building of a package, than  with ipkg-build. However, ipkg-mk can't fix the problem of having to have ''root'' access to build non-trivial packages. It also does not fix the problem of missing user or group definitions on the build system.
 +
 +
{{Postit|Root|One almost for sure needs root rights on the build system to correctly build a non-trivial package.}}
  
 
=== Fixing ipkg-build v1.7 ===
 
=== Fixing ipkg-build v1.7 ===

Latest revision as of 02:02, 11 September 2007

This article is based on the work of nix & titimred from www.linkstationwiki.org


Contents

Overview

This article explains how to build an ipkg package. It is intended for software developers and package maintainers.

Two methods are described

  1. The classic way, using ipkg-build from the ipkg-utils collection, and
  2. using a wrapper tool ipkg-mk around ipkg-build

In addition, reference information on the package format and files is provided, as well as information on setting up an own feed.

Building an .ipk package - using ipkg-utils

ipkg-utils

.ipk packages can be built using the tools contained in ipkg-utils. You may download ipkg-utils from the downloads area or from the ipkg-utils home page. To ensure compatibility, packages which are to be submitted to the official LinkStationWiki ipkg feed should be built using the version of ipkg-utils available from the downloads area.

Most of the tools contained in ipkg-utils, such as ipkg-build, are shell scripts. Please note, however, that some of the tools require Python. Non of them comes with any documentation. From studying the source code it has been concluded that ipkg-utils contains the following tools:

ipkg-accept-incoming
Used for managing the handhelds.org feed (copies uploaded packages to the actual feed and triggers the re-building of the feed's package index).
ipkg-build
Builds a package from a prepared directory structure. This is the most important tool. It can run stand-alone and is a shell script.
ipkg-buildpackage
Builds a package from a source tarball.
ipkg-compare-indexes
Compares two Package index files of two different feed directories. For each different .ipk package version the packages' contents is also compared with ipkg-diff. Requires Python.
ipkg-compare-versions
compares version numbers?
ipkg-deb-build
build a Debian file format .ipk from a directory
ipkg-deb-unbuild
Unpacks (but not installs) a Debian file format .ipk
ipkg-diff
Compares two .ipk files
ipkg-extract-file
extracts a single file from an .ipk package
ipkg-ipk
Retired. Replaced by ipkg-build
ipkg-link
Links (and unlinks) ipkg meta data from some non-volatile storage (e.g. flash memory) to the current file system. Probably only useful on systems where packages are installed in flash ram.
ipkg-make-familiar
('familiar' is a handhelds.org distribution for the iPAQ).
ipkg-make-index
Used for generating the meta-data needed for providing a feed. The script generates the necessary index files from a list of .ipkg packages. Requires Python.
ipkg-show-deps
Shows package dependencies, requires Python
ipkg-unbuild
Unpacks (but not installs) a package back into a directory structure.
ipkg-update-index
Used for providing the index files of a feed. Requires Python.
ipkg-upload
Uploads packages to the handhelds.org feed (don't use it to supply LS packages to handhelds.org, since handhelds.org doesn't distribute LS packages)

Using ipkg-build from ipkg-utils

The normal but tedious method for building an .ipk is to use ipkg-build. You must start by compiling the software package, either directly on the LinkStation or using the Projects/CrossToolchains cross-compilation tool chain(s). ipkg-build requires several things in order to properly build an .ipk:

  1. A special meta-data file named control (more on this in the Packge structure section)
  2. The input files must be structured in directories exactly as they should appear when installed. Which is a tedious task. See ipkg-mk below for an alternative.
  3. The owner, group, and access permissions of the input files must be configured as they should appear when installed
Build System
Bar.png
The term build system has two meanings
  1. A software system, e.g. a Makefile system, for building some software from source code.
  2. The computer and environment where a software and packages are constructed.

The actual meaning should be clear from the context.


We will call this directory structure the prototype structure for the purpose of this document. The system (LinkStation) on which you want to install packages will be called the target system. The system on which you build the software and the package will be called the build system.

The user and group ownership as well as the access modes of all files, directories, devices, etc. in the prototype structure need to be set up exactly as they should later appear on the target system. ipkg-build allows to force all files to have the same user and group ownership (-o and -g option), but this does not help if files in the package should have different ownership (e.g. if some should belong to root, while others should belong to bin).

This procedure of setting up a prototype directory structure is rather inconvenient and error prone. Also - this is a principle limitation of the used format - everything which can not be archived by GNU tar or which can not be set up on the build system can't be packed. For example, if an installed file should belong to a group abc, but if there is no group abc on the build system, then the prototype can't be set up as desired. Either the build system first has to be changed (the group added, with exactly the group number as needed on the target system), or some post-install script to fix this after installation has to be added to the package. There is little chance to set up the prototype directory structure of a non-trivial package without root access on the build system. This is a severe disadvantage of ipkg, for example in a corporate environment, where getting root access is in general verboten.

Also, files accidentally left in the prototype directory do end up in the package and are installed, even if they were not intended for deployment at all. The only exception are backup files ending with '~', since ipkg-build can clean them up before packaging.

ipkg-mk (described below) is a tool to gain more control over the building of a package, than with ipkg-build. However, ipkg-mk can't fix the problem of having to have root access to build non-trivial packages. It also does not fix the problem of missing user or group definitions on the build system.

Root
Bar.png
One almost for sure needs root rights on the build system to correctly build a non-trivial package.


Fixing ipkg-build v1.7

ipkg-build in the ipkg-utils-1.7 has a minor bug when a tar archive is used as the outer wrapper (-c option). In this case ipkg-build does not observer the -o and -g options on the files wrapped by the outer wrapper (it does observe them for the files in the inner wrapper). This can be fixed by changing line 240 from

( cd $tmp_dir && tar -zcf $pkg_file ./debian-binary ./data.tar.gz ./control.tar.gz ))


to

( cd $tmp_dir && tar $ogargs -zcf $pkg_file ./debian-binary ./data.tar.gz  
./control.tar.gz )

ipkg-build also has a bug when the -o and -g options are used in the order -g group -o owner instead of -o owner -g group. In case of -g group -o owner the group setting is not observed. The bug is in the getopts case handling, but since it can be circumvented by using the options in the right order no patch has been developed.

The parsing of the '-C' (uppercase 'C') option is also faulty.


Building an .ipk - using ipkg-mk on top of ipkg-build

Introduction

ipkg-mk is a script which

  • takes a prototype package description as input,
  • spools (creates) the necessary prototype directory structure, and
  • uses ipkg-build to construct a package from the spooled prototype directory structure.

These are steps (except the last one) which are either not handled by ipkg-build at all, or are very tedious. ipkg-mk provides a paradigm change. From having to somehow physically construct the package directory structure, one can now declare that structure in a simple definition language, and leave it to the tool to do the rest.

               +---------+      prototype     +------------+
prototype ---> | ipkg-mk | ---> directory --->| ipkg-build | ---> package
               +---------+      structure     +------------+
                    ^
                    |
              CONTROL files
            application files

The package layout declaration is in what is called a prototype file, since it specifies the prototypical format of the package. The format is a variant of the Unix System V Release 4 (SVR4) package management's prototype description format. By relying on an explicit prototype description file it is possible to

  • gain more control over the package structure (explicit descriptions instead of implicit file attributes in some directory structure),
  • to have the package structure in one place (instead of having to analyse a directory structure), and to
  • be able to version-control the package structure (since the prototype description file can and should be placed under version control), e.g. using rcs, cvs, sccs or subversion for version control.

ipkg-mk does not fix some of the principle problems of the ipkg package format. For example, it does not fix the problem of having to have root rights. In fact, ipkg-mk requires to be executed by root.

ipkg-mk comes with documentation (man pages) describing the input format in detail. Users familiar with building SVR4 packages should feel at home.

Obtaining and installing ipkg-mk

To build a package with ipkg-mk, ipkg-mk itself and ipkg-build need to be installed. You should also be able to format man pages in order to read the documentation. Desktop Linux versions do come with man by default. If you build on the LS you might want to install a package like awf (a formatter) and awman (a man clone using awf).

So, currently the installation of ipkg-mk on the LS with OpenLink requires some manual work:

  • (Only on pre OpenLink 0.60) Follow the manual ipkg installation instructions to obtain, install and update the ipkg client itself.
  • Download the [| ipkg-utils], extract the ipkg-build script out of the archive and place it in /usr/bin.
  • Install the awf formatter (needed for viewing the documentation). This can already be done via ipkg:
ipkg install http://people.freenet.de/lsnix/LinkStation/awf_0.1-1_all.ipk
However, if you don't have a working ipkg installations, see Install an .ipk package without having the ipkg package management system (for end-users) for manually installing awf and all the other mentioned packages below.
  • Install the [aw]man package (for formating and viewing manual pages):
ipkg install http://people.freenet.de/lsnix/LinkStation/awman_0.1-1_all.ipk
  • And finally (phew ...) install ipkg-mk:
ipkg install http://people.freenet.de/lsnix/LinkStation/ipkg-mk_0.2-1_all.ipk

To read the ipkg-mk documentation you can now type:

man ipkg-mk
man ipkg-prototype

And to view the documentation for the formatter and the man page viewer you can type:

man awf
man man
man -s 7 man
man ms

To speed up man, create a user and group 'man', set up cat directories and view the man pages once as root. This will create cached preformatted versions which view much faster.

Build a package

Build with manually created prototype File

Once the environment is set up, the following steps can be performed to build a package with ipkg-mk:

  1. Create a control file
  2. In case the package needs them, create pre/post installation scripts ([pre|post][inst|rm])
  3. Build the software you want to package, e.g. using make(1)
  4. Create a prototype file, which describes the desired package layout (see below for an example)
  5. Run ipkg-mk with the prototype file as input. This should best be automated with a build rule in a Makefile.

If you build directly on the LS, specify the -c option to ipkg-mk to use tar instead of ar for the outer wrapper of the package, since the LS' busybox ar can't create archives.

The result should be the desired package.

prototype files are rather simple. As an example, the following is the prototype file which is used to pack ipkg-mk v0.1-1 itself into an .ipk package:

# CONTROL files
i control
i copyright
i preinst
# The binary d none /usr 755 bin bin d none /usr/bin 755 bin bin f none /usr/bin/ipkg-mk 555 bin bin
# Documentation d none /usr/man 755 bin bin d none /usr/man/man1 755 bin bin d none /usr/man/man4 755 bin bin f none /usr/man/man1/ipkg-mk.1 444 bin bin f none /usr/man/man4/ipkg-prototype.4 444 bin bin

See the ipkt-prototype(4) man page for more details of the format.

Build with ipkg-proto generated prototype File

In order to create a raw prototype file (which needs further manual editing) from an existing directory structure, a tool called ipkg-proto is available.

The following image depicts the workflow:

                                                   +------------+
 existing       +------------+         raw         | manual     |
 directory ---> | ipkg-proto | ---> prototype ---> | editing/   | --+
 structure      +------------+         file        | refinement |   |
     ^                                             +------------+   |
     |                                                              |
application's        +------------- prototype <---------------------+
   files             |
     |               v
     |          +---------+      prototype     +------------+
     +--------> | ipkg-mk | ---> directory --->| ipkg-build | ---> package
                +---------+      structure     +------------+
                     ^
                     |
               CONTROL files
          add. application files
  1. The application's files are build (e.g. created from source code), or they are obtained in some other way.
  2. The application's files are then placed into a directory structure which mimics the file's organization on the target system. Build systems, like the typical GNU build system used for many free software, can be convinced to do this via their install target.
  3. ipkg-proto is run to create an initial, raw prototype file.
  4. The prototype file is manually edited to refine and complete it.
  5. ipkg-mk is used to evaluate the prototype file and copy (spool) the application files and any referenced CONTROL files to a clean prototype directory structure.
  6. Finally ipkg-build is used to transfer the prototype directory structure into the desired package.

ipkg-proto can be installed via ipkg:

ipkg install http://people.freenet.de/lsnix/LinkStation/ipkg-proto_0.1-1_all.ipk

The tool comes with an own man page, which can be viewed if a man command is installed as

man ipkg-proto

The tool can e.g. be run on an existing directory (/lib in the example) as it follows

$ ipkg-proto /usr
f none /lib/ld-2.3.2.so 755 root root
s none /lib/ld.so.1=ld-2.3.2.so
f none /lib/libBrokenLocale-2.3.2.so 644 root root
s none /lib/libBrokenLocale.so.1=libBrokenLocale-2.3.2.so
f none /lib/libSegFault.so 644 root root
f none /lib/libanl-2.3.2.so 644 root root
s none /lib/libanl.so.1=libanl-2.3.2.so
f none /lib/libc-2.3.2.so 755 root root
s none /lib/libc.so.6=libc-2.3.2.so
s none /lib/libcom_err.so.2=libcom_err.so.2.0
...

Package structure / prototype directory structure

Overview

The data (files etc.) which should become part of the package must be arranged in the prototype directory structure so they can be packed with ipkg-build. For the sake of this document we will call the top-level directory of the prototype directory structure ./spool. Building such a directory structure with a tool will be called spooling (ipkg-mk is such a spooling tool). If no such a tool is available, the prototype directory structure needs to be set up manually.

CONTROL Data

Below the spool directory needs to be a CONTROL directory (can also be called DEBIAN) with a couple of optional and required files:

./spool/ -+- CONTROL/ -+- control   # mandatory - package description
          |            +- preinst   # optional  - pre-install script
          |            +- postinst  # optional  - post-install script
          |            +- prerm     # optional  - pre-remove script
          |            +- postrm    # optional  - post-remove script
          |            +- conffiles # optional  - list of volatile config files
          +- <package data dirs/>

All files in the CONTROL directory need to be readable. Scripts also need to be executable (mode 555 or better). It is possible to place additional, non-standard files in the CONTROL directory. For example the directory is a nice place for a copyright file - which then e.g. can be displayed by a simple preinst file at the beginning of an installation.

CONTROL/control file (mandatory)

Overview

Provisioning of a control file for an ipkg package is mandatory. The control file is an ASCII text file, consisting of key/value pairs, one per line. A key and a its value are separated by a column and a space ': '.

A couple of keys within a control file are mandatory, while others are optional. In addition, it is possible to introduce own keys. Such own keys are ignored by the ipkg client. However, since it is e.g. possible to read the control file from within a pre/post install/remove script, such keys can be used for package-specific configuration. Another usage for own keys is to add packaging information, like information from a version control system. It is recommended to name all such own keys starting with 'X-' to ensure they don't clash with predefined keys.

The control file needs to be placed in the CONTROL directory of the spool directory with read permissions. A clause like

i control

or

i control=source-of-the-control-file

in a prototype file for ipkg-mk will ensure this.

Mandatory information

This section lists the mandatory information (keys), which need to be provided in a control file. However, the list, particular the key descriptions, is likely to be slightly incorrect. The information has been taken from handhelds.org, and ammanded with real-world experience. Figuring out the exact meaning and purpose of a key will require some further study of the ipkg-cl source code.

Required entries in the control file are:

Package:
Name of the package. The name must match the regular expression [a-z0-9.+-]\+. Please note that uppercase letters are not permitted. Thus, e.g. package names like myNewSoftware are not permitted.
Version:
Version number, in the form [:epoch] version [-fam frevision] [-revision]]
epoch
A timestamp, seconds since the epoch (details unknown)
version
should indicate the version number of the packaged software, and must at least consist of one digit and match the regular expression [a-zA-Z0-9.+]\+. Please note that letters (uppercase and lowercase) are permitted as part of the version "number".
frevision
Optional familiar revision ? -fam[0-9]\+ handhelds.org is unclear about the exact meaning of this component of the version information. familiar is a distribution for he iPAQ.
revision
Optional, indicates the package build revision. It should be incremented each time the same software is re-packaged. If version is stepped, revision can be reset. -[0-9]\+
Architecture:
Architecture name. Possible names are:
all
Indicates a processor/architecture independent package, like documentation or shell scripts.
noarch
No particular architecture specified.
mipsel
MIPSel architecture (LinkStation II with MIPSel CPU)
powerpc
PowerPC architecture (LinkStation I with PowerPC CPU)
arm
indicates software for an ARM processor (There is no ARM processor in the Buffalo LS product family. Valid names for HG, TS need to be determined)
Maintainer:
Typically the name and e-mail address of the maintainer of the package, the package builder (not neccessarily the author of the software)
Section:
(exact meaning needs to be clarified)
admin
?
base
?
comm
Some communication program?
editors
Some editor?
extras
?
graphics
?
libs
Libraries?
misc
?
net
Networking tool/program?
text
Text editor / text processing program?
web
Web server, web pages, tools?
x11
X11 or X11 program?
Priority:
(meaning needs to be clarified). Normally optional should be used.
required
A required package (what's the difference to the Essential entry?)
standard
which standard?
important
?
optional
An optional package
extra
?
Description:
A textual description of the package contents. Should be limited to 80 chars per line. Lines can be continued on the next line, which then has to start with a space. Empty lines are indicated by a single '.' after the space.
Source:
A URL or a list of filenames pointing to the source code. (mandatory, but not mentioned at handhelds.org)
Optional Information

In addition to the mandatory information, at least the following keys are recognized by ipkg.

Depends:
Dependencies on other packages. A comma separated list of package names (Can names with versions be specified here, or just names?)

While Depends: is documented, there are a lot of undocumented parameters, to. Many of these are not supposed to be used in a package control file. They are used internally in ipkg's package database - which happens to use an enhanced version of the control file:

Filename:
?
MD5sum:
? (lowercase 's')
MD5Sum:
? (uppercase 's')
Size:
?
Installed-Size:
?
Installed-Time:
?
Essential:
Flag, argument yes
Status:
Internally used only? Three space-separated arguments: want flag status
want
unknown, install, deinstall, purge
flag
ok, reinstreq, hold, replace, noprune, prefer, obsolete, user
status
not-installed, unpacked, half-configured, installed, half-installed, config-files, post-inst-failed, removal-failed
Conffiles:
? List of name/md5sum pairs
Provides:
?
Pre-Depends:
?
Recommends:
?
Suggests:
?
Conflicts:
?
Replaces:
?

Scripts

Things common to all CONTROL Scripts
  • All CONTROL scripts are optional
  • A script, if it exists, should return 0 on success. The only exception is preinst. A non-zero return value from preinst will abort the installation. (what happens if the other scripts return a non-zero value?)
  • All scripts are allowed to assume that they are connected to a terminal. Which means for example, that all scripts are allowed to interact with the user, asking for data, and expecting a response.

However, user interaction should be avoided if possible to simplify package handling and automated installation.

  • The environment variable PKG_ROOT is set to the root of the package installation (-d/est ipkg command line argument or dest entry in /etc/ipkg.conf). This allows to access package contents in the installed, or to-be-installed, location.
  • All CONTROL files (scripts, data files, additional non-standard files) are extracted to the same temporary directory. Therefore it is possible to find other CONTROL files from within a script by obtainig the temporary directory as:
controlDir=`dirname "$0"`
  • All scripts are called with one or more arguments indicating the actual reason for why the script is called. This can be used to only provide one single script (under different symbolic names), which dispatches the actual operation according to the command line argument. This makes sense if all scripts would contain a lot of duplicated code. However prerm and postrm us the same argument and can't be distinguished just from the argument:
case "$1" in
update) ...
        ;;
install) ...
        ;;
configure) ...
        ;;
remove) script=`basename "$0"`
        if [ "$script" 0 "prerm" ] ; then
                ...
        else
                ...
        fi
        ;;
*) # unknown error
        ;;
esac
CONTROL/preinst Script (optional)

This script, if it exists, is called by ipkg with one of the following arguments before the actual installation:

upgrade oldversion: Indicates that this is an upgrade of the existing version oldversion.
install version: Indicates that this is an installation of version version which contains volatile config files.
install:Indicates a 'normal' installation (no config files).

Things which make sense to program in the script are:

  • Display of a copyright message
  • Display of a license, possibly with a request to accept the license
  • Backup of some data which will be overwritten by the package
  • Creation of package-exclusive resources. E.g. package-specifc users or groups.

If the script returns a non-zero exit status then the installation of the package is aborted.

CONTROL/postinst Script (optional)

If the script exists it is called with the argument configure after the installation of the package, or when

ipkg configure packagename

was run.

CONTROL/prerm Script (optional)

If the script exists it is called with the argument remove prior to removal of the package.

Example of things which can (should) be implemented here are:

  • Stopping of any related processes, before the binaries are removed
  • Unloading modules (if relevant)
  • Backup of user-created data or other valuable data
CONTROL/postrm Script (optional)

If exists, called with the argument remove after the removal of the package.

Things which can/should be implemented here:

  • Restoring of files backed-up prior to the installation of the package.
  • Removal of resources allocated specifically for the package (e.g. users or groups created just for the package), or directories exclusively used by the package.
CONTROL/conffiles file (optional)

conffiles contains a list of configuration files (one per line), which are part of the package. A file mentioned in conffiles is not just removed/overriden by a new package installation. Instead the user is asked about what to do with the existing file.

Package Data Directories

The package data directories hold the actual files which should be installed on the target system:

./spool/ -+- CONTROL/ --- <control files>
          |
          +- <package data dirs/>

The structure of the package data directories must match the stucture of the files as intended on the target system. For example, if an application, consisting of a binary, a man page, a shared library and a configuration file, should be installed, the structure might look like:

./spool/ -+- CONTROL/ --- <control files>
          +- usr/ -+- bin/ --- app
          |        +- lib/ -+- libapp.so.1.0
          |        |        +- libapp.so.1   -> libapp.so.1.0
          |        |        +- libapp.so     -> libapp.so.1
          |        +- man/ --- man1/ --- app.1
          +- etc/ --- app.conf

Note: -> indicates a symbolic link

The above structure is just an example. It should not be blindly copied for a real-world package. Instead the package layout, and thus the structure on the target system should be carefully planed. Things to consider include:

  • Should the application files be distributed into the global bin, man, lib directories (as shown in the example), or should the application files be kept in an own subdirectory structure (/opt/<app>/[bin|lib|man|etc])?
  • Which user and group ownerships should the files get?
  • Which file access modes should the files get?

Particularly, security issues should be considered here.

All this has already to be set up in the prototype directory structure. For example the ./spool/usr/bin/app application in the example should already be set to be readable and executable (e.g. mode 555) and to user:group bin:bin in the prototype directory structure.

Manually setting up the prototype directory structure is a tedious task. It should best be automated with some add-hock script or a dedicated tool like ipkg-mk, integrated into a make-based build system.

Converting the prototype structure to the package

The above described directory structure is converted into the package. You don't have to assemble the package manually (e.g. ipkg-build does it for you), but it is helpful to know the structure of a package when something doesn't work.

The structure is as it follows. The exact format is not specified anywhere, but the following is known to work.

  • The files in the CONTROL directory are packed into a gziped tar archive called control.tar.gz
  • All other files and directories are packed into a gziped tar archive called data.tar.gz
  • control.tar.gz and data.tar.gz, plus a file called debian-binary, are either packed in yet another tar file, or in an ar file. This is called the outer wrapper and forms the final .ipk package. The suffix .ipk is used intead of that of a gziped tar archive (.tar.gz) or an ar archive (.a).
<pkg-name>.ipk -+- control.tar.gz  <- <control files>
                +- data.tar.gz     <- <package data dirs>
                +- debian-binary   <- "2.0"

debian-binary just contains the text 2.0, to indicate the package is also compatible with the debin package management format 2.0. The file is ignored by ipkg.

If the package contains special files like character or block special files (devices) then data.tar.gz needs to be packed with a version of tar which can pack such special files. GNU tar is such a version. Many tar's of classic Unix systems can't do this.

All in all the package structure is relative simple. It should even be possible to create such a package manually in case of emergency.. There are indications that slight variants, e.g. using uncompressed, instead of compressed tar files also work.

The package-build environment

this should probably become an own page - hey, this is a wiki :-)

Setting up your package build-environment directly on the LS

This paragraph is currently a stub.

Feel free to add content to it.

stub Hints

If you build packages on the LS be aware that the LS comes with the busybox ar archive program. That program is not capable of creating archives, it can just extract files from them. Therefore, the normal ipkg-build program will fail on the LS, unless you do one of the following:

  1. Use the -c (lowercase 'c', not the uppercase 'C' option). This tells ipkg-build (and imkg-mk) to wrap the package up in a gziped tar file instead of an ar file. This is the easiest way to fix the problem, and the recommended way. gziped tar files are allowed as ipk files. In fact, for some time this was the default wrapper instead of ar.
  2. Install a complete ar

Setting up your cross-package build-environment on Unix/Linux

stub - need the GNU version of tar and GNU gzip on a standard Unix system. Linux of course already comes with them

Setting up your cross-package build-environment on Windows

You need a Unix-like environment, like [| Cygwin], since the build tools are shell scripts and use other Unix tools like tar, gzip, and ar. Of course, you also need a cross-compilation environment to first build the software you want to package.

Once you have set up your cygwin environment you can follow the procedures for cross-package building under Unix/Linux.

Sample CONTROL/control files

A sample architecture-independent ipkg CONTROL/control file

Architecture independent packages are packages which e.g. control scripts which run on "any" architecture or documentation which is not architecture specific.

Package: sample-pkg-name
Section: base
Priority: optional
Version: 1.0.1-3
Architecture: all
Maintainer: you@example.com
Source: http://origin.of.the.sourcecode.of.the.software
Depends: list,of,other,packages
Description: Description of the software

A sample PPC ipkg CONTROL/control file

This paragraph is currently a stub.

Feel free to add content to it.

A sample MIPSel ipkg CONTROL/control file

This paragraph is currently a stub.

Feel free to add content to it.

A sample TeraStation ipkg CONTROL/control file

This paragraph is currently a stub.

Feel free to add content to it.

Automating the packaging with make

First of all, you should of course obtain a version of make(1). It is provided via the LinkStationWiki feed. So, if you have a working ipkg client setup, make can be installed with:

ipkg install make

The package does not contain documentation. Since the make in the package is actually a GNU make, you can find an online version of the documentation at [[1]]. If you have never worked with make it is highly recommended to study the documentation intensively (also, O'Reilly offers an nice book about GNU make).

make uses so called makefiles as input. The following is an example for a Makefile using ipkg-build to buld a package. Note the long and tedious setup of the portotype directory in the $(IPK) rule:

NAME    = my-pkg#
VERSION = 1.0-1#
ARCH    = all#
IPK     = $(NAME)_$(VERSION)_$(ARCH).ipk
CONTROL_FILES = control preinst # contents of the CONTROL dir DATA_FILES = the application files
default: $(IPK)
# # Construct the control file on the fly, so data in this Makefile # and in the control file match # control: control.tmpl rm -f $@ echo "Package: $(NAME)" > $@ || { rm -f $@; exit 1; } echo "Version: $(VERSION)" >> $@ || { rm -f $@; exit 1; } echo "Architecture: $(ARCH)" >> $@ || { rm -f $@; exit 1; } cat control.tmpl >> $@ || { rm -f $@; exit 1; }
clean:: rm -f control
# # Build package # $(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile rm -f $@ rm -rf /tmp/pkg$(NAME) # # construct prototype structure # mkdir /tmp/pkg$(NAME) mkdir /tmp/pkg$(NAME)/CONTROL cp $(CONTROL_FILES) /tmp/pkg$(NAME)/CONTROL mkdir -p /tmp/pkg$(NAME)/usr/bin mkdir -p /tmp/pkg$(NAME)/usr/lib mkdir -p /tmp/pkg$(NAME)/usr/man/man1 cp some-files /tmp/pkg$(NAME)/usr/bin ... ... # # finally build the package # ipkg-build -c -o root -g root /tmp/pkg$(NAME) rm -rf /tmp/pkg$(NAME)
clean:: rm -f $(IPK)

The following is a version of the $(IPK) build rule using ipkg-mk. The other rules can remain the same. The package layout is now declared in the prototype file instead of coded into the Makefile:

$(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile prototype
       rm -f $@
       ipkg-mk -c
clean:: rm -f $(IPK)

Obviously, the Makefile can be much shorter using ipkg-mk.

Feeds

Once you have packaged your software, you might want to consider to make it available to others by providing it via a feed. You can either try to submit it to an existing feed (recommendet), or you could set up your own feed. Both alternatives are discussed in the following sections.

Submitting your package

There is no standard mechanism to submit a package to a particular feed. Each feed operator has set up his/her own mechnism and rules. Articles/GeneralIpkgFeeds contains a list of known feeds and pointers to the operators' submission guidelines.

Setting up your own Feed

Before seting up an own feed, consider instead to submit it to an existing feed. Also, consider that operating a useful feed requires resources and regular maintenance.

Setting up an own feed is rather simple. Actually, people often operate several feeds, e.g. a stable and an unstable feed, and feeds for different CPU architectures at the same time. Setting up a feed works as it follows:

  • First some ftp or web space is needed.

Then:

  • All .ipk files for one feed should go into one directory on that ftp or web space. Typically for a LinkStation feed the directory name should be that of the particular processor architecture, e.g. mipsel, or ppc.
  • Further it is common to provide a stable feed for trusted and tried packages, and an unstable feed for less tested (freshly uploaded) packages.
  • For each feed an index file called Packages needs to be created from the .ipk packages (it can also be gziped and called Packages.gz). The file contains the control information from each package in a feed. The script ipkg-make-index from the ipkg-utils can be used to build this meta-data.
  • Announce the feed, so people can add the feed to their /etc/ipkg.conf configuration file.

Typically, an unstable feed is supposed to contain packages which have not been verified at all, or not extensively verified. A stable feed should contain only verified packages. Package verification should include some security check.