Alain Bonnefoy <alain.bonnefoy@rieter.com> wrote:
Hi,
I’m still looking for documentations written by Jerry Chappel about QPG
files. AFAIR these articles were accessible through
qdn.qnx.com/articles/Aug2701.
For more infos look at
http://www.qnx.com/developers/articles/article_877_1.html > and check for
blue colored text !
Please, I really need these informations!
At one point, I modified Jerry’s articles to go into the docs. When we
stopped using packages in 6.3, I removed the new chapters. To help you
get your work done, I’m posting those chapters. First, here’s the one
on creating packages:
#[1]NEXT [2]PREVIOUS
[3][Previous] [4][Contents] [5][Index] [6][Next]
Appendix: Creating Packages
This appendix includes:
- [7]QNX package manifests (QPM)
- [8]The packager utility
- [9]Preparing to package
- [10]Running packager
- [11]Warnings and error messages
- [12]Testing your package
- [13]Working with a package-generation (QPG) file
- [14]QPG structure
- [15]Generating a repository
- [16]Hey, nice package!
If you want to create packages that other users can install, the
easiest way is to use the [17]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).
QNX package manifests (QPM)
The QNX package manifest (QPM) file describes all aspects of a
package, including:
- a list of the files within the package
- the locations where each of the files is to be installed
- a description of the package
- any requirements that the package has
- other packages that the package depends on (or those that conflict
with it)
- any scripts to be executed when someone installs or uninstalls the
package.
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
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 [18]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 “[19]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.
Preparing to package
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 the directory structure and copy your files into the
correct locations.
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.
Note: 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.
- Take an existing .tgz, .tar.gz, or .tar.F file and expand it into
a new 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.
- Take an existing package and have packager unzip it into a given
directory.
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 (/).
Running packager
You’ll find that packager asks many questions. Here are some hints for
answering them:
- There’s no way to avoid the questions. While you may be tempted to
use answers from a previous manifest (using the -m option), we
strongly recommend that you answer the questions fully. This step
ensures that you have a well-formed package that works well.
- The packager won’t let you simply enter default values for
everything. Some questions require a response, especially those
that determine the uniqueness of your package (i.e. product
identifier and vendor identifier) and ensure that it doesn’t
conflict with anyone else’s package. If you don’t supply these
values, packager sounds the system bell.
- Check for warnings during the creation of your package – every
warning is important.
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:
Product identifier
The name used by other packages to reference your package. It
should be a short, simple identifier (no more than 13
characters), and be made up only of alphanumeric characters,
dashes, and underscores. Ideally it should be a single
lowercase word that’s a short form of your product name.
Vendor identifier
Your company’s name or your name. This helps ensure that your
packages don’t conflict with anyone else’s (that may have
identical product identifiers). Together, the vendor identifier
and product identifier describe your product uniquely within
the QNX community.
Release version
The version number of your product (e.g. 1.0, 2.3.4, 14.2A). If
you’re porting software from another source, you should use the
software’s original version number and simply change the
release-build number each time you remake the software. If you
do this, the version number accurately reflects the
source-program’s version.
Release build
An integer that indicates the build number of your package. You
should increment this number by one each time that you change
your software, unless you change the version number. You should
reset the release-build number to 1 whenever the version
changes.
Package release
An integer that indicates the release number of your package.
You should increment this number by one each time you repackage
your software, even if you haven’t changed the software. You
should reset this number to 1 whenever the version or build
number changes.
Content topic
The topic you select for your package from the list supported
by the QNX software installer. The packager shows all available
topics and lets you select increasingly specific topics until
you’ve fully described the location where you want your package
to appear in your repository. The packager lets you search by
keyword to quickly find an appropriate topic. The more specific
you are in choosing the topic, the more organized your
repository will be later, especially if the repository includes
many packages.
Product name
The product’s name is obviously very important for telling the
user exactly what they’re about to download/install. This is
the name that appears in the QNX software installer in the list
of packages in the repository, and should be a descriptive,
capitalized name such as Packager or QNX Software Installer.
The QNX software installer automatically tacks for x86, or
similar qualifiers on the end when the package is displayed, so
you don’t have to enter processor or version references in this
field.
Product description long
This field defines the complete description that appears in the
QNX software installer when a user clicks on your package in
the list of available packages. This field should consist of
one or two paragraphs describing your product and its main
features.
License URL
To have a license show up when your software is installed, you
can specify the URL for the license file as your response to
this question. By entering a file name that’s on your local
hard drive, you include a copy of the license file in your
package (QPR) without having to put the file into your base
directory structure. When you enter a local file in response to
this question, the file is copied into the package.repdata
directory that corresponds to your package. The packager
displays a message stating that the file has been copied into
the package. After you answer this question, you should confirm
that this message is shown, or users might not be able to
install 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.
Scripts
You can execute scripts at the following times during the life of a
package:
- Pre-install or Post-install – before or after the installation
takes place
- Pre-use or Post-use – before or after the activation of a package
- Pre-unuse or Post-unuse – before or after the deactivation of a
package
- Pre-uninstall or Post-uninstall – before or after the removal 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.
Note: You can’t execute a package’s files before you activate the
package or after you deactivate it.
Dependencies
Your package might need another package in order to operate correctly.
Such requirements are specified by entering dependencies.
Note: 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.
Photon launch menu
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:
Launch menu position
The name to appear on the launch menu. This name shouldn’t be
longer than 25 characters.
Topic
The hierarchy under which the entry is to appear. You can enter
any values here, but they must all be under the Applications/
heading. You should stick to the standard ones shown in the
launch menu (i.e. Applications/Editors, Applications/Utilities,
Applications/Internet, Applications/MultiMedia,
Applications/Development, or Applications/Games).
Execution command
The command to execute when the operator clicks on the menu
item. This must be a fully qualified command (e.g.
/usr/photon/bin/ped -r readme.txt).
Warnings and error messages
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:
Warning: /usr/local should not be packaged using this utility.
The /usr/local directory is considered to be a special
directory that can contain files from a number of different
software packages. The packager utility is intended for a
single product that should install its files into /opt/bin,
/usr/share, or similar directories. You should copy the
required files into a different directory before packaging
commences.
Warning: There are files at the root, where only directories should
reside.
All of your files should be installed into the correct
directory. The packager detects if you have files destined to
be installed at the root directory (/), where only
subdirectories should ever appear (with the exception of system
files). You should relocate your files to appear within the
correct subdirectories.
Warning: Uncommon directory paths have been detected.
We recommend that you use a set of standard directories. Your
files should all appear within this directory structure. If
this message appears, you should relocate your files into one
of the following standard root directories: /boot, /dev, /etc,
/opt, /usr, or /var.
Error: This is a required field.
You must fully answer some of questions that packager asks; you
may not simply accept the default value (or no value) for the
question asked. The packager asks the question again until you
answer it properly.
Error: This value cannot exceed n characters.
There is a maximum length to this field that must not be
exceeded.
Error: QNX software can only be released by QNX Software Systems Ltd.
If you try to answer questions as if you were packaging QNX
software, this message may appear. Answer with your own company
or personal information.
Testing your package
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.
Caution: 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.
Working with a package-generation (QPG) file
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:
- Generate your package.
- Tell packager to generate a QPG (QNX Package Generation) file from
your package
- Edit the QPG to point to your source files on disk.
- Pass the QPG file to packager to regenerate your package.
- Test the resulting package.
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:
- command-line options
- ownership/editor of the package
- other QPG files to merge as if they were part of the same QPG
- a list of manifest values for packager to use as answers to its
questions
- a list of files to be packaged, along with their installation
locations.
For more information about the options in a QPG file, see “[20]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:EmailAddressjoe_blow@home.com</QPG:EmailAddress>
QPG:CompanyMy Company Inc.</QPG:Company>
QPG:DepartmentResearch 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" pr
oc=“arm”/>
<QPG:Add type=“file” file="/usr/lib/libsocks.a" install="/usr/test/" targ
et=“arm”/>
<QPG:Add file="/usr/test/libsocks.so" install="/usr/test/" filetype=“syml
ink” linkto=“libsocks.so.1”/>
</QPG:Files>
QPG:PackageFilter
QPM:PackageManifest
QPM:PackageDescription
QPM:PackageTypeApplication</QPM:PackageType>
QPM:PackageReleaseUrgencyLow</QPM:PackageReleaseUrgency>
QPM:PackageReleaseNotes/
QPM:PackageRepository/
QPM:PackageReleaseNumber/
</QPM:PackageDescription>
QPM:ProductDescription
QPM:ProductNameTast</QPM:ProductName>
QPM:ProductIdentifiertast</QPM:ProductIdentifier>
QPM:ProductEmailsupport@home.com</QPM:ProductEmail>
QPM:VendorNameMy Company Inc.</QPM:VendorName>
QPM:VendorInstallNamemyco</QPM:VendorInstallName>
QPM:VendorURLwww.home.com</QPM:VendorURL>
QPM:VendorEmbedURL/
QPM:VendorEmailsupport@home.com</QPM:VendorEmail>
QPM:AuthorNameJoe Blow</QPM:AuthorName>
QPM:AuthorURL/
QPM:AuthorEmbedURL/
QPM:AuthorEmail/
QPM:ProductIconSmall/
QPM:ProductIconLarge/
QPM:ProductHomeURL/
QPM:ProductDescriptionEmbedURL/
QPM:ProductDescriptionURL/
</QPM:ProductDescription>
QPM:ReleaseDescription
QPM:ReleaseDate2001/03/01</QPM:ReleaseDate>
QPM:ReleaseVersion1.0</QPM:ReleaseVersion>
QPM:ReleaseUrgencyMedium</QPM:ReleaseUrgency>
QPM:ReleaseStabilityStable</QPM:ReleaseStability>
QPM:ReleaseNoteMinorInitial public release</QPM:ReleaseNoteMinor>
QPM:ReleaseNoteMajorThis initial public release of Tast coincides
with the deadlines set forth in the company prospectus.</QPM:Releas
eNoteMajor>
QPM:CountryExclude/
</QPM:ReleaseDescription>
QPM:ContentDescription
QPM:ContentTopicSoftware Development/Build Tools/Packaging</QPM:Con
tentTopic>
QPM:ContentKeywordtast,sample</QPM:ContentKeyword>
QPM:DisplayEnvironmentConsole</QPM:DisplayEnvironment>
QPM:TargetAudienceDeveloper</QPM:TargetAudience>
</QPM:ContentDescription>
QPM:ProductInstallationDependencies
QPM:ProductRequirementsNo extra requirements.</QPM:ProductRequireme
nts>
</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://w
ww.qnx.com"/>
</QPM:Launch>
</QPM:FileManifest>
</QPG:PackageFilter>
</QPG:Values>
</QPG:Generation>
Note: 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.
Symbolic links
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”/>
Working with components
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.
Forcing files into certain packages
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 [21]QPG:Add in “[22]QPG
structure,” later in this appendix.
Here are some examples that show common ways to redirect files:
- The packager uses the ELF header information, along with the file
extension, to determine what type of file you’re packaging. You
can override this and force a change to the file type, by setting
the filetype attribute. For instance, set filetype=“exe” to force
a file to be considered executable, and to appear in a
processor-specific package that corresponds to a proc=“processor”
attribute, like this:
<QPG:Add file=“src/include/readme.txt” filetype=“exe” proc=“x86”
install="/opt/share/"/>
- The packager automatically strips your executable files so that
unnecessary debug information isn’t left in your packaged files.
This behavior is sometimes undesirable, so you can turn it off. To
change this for the entire session, specify this tag in the
QPG:Options section:
<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”/>
- The packager attempts to keep your file’s ownership, group, and
permissions identical to the original file’s settings. To override
this behavior, or to apply specific settings to a file, use the
permissions, user, and group attributes, as required:
<QPG:Add file=“src/bin/my_program” install="/opt/bin/" permissions=“x+s”/>
Merging other QPG files
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:ReleaseCopyrightPublic Domain License</QPM:ReleaseCopyright>
QPM:ReleaseCopyrightURLrep://LicenseUrl/license.txt</QPM:ReleaseCopyrigh
tURL>
</QPM:ReleaseDescription>
QPM:LicenseUrlrepdata://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
[23]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>
SLIB packages
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:ContainsLibrarylibmine.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.
Regenerating a package
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.
QPG structure
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:
[24]QPG:Generation
[25]QPG:Options
[26]</QPG:Options>
[27]QPG:Responsible
[28]</QPG:Responsible>
[29]QPG:Owner
[30]</QPG:Owner>
[31]QPG:MergeFilter
[32]</QPG:MergeFilter>
…
[33]QPG:Merge
[34]</QPG:Merge>
…
[35]QPG:Generate
[36]</QPG:Generate>
…
[37]QPG:Values
[38]QPG:PackageFilter
[39]</QPG:PackageFilter>
…
[40]QPG:Files
[41]QPG:Add
[42]</QPG:Add>
…
[43]QPG:File
[44]</QPG:File>
…
[45]</QPG:Files>
[46]</QPG:Values>
[47]</QPG:Generation>
Any QPG file can reference other QPG files (using the [48]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 [49]QPG:Files), and define the
manifest settings that will be used for all generated packages (see
[50]QPG:PackageFilter).
Note: 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 [51]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:
- When you add a personal script to a package by putting the script
block into a QPG file, you must give the location of the script
explicitly, which isn’t possible because you can’t know in advance
the exact directory path of the package – it could change (for
example, because of the build number).
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.
- Similarly, when adding a license to a package by putting the
tag into a QPG file, you must give the location of
the license explicitly, which might not be possible because you
don’t know the exact filename of the QPR file – it could change
(for example, because of the build number).
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.
QPG:Generation
This is the top-level tag for a QPG file. This tag can include the
following tags:
QPG:Options
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.
QPG:User
This tag controls how much help packager gives you. The
attributes include:
- verbosity=0 (normal), 1 (advanced), 2 (expert)
- unattended=yes (accept defaults only), no (ask for
non-QPR-specified elements)
- listfiles=yes (show each file to be packaged), no (show only
the number of files to be packaged).
QPG:Defaults
Where to find the default answers for packager’s questions. The
attributes include:
- type=value, where value is one of:
o qnx_package – based on a QPM/QPK/QPR file
o none – don’t use a default file.
- file=filename (which file to use)
QPG:Source
Where to find the source files. The only attribute is:
- basedir=directory – which directory is the base directory.
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.
QPG:Release
Specifications for the release number. The attributes include:
- number=+ (autoincrement), - (don’t autoincrement)
- date=today (set the release date to today), default (use the
date found in the previous QPM/QRM). This option matters only
if you don’t specify the tag(s) explicitly in
the QPG file.
QPG:Build
Specification for the build number:
- number=+ (autoincrement), - (don’t autoincrement), n (use
this number), date (use today’s date, in the form
yyyymmddhh).
QPG:FileSorting
Options to use when sorting:
- strip=yes|no (strip files when sorting)
- ownership=standard (change the ownership where possible),
override (don’t change the ownership)
- dir=directory (which directory to sort into and not clean
up), none (don’t sort into a specific directory)
QPG:Package
Options for the package as a whole:
- targets=combine (combine targets into one package), standard
(separate target packages)
- filter=pattern (pattern must match the product identifier for
the package to be actually filled with files. This is for
package testing purposes only.)
- compatible=default (use the package version in the manifest),
version (desired version – e.g. 1.01 – to appear in the
manifests.
- union=terminate (union the root-level directories only), deep
(union entries are as deep as possible), default (same as
deep)
QPG:Repository
Options for the repository:
- generate=yes (create QPR files), no (create QPK/QPM files
only)
- index=yes (create an index file of the final directory), no
(don’t create an index file)
- content=yes (create a content.tgz file), no (don’t creat a
content file)
- qrm=yes (create a repository.qrm file), no (don’t create
repository.qrm)
QPG:FinalDir
The attributes include:
- dir=directory (the directory to put the final QPM/QPK/QPR
files into), none (use the current working directory only to
sort the final files)
QPG:Cleanup
Options for cleaning up:
- manifest=clean (remove the manifests), keep (keep the
manifests).
QPG:Responsible
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:
QPG:Owner
This tag supports this attribute:
- file=filename – the location of the owner’s QPG file that
contains only a QPG:Responsible section.
QPG:MergeFilter
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
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:
- file=filename – the location of another QPG file to merge.
QPG:Generate
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:
- dir=directory – what to use for the current working directory for
the new instance of packager.
- wait=yes – wait until packager is complete before continuing (the
default), or no to continue immediately.
QPG:Values
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.
QPG:PackageFilter (multiple entries)
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:
- type=value, where value is one of:
- core – only for packages with no parent
- all – for all generated packages
- ignore – the parentage doesn’t matter (the default)
- child – only for packages with a parent –
processor-specific packages.
- proc=value, where value is one of:
- any – any processor-specific package
- none – any CPU-independent package
- ignore – the processor is irrelevant (the default)
- name – the processor name.
- target=value, where value is one of:
- any – any target-specified package
- none – any package where the target isn’t specified
- ignore – the target is irrelevant (the default)
- name – the target name.
- component=value, where value is one of:
- any – any component type-specific package
- none – any package where the component type isn’t specified
- ignore – the component type is irrelevant (the default)
- name – the component type itself.
The following sections correlate directly to the MANIFEST tags, and
the tags used must match exactly.
Note: Entries that you specify in this section explicitly cause an
attended session of packager not to ask the questions that correspond
to those entries.
- xmlmultiple=true – if this attribute is present on any tag in
this section, the added block is added to existing blocks of the
same name, instead of overwriting the previous block, which is
what’s normally done. This is required on tags that can have
multiple entries, such as QPM:Dependency, QPM:Script,
QPM:Launch, and QPM:File.
QPG:Files
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).
QPG:Add (multiple entries)
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 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 [59]QPG:Rule tag later in this appendix.
The attributes for QPG:Add include:
- type=value, where value is one of:
- file – add the following files (the default)
- dir – add all of the files under the following directory
- tree – add all files in the following directory and its
subdirectories.
- file=pattern – the pattern to match the source file(s) to include
in the package. If the type attribute is dir or tree, then this
attribute holds the directory name.
Note: The file attribute is the only one that you have to have for
each QPG:Add entry.
- pinfo=pattern – the explicit filename of the .pinfo file, or the
location of the .pinfo file, relative to the source file.
If the pattern is $, the resulting filename is used, with .pinfo
appended onto it (replacing its extension if there is one).
- install=directory – the directory to install the file in, which
must end in a slash (/), or the exact filename to use when the
source file is installed, overriding the default packager
location. This attribute is optional – if you don’t include it,
the installation location is determined by the file type, or it’s
gathered from a .pinfo file.
- license=license – the license to apply to the specified file(s).
This license is added to whatever licenses you specify in the
.pinfo file.
- permissions=value – the chmod arguments to apply, or default if
you don’t want to change the permissions.
- user=value – the chown arguments to apply, or default if you
don’t want to change the ownership.
- group=value – the chgrp arguments to apply, or default if you
don’t want to change the group.
- stacksize=value – the stack size to use for this program (in
bytes), which is applied using ldrel -S, or default if you don’t
want to change the stack size.
- description=value – a textual description of the purpose of the
file(s), or default.
- name=text – the name of the file(s).
- filter=value – the exact settings to use for the specified proc,
target, or component.
- proc=value, where value is one of:
- any – any processor-specific package
- none – any CPU-independent package
- ignore – the processor is irrelevant
- name – the processor name
- default – packager determines the host processor.
- target=value, where value is one of:
- any – any target-specified package
- none – any package where the target isn’t specified
- ignore – the target is irrelevant
- name – the target name
- default – packager determines the target processor.
- component=value, where value is one of:
- any – any component type-specific package
- none – any package where the component type isn’t specified
- ignore – the component type is irrelevant
- name – the component type itself
- default – packager determines the component type.
- handling=value, where value is one of:
- repdata – the file is a repository data file that’s to be
copied into the repository but not packaged
- pkgdata – the file is package data to be copied into the
required QPK files, but not included in the manifests
- script – same as pkgdata
- exclude – don’t package the file
- copy – add the specified file, even if it’s already listed,
with a different install location
- default – none of the above.
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”/>
- filetype=value, the type of the file, where value is one of:
- dir – directory
- doc – documentation
- exe – an ELF executable
- obj – a relocatable object for linking
- so – a shared object for linking and executing