This section describes the bundle specification for the Canterbury legacy
application framework, which has been removed in v2022dev2
and is therefore not recommended for
new development. See the application framework document for further information on the new,
replacement framework.
Version: 1.2.0
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
This specification uses semantic versioning. After version 1.0.0 is finalized, the major version number (first component) will be incremented if a change makes previously-valid application bundles cease to work or be valid, for example changing “MAY” to “MUST” or “MUST NOT”. The minor version number (second component) will be incremented if a change makes previously-invalid application bundles valid, for example changing “MUST” or “MUST NOT” to “MAY”. The micro version number (third component) will be incremented for editorial changes that do not affect the validity of an application bundle.
Introduction
This document aims to provide a stable filesystem layout for Apertis store application bundles that can remain valid across multiple versions.
To keep older application bundles installable on newer Apertis releases, we anticipate that incompatible changes (incrementing the major version) are to be made very infrequently. If necessary, Apertis framework components might be made to support multiple major versions of this specification.
A secondary goal of this specification is to provide a basis for the structure of built-in application bundles. Authors of built-in application bundles do not necessarily need to limit themselves to the baseline set by this specification, since a built-in application bundle will only be upgraded or rolled back at the same time as a corresponding upgrade or rollback for the Apertis platform. However, by following the requirements and recommendations in this specification, a built-in application bundle author can minimize the changes necessary between Apertis platform releases. Please see Appendix: built in application bundles for differences between the required structure of store bundles and the required structure of built-in application bundles.
App-bundles contain some or all of the following files:
bin/*
( Executables)etc/apparmor.d/Applications.
bundle-ID ( AppArmor profile)lib/*
( Libraries)libexec/*
( Executables)share/applications/
entry-point.desktop
( Entry points)share/glib-2.0/schemas/
schema-ID.gschema.xml
( GSettings schemas)share/glib-2.0/schemas/gschemas.compiled
( GSettings schemas)share/icons/hicolor/64x64/apps/
bundle-ID.png
( Icon for the bundle)share/icons/hicolor/64x64/apps/
entry-point.png
( Icons for entry points)share/icons/
theme/
( Icons for use by the bundle)share/locale/*/LC_MESSAGES/*.mo
( Localized strings)share/metainfo/
bundle-ID.appdata.xml
( Bundle metadata)share/metainfo/
bundle-ID.metainfo.xml
( Bundle metadata)share/themes/
theme/*
( Theme data for use by the bundle)share/*
( Generic resource data)
all of which will be installed relative to /Applications/
bundle-ID.
To reduce its length, this specification does not generally provide rationale for its requirements. Please see the Apertis concept designs for design rationale, in particular the Applications concept design, Application Layout concept design and Application Entry Points concept design.
Bundle ID
Each Apertis application bundle has a bundle ID, which MUST consist
of two or more components separated by dots (U+002E FULL STOP). Each
component MUST start with an ASCII letter (A-Z
, a-z
) or underscore
_
, and contain only ASCII letters, underscores and ASCII decimal digits
(0-9
). Bundle IDs MUST NOT contain non-ASCII characters, for example
accented letters such as ä
.
Note that these are the same as the requirements for a D-Bus interface name, which are stricter than the requirements for a D-Bus bus name or a GApplication application ID: every bundle ID is a valid bus name and a valid GApplication application ID, but not every bus name or application ID is a valid bundle ID.
Reversed domain name
The author of an application MUST choose a bundle ID that starts with a
reversed domain name controlled by that
author, with any hyphen/minus signs -
replaced by underscores _
, and
_
prepended to any component that starts with a digit.
For example, the owner of the domain name collabora.com
controls the
reversed domain name com.collabora
and might choose to name an app bundle
com.collabora.ShoppingList
.
Domain names with hyphen/minus signs, or with components starting with
a digit, require special treatment to avoid syntactically invalid bundle IDs.
If the owner of 7-zip.org
wishes to base bundle IDs on that domain name,
they MUST use a bundle ID starting with org._7_zip
; for example, they might
choose to name an app bundle org._7_zip.Archiver
.
Top-level directory
Each application bundle is made available on the user’s system as a
subdirectory of /Applications
whose name is the same as the bundle ID.
App bundles MUST NOT include any file outside that directory.
For example, the app bundle com.example.ShoppingList
would use a
top level directory /Applications/com.example.ShoppingList/
.
For brevity, this document will refer to this directory as ${prefix}
.
Bundle metadata
Each app-bundle MUST install exactly one file in the
${prefix}/share/metainfo/
directory. The contents of that file
are interpreted according to the AppStream upstream XML specification.
This table provides a summary of the relevant tags. All other tags are either not recommended for any type of bundle, or not allowed.
Tag | Status |
---|---|
id |
required, must be bundle ID |
name |
required |
summary |
recommended |
description |
recommended |
developer_name |
recommended |
metadata_license |
required, should be CC0-1.0 |
project_license |
optional |
url |
optional |
releases |
required |
releases → release |
required, exactly one |
provides |
optional |
provides → dbus |
optional |
provides → any other |
not allowed |
custom → value |
optional |
If the app-bundle has Entry points, the file MUST be named
either ${bundle_id}.appdata.xml
or ${bundle_id}.metainfo.xml
, replacing
${bundle_id}
with the Bundle ID. In this case the component
tag MUST
have its type
attribute set to desktop
.
If the app-bundle does not have Entry points, the file MUST be named
${bundle_id}.metainfo.xml
, again replacing ${bundle_id}
with the
Bundle ID. In this case the component
tag MUST NOT have a type
attribute.
The id
tag MUST contain exactly the Apertis Bundle ID.
The name
tag MUST contain a human-readable name for the app-bundle,
for example Shopping List
.
The summary
, description
and developer_name
tags SHOULD be present,
with the contents described by the AppStream upstream XML specification.
The metadata_license
tag MUST be present, and MUST contain the
identifier of a permissive license under which the metadata can be
redistributed. This license SHOULD be the Creative Commons Zero license,
CC0-1.0
, allowing unlimited redistribution of the metadata with or
without modifications (for example in the user interface of an app-store).
The metadata_license
does not imply anything about the terms under which
the app-bundle itself can be distributed: app-bundles themselves MAY be
distributed under any license of their copyright holder’s choice,
including proprietary licenses. The bundle metadata MAY represent that
license in the project_license
tag, as described in the
AppStream upstream XML specification.
The url
tag MAY be present, with the types and contents described by
the AppStream upstream XML specification.
The releases
tag MUST be present, and MUST contain exactly one
release
tag. The release
tag MUST have a version
attribute.
Its value MUST start with a digit and contain only digits and
U+002E FULL STOP characters.
Note that this is a more strict requirement than in the AppStream upstream
XML specification, which allows additional release
tags describing
older releases.
Future directions:
This is a very strict versioning syntax, matching what Ribchester accepts in Apertis 16.09. We should consider expanding this in a future minor version of this specification to be able to accept dpkg-style versions like
1.2.3~beta1+bugfix2
. This will require a formal specification for how these version numbers are to be compared, possibly deferring to Debian Policy.The Applications concept design calls for the version number to be split into an application version and a store version, analogous to the roles of the upstream version and Debian revision in Debian.
Open question: is the store version encoded in the
release
tag, or is it stored in acustom
tag or separately?
The provides
tag MAY be present. It MAY contain a dbus
tag, with its
type
attribute set to user
, for each well-known name provided by an
entry point in this application bundle. It MUST NOT contain any of the
other child tags that can be provided.
The mimetypes
tag MUST NOT be present. In Apertis, content-type support
is handled by Entry points.
The project_group
tag MUST NOT be present.
Tags that are not specified in the AppStream upstream XML specification
MUST NOT be present, with the exception of custom
(see
Extended bundle metadata, below).
Tags not specified in this document, in particular screenshots
, suggests
,
translation
and update_contact
, SHOULD NOT be present.
Extended bundle metadata
The bundle metadata MAY include one custom
tag at the next level
of hierarchy below component
. This tag MAY contain value
child tags,
each with a key
attribute and XML character data (text) content. It MUST
NOT contain other child tags or text.
Later versions of this specification will define keys starting with
X-Apertis-
. Keys with that prefix that are not defined in this document
MUST NOT be present. The current version of this document does not define
any such keys.
Other vendors MAY define keys starting with X-
followed by a name
distinctive to the vendor.
Other keys SHOULD NOT be present.
For example, if a future version of this specification defined
a key X-Apertis-ExampleColour
, and a vendor Wayne Industries defined
a key X-Wayne-BatmobileCompatible
, this might result in bundle
metadata like this:
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>net.example.Extended</id>
<custom>
<value key="X-Apertis-ExampleColour">#00cc00</value>
<value key="X-WayneIndustries-BatmobileCompatible">true</value>
</custom>
… additional metadata here …
</component>
It is anticipated that this mechanism will be used for Apertis-specific or automotive-specific extensions that are considered insufficiently general to be included in the AppStream standard.
AppArmor profile
Apertis uses AppArmor to provide security between application bundles.
Each app-bundle MUST install exactly one AppArmor profile file at
${prefix}/etc/apparmor.d/Applications.${bundle_id}
, replacing
${bundle_id}
with the Bundle ID.
This file MUST define exactly one AppArmor profile. Its name MUST be
exactly /Applications/${bundle_id}/**
, again replacing ${bundle_id}
with the bundle ID. It MUST NOT have any
local profiles (also known as child profiles
or subprofiles), and in particular MUST NOT have any hats
(which are a special case of local profiles).
This file SHOULD contain the following rules, replacing @BUNDLE_ID@
with the
Bundle ID throughout:
/Applications/@BUNDLE_ID@/** {
#include <abstractions/chaiwala-base>
#include <abstractions/dbus-session-strict>
#include <abstractions/fonts>
/Applications/@BUNDLE_ID@/{bin,libexec}/* pix,
/Applications/@BUNDLE_ID@/{bin,lib,libexec}/{,**} mr,
/Applications/@BUNDLE_ID@/share/{,**} r,
owner /var/Applications/@BUNDLE_ID@/users/** rwk,
owner link
subset /var/Applications/@BUNDLE_ID@/users/**
-> /var/Applications/@BUNDLE_ID@/users/**,
dbus send
bus=session
path=/org/freedesktop/DBus
interface=org.freedesktop.DBus
member={RequestName,ReleaseName}
peer=(name=org.freedesktop.DBus),
dbus bind bus=session name="@BUNDLE_ID@",
dbus bind bus=session name="@BUNDLE_ID@.*",
dbus (send, receive) bus=session peer=(label=/Applications/@BUNDLE_ID@/**),
dbus receive bus=session peer=(label=/usr/bin/canterbury),
signal receive peer=/usr/bin/canterbury,
}
The profile MAY add additional permissions. The app-store curator is expected to check additional permissions carefully.
Future direction: the profile should be generated from simpler metadata in a future minor version of this specification.
Future direction: if we recommend particular interpreters — for example
/bin/sh
for wrappers that set environment variables, a JavaScript or Python interpreter for interpreted app code, or a webapp runtime for HTML5 apps — then the generic profile recommendation should allow those interpreters to be used.
Entry points
Each app-bundle MAY install .desktop
files in the
${prefix}/share/applications/
directory. The contents of that file
are interpreted according to the Desktop Entry Specification.
App bundles are not required to install any entry points at all, but many features can only be provided by an app bundle that has entry points: Graphical programs in the main menu MUST have an entry point, and Content type and uri scheme handlers MUST have a Main entry point.
The name of each desktop entry file, excluding the .desktop
extension, is
called the Entry point ID.
This table provides a summary of the allowed, recommended and optional fields. All other fields are either not recommended for any type of entry point, or not allowed. A table cell containing a literal value indicates that the field is required and must have exactly that value.
Field | Main entry point | Other graphical programs | Agents |
---|---|---|---|
Categories |
required | required | not recommended |
Exec |
required | required | required |
GenericName |
optional | optional | optional |
Icon |
required | required | not recommended |
Interfaces |
optional | optional | optional |
MimeType |
optional | not allowed | not allowed |
Name |
recommended | recommended | recommended |
NoDisplay |
optional | optional | true |
OnlyShowIn |
Apertis; |
Apertis; |
Apertis; |
Path |
optional | optional | optional |
Type |
Application |
Application |
Application |
X-Apertis-CategoryIcon |
required | required | not recommended |
X-Apertis-CategoryLabel |
required | required | not recommended |
X-Apertis-Type |
application |
application |
agent-service |
X-GNOME-FullName |
optional | optional | optional |
DBusActivatable |
true recommended |
true recommended |
true recommended |
X-Apertis-ServiceExec |
recommended | optional | not allowed |
X-Apertis-ParentEntry |
not recommended | optional | not allowed |
General fields for all entry points
Type
MUST be set to Application
.
OnlyShowIn
MUST be set to Apertis;
.
Exec
MUST be present. The first word in Exec
MUST be the absolute path
to an executable in either ${prefix}/bin
or ${prefix}/libexec
.
Subsequent words in Exec
MUST NOT use the %
placeholders such as %F
.
The Canterbury application manager does not support those placeholders.
Subsequent words in Exec
MUST NOT be exactly app-name
, play-mode
or url
, and SHOULD NOT be exactly menu-entry
.
These words cause unexpected special behaviour in Apertis 16.06. After this special behaviour has been removed, future minor versions of this specification should remove this limitation.
Name
SHOULD be specified. Its value MAY be a “brand name” such as Firefox
,
a generic name such as Web browser
, or a combination of the two such as
Firefox web browser
.
GenericName
SHOULD be specified if its value would differ from Name
.
If present, its value MUST be a generic (unbranded) name such as Web browser
,
for use in user interfaces whose designer wishes to standardize on generic
names.
X-GNOME-FullName
SHOULD be specified if its value would differ from Name
.
If present, its value SHOULD be a full name incorporating both the brand name
and the generic name, for example Firefox web browser
, suitable for use in
situations where it is necessary to disambiguate between entry points with
the same GenericName
(for example if both Firefox and Chrome have
GenericName=Web browser
).
Translated versions of these names,
such as Name[fr]
, MAY be present using the localestring mechanism
defined in the Desktop Entry Specification.
Path
MAY be set, with its usual meaning (it sets the current working
directory for the program). If Path
is not set, programs in the
app-bundle will inherit the working directory of the parent process,
and MUST NOT assume that it will take any particular value.
Interfaces
MAY be set, for interface discovery.
DBusActivatable
MAY be present and set to true
, as described in
D-Bus activation.
X-Apertis-ServiceExec
MAY be set, as described in D-Bus activation.
X-Apertis-ParentEntry
MAY be set, as described in Multiple views.
The following keys MUST NOT be present:
Encoding
(the encoding MUST be UTF-8, which is the default)Hidden
(this misleadingly named key is used to mark entry points as deleted, which is not useful in this context)NotShowIn
StartupNotify
StartupWMClass
Terminal
URL
Version
(version 1.0 of the Desktop Entry specification is assumed)
The following keys SHOULD NOT be present, and application bundles SHOULD NOT rely on their normal functionality (if any):
Actions
Comment
Environment
Keywords
TryExec
X-Apertis-AudioChannelName
X-Apertis-AudioResourceOwner
X-Apertis-AudioRole
X-Apertis-BackgroundState
X-Apertis-BandwidthPriority
X-Apertis-DataExchangeRules
(obsolete)X-Apertis-ManifestUrl
(obsolete)X-Apertis-SettingsIcon
(set anIcon
instead)X-Apertis-SettingsName
(set thename
in the Bundle metadata instead)X-Apertis-SettingsPath
(use the mechanism described in GSettings schemas instead)X-Apertis-SplashScreen
X-Apertis-WindowName
(obsolete)
Future directions:
X-Apertis-AudioRole
,X-Apertis-BackgroundState
andX-Apertis-BandwidthPriority
are under consideration for a future minor version of this specification, but are not currently considered to be stable.
Entry point ID
Each entry point MUST have an entry point ID, which is a string with the
same syntax requirements as a Bundle ID. The name of the .desktop
file
MUST be the entry point ID followed by .desktop
.
Like the Bundle ID, all entry point IDs in an app-bundle MUST start with a Reversed domain name controlled by the author. It is RECOMMENDED that all entry point IDs in an app-bundle either match its bundle ID exactly, or start with the bundle ID followed by a dot.
A single executable program MAY be represented by more than one entry point.
If a program will request a D-Bus well-known bus name to provide interfaces to graphical programs in the same bundle, the well-known bus name MUST be the same as one of its entry point IDs.
Main entry point
Each app-bundle that has any entry points SHOULD have an entry point whose Entry point ID is exactly the Bundle ID. This entry point is referred to as the main entry point, and MUST be a [graphical program][Graphical programs].
Certain metadata fields of the main entry point, including its Categories
,
Icon
and MimeType
, are copied into the cache of bundle metadata during
installation and hence made available to platform applications.
Content type and URI scheme handlers
The Main entry point MAY be registered as the content type handler for
media types such as audio/mpeg
, by setting MimeType
to a list of
content types, each followed by a semicolon ;
.
Non-main entry points MUST NOT be content type handlers. For example,
a media player with support for the MP3 and RealAudio formats might use
MimeType=audio/mpeg;audio/vnd.rn-realaudio;
in its entry point.
The Main entry point MAY be registered as the handler for
URI schemes such as tel
or http
, by
including an entry in MimeType
for the pseudo-content-type
x-scheme-handler/
scheme, for example x-scheme-handler/http
for a
web browser. Non-main entry points MUST NOT be URI scheme handlers.
If the entry point implements D-Bus activation, sending the
org.freedesktop.Application.Open
method call to the
object path corresponding to its entry point ID MUST result in it attempting
to open the URI or URIs passed as parameters.
Graphical programs
Each graphical program (user interface, HMI) that will be directly launched by the user MUST have an entry point. Each graphical program that will be associated with content types or URIs MUST have an entry point.
A graphical program MAY have more than one entry point, to appear in menus more than once (for example, the Frampton media player uses this to appear three times under the names Artists, Albums and Songs).
Graphical programs MUST set X-Apertis-Type
to application
.
This is required by Apertis 16.09, but might be phased out in a later minor version of this specification.
If a graphical program is intended to be shown in the menus, NoDisplay
MUST NOT be specified. Otherwise, it MUST be specified and set to true
(for example, the Frampton media player uses this to allow its main entry
point to be associated with media file types while hiding it from the
menus).
Categories
MUST be set to a list of appropriate menu categories from the
freedesktop.org Desktop Menu Specification,
each followed by a semicolon ;
. There MUST be at least one Main Category.
X-Apertis-CategoryLabel
MUST be set to the human-readable English name
of a single category, which MUST be in title-case with no special
formatting (for example, Video & TV
is correct, while V I D E O & T V
is not).
This is required by Apertis 16.09, but should be phased out in favour of having launchers parse Categories in a later minor version of this specification.
X-Apertis-CategoryIcon
MUST be set to the name of the icon to be used
for the category in launchers, with no /
characters or
file-type extension, for example icon_music_AC
. The icon MUST be
chosen from among those provided by the platform’s launcher (the allowed
values are therefore platform-specific).
This is required by Apertis 16.09, but should be phased out in favour of having launchers parse Categories in a later minor version of this specification.
Icon
MUST be set to the name of either the Icon for the bundle or one
of the Icons for entry points, as a bare icon name (without any /
characters, and without a file-type extension such as .png
or .svg
). In
particular, this implies that its string value MUST match either the
Bundle ID, or the Entry point ID of an entry point.
Multiple views
Some application designs have a group of entry points that are all implemented by invoking the same executable with different parameters, all implemented in the same process. For example, a music player might have separate entry points to view the music library grouped by artist or album, or as a single flat list of songs.
In applications that work like this, one of these views MUST be nominated to be the parent entry point, with the others as child entry points. The parent will usually be the Main entry point, although this is not required. The main entry point SHOULD NOT be a child entry point.
A parent entry point MUST NOT have the X-Apertis-ParentEntry
field.
It MUST set DBusActivatable
to true
, and implement
[D-Bus activation] for its own entry point ID and the entry point IDs
of all associated child entry points. It SHOULD set
X-Apertis-ServiceExec
.
Child entry points MUST set the X-Apertis-ParentEntry
field
to the Entry point ID of the parent entry point, and MUST set
DBusActivatable
to true
. They MUST NOT set X-Apertis-ServiceExec
.
Agents and other non-graphical programs MUST NOT be parent or child entry points.
D-Bus activation
Programs in an app-bundle MAY declare that they implement D-Bus activation
by setting DBusActivation
to true
in each entry point that starts the
same program.
Graphical program entry points that set DBusActivation
to true
and do not have an X-Apertis-ParentEntry
field SHOULD also have an
X-Apertis-ServiceExec
field. The X-Apertis-ServiceExec
field has the
same syntax as the standard Exec
field.
Agents MUST NOT have an X-Apertis-ServiceExec
field, since their Exec
field has essentially the same meaning.
We define the service activation command line to be the
X-Apertis-ServiceExec
field if present, or the Exec
field otherwise.
The service activation command line MUST be a command-line that will start
the program without opening any graphical windows, such that it will be
ready to receive D-Bus requests. If a program uses the GApplication
API (which is recommended), then the service activation command line for
graphical programs will typically be the absolute path of the executable
followed by a space and the --gapplication-service
argument, for example
X-Apertis-ServiceExec=/Applications/com.example.ShoppingList/bin/main --gapplication-service
,
while the service activation command line for agents and other non-graphical
programs (with the G_APPLICATION_IS_SERVICE
flag)
will typically just be the path to the executable.
When the service activation command line for a graphical program is
launched, the resulting process MUST export a D-Bus object path that
is derived from the entry point ID by prepending /
and replacing
each .
with /
, then request a well-known name equal to the entry
point ID. The interfaces of that object path MUST include at least the
org.freedesktop.Application
interface, and MAY include
additional standard or non-standard interfaces such as the
org.gtk.Application
interface
used by GLib’s GApplication objects. When launched in this way, the
process MUST NOT behave as though any of its entry points were activated
until it receives an appropriate D-Bus method call; in particular, it
MUST NOT open any windows until it is told to do so.
When the service activation command line for an agent or non-graphical
program is launched, the resulting process MAY export a D-Bus object
path implementing org.freedesktop.Application
as above, but is not
required to do so. If it does, the Activate
and Open
methods are
not required to be implemented, since they are unlikely to be useful
for non-graphical programs.
If an entry point has an X-Apertis-ParentEntry
field (a
[child entry point][Multiple views]), when the parent entry point
named in that field is started by its service activation command line,
the resulting process MUST also export D-Bus object paths and request
well-known names corresponding to the entry point IDs of each of its
child entry points.
For graphical programs, sending the
org.freedesktop.Application.Activate
D-Bus method call
to one of the object paths described above MUST
result in the program displaying whatever window is appropriate for the
corresponding entry point. If the graphical program implements
[content-type handling][Content type and uri scheme handlers],
then the same is true for the
org.freedesktop.Application.Open
method.
This requirement is not applicable to agents and other non-graphical
programs.
The process MAY export additional object paths and interfaces. It SHOULD NOT request additional well-known names.
When the Exec
command of a D-Bus-activatable graphical entry point
is launched, the resulting process MUST arrange for a program to be
run (directly or indirectly) that will request the well-known name
corresponding to that entry point ID, export the corresponding
D-Bus object path, and behave as though that object path had
received an Activate
or Open
method call, modified according to the
command-line arguments if appropriate: in other words, it has behaviour
similar to the Exec
command of a non-D-Bus-activatable graphical
program. If the program uses the GApplication API, this will
normally be achieved by setting Exec
to the absolute path of the
executable, with no arguments, for example
Exec=/Applications/com.example.ShoppingList/bin/main
. This requirement
is not applicable to agents and other non-graphical programs.
See the specification of the Application interface for more details about its methods.
Agents
Each agent (background service) MUST have an entry point.
Agents MUST set X-Apertis-Type
to agent-service
.
This is required by Apertis 16.09, but might be phased out in a later minor version of this specification.
Agents MUST set NoDisplay
to true
.
Agents SHOULD set DBusActivatable
to true
, and implement
D-Bus activation as described above.
Paths for other file types
Executables
Any executable programs in the app-bundle MUST be installed in either
the ${prefix}/bin
or ${prefix}/libexec
directory, or a descendant
directory in ${prefix}/libexec
. For example, these
paths are valid:
${prefix}/bin/my-executable
${prefix}/libexec/my-helper-executable
${prefix}/libexec/other-helper/other-helper-executable
Suitable directories are conveniently available as
${bindir}
,${libexecdir}
and ${pkglibexecdir}` when using Automake.
Libraries
An Apertis application bundle MAY contain private libraries for use by that application bundle, for example shared libraries written in C or C++, or Python modules.
If present, architecture-dependent library files MUST be located in the
${prefix}/lib
directory or a descendant of that directory.
Architecture-independent library files such as “pure Python” modules
MUST be located in either the ${prefix}/lib
or ${prefix}/share
directory,
or a descendant of one of those directories.
For example, the app bundle com.example.ShoppingList
might contain
library files /Applications/com.example.ShoppingList/lib/libwebapi.so.0
or
/Applications/com.example.ShoppingList/lib/python3/webapi/__init__.py
.
Native executables SHOULD be linked with a DT_RPATH
pointing to the
location of their required libraries. For example, the ShoppingList
app bundle described above might be linked using
gcc -Wl,-rpath=/Applications/com.example.ShoppingList/lib
.
If the app bundle is built using GNU automake and libtool, this will typically be done automatically.
Programs in app-bundles MUST NOT assume that any special environment variables
to locate libraries, such as LD_LIBRARY_PATH
, GI_TYPELIB_PATH
or
PYTHONPATH
, will be set by the application framework. For example, if the
ShoppingList app bundle described above needs to be able to load
/Applications/com.example.ShoppingList/lib/python3/webapi/__init__.py
via the Python statement import webapi
, it cannot assume that
/Applications/com.example.ShoppingList/lib/python3
is already in sys.path
.
Its main executable might prepend that directory to sys.path
, or its
main executable might be a shell script that sets PYTHONPATH
and then runs
the underlying Python code with exec
.
A possible change in future minor versions of this specification would be to set a specified list of environment variables used by a specified set of recommended libraries, such as
LD_LIBRARY_PATH
for libc andGI_TYPELIB_PATH
for GObject-Introspection. Python is not among our recommended frameworks, so we would probably still not includePYTHONPATH
.
For each native ELF library, the app-bundle MUST contain a file whose name
exactly matches the SONAME (ELF DT_SONAME
) of the library, in a directory
that will be searched by all executables that use that library (for example
via DT_RPATH
or LD_LIBRARY_PATH
). This file MUST either be a regular file
(the library itself), or a symbolic link to the library’s “real name”.
Building and installing shared libraries using GNU libtool is RECOMMENDED:
libraries built like this will typically have a correct symbolic link from the
SONAME
to the “real name” without further action from the developer.
For example, if the ShoppingList app-bundle has executables linked to
a private library whose SONAME
is libwebapi.so.0
, it might include
a regular file with exactly that name; or it might include a regular file named
libwebapi.so.0.1.2
, and a symbolic link libwebapi.so.0 → libwebapi.so.0.1.2
.
Icon for the bundle
The app-bundle MAY have an icon to represent the bundle as a whole, in a
generic user interface icon theme. The generic user interface icon theme
is represented by the reserved theme name hicolor
, as required by the
freedesktop.org Icon Theme Specification.
If the app-bundle has this icon, it MUST be in Portable Network Graphics format, 64×64 pixels in size, and MUST be located at
${prefix}/share/icons/hicolor/64x64/apps/${name}.png
where ${name}
is set to the Bundle ID.
Open question: I’m arbitrarily choosing 64x64 because that’s what the AppStream specification uses, but do we have a different preferred size in Apertis?
To minimize display artefacts caused by resizing, the app-bundle MAY make
this icon available in some or all of the additional sizes used in the
freedesktop.org reference implementation
of the hicolor
fallback theme
(8, 16, 22, 24, 32, 36, 42, 48, 64, 72, 96, 128, 192, 256 or 512 pixels).
These MUST be installed to the corresponding path with 64x64
replaced by
the appropriate size.
The app-bundle MAY have variations of this icon that fit better in
specific user interface themes. If present, these MUST be installed
to the corresponding path with hicolor
replaced by the name of the
intended theme. For example, if a theme named net.example.Metallic
is popular, an app-bundle might include a version of its own icon that has
been designed to coordinate well with the Metallic theme, at
${prefix}/share/icons/net.example.Metallic/64x64/apps/${name}.png
Icons for entry points
Any entry point MAY have an icon to represent it. If present, it MUST
be named in the same way as the icon for the bundle as a whole, except
that ${name}
is set to the Entry point ID instead of the bundle ID.
Note that this means the Main entry point of the app-bundle will always use the same icon as the bundle itself.
Icons for use by the bundle
The app-bundle MAY contain other icons. They SHOULD be arranged according to the freedesktop.org Icon Theme Specification.
For example, if the app-bundle is an email client, it might include a
mail-mark-important
icon for use by a “Mark as Important” button. If it
has a generic version for use by unrecognised themes, and that generic
version is 24 pixels in size, that version might be installed in:
${prefix}/share/icons/hicolor/24x24/actions/mail-mark-important.png
If the app-bundle also has a version for use by a popular theme named
net.example.Metallic
, it might install that as:
${prefix}/share/icons/net.example.Metallic/24x24/actions/mail-mark-important.png
The app-bundle MAY assume that it will be launched with the
XDG_DATA_DIRS
environment variable
set to a value that includes ${prefix}/share
, so
that common icon theme implementations such as GtkIconTheme will
automatically use icons from the ${prefix}
.
Theme data for use by the bundle
The app-bundle MAY install theme data into subdirectories of
${prefix}/share/themes
whose names correspond to theme names.
The app-bundle MAY assume that it will be launched with the
XDG_DATA_DIRS
environment variable
set to a value that includes ${prefix}/share
, so
that common theme implementations such as GtkCssProvider will
automatically use theme data from the ${prefix}
.
GSettings schemas
GSettings schemas are used for preferences.
The app-bundle MAY install one or more GSettings schemas into
${prefix}/share/glib-2.0/schemas/
. The filenames used MUST be the
schema ID followed by .gschema.xml
, optionally accompanied by enum
definitions in a file named by the schema ID followed by .enums.xml
.
Each schema ID SHOULD either match the Bundle ID exactly, or
start with the bundle ID followed by a dot.
If the app-bundle installs any schemas, then it MUST also install a compiled
binary form of those schemas, in
${prefix}/share/glib-2.0/schemas/schemas.compiled
. The
glib-compile-schemas
tool can be used to compile this binary form.
The app-bundle MAY install a schema whose schema ID matches the Bundle ID exactly. If it does, then that schema’s child schemas MUST all start with the bundle ID followed by a dot, and that schema and its child schemas will be made available in the system settings user interface.
If the app-bundle author does not intend for it to appear in the system
settings user interface, then the app-bundle MUST NOT use its bundle ID
as a schema ID. It MAY use an alternative schema ID such as
${bundle_id}.Internal
, resulting in a schema file named
${bundle_id}.Internal.gschema.xml
.
The app-bundle MAY assume that it will be launched with the
XDG_DATA_DIRS
environment variable
set to a value that includes ${prefix}/share
, so
that GSettings will automatically use these schemas.
Localized strings
Some file formats, such as .desktop
files and AppStream XML, put
localized strings
in a single file, typically built from an international English
version and a set of translations at build-time. For the following file
formats, the app-bundle MUST include all of its supported translations
(for example a translated Name
) in a single file:
Otherwise, application bundles that contain localized strings SHOULD use
GNU gettext
.mo
files. These SHOULD be stored in the ${prefix}/share/locale
hierarchy,
with a subdirectory named for the locale in which the language is used,
and a LC_MESSAGES
subdirectory inside that containing one or more .mo
files. The name of the .mo
files (the text domain) SHOULD either be
exactly the Bundle ID, or the bundle ID followed by a dot and
one or more additional components. Using a single text domain whose name
is exactly the bundle ID is RECOMMENDED.
For example, if the app bundle com.example.ShoppingList
is localized into
generic international French, French as spoken in Canada, and
Uzbek written in Cyrillic, it might contain:
/Applications/com.example.ShoppingList/share/locale/fr/LC_MESSAGES/com.example.ShoppingList.mo
/Applications/com.example.ShoppingList/share/locale/fr_CA/LC_MESSAGES/com.example.ShoppingList.mo
/Applications/com.example.ShoppingList/share/locale/uz@cyrillic/LC_MESSAGES/com.example.ShoppingList.mo
The other LC_
directories used by gettext MAY exist alongside LC_MESSAGES
.
If using gettext
, programs in the app bundle would typically have to make
API calls similar to these to activate these localized strings:
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, DATADIR "/locale");
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
where DATADIR
would be defined to \"${datadir}\"
by the build system
(expanded to /Applications/com.example.ShoppingList/share
at build time),
and GETTEXT_PACKAGE
would be defined to com.example.ShoppingList
in
this example.
In general, use of gettext is not mandatory, and neither is this specific
layout.
Application bundles MAY store localized strings in any format of their
choice, in any subdirectory of ${prefix}/lib
or ${prefix}/share
.
If this is done, the application bundle author is responsible for arranging
for those localized strings to be loaded.
There is one special case where use of gettext and this specific layout
is mandatory. If an app bundle contains GSettings schemas, and those
schemas support localized contents by using the gettext-domain
attribute,
then the gettext-domain
that is declared MUST be either the Bundle ID,
or the bundle ID followed by a dot and one or more additional name
components. Again, using exactly the bundle ID for the gettext domain
is RECOMMENDED.
One possible direction for a future minor version would be to allow GSettings schemas to include inline translations, similar to
.desktop
files. This would require GLib modifications: at the moment this is specifically not allowed by GLib.
Generic resource data
Non-executable resource files such as graphics and sounds MUST be located
in either the ${prefix}/lib
or ${prefix}/share
directory, or a descendant
of one of those directories.
CPU-architecture-dependent resource files MUST be located in the ${prefix}/lib
directory or a descendant of that directory. CPU-architecture-independent
resource files SHOULD be located in the ${prefix}/share
directory or
a descendant of that directory.
The app-bundle MAY assume that it will be launched with the
XDG_DATA_DIRS
environment variable
set to a value that includes ${prefix}/share
, so
that any library that uses that variable (for example via
g_get_system_data_dirs()
) will automatically load resource files from
the appropriate subdirectory of ${prefix}/share
.
The app-bundle MUST NOT assume that the application framework will set
environment variables that make it load resource files from ${prefix}/lib
.
Example
For example, suppose the owner of example.net
produces an application
named Shopping List, with a graphical program to display shopping lists,
and a background agent to pop up reminders when the vehicle is driven
near a supermarket. Suppose the agent provides a D-Bus API to the
graphical program.
Suppose this application also opens the application/vnd.example.shoppinglist
content type, and handles myproduct:
URIs.
Suppose the bundle ID is net.example.ShoppingList
, so the bundle’s files
will be available at /Applications/net.example.ShoppingList
.
The minimal metadata required for this bundle might resemble what is shown
in this section; all paths are given relative to
/Applications/net.example.ShoppingList
, which we will refer to as
${prefix}
.
[Application bundle metadata][Bundle metadata], to be installed as
${prefix}/share/metainfo/net.example.ShoppingList.appdata.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>net.example.ShoppingList</id>
<metadata_license>CC0-1.0</metadata_license>
<name>Shopping List</name>
<summary>Keep track of your groceries</summary>
<description>
<p>Never run out of cornflakes again with this easy-to-use shopping
list manager, featuring:</p>
<ul>
<li>Special offer notifications</li>
<li>Driving directions to the nearest supermarket</li>
<li>Cloud synchronization</li>
</ul>
<developer_name>Example Software Inc.</developer_name>
<url type="homepage">https://example.net/shopping-list/</url>
<release version="1.0" date="2016-08-23" />
</component>
The [settings schema][GSettings schemas] would be installed to
${prefix}/share/glib-2.0/schemas/net.example.ShoppingList.gschema.xml
,
optionally accompanied by
${prefix}/share/glib-2.0/schemas/net.example.ShoppingList.enums.xml
.
Those files would be compiled into
${prefix}/share/glib-2.0/schemas/gschemas.compiled
, for example by using a
command like
glib-compile-schemas --strict ${DESTDIR}${prefix}/share/glib-2.0/schemas
while building the bundle.
Localized strings used in the app itself, or in its GSettings schema, would
be installed as
${prefix}/share/locale/${locale}/LC_MESSAGES/com.example.ShoppingList.mo
,
where ${locale}
represents a locale such as fr_CA
or de
.
Main entry point for the user interface, to be installed as
${prefix}/share/applications/net.example.ShoppingList.desktop
:
[Desktop Entry]
Categories=Utility;
Exec=/Applications/net.example.ShoppingList/bin/gui
GenericName=Shopping List
Icon=net.example.ShoppingList
MimeType=application/vnd.example.shoppinglist;x-scheme-handler/myproduct;
Name=Shopping List
OnlyShowIn=Apertis;
Type=Application
X-Apertis-Type=application
X-GNOME-FullName=Example Shopping List
DBusActivatable=true
X-Apertis-ServiceExec=/Applications/net.example.ShoppingList/bin/gui --gapplication-service
The user interface’s [icon][Icon for the bundle] would be installed as
${prefix}/share/icons/hicolor/64x64/apps/net.example.ShoppingList.png
.
[Entry point][Entry points] for the agent, to be installed as
${prefix}/share/applications/net.example.ShoppingList.Agent.desktop
:
[Desktop Entry]
Exec=/Applications/net.example.ShoppingList/bin/agent
NoDisplay=true
OnlyShowIn=Apertis;
Type=Application
X-Apertis-Type=agent-service
X-GNOME-FullName=Example Shopping List
DBusActivatable=true
AppArmor profile, to be installed as
${prefix}/etc/apparmor.d/Applications.net.example.ShoppingList
:
/Applications/net.example.ShoppingList/** {
#include <abstractions/chaiwala-base>
#include <abstractions/dbus-session-strict>
/Applications/net.example.ShoppingList/{bin,libexec}/* pix,
/Applications/net.example.ShoppingList/{bin,lib,libexec}/{,**} mr,
/Applications/net.example.ShoppingList/share/{,**} r,
owner /var/Applications/net.example.ShoppingList/users/** rwk,
dbus send
bus=session
path=/org/freedesktop/DBus
interface=org.freedesktop.DBus
member={RequestName,ReleaseName}
peer=(name=org.freedesktop.DBus),
dbus bind bus=session name="net.example.ShoppingList",
dbus bind bus=session name="net.example.ShoppingList.*",
dbus (send, receive) bus=session
peer=(label=/Applications/net.example.ShoppingList/**),
dbus receive bus=session peer=(label=/usr/bin/canterbury),
signal receive peer=/usr/bin/canterbury,
}
Future directions
Future versions of this specification could include layout and contents specifications for particular categories of system extensions, in particular user-installable UI themes and language packs.
Appendix: built-in application bundles
Built-in application bundles are maintained as part of the platform, and so are outside the scope of this specification. However, their structure is similar.
As a general principle, built-in application bundles that closely resemble a store application bundle, other than the structural differences listed here, will be as portable between platform versions as a similar store application bundle would be. Built-in application bundles that diverge more from that model will be more tightly-coupled to the platform for which they were designed, and so are more likely to need alterations for newer platform versions.
Structural differences
In general, built-in application bundles MUST have a structure analogous to
store application bundles, replacing /Applications
with /usr/Applications
in all path prefixes. In particular, the ${prefix}
for a built-in application
bundle is /usr/Applications/
followed by the bundle ID.
As an exception to the usual use of the ${prefix}
, built-in application
bundles MUST install their [AppArmor profiles][AppArmor profile] directly to
/etc/apparmor.d
, in a file named
/etc/apparmor.d/usr.Applications.${bundle_id}
where ${bundle_id}
is to
be replaced by the Bundle ID.
They MUST NOT contain /usr/Applications/*/etc/apparmor.d
.
For the following categories of files, if an equivalent store application
bundle would include files in that category, built-in application bundles
MUST install the real files into ${prefix}/share
. Additionally, the .deb
file for the built-in application bundle must include symbolic
links /usr/share/*
pointing to the corresponding regular files in
${prefix}/share/*
:
For example, the .deb
file for a built-in application bundle
org.apertis.Eye
might include a symbolic link
/usr/share/applications/org.apertis.Eye.desktop
pointing to the main
entry point’s real file
/usr/Applications/org.apertis.Eye/share/applications/org.apertis.Eye.desktop
,
and similar symbolic links for GSettings schemas, icons and the bundle
metadata.
For the following categories of files, if an equivalent store application
bundle would include files in that category, built-in application bundles
MUST install the files into ${prefix}
, but MUST NOT include symbolic
links to them in /usr/*
:
- Executables
- Libraries
- Icons for use by the bundle
- Localized strings
- Theme data for use by the bundle
- Generic resource data
Permissions and policy differences
Recommendations and requirements that refer to the app-store curator do not apply to built-in application bundles. The platform vendor has total control over both the platform layer and the built-in application bundles that are packaged with it; they are responsible for ensuring that those components fit together correctly and meet their functional and security requirements. For example, a platform vendor can provide any AppArmor profile for a built-in application bundle, and it is up to the platform vendor to ensure that the profile is consistent with their security policy.
Graphical programs
Built-in application bundles do not necessarily need to provide their own user interfaces if they rely on an underlying service, for example one that is running in the automotive domain, to display a user interface. Where this specification calls for a particular entry point to be a graphical program, that requirement or recommendation does not apply to built-in application bundles. A built-in application bundle could provide similar functionality by communicating with other processes, either locally or in the automotive domain, and arranging for those other processes to display graphics instead.
However, if this is done, then the built-in application bundle is necessarily somewhat tightly coupled to the component to which it delegates its user interface.
Command line arguments
Built-in app-bundles SHOULD NOT use the play-mode
, app-name
or url
tokens in their Exec
arguments. This is a weaker prohibition than for
store app-bundles, which MUST NOT use those tokens. This exception is
made for backwards compatibility. Please note that the special case
made for these tokens in and before Apertis 17.03 is deprecated, and their
effect will change in future releases.
Agents and other non-graphical programs in built-in app-bundles SHOULD NOT
have an X-Apertis-ServiceExec
field. This is a weaker prohibition
than for non-graphical programs in store app-bundles, which MUST NOT have
that field: it allows those agents and non-graphical programs to make use
of the special tokens like play-mode
when run on Apertis 17.03, without
including them in the service command-line. This exception is made for
backwards compatibility, and is considered deprecated.