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

From NAS-Central Buffalo - The Linkstation Wiki
Jump to: navigation, search
(Setting up your package build-environment directly on the LS)
m
 
(39 intermediate revisions by 9 users not shown)
Line 1: Line 1:
 +
{{Template:Articles}}
 +
<center><font color=red>''This article is based on the work of nix & titimred from www.linkstationwiki.org''</font></center>
 +
 +
 
== Overview ==
 
== Overview ==
  
Line 6: Line 10:
 
Two methods are described
 
Two methods are described
  
#'''The classic way, using '''ipkg-buld''' from the '''ipkg-utils''' collection, and'''
+
#The classic way, using ''ipkg-build'' from the ''ipkg-utils'' collection, and
#'''using a wrapper tool ''ipkg-mk'' around ''ipkg-build''''
+
#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.
 
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 ==
 
== Building an .ipk package - using ipkg-utils ==
 +
  
  
 
=== 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://www.linkstationwiki.net/downloads 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://www.linkstationwiki.net/downloads 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 23: Line 27:
 
;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-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.
+
;<font color=red>ipkg-build</font>:<font color=red>Builds a package from a prepared directory structure. This is the most important tool. It can run stand-alone and is a shell script.</font>
  
 
;ipkg-buildpackage:Builds a package from a source tarball.
 
;ipkg-buildpackage:Builds a package from a source tarball.
Line 41: Line 45:
 
;ipkg-ipk:Retired. Replaced by ipkg-build
 
;ipkg-ipk:Retired. Replaced by ipkg-build
  
;ipkg-link:Links (and unlinks) ipkg meta data from some non-volatile storrage (e.g. flash memory) to the current file system. Probably only useful on systems where packages are installed in flash ram.
+
;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-familiar:('familiar' is a handhelds.org distribution for the iPAQ).
Line 55: Line 59:
 
;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'')
 
;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 ==
+
=== Using ipkg-build from ipkg-utils ===
  
 +
The normal but tedious method for building an '''.ipk''' is to use '''ipkg-build'''. You must start by [[Articles/GeneralCreatingAPackage|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''':
  
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 toolchain(s)]]. '''ipkg-build''' requires several things in order to properly build an '''.ipk''':
+
# A special meta-data file named '''control''' (more on this in the [[#Package structure / prototype directory structure|Packge structure]] section)
 
+
# The input files must be structured in directories exactly as they should appear when installed. Which is a tedious task. See [[#Building an .ipk - using ipkg-mk on top of ipkg-build|ipkg-mk]] below for an alternative.
# A special meta-data file named '''control''' (more on this in the [[#PkgStruct|Packge structure]] section)
+
# The input files must be structured in directories exactly as they should appear when installed. Which is a tedious task. See [[#IpkgMk|ipkg-mk]] below for an alternative.
+
 
# 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 indentify 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 70: Line 76:
 
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'').
 
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 prinicple 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.
+
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.
 
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.
  
[[#IpkgMk|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 ===
  
 
+
'''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
'''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 wraped 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 ))
 
  ( cd $tmp_dir && tar -zcf $pkg_file ./debian-binary ./data.tar.gz ./control.tar.gz ))
Line 87: Line 93:
 
to
 
to
  
  ( cd $tmp_dir && tar =]%red%$ogargs%black%[= -zcf $pkg_file ./debian-binary ./data.tar.gz   
+
  ( cd $tmp_dir && tar <font color=red>$ogargs</font> -zcf $pkg_file ./debian-binary ./data.tar.gz   
 
  ./control.tar.gz )
 
  ./control.tar.gz )
  
Line 94: Line 100:
 
The parsing of the '-C' (uppercase 'C') option is also faulty.
 
The parsing of the '-C' (uppercase 'C') option is also faulty.
  
 
[[#IpkgMk]]
 
  
 
== Building an .ipk - using ipkg-mk on top of ipkg-build ==
 
== Building an .ipk - using ipkg-mk on top of ipkg-build ==
Line 101: Line 105:
 
=== Introduction ===
 
=== Introduction ===
  
'''ipkg-mk''' is a script which takes a prototype package description as input, spools (creates) the necessary prototype directory structure, and use '''ipkg-build''' to construct a package from the spooled prototype directory structure.
+
'''ipkg-mk''' is a script which  
 +
*takes a <tt>prototype</tt> 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 tool's prototype description format is a variant of the Unix System V Release 4 (SVR4) package management's prototype description format. By relying on an explicite prototype description file it is possible to  
+
The package layout declaration is in what is called a <tt>prototype</tt> 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 (explicite descriptions instead of implicite file attributes in some directory structure)''',
+
*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'''
+
*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).'''
+
*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''' 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''.
Line 117: Line 134:
 
=== Obtaining and installing ipkg-mk ===
 
=== 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 formater) and '''awman''' (a '''man''' clone using '''awf''').
+
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:
 
So, currently the installation of '''ipkg-mk''' on the LS with OpenLink requires some manual work:
  
*''' (''Only on pre OpenLink 0.60'') Follow the [[Articles/GeneralIpkgOnLinkstation#ManInst|manual ipkg installation]] instructions to obtain, install and update the '''ipkg''' client itself.'''
+
*(''Only on pre OpenLink 0.60'') Follow the [[Articles/GeneralIpkgOnLinkstation#ManInst|manual ipkg installation]] instructions to obtain, install and update the '''ipkg''' client itself.
  
*''' Download the [[ftp://ftp.handhelds.org/packages/ipkg-utils/ipkg-utils-1.7.tar.gz | ipkg-utils]], extract the '''ipkg-build''' script out of the archive and place it in '''/usr/bin'''.'''
+
*Download the [[ftp://ftp.handhelds.org/packages/ipkg-utils/ipkg-utils-1.7.tar.gz | ipkg-utils]], extract the '''ipkg-build''' script out of the archive and place it in <tt>/usr/bin</tt>.
 +
 
 +
*Install the '''awf''' formatter (needed for viewing the documentation). This can already be done via '''ipkg''':
  
*''' Install the '''awf''' formater (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
 
  ipkg install http://people.freenet.de/lsnix/LinkStation/awf_0.1-1_all.ipk
  
*''' Install the [aw]man package (for formating and viewing manual pages):'''
+
: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
 
  ipkg install http://people.freenet.de/lsnix/LinkStation/awman_0.1-1_all.ipk
  
*''' And finally (''phew ...'') install @@ipkg-mk@@:'''
+
*And finally (''phew ...'') install '''ipkg-mk''':
  
 
  ipkg install http://people.freenet.de/lsnix/LinkStation/ipkg-mk_0.2-1_all.ipk
 
  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:
+
To read the '''ipkg-mk''' documentation you can now type:
  
 
  man ipkg-mk
 
  man ipkg-mk
 
  man ipkg-prototype
 
  man ipkg-prototype
  
And to view the documentation for the formater and the man page viewer you can type:
+
And to view the documentation for the formatter and the man page viewer you can type:
  
 
  man awf
 
  man awf
Line 149: Line 168:
 
  man ms
 
  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 preformated versions which view much faster.
+
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 a package ===
 
+
==== Build with manually created <code>prototype</code> File ====
 
Once the environment is set up, the following steps can be performed to build a package with '''ipkg-mk''':
 
Once the environment is set up, the following steps can be performed to build a package with '''ipkg-mk''':
  
Line 164: Line 183:
  
 
The result should be the desired package.  
 
The result should be the desired package.  
[[#ProtoExample]]
+
 
 
'''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:
 
'''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:
  
Line 184: Line 203:
 
See the '''ipkt-prototype'''(4) man page for more details of the format.
 
See the '''ipkt-prototype'''(4) man page for more details of the format.
  
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. It can be installed via '''ipkg''':
+
==== Build with '''ipkg-proto''' generated <code>prototype</code> 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
 +
 
 +
#The application's files are build (e.g. created from source code), or they are obtained in some other way.
 +
#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.
 +
#'''ipkg-proto''' is run to create an initial, raw ''prototype'' file.
 +
#The ''prototype'' file is manually edited to refine and complete it.
 +
#'''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.
 +
#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
 
  ipkg install http://people.freenet.de/lsnix/LinkStation/ipkg-proto_0.1-1_all.ipk
Line 193: Line 240:
  
 
The tool can e.g. be run on an existing directory ('''/lib''' in the example) as it follows
 
The tool can e.g. be run on an existing directory ('''/lib''' in the example) as it follows
 
 
   
 
   
 
  $ ipkg-proto /usr
 
  $ ipkg-proto /usr
Line 207: Line 253:
 
  s none /lib/libcom_err.so.2=libcom_err.so.2.0
 
  s none /lib/libcom_err.so.2=libcom_err.so.2.0
 
  ...
 
  ...
 
 
[[#PkgStruct]]
 
  
 
== Package structure / prototype directory structure ==
 
== Package structure / prototype directory structure ==
Line 215: Line 258:
 
=== Overview ===
 
=== 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 directoy 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.
+
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 ==
+
=== 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:
 
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  # manadatory - package description
+
  ./spool/ -+- CONTROL/ -+- control  # mandatory - package description
           |            [=+-=] preinst  # optional - pre-install script
+
           |            +- preinst  # optional - pre-install script
           |            [=+-=] postinst  # optional - post-install script
+
           |            +- postinst  # optional - post-install script
           |            [=+-=] prerm    # optional - pre-remove script
+
           |            +- prerm    # optional - pre-remove script
           |            [=+-=] postrm    # optional - post-remove script
+
           |            +- postrm    # optional - post-remove script
           |            [=+-=] conffiles # optional - list of volatile config files
+
           |            +- conffiles # optional - list of volatile config files
           [=+-=] <package data dirs/>
+
           +- <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.
 
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.
  
[[#ControlFile]]
+
===='''CONTROL/control''' file (mandatory) ====
'''CONTROL/control''' file (mandatory)
+
===== Overview =====
==== 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 ': '.
 
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 ': '.
Line 249: Line 291:
 
in a '''prototype''' file for '''ipkg-mk''' will ensure this.  
 
in a '''prototype''' file for '''ipkg-mk''' will ensure this.  
  
==== Mandatory information ====
+
===== 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.
+
This section lists the mandatory information (keys), which need to be provided in a <tt>control</tt> 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:
+
Required entries in the <tt>control</tt> file are:
  
'''Package -'''
+
;Package<nowiki>:</nowiki>: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.
  
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<nowiki>:</nowiki>: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]\+''
  
'''Version -'''
+
;Architecture<nowiki>:</nowiki>: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'')
  
Version number, in the form ''[:''epoch''] ''version''[-fam''frevision''][-''revision'']]''
+
;Maintainer<nowiki>:</nowiki>:Typically the name and e-mail address of the maintainer of the package, the package builder (not neccessarily the author of the software)
  
''epoch''
+
;Section<nowiki>:</nowiki>:(''exact meaning needs to be clarified'')
A timestamp, seconds since the epoch (details unknown)
+
:;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?
  
''version''
+
;Priority<nowiki>:</nowiki>:(''meaning needs to be clarified''). Normally ''optional'' should be used.
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".
+
:;required:A required package (''what's the difference to the Essential entry?'')
 +
:;standard:''which standard?''
 +
:;important:?
 +
:;optional:An optional package
 +
:;extra:?
  
''frevision''
+
;Description<nowiki>:</nowiki>: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.
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''
+
;Source<nowiki>:</nowiki>:A URL or a list of filenames pointing to the source code. (mandatory, but not mentioned at handhelds.org)
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'''
+
===== Optional Information =====
  
Architecture name. Possible names are:
+
In addition to the mandatory information, at least the following keys are recognized by ''ipkg''.
::'''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 -'''  
+
;Depends<nowiki>:</nowiki>:Dependencies on other packages. A comma separated list of package names (''Can names with versions be specified here, or just names?'')
  
Typically the name and e-mail address of the maintainer of the package, the package builder (not neccessarily the author of the software)
+
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:
  
'''Section -'''
+
;Filename<nowiki>:</nowiki>:?
 +
;MD5sum<nowiki>:</nowiki>:? (lowercase 's')
 +
;MD5Sum<nowiki>:</nowiki>:? (uppercase 's')
 +
;Size<nowiki>:</nowiki>:?
 +
;Installed-Size<nowiki>:</nowiki>:?
 +
;Installed-Time<nowiki>:</nowiki>:?
 +
;Essential<nowiki>:</nowiki>:Flag, argument <tt>yes</tt>
 +
;Status<nowiki>:</nowiki>:Internally used only? Three space-separated arguments: ''want'' ''flag'' ''status''
 +
:;want:<tt>unknown</tt>, <tt>install</tt>, <tt>deinstall</tt>, <tt>purge</tt>
 +
:;flag:<tt>ok</tt>, <tt>reinstreq</tt>, <tt>hold</tt>, <tt>replace</tt>, <tt>noprune</tt>, <tt>prefer</tt>, <tt>obsolete</tt>, <tt>user</tt>
 +
:;status: <tt>not-installed</tt>, <tt>unpacked</tt>, <tt>half-configured</tt>, <tt>installed</tt>, <tt>half-installed</tt>, <tt>config-files</tt>, <tt>post-inst-failed</tt>, <tt>removal-failed</tt>
 +
;Conffiles<nowiki>:</nowiki>:? List of name/md5sum pairs
 +
;Provides<nowiki>:</nowiki>:?
 +
;Pre-Depends<nowiki>:</nowiki>:?
 +
;Recommends<nowiki>:</nowiki>:?
 +
;Suggests<nowiki>:</nowiki>:?
 +
;Conflicts<nowiki>:</nowiki>:?
 +
;Replaces<nowiki>:</nowiki>:?
  
(''exact meaning needs to be clarified'')
+
==== Scripts ====
 
+
===== Things common to all CONTROL Scripts =====
::'''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 requred 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?'')
+
 
+
''lots of unexplained parameters'':
+
''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 <tt>yes</tt>
+
:'''Status''':Internally used only? Three space-separated arguments: ''want'' ''flag'' ''status''
+
::''want'':<tt>unknown</tt>, <tt>install</tt>, <tt>deinstall</tt>, <tt>purge</tt>
+
::''flag'':<tt>ok</tt>, <tt>reinstreq</tt>, <tt>hold</tt>, <tt>replace</tt>, <tt>noprune</tt>, <tt>prefer</tt>, <tt>obsolete</tt>, <tt>user</tt>
+
::''status'': <tt>not-installed</tt>, <tt>unpacked</tt>, <tt>half-configured</tt>, <tt>installed</tt>, <tt>half-installed</tt>, <tt>config-files</tt>, <tt>post-inst-failed</tt>, <tt>removal-failed</tt>
+
:'''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
 
* All '''CONTROL''' scripts are optional
Line 390: Line 401:
 
  esac
 
  esac
  
=== CONTROL/preinst Script (optional) ===
+
===== CONTROL/preinst Script (optional) =====
  
 
This script, if it exists, is called by '''ipkg''' with one of the following arguments before the actual installation:
 
This script, if it exists, is called by '''ipkg''' with one of the following arguments before the actual installation:
Line 407: Line 418:
 
If the script returns a non-zero exit status then the installation of the package is aborted.
 
If the script returns a non-zero exit status then the installation of the package is aborted.
  
=== CONTROL/postinst Script (optional) ===
+
===== CONTROL/postinst Script (optional) =====
  
 
If the script exists it is called with the argument '''configure''' after the installation of the package, or when
 
If the script exists it is called with the argument '''configure''' after the installation of the package, or when
Line 415: Line 426:
 
was run.
 
was run.
  
=== CONTROL/prerm Script (optional) ===
+
===== CONTROL/prerm Script (optional) =====
  
 
If the script exists it is called with the argument remove prior to removal of the package.
 
If the script exists it is called with the argument remove prior to removal of the package.
Line 425: Line 436:
 
* Backup of user-created data or other valuable data
 
* Backup of user-created data or other valuable data
  
=== CONTROL/postrm Script (optional) ===
+
===== CONTROL/postrm Script (optional) =====
  
 
If exists, called with the argument '''remove''' after the removal of the package.
 
If exists, called with the argument '''remove''' after the removal of the package.
Line 434: Line 445:
 
* 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.
 
* 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) ===
+
===== 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.
 
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.
  
Line 441: Line 452:
 
The package data directories hold the actual files which should be installed on the target system:
 
The package data directories hold the actual files which should be installed on the target system:
  
  ./spool/ [=-+-=] CONTROL/ [=---=] <control files>\\
+
  ./spool/ -+- CONTROL/ --- <control files>
           |\\
+
           |
           [=+-=] <package data dirs/>
+
           +- <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:
+
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>
+
  ./spool/ -+- CONTROL/ --- <control files>
           [=+-=] usr/ [=-+-=] bin/ [=---=] app
+
           +- usr/ -+- bin/ --- app
           |        [=+-=] lib/ [=-+-=] libapp.so.1.0
+
           |        +- lib/ -+- libapp.so.1.0
           |        |        [=+-=] libapp.so.1 [=->=] libapp.so.1.0
+
           |        |        +- libapp.so.1   -> libapp.so.1.0
           |        |        [=+-=] libapp.so [=->=] libapp.so.1
+
           |        |        +- libapp.so     -> libapp.so.1
           |        [=+-=] man/ [=---=] man1/ [=---=] app.1
+
           |        +- man/ --- man1/ --- app.1
           [=+-=] etc/ [=---=] app.conf
+
           +- etc/ --- app.conf
  
''Note:'' '''[=->=]''' indicates a symbolic link
+
''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:
 
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]''')?
+
* 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>/<nowiki>[bin|lib|man|etc]</nowiki>''')?
 
* Which user and group ownerships should the files get?
 
* Which user and group ownerships should the files get?
 
* Which file access modes should the files get?
 
* Which file access modes should the files get?
Line 471: Line 482:
 
=== Converting the prototype structure to the package ===
 
=== Converting the prototype structure to the package ===
  
The above described directory structure is converted into the package (e.g. by @@ipkg-build@@) as it follows. The exact format is not specified anywhere, but the following is known to work.
+
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 files in the @@CONTROL@@ directory are packed into a gziped tar archive called @@control.tar.gz@@
+
The structure is as it follows. The exact format is not specified anywhere, but the following is known to work.
*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>
+
*The files in the <tt>CONTROL</tt> directory are packed into a gziped ''tar'' archive called <tt>control.tar.gz</tt>
                [=+-=] data.tar.gz     <- <package data dirs>
+
*All other files and directories are packed into a gziped ''tar'' archive called <tt>data.tar.gz</tt>
                [=+-=] debian-binary   <- "2.0"
+
*<tt>control.tar.gz</tt> and <tt>data.tar.gz</tt>, plus a file called <tt>debian-binary</tt>, are either packed in yet another ''tar'' file, or in an ''ar'' file. This is called the ''outer wrapper'' and forms the final <tt>.ipk</tt> package. The suffix <tt>.ipk</tt> is used intead of that of a gziped ''tar'' archive (<tt>.tar.gz</tt>) or an ''ar'' archive (<tt>.a</tt>).
  
@@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@@.
+
<pkg-name>.ipk -+- control.tar.gz  <- <control files>
 +
                +- data.tar.gz    <- <package data dirs>
 +
                +- debian-binary   <- "2.0"
  
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.
+
<tt>debian-binary</tt> 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 <tt>data.tar.gz</tt> 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.
 
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 ===
+
== The package-build environment ==
  
 
''this should probably become an own page - hey, this is a wiki :-)''
 
''this should probably become an own page - hey, this is a wiki :-)''
 
   
 
   
==== Setting up your package build-environment directly on the LS ====
+
=== Setting up your package build-environment directly on the LS ===
 
+
{{stubpar}}
  
 
stub Hints
 
stub Hints
Line 498: Line 511:
 
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:
 
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:
  
#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'''.
+
#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'''.
 
+
 
#Install a complete '''ar'''
 
#Install a complete '''ar'''
  
==== Setting up your cross-package build-environment on Unix/Linux ====
+
=== 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''
 
''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 ====
+
=== Setting up your cross-package build-environment on Windows ===
  
You need a Unix-like environment, like [[http://www.cygwin.com/ | 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.
+
You need a Unix-like environment, like [[http://www.cygwin.com/ | 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.
 
Once you have set up your cygwin environment you can follow the procedures for cross-package building under Unix/Linux.
  
 
+
== Sample <tt>CONTROL/control</tt> files ==
==== A sample architecture-independen ipkg CONTROL/control file ====
+
=== A sample architecture-independent ipkg <tt>CONTROL/control file</tt> ===
 
Architecture independent packages are packages which e.g. control scripts which run on "any" architecture or documentation which is not architecture specific.
 
Architecture independent packages are packages which e.g. control scripts which run on "any" architecture or documentation which is not architecture specific.
  
  %argStyle%[@
+
  Package: sample-pkg-name
Package: sample-pkg-name
+
Section: base
Section: base
+
Priority: optional
Priority: optional
+
Version: 1.0.1-3
Version: 1.0.1-3
+
Architecture: all
Architecture: all
+
Maintainer: you@example.com
Maintainer: you@example.com
+
Source: http://origin.of.the.sourcecode.of.the.software
Source: http://origin.of.the.sourcecode.of.the.software
+
Depends: list,of,other,packages
Depends: list,of,other,packages
+
Description: Description of the software
Description: Description of the software
+
@]
+
 
+
==== A sample PPC ipkg CONTROL/control file ====
+
 
+
==== A sample MIPSel ipkg @@CONTROL/control@@ file ====
+
 
+
==== A sample TeraStation ipkg @@CONTROL/control@@ file ====
+
 
+
 
+
  
==== Automating the packaging with ''make'' ====
+
=== A sample PPC ipkg <tt>CONTROL/control</tt> file ===
 +
{{stubpar}}
 +
=== A sample MIPSel ipkg <tt>CONTROL/control</tt> file ===
 +
{{stubpar}}
 +
=== A sample TeraStation ipkg <tt>CONTROL/control</tt> file ===
 +
{{stubpar}}
 +
== 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:
+
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
 
  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 [[http://www.gnu.org/software/make/manual/make.html]]. 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).
+
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 [[http://www.gnu.org/software/make/manual/make.html]]. 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:
+
'''make''' uses so called ''makefiles'' as input. The following is an example for a <tt>Makefile</tt> using '''ipkg-build''' to buld a package. Note the long and tedious setup of the portotype directory in the $(IPK) rule:
  
  %argStyle%[@
+
  NAME    = my-pkg#
NAME    = my-pkg#
+
VERSION = 1.0-1#
VERSION = 1.0-1#
+
ARCH    = all#
ARCH    = all#
+
IPK    = $(NAME)_$(VERSION)_$(ARCH).ipk<br>
IPK    = $(NAME)_$(VERSION)_$(ARCH).ipk
+
CONTROL_FILES = control preinst # contents of the CONTROL dir
 
+
DATA_FILES    = the application files<br>
CONTROL_FILES = control preinst # contents of the CONTROL dir
+
default: $(IPK)<br>
DATA_FILES    = the application files
+
#
 
+
# Construct the control file on the fly, so data in this Makefile
default: $(IPK)
+
# and in the control file match
 
+
#
#
+
control: control.tmpl
# Construct the control file on the fly, so data in this Makefile
+
# and in the control file match
+
#
+
control: control.tmpl
+
 
         rm -f $@
 
         rm -f $@
 
         echo "Package: $(NAME)"      > $@ || { rm -f $@; exit 1; }
 
         echo "Package: $(NAME)"      > $@ || { rm -f $@; exit 1; }
 
         echo "Version: $(VERSION)"  >> $@ || { rm -f $@; exit 1; }
 
         echo "Version: $(VERSION)"  >> $@ || { rm -f $@; exit 1; }
 
         echo "Architecture: $(ARCH)" >> $@ || { rm -f $@; exit 1; }
 
         echo "Architecture: $(ARCH)" >> $@ || { rm -f $@; exit 1; }
         cat control.tmpl            >> $@ || { rm -f $@; exit 1; }
+
         cat control.tmpl            >> $@ || { rm -f $@; exit 1; }<br>
 
+
clean::
clean::
+
         rm -f control<br>
         rm -f control
+
#
 
+
# Build package
#
+
#
# Build package
+
$(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile
#
+
$(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile
+
 
         rm -f $@
 
         rm -f $@
 
         rm -rf /tmp/pkg$(NAME)
 
         rm -rf /tmp/pkg$(NAME)
Line 593: Line 595:
 
         #
 
         #
 
         ipkg-build -c -o root -g root /tmp/pkg$(NAME)
 
         ipkg-build -c -o root -g root /tmp/pkg$(NAME)
         rm -rf /tmp/pkg$(NAME)
+
         rm -rf /tmp/pkg$(NAME)<br>
 
+
clean::
clean::
+
 
         rm -f $(IPK)         
 
         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@@:
+
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 <tt>prototype</tt> file instead of coded into the <tt>Makefile</tt>:
  
  %argStyle%[@
+
  $(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile prototype
$(IPK): $(CONTROL_FILES) $(DATA_FILES) Makefile prototype
+
 
         rm -f $@
 
         rm -f $@
         ipkg-mk -c
+
         ipkg-mk -c<br>
 
+
clean::
clean::
+
 
         rm -f $(IPK)
 
         rm -f $(IPK)
@]
 
  
[[#Feeds]] (:comment  Provide an anchor allowing to referenceto the following section:)
+
Obviously, the <tt>Makefile</tt> can be much shorter using ''ipkg-mk''.
  
 
== Feeds ==
 
== 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.
 
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.
Line 619: Line 615:
 
=== Submitting your package ===
 
=== 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.
+
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 ===
 
=== Setting up your own Feed ===
  
Line 627: Line 623:
 
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:
 
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:
+
* 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''.
 
* 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.  
 
* 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.
+
* For each feed an index file called <tt>Packages</tt> needs to be created from the .ipk packages (it can also be gziped and called <tt>Packages.gz</tt>). 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.
+
* Announce the feed, so people can add the feed to their <tt>/etc/ipkg.conf</tt> 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.
 
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.
 +
 +
[[Category:General]]
 +
[[Category:Ipkg]]

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.