![]() |
![]() |
![]() |
![]() |
This appendix includes:
If you want to create packages that other users can install, the easiest way is to use the packager utility. It leads you through the process, and it prompts you for the required information. If you have a QNX Package Manifest (qpm) file, you can speed up the process by having packager use it for the default answers.
Packages keep all aspects of a product in one manageable file. A package is similar to a .tgz file -- it's a compressed version of all of the files that make up your product.
Packages, however, have additional elements beyond the standard "tarball" you may have seen before. Packages also include a manifest, and any support files used within the package, such as licenses, scripts, or HTML web pages. Since all of this information is packaged together, the QNX software installer can extract the required information to install your product into the package filesystem (which, by default, manages all software on your system).
This appendix describes the packager utility and how you can use it to combine your own product into a set of packages that you can either distribute or make available on a repository (a set of packages at a particular URL location).
The QNX package manifest (QPM) file describes all aspects of a package, including:
You can use any standard ASCII text editor to edit the QPM file, which follows XML formatting guidelines. However, we recommend that you not edit the file by hand. Instead, you should make any changes to the package as part of a repackaging procedure, using packager. This not only ensures that the data is entered correctly, it also updates other information automatically, such as the date that the package was created, the release number, and the size of your product. The packager also gathers and compresses your files into the required structure.
The packager utility generates packages with all the necessary tags to comply with both current and future versions of the QNX software installer. You can also use packager to repackage existing packages to reflect updates in the program or to create patches from a previous package to a new one.
There are a lot of tags that make up a QPM file, so you should expect a correspondingly large number of questions in order to make a package that is accurate and detailed. The packager was designed as a command-line utility so that after you've answered these questions once, it's easy to pass your previous package as a command-line argument and bypass the questions next time.
If you look at the documentation for packager in the Neutrino Utilities Reference, you'll see that there are many options that you can specify. Don't let this daunt you -- you can create a package-generation (QPG) file that lets you automate the packaging process, and then you'll have to type only packager to build a brand-new package at any time. For more information, see "Working with a package-generation (QPG) file," later in this appendix.
When packager asks you a question, it provides a default value in parentheses, like this: (default). To use the default value, press Enter without entering any text. Press Ctrl-B to go to the previous question if you make a mistake.
The packager utility gives you detailed comments about each question (by default). Once you're used to the questions, you can pass the -v1 (advanced mode) or -v2 (expert mode) option to reduce the amount of information shown for each question.
The default packaging method that packager uses expects that you pass it a directory as the only argument. This directory holds all of the files that you would like to have packaged, laid out in a directory structure that reflects the root (/) filesystem, when the files are installed. Public software should all be installed under the /opt directory. For example, if you type:
packager basedir/
then packager takes all files under basedir and puts them into your package by creating a QPM file. This file lists all answers to the questions, along with a list of the files under the basedir directory.
The packager also creates a QNX package file (QPK) which is a tarred/gzipped archive of the manifest file (renamed MANIFEST), and each of the files in the basedir directory. By default, packager also creates a QNX repository file (QPR) which is itself a tarred/gzipped archive of the QPM and QPK files. You can view the contents of a QPK or a QPR file by typing tar -ztf filename.qpk.
When packager is sorting your files, it automatically detects any executable files made to execute on a particular processor (host) and creates a separate package to put these files into; packager also automatically makes links between these processor-specific and processor-independent packages. So, when packager is working, you may see two QPM files and two QPK files created. The QPR file is an archive of all four files. In fact, if you have files to be hosted on other processors, a separate QPR file is created for each processor.
In addition, if you have executable files that generate files targeting different processors or header (.h) files, packager starts to create development packages with a -dev- qualifier in the file name. There's no limit to how many packages packager may create as it works, although you can expect to see two for a standard package, and perhaps six for an advanced one.
Before you run packager, put your files into a directory structure that reflects where they should appear when someone installs your package. You can do this in a number of different ways:
Create an empty directory to hold your files, such as basedir or myappdir. This directory then reflects your root filesystem (/). Within that directory, create directories such as /opt or /usr.
![]() |
If you create an /opt directory with a standard
directory inside it (e.g. /opt/bin), packager
will later ask if you want to automatically union /opt/bin
to /usr/bin.
You should answer yes.
Similarly, if you make a directory structure that's uncommon (e.g. /mydir), packager will tell you that you have an "Uncommon Directory Path (/mydir)," indicating that you should move your program to a standard location. In response, tell packager to exit, and then correct your paths. Once the directory structure is in place, copy each of your files (for this product) into their respective locations within this basedir directory. |
Again, create an empty directory to hold your files, such as basedir or myappdir, which then reflects your root filesystem (/). Copy your compressed file into this directory. Decompress the file or files, as required, to make the directory structure required for your program. Once the files are in place, remove the compressed file.
As above, create an empty directory to hold your files. Run packager with the -z option, followed by the name of the package (either a QPK or a QPR) and the base directory. For example:
packager -z mypackage-1.0-x86-me.qpk basedir/
If you're using a QPR file, all files within it are decompressed into the base directory. If you're using a QPK file, you may wish to decompress a number of the files into the same directory. To do this, just enter the first part of the QPK files that are common to all desired QPK files in your current directory, as shown here:
packager -z mypackage-1.0- basedir/
The packager utility extracts the files from your package(s) and places them into basedir as it would if they were installed on your root filesystem (/).
You'll find that packager asks many questions. Here are some hints for answering them:
For example, you may be asked if you would like to union your /opt directory to the /usr directory. Always answer affirmatively. If you union the two directories, your software appears as if it were in the /usr directory. As a result, public software appears all in the same place /usr), but a system administrator can manage it from a common location (/opt) without fear of harming the operating system itself.
Here are some of the more important things that packager might ask about your package:
After packager has asked you the basic questions, it sorts your software into the packages needed to properly install your product. Once this sorting is complete, packager asks you another set of questions.
Different questions apply to different packages. So for each package, packager first displays the name of the package, and then asks various questions, which can be divided into these main sections: scripts, dependencies, and the QNX Photon launch menu.
You can execute scripts at the following times during the life of a package:
As well as choosing when the script is to be executed, you may decide to execute either your own script, or to simply run a program that's available on the filesystem.
![]() |
You can't execute a package's files before you activate the package or after you deactivate it. |
Your package might need another package in order to operate correctly. Such requirements are specified by entering dependencies.
![]() |
The packager
automatically inserts tags into your package that describe any shared-object
libraries that your package contains or needs
(packager runs objdump on all
executable files in your package to determine any libraries that they need).
The QNX software installer automatically turns any required shared objects into dependencies that must be satisfied in order for your package to be installed. So, you don't need to add dependencies on packages that provide shared objects that your product inherently requires (e.g. if you're packaging a QNX Photon microGUI application, an automatic dependency on libph.so.2 is placed in your package). |
Also, packager automatically puts in dependencies between any development packages that it generates, so you don't need to add dependencies between these packages either.
For any other situation where your package requires another package's presence, you can manually specify a dependency when packager prompts you. To enter a dependency, simply enter the name of any file on your local system that's required for proper operation of your package. The packager automatically determines the package from which the file originated and adds the dependency on that package into your new package.
You may specify any number of items to appear in QNX Photon's launch menu when this package is active. For each, answer the questions as follows:
As packager works to create your packages, it displays many messages, starting with a welcome message indicating the process that is about to be undertaken. If packager detects any problems with the command-line options that you've entered, it displays an error message, followed by its standard usage message. If you see this usage message, check above it for possible indications of what went wrong. If no error is shown, confirm that the options that you entered are valid. Here are some of the warnings and errors you may encounter:
Once you've created your package, try to install it using the QNX software installer, by typing:
qnxinstall -u mypackage.qpr
or:
cl-installer -o mypackage.qpr
The QNX software installer shows your software as a new package that's ready to be installed. When you install it, no errors or warnings should appear. You can then verify on the command line that your files are actually installed in the locations you've specified.
If your package doesn't show up in the QNX software installer, try adding a -v (verbose) option to your command line. The installer displays messages for any errors that it detects in the package. If your package is shown as being installed already, you may have chosen the same product identifier or vendor identifier as another package that's already installed.
If there appear to be missing files, or something simply doesn't seem to be correctly installed, you can check the manifest for the packages you've installed. As long as you're using the default user repository to install your package, the files are located in /pkgs/repository. Under that directory, find your vendor directory, then the package identifier directory, and finally the version directory. For example, if packager had its own package, it would be found at /pkgs/repository/qnx/packager/core-1.1/.
Inside this directory, you'll find a file called manifest. This is a copy of the QPM file for this package and includes all processor-independent information about the package. If you have processor-specific components to your package, look for a subdirectory with the same name as the processor (e.g. x86), which contains another manifest for the processor-specific portion of your package.
![]() |
If you choose to edit the manifest file, make sure that you follow the XML formatting rules. If you change some values, you might make your package unusable, to the point where the QNX software installer won't understand the package well enough even to remove it! This information is for reference purposes only, and you should remember that using the packager utility is the only correct way to make your packages. |
Learning to automate the packaging process means that future changes to your software are easily reflected in a new package without much effort. Here are the steps you'll follow:
You can use the QPG file to provide the command-line options and answers to packager's questions automatically, without your intervention. It's also an XML-style document that you can edit using any standard ASCII text editor (but we don't recommend this). You can generate an initial QPG file by typing:
packager -m mypackage.qpr -x basedir
This command generates a file called package.qpg that contains the manifest values in your package, and a reference to each of the files inside your package. The basedir that you specify should be the directory that you created in your initial packaging session, where your files reside.
If you do a use packager command, you may notice that packager accepts either a basedir or a qpg_file as its final argument. If you don't specify a basedir on the command line when you start packager, you can specify a QPG file name for packager to use. If you don't specify one, packager looks for a package.qpg file by default. This lets you simply type packager on the command line, and packager rebuilds your package according to the options in the local package.qpg file.
A QPG file has these main sections:
For more information about the options in a QPG file, see "QPG structure," below.
Here's a sample QPG file that shows all the elements that might appear in your final generation file:
<QPG:Generation>
<QPG:Options>
<QPG:User unattended="yes" verbosity="1" listfiles="yes"/>
<QPG:Release number="+"/>
<QPG:Defaults type="qnx_package" file="my_package-1.0-x86-qnx.qpr"/>
<QPG:FileSorting strip="yes"/>
<QPG:Package targets="combine" union="terminate"/>
<QPG:Repository generate="yes"/>
</QPG:Options>
<QPG:Responsible>
<QPG:EmailAddress>joe_blow@home.com</QPG:EmailAddress>
<QPG:Company>My Company Inc.</QPG:Company>
<QPG:Department>Research and Development</QPG:Department>
</QPG:Responsible>
<QPG:Merge file="common/exclusions.qpg"/>
<QPG:Values>
<QPG:Files>
<QPG:Add file="CVS" handling="exclude"/>
<QPG:Add file="src/gcc_ntox86/pkg-installer" permissions="u+s" install="/opt/photon/bin/"/>
<QPG:Add type="tree" file="config/" install="/"/>
<QPG:Add file="/usr/lib/libsocks.so" install="/usr/test/libsocks.so.1" proc="arm"/>
<QPG:Add type="file" file="/usr/lib/libsocks.a" install="/usr/test/" target="arm"/>
<QPG:Add file="/usr/test/libsocks.so" install="/usr/test/" filetype="symlink" linkto="libsocks.so.1"/>
</QPG:Files>
<QPG:PackageFilter>
<QPM:PackageManifest>
<QPM:PackageDescription>
<QPM:PackageType>Application</QPM:PackageType>
<QPM:PackageReleaseUrgency>Low</QPM:PackageReleaseUrgency>
<QPM:PackageReleaseNotes/>
<QPM:PackageRepository/>
<QPM:PackageReleaseNumber/>
</QPM:PackageDescription>
<QPM:ProductDescription>
<QPM:ProductName>Tast</QPM:ProductName>
<QPM:ProductIdentifier>tast</QPM:ProductIdentifier>
<QPM:ProductEmail>support@home.com</QPM:ProductEmail>
<QPM:VendorName>My Company Inc.</QPM:VendorName>
<QPM:VendorInstallName>myco</QPM:VendorInstallName>
<QPM:VendorURL>www.home.com</QPM:VendorURL>
<QPM:VendorEmbedURL/>
<QPM:VendorEmail>support@home.com</QPM:VendorEmail>
<QPM:AuthorName>Joe Blow</QPM:AuthorName>
<QPM:AuthorURL/>
<QPM:AuthorEmbedURL/>
<QPM:AuthorEmail/>
<QPM:ProductIconSmall/>
<QPM:ProductIconLarge/>
<QPM:ProductHomeURL/>
<QPM:ProductDescriptionEmbedURL/>
<QPM:ProductDescriptionURL/>
</QPM:ProductDescription>
<QPM:ReleaseDescription>
<QPM:ReleaseDate>2001/03/01</QPM:ReleaseDate>
<QPM:ReleaseVersion>1.0</QPM:ReleaseVersion>
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
<QPM:ReleaseStability>Stable</QPM:ReleaseStability>
<QPM:ReleaseNoteMinor>Initial public release</QPM:ReleaseNoteMinor>
<QPM:ReleaseNoteMajor>This initial public release of Tast coincides
with the deadlines set forth in the company prospectus.</QPM:ReleaseNoteMajor>
<QPM:CountryExclude/>
</QPM:ReleaseDescription>
<QPM:ContentDescription>
<QPM:ContentTopic>Software Development/Build Tools/Packaging</QPM:ContentTopic>
<QPM:ContentKeyword>tast,sample</QPM:ContentKeyword>
<QPM:DisplayEnvironment>Console</QPM:DisplayEnvironment>
<QPM:TargetAudience>Developer</QPM:TargetAudience>
</QPM:ContentDescription>
<QPM:ProductInstallationDependencies>
<QPM:ProductRequirements>No extra requirements.</QPM:ProductRequirements>
</QPM:ProductInstallationDependencies>
</QPM:PackageManifest>
</QPG:PackageFilter>
<QPG:PackageFilter type="core" component="none">
<QPM:FileManifest>
<QPM:Launch name="QNX Software Systems" xmlmultiple="true">
<QPM:String name="Topic" value="Applications/Development"/>
<QPM:String name="Command" value="/usr/photon/bin/voyager -u http://www.qnx.com"/>
</QPM:Launch>
</QPM:FileManifest>
</QPG:PackageFilter>
</QPG:Values>
</QPG:Generation>
![]() |
Edit the QPG file carefully since it must follow the XML format, where each opening tag has a corresponding closing tag, and spelling mistakes aren't tolerated. |
The list of files, <QPG:Files>, is the most advanced (and flexible) part of the QPG file. Here, you can list the files to package from your hard disk (in any location), the location where they should appear once the package is installed, the types of files they are, any special handling for the files, and any files that should be excluded from your package. The packager utility automatically determines each of these values, if they aren't specified, as long as you provide the source file name (with the file attribute) and the install location (the install attribute).
The <QPG:PackageFilter> section is where you place manifest tags that you would like to appear in the final package manifest(s). The easiest way to fill in this section is to let packager create the QPG for you (-x option). However, when you're trying to add a special feature of some kind, e.g. launch-menu items, you can edit this section to include all the tags you need.
The packager determines some manifest tags each time that you run it. so specifying those values has no effect in the generated packages. An empty tag has the effect of suppressing the question for that tag when you run packager in attended mode.
To create a symbolic link, add another <QPG:Add> line like this to your QPG file:
<QPG:Add file="sym_link_name" install="/opt/bin/"
filetype="symlink" linkto="file/to/link/to"/>
When packager detects the filetype="symlink" attribute, it recognizes this as a request to put a symbolic link into one of your packages. It automatically searches the other files being packaged, looking for the file that the symbolic link points to. When packager finds the file, it places the symbolic link into the same package as the file.
For example, to add a file, libmine.so, from your hard drive, but install it as a different file, libmine.so.1, and then create a symbolic link from libmine.so to libmine.so.1, specify these tags:
<QPG:Add file="src/lib/libmine.so" install="/opt/lib/libmine.so.1"/>
<QPG:Add file="libmine.so" install="/opt/lib/" filetype="symlink"
linkto="libmine.so.1"/>
Components are optional parts of a master product. Parts of your software can be installed with or without other components. For example, think of the set of Photon packages, which consists of a core package, a drivers component, a games component, and other components. With a single session of packager, you can generate a product and all of its components.
You can make any file that you're packaging a part of a component, by adding component="component_name" to the <QPG:Add> line:
<QPG:Add file="bin/my_game" install="opt/bin/" component="games"/>
When packager finds such a line, it puts the file into a new package that has a <QPM:PackageModel> tag of games, with the same product identifier as your core package. This new package is independent of the other portions of your product, but its installation location will be alongside the rest of the product it's derived from. For example:
/pkgs/base/qnx/ph/core-2.0.2/ /pkgs/base/qnx/ph/games-2.0.2/ /pkgs/base/qnx/ph/drivers-2.0.2/
Note that packager uses components automatically when it detects that you're attempting to package development files. Let's say you're packaging some header (*.h) files. When packager detects these files, it automatically creates a component for your package called dev. This development package contains all of the files that are part of the software-development process. Only executable files and configuration files actually go into the core product itself.
If you don't want to create a development (dev) package for your software, or if packager puts a file into a package that you didn't want it to, it's possible to force packager to handle files differently. To do this, make further specifications on the <QPG:Add> line to tell packager exactly how to handle the file. For more information, see the description of the <QPG:Add> in "QPG structure," later in this appendix.
Here are some examples that show common ways to redirect files:
<QPG:Add file="src/include/readme.txt" filetype="exe" proc="x86" install="/opt/share/"/>
<QPG:FileSorting strip="no"/>
You can specify that a particular file not be stripped when packaged, as shown here:
<QPG:Add file="src/bin/my_program" install="/opt/bin/" strip="no"/>
<QPG:Add file="src/bin/my_program" install="/opt/bin/" permissions="x+s"/>
By adding a <QPG:Merge> entry into your QPG file, you can simplify a complicated product into a number of easy-to-manage QPG files. Note that packager reads the <QPG:Options> block only from the primary QPG file; packager ignores a merged QPG file's option block.
For example, your package.qpg file might show:
<QPG:Merge file="author.qpg"/> <QPG:Merge file="drivers.qpg"/> <QPG:Merge file="/home/common/license.qpg"/>
Here's a sample license.qpg you can use to add a license to your package:
<QPG:Generation>
<QPG:Values>
<QPG:PackageFilter>
<QPM:PackageManifest>
<QPM:ReleaseDescription>
<QPM:ReleaseCopyright>Public Domain License</QPM:ReleaseCopyright>
<QPM:ReleaseCopyrightURL>rep://LicenseUrl/license.txt</QPM:ReleaseCopyrightURL>
</QPM:ReleaseDescription>
<QPM:LicenseUrl>repdata://LicenseUrl/license.txt</QPM:LicenseUrl>
</QPM:PackageManifest>
</QPG:PackageFilter>
<QPG:Files>
<QPG:Add file="/location/of/your/license.txt"
install="LicenseUrl/license.txt" handling="repdata"/>
</QPG:Files>
</QPG:Values>
</QPG:Generation>
If you want to use this file, add the <QPG:Merge> line to your main QPG file and be sure to remove the manifest tags that are referenced in the license.qpg file (i.e. <QPM:ReleaseCopyright>, <QPM:ReleaseCopyrightURL>, and <QPM:LicenseURL>) from your main QPG file.
When merging, you may want to apply a set of file attributes to an entire QPG file. For instance, you might change the destination component for the files referenced within the QPG. To do this, use a <QPG:MergeFilter> block with the desired attributes around any number of <QPG:Merge> commands:
<QPG:MergeFilter component="games">
<QPG:Merge file="src/games/photon_games.qpg"/>
<QPG:Merge file="src/games/xphoton_games.qpg"/>
</QPG:MergeFilter>
The packager automatically detects any shared-object libraries (*.so files) that you're packaging and inserts a corresponding <QPM:ContainsLibrary> tag into the manifest of a package that contains such a library:
<QPM:ContainsLibrary>libmine.so.1</QPM:ContainsLibrary>
Similarly, if any files you're packaging require a shared object library in order to operate correctly (and you aren't packaging such a library alongside the files), then packager automatically adds a corresponding <QPM:RequiresLibrary> tag into the manifest of the package that contains such a requirement. This becomes an automatic dependency when the package is installed.
If the required library isn't available, the QNX software installer searches all installed software to try to find another package that contains the required library. If such a package isn't installed, the QNX software installer searches all known repositories for a package that contains the corresponding <QPM:ProvidesLibrary> tag. To avoid downloading a large package that happens to contain the library you require, and perhaps a lot of unnecessary files as well, the QNX software installer tries to find a small package that contains only a set of libraries. Such a package is called a SLIB package.
When you're packaging your files and a shared object library is detected, the library is copied into the package you're making, as well as into a SLIB package. This SLIB package has a similar name to your package; the only difference is that the component name has slib- added to it. The SLIB package is made available alongside your product (in the same repository), but it doesn't show up in the installer as a new package. It's there only for dependency resolution, in case someone installs a package that requires one of your libraries, but doesn't already have your product installed.
For example, if you're packaging a QNX Photon microGUI application, your application already requires phlib.so.1 internally, and packager puts these requirements into your package. The great advantage of SLIB packages is that you don't have a separate dependency that QNX Photon be installed, since this happens automatically when your package is installed.
Each time you generate a package, you must change its version number, its build number, or its release number. By doing so, you ensure that the QNX software installer will uninstall any previous versions of the program and will recognize your package as being a newer version than the one already installed.
You can change the version number for your software at any time, usually to indicate that its features have changed, or that a new architecture is in place. You can set the version number in the QPG file under the <QPM:ReleaseVersion> tag. You must use this format:
major[.minor[.sub]][letter]
For example: 1.0, 1.0A, 2.13.0, 2.13.1A, 7.15.433B
If you're keeping the same version, you can change the build number (an integer) to indicate that the software has been rebuilt, perhaps after you've fixed bugs or made minor changes. You can set the build number in your QPG using the <QPM:ReleaseBuild> tag, however, this fixes the build number and forces you to change the QPG each time you execute packager. A better method is to set an option in the <QPG:Generation> block. Add the <QPG:Build> tag and either set the build number to + (auto-increment), or to date (use today's date in the form, yyyymmddhh). You can also set the build number from the command line by using the -b option.
If you're keeping the same version and build number, you can change the release number to indicate that the software hasn't been modified and that you're simply repackaging the software. The packager automatically increases the release number (an integer) each time you run packager, although it resets the release number to 1 whenever the build number changes.
You can also set the release number in your QPG using the <QPM:PackageReleaseNumber> tag. However, this also fixes the release number and forces you to change the QPG each time that you run packager. You can disable auto-incrementation by setting the block. Add the tag and set the release number to - (don't auto-increment). You can also disable auto-incrementation from the command line, by using the -i option.
You can use QPG files to tell the packager utility how to generate packages, so that you don't need to have direct intervention when building packages; this permits automated packaging as needed. The main advantage is that files don't need to appear in a directory structure that matches the installation directory structure -- this is a significant advantage over the packager utility's default operation, and lets you keep your development setup without having to copy the files to another part of your filesystem.
The basic structure of sections in a QPG file is as follows:
<QPG:Generation>
<QPG:Options>
</QPG:Options>
<QPG:Responsible>
</QPG:Responsible>
<QPG:Owner>
</QPG:Owner>
<QPG:MergeFilter>
</QPG:MergeFilter>
...
<QPG:Merge>
</QPG:Merge>
...
<QPG:Generate>
</QPG:Generate>
...
<QPG:Values>
<QPG:PackageFilter>
</QPG:PackageFilter>
...
<QPG:Files>
<QPG:Add>
</QPG:Add>
...
<QPG:File>
</QPG:File>
...
</QPG:Files>
</QPG:Values>
</QPG:Generation>
Any QPG file can reference other QPG files (using the <QPG:Merge> specifier). Thus, your main QPG can reference a number of smaller (easier to manage) QPG files. Merging QPG files lets you add to the list of files to be packaged (see <QPG:Files>), and define the manifest settings that will be used for all generated packages (see <QPG:PackageFilter>).
![]() |
The <QPG:Options> section (command-line adjustments) isn't merged -- packager uses only the primary QPG file's <QPG:Options> section. |
For example, you might have one QPG file that sets up a product's license settings and adds the license.txt file to the package.
Use a <QPG:Add> entry for each file that you want to include in the package. Wildcards are allowed, or you can add an entire directory or directory tree.
Note the following:
To fix this, refer to the script as pkg://script1. The packager replaces the pkg:// with rep://path/to/the/package/ each time that you build the package. You can use the pkg:// qualifier in any part of the manifest; right before the manifest is written, the packager replaces the qualifier with the actual value.
To fix this, refer to the license as repdata://LicenseUrl/license.txt. The packager replaces the repdata:// with rep://package.repdata/ each time that you build the package. You can use the repdata:// qualifier used in any part of the manifest; right before the manifest is written, the packager replaces the qualifier with the actual value.
This is the top-level tag for a QPG file. This tag can include the following tags:
The options that you put in this section specify the command-line options to be used when you run packager. Options that you actually specify on the command-line override any options entered in the QPG file (unless you specify the -y option). Options are used in the original (first) QPG file only; merged QPG files' options are ignored.
If you don't specify this entry, and you don't specify the base directory on the command line, then packager doesn't do a directory scan; only files in QPGs are packaged.
This section specifies the company/department/employee who is responsible for the files referenced in this QPG. You can have as many occurrences of the following tags as you need, and you can omit any that you don't need:
This tag supports this attribute:
You can define any number of attributes, which will be applied to all <QPG:Add> and <QPG:PackageFilter> entries within any merged QPG files within this block. For example, <QPG:MergeFilter component="drivers"> sets all subsequently merged QPG files within this block to have component="drivers" if the component attribute isn't already set.
This section can also appear within another <QPG:MergeFilter> block, if necessary (i.e. nesting is valid).
If a <QPG:Add> or <QPG:PackageFilter> tag has an inherit="no" attribute, then no attributes are inherited from any of its ancestor <QPG:MergeFilter> tags.
<QPG:Merge> entries specify another QPG file to include as if it were part of this QPG file. You can use any number of these tags to build a package from any number of small QPG files/programs.
This tag supports this attribute:
Optionally, a QPG file can specify that another package must be built as a result of building the current package. Another instance of the packager utility is started, and you can specify whether or not the current instance should wait for the second instance to finish. This is useful when you're generating dependent packages.
The attributes include:
This block defines all the manifest values and files that you want to include in the package. Use <QPG:PackageFilter> to direct certain values into particular manifests. Files can have the same direction.
When you use a <QPG:PackageFilter>, you can specify any or all of the following attributes, which must all match in order to be merged into a particular package's manifest:
The following sections correlate directly to the MANIFEST tags, and the tags used must match exactly.
![]() |
Entries that you specify in this section explicitly cause an attended session of packager not to ask the questions that correspond to those entries. |
Use this section to specify the files and/or directories to include in the package you're generating. To get files into a package, you can specify a base directory on packager's command line, specify a <QPG:Source> tag in the <QPG:Options> section, or add any number of the following tags.
You can also use this section to exclude particular files from being packaged, or have them inserted into the QPK or QPR only (without being in the manifest).
Use this tag to add files to the package. Use a type attribute to specify what you're adding, and a file attribute to specify the file/directory to add. The values that you enter here are applied to all files added (pattern-matched). However, if a .pinfo file is also present, its values override the values specified here.
For example, to add a license file to the repository directory, use the following:
<QPG:Add file="./license.txt" install="LicenseUrl/" handling="repdata"/>
The corresponding <LicenseUrl> tag could be:
rep://packager-1.1-qnx.repdata/LicenseUrl/license.txt
A <QPG:Add> tag can enclose any number of <QPG:Rule> tags. For more information about rules (an advanced feature), see the description of the <QPG:Rule> tag later in this appendix.
The attributes for <QPG:Add> include:
![]() |
The file attribute is the only one that you have to have for each <QPG:Add> entry. |
If the pattern is $, the resulting filename is used, with .pinfo appended onto it (replacing its extension if there is one).
For example, to add a script (in a QPG file), specify:
<QPG:Add handling="script" file="script_filename" install="/"/>
If it's a processor-dependent script, specify:
<QPG:Add handling="script" file="script_filename"
install="/" proc="x86" filter="exact"/>
<QPG:Add file="symbolic_link_name"
install="install_directory/" filetype="symlink"
linkto="file/to/link/to"/>
or specify default to remove the linkto attribute.
The packager utility creates these entries dynamically. Don't add this section by hand; use <QPG:Add> tags instead -- they allow pattern-matching (see above).
When you use a <QPG:Add> tag to add a file, the tag can enclose any number of <QPG:Rule> commands. As packager sorts the files, it checks them against each rule, in the order that the rules are specified. The file may match more than one rule.
![]() |
If you specify multiple rules in exactly the same way, they're merged into one entry. To prevent this behavior, add an xmlmultiple="true" attribute to each rule that might conflict with another. |
When a rule is matched, the rule's attributes are copied into the file's attributes, thus redirecting it, renaming it, and so on. The following attributes aren't copied, because they're part of the rule itself:
You can use the $(PROCESSOR) macro to match any processor. For example, /$(PROCESSOR)/usr/bin/ph*. The $(PROCESSOR) can also be specified in any of the attributes on this Rule line, and the matching processor will be inserted. For example:
You can also use packager to generate a repository (a location holding any number of packages) and make it available to anyone who can access that repository. To do this, place all of your desired QPM and QPK files into the repository directory. (If you're working with QPR files, decompress them using tar -zxf my_package.qpr). Change directory into this repository and type packager -r.
The packager asks you a number of questions related to your repository, which you should answer fully. The description is the first thing a user sees after clicking on your repository, so it should be as detailed and accurate as possible.
As it generates your repository, packager creates the following files:
Whenever you change the packages that appear in your repository, or when any packages are changed, you should again run packager -r in this directory. Once you've answered the questions, you won't have to answer them again, so you may wish to subsequently run the packager unattended and in expert mode, by typing packager -ruv2.
There are many shortcuts that people take that make their packages reasonable and usable, but not necessarily complete. This section describes some tips and suggestions on how to make your packages better, along with some hints on how to modify your QPG to simplify package creation even further.
What's the most obvious part of a package? It to be the things that users see when the package is presented to them: the product name and description.
The product name must be short, descriptive, and unique, so that no one will confuse your product with someone else's. Although we recommend that the product identifier be all in lowercase, for the product name, you should use an initial uppercase letter followed by lowercase, except where the product actually has explicit capitalization in its name (e.g. cURL).
![]() |
Don't put references to a processor or the version in the product name. |
For example, here's a correctly presented product name:
<QPM:ProductName>Python<QPM:ProductName>
The product description is where you have to be most careful and succinct -- the old saying is true: first impressions are important. Here are some suggestions:
For example, you may be tempted to describe your product as the "C/C++ IDE for all your needs," but "C/C++ Integrated Debugger/Editor with an advanced feature set for developers" is better.
Samba is an Open Source/Free Software suite that provides seamless file and print services to SMB/CIFS clients. You can use Samba to access your QNX files from within your Windows environment.
More is better when it comes to describing your product to potential users.
After you've used packager, the first thing you might want to check is the list of packages that it created.
Quite often, packager creates more packages than you need for a simple product. For instance, if you have .h or .a files, packager creates separate Development packages to house these files, which are obviously for development purposes only. This is a useful feature, but if the product that you're packaging is inherently a development utility, separating the files into development and nondevelopment packages adds extra complexity that isn't needed.
The question you have to ask yourself is whether you want the user to be able to install just the executable portion, or to install just the development portion, without the other packages. If the answer is yes, then packager has done all the work for you. However, if there's no need for users to have this granularity, you should tell packager not to create separate development packages at all; the files will be merged into the other packages automatically. To achieve this, you can do one of these things:
Or:
<QPG:Generation>
<QPG:Options>
<QPG:FileSorting dev="no"/>
<//QPG:Options>
<//QPG:Generation>
The generated packages will no longer have the dev- portion of their names.
A patch lets you release just the changes to a product instead of releasing a whole new version of it. You can tell packager to generate packages that contain only the files that have changed since the last full product release.
The patched packages are usually significantly smaller, so the user needs less disk space to keep both versions installed at once; to reinstate the original version, you need only deactivate -- not remove -- the patch. There are, however, some prerequisites to generating a patch:
To generate a patch, you need to have a QPP file. The QPP file indicates to packager where it can find your previously released product's QPR or QPK files, the version of the previously released product, and the date on which the product was released. You can generate a sample QPP file by typing packager -j4. The resulting file looks like this:
<QPP:Patches>
<QPP:Release productid="pid" vendorid="vid">
<QPP:File>mypackage-1.0.qpr</QPP:File>
<QPP:Location>/home/package/directory/</QPP:Location>
<QPP:Date>yyyymmddhh</QPP:Date>
<QPP:Version>1.0</QPP:Version>
<QPP:PatchIdentifier>patchA</QPP:PatchIdentifier>
<QPP:Responsible>Guy Responsible</QPP:Responsible>
<QPP:Email>gresponsible@home.com</QPP:Email>
<QPP:Notes>Notes regarding this release</QPP:Notes>
</QPP:Release>
</QPP:Patches>
Once you have the QPP file, modify it to match your product information:
![]() |
You can add any number of <QPP:Release> blocks, so you can use a single QPP to patch any number of products or in any number of packaging sessions. Each <QPP:Release> block must have a unique combination of productid and vendorid. |
Once you've set up the QPP file properly, use the -h option to packager (along with whatever other arguments you would normally pass to the utility to generate an unpatched package), with your QPP file in order to indicate to packager that you're potentially generating a patch. For example:
packager -h my.qpp my.qpg
Remember that in my.qpg you must be generating a patch that's a different version from what you're patching. You usually set the <QPM:ReleaseVersion> to your original version, with an appended uppercase A, B, C, etc. (without any spaces) to make your new release version (e.g. the first patch to 5.7 would be 5.7A).
While packager works, it displays some messages related to patching:
![]() |
Packages that had no changes between the original and the patch aren't generated. The generated packages have automatic dependencies on the original packages that you've patched, so the user needs only select your patch in order to gain a working product. |
![]() |
![]() |
![]() |
![]() |