Dev:Packaging

Packaging is the step prior to sharing or releasing a tweak/application/tool/library/theme. Here you put all your project files into a single nicely wrapped file that others can install on their devices.

Cydia is based on Debian APT (Advanced Packaging Tool), so a lot of general documentation about packaging for APT also applies to packaging for Cydia.

To do: bring over http://iphonedevwiki.net/index.php/MobileSubstrate_Pitfalls#Packaging too.

Best Practices

 * Do not create mobile-owned files and/or directories in your package. Stay out of mobile's home directory!
 * All package files are installed as root. Your software should create any required files or directories at runtime.
 * This is doubly important for preferences. A user's preferences do not belong in a package: if preferences are stored in the package, they will be overwritten when you release an update, and deleted when the user uninstalls your software (even temporarily!)
 * Do not use postinst/preinst/extrainst_ for file management purposes!
 * Do not store in the package files or directories that your software could create.
 * Do not enforce permissions that your package should contain. dpkg uses an expressive packaging format that has support for permissions, ownership, and links. Use that support!
 * Make sure your package doesn't include hidden .DS_Store, ._*, or thumbs.db files.
 * will disable resource forks (._* files) being included on OS X with Theos.
 * Adding  to your package staging commands in Theos/DragonBuild will ensure they are deleted before packaging.

dpkg-deb
Likely the most ideal software to use for packaging .debs. Part of the dpkg suite.

Some repo software requires the -Zgzip flag, so I would advise using this.

Example usage:

`dpkg-deb --build -Zgzip -z9 my/tweak/staging/directory packages/`

This will build the contents of `my/tweak/staging/directory` (see #Staging) into a package located in the folder `packages`.

" To do: Add other utilities (.pl, .py, et al.) usage, etc). "

Control file
Fields with a * are typically added by your repo. Verify yourself with your repo as to which fields need to be added by you and which are added by the repository.

If you need to list dependencies or conflicting packages, Debian's packaging manual may be useful (because Cydia packaging is based on Debian packaging): Syntax of relationship fields, Dependencies, Conflicts -- or if you're submitting this package to a default repository, you can just ask your repository maintainer for help with this.

For information on the package version format and how versions are sorted, see this page of the Debian packaging manual.

Other files
You can add,  ,  ,  , and   files to run scripts at various points of the package installation and uninstallation lifecycle. It's important to be conservative with this code - as Best Practices explains, "Do not use postinst/preinst/extrainst_ for file management purposes! Do not store in the package files or directories that your software could create. Do not enforce permissions that your package should contain. dpkg uses an expressive packaging format that has support for permissions, ownership, and links. Use that support!"

If your package scripts have problems, especially upon uninstallation, this can be very frustrating for your user because that can be very hard to fix for them. You don't want to cause the dreaded "subprocess pre-removal script returned error" and "Sub-process /usr/bin/dpkg returned an error code" error messages. A related unfortunate reality is that if your package has complex scripts, that can increase the chances that if a pirate repository poorly repackages your tweak, somebody doing "try before they buy" can run into those error messages and get frustrated.

Documentation about these scripts in the Debian packaging manual: basics and more info.

extrainst_
 I get a lot of requests for things like "I want to run stuff after the install, but only on install, not on upgrade". APT/dpkg is miserable at this. Its sad, but true. It has a file called postinst, but postinst is really designed for reconfiguring a package, not for installing it: its called /long after/ the package is installed (like, APT will go on and install more things and then queue up the postinst files to the very end) and it doesn't /really/ know anything about the package.

Example: in a postinst you know that the previous configuration on disk was from version 1.0, but not that 1.0 itself was actually on disk. And if you are a new install it still tells you that /you're/ already the configuration there (which is really just a stupid semantic).

/So/, after dealing with an issue in a package with _BigBoss_, I have decided to do something about this: I have added to dpkg a new script called extrainst_. This script takes one of two arguments: install or upgrade (in which case you also get the version you are upgrading from), and is designed to completely ignore configuration files (so if you were previously in a configuration file only state that isn't considered "installed"). I believe that this new script now provides a very simple conceptualization for how you do "extra stuff" during an install.

In fact, if you are previously coming from Installer, this script will likely feel like "ahhhh".

To use this new script (which yes, really ends in an underscore) your package should Pre-Depends: dpkg (>= 1.13.25-5). This will make it so that that version of dpkg is actually available during the install and is used to run the scripts. (Yes, this will work even during the install using the old version of dpkg to upgrade dpkg and then switching to the new version of dpkg to install your script ;P).

If this script fails then the install is considered to not have worked and the installation procedure will get rolled back (files will get removed, replaced back to the backup copies if it was an upgrade, and a million random scripts will get called with irritatingly complicated to remember arguments).

(Note that this version of dpkg isn't up right now, but will be up within an hour or two: i.e., long before any of you is likely to bother to try to use it ;P).

An example extrainst_:


 * 1) !/bin/bash

if | $1 == upgrade ; then do_something awesome fi

if $1 == upgrade && $2 == 1.0-4 ; then fix_bug_in old version fi

-J To see the whole discussion about this, see this thread.

Telling Cydia to respring/reboot etc. after install
From this paste

To do: Explain how it fits into Debian packaging (how it interacts with apt/aptitude/dpkg/Cydia).

''This should be looked at deeper. This is an implementation of communicating via file descriptors to Cydia from a C program ''

Infinite upgrade
If your Package Manager (Cydia, et al.) continuously shows a pending upgrade, there may be an error in your control file. This can be caused by a missing "Installed-Size" field. If you've packaged your tweak/theme manually, be sure to include this field.