All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Application Definition (.adef) Files

These sections are available in the .adef files (in alphabetical order):

bindings
cpuShare
executables
files
fileSystemSize
groups
import
memLimit
mqueueSize
numProcs
provides
processes
requires
rtSignalQueueSize
sandboxed
start
version
watchdogTimeout
watchdogAction

version

Optional field that specifies a string to use as the application's version string.

Note
  • mkapp –append-to-version=XXXX can be used to append "XXXX" onto the application's version string.
  • app foo version can be used on-target to get the app's version string.
version: 0.3a

sandboxed

Specifies if the app will be launched inside a sandbox.

Permitted content in this section is:

  • true - app will be run inside of a sandbox.
  • false - app won't be run in a sandbox.

The default is true.

If an app is not inside of a sandbox (unsandboxed), it can see the target device's real root file system. A sandboxed app can't see the target's real root file system; instead, a sandboxed app has its own, separate root file system (which it can't leave).

Each app has its own user ID and primary group ID. User name and primary group name is "appxxxx", where the "xxxx" is replaced with the name of the app.

Sandboxed apps aren't allowed to be members of other groups and are not allowed to have any capabilities (see "man 7 capabilities") set on their executables.

Unsandboxed apps are allowed to have executables with capabilities and be members of other groups (see the "groups:" section).

While a user and/or group will be automatically created if missing for the specified app, only users and groups of sandboxed apps will be automatically deleted when those apps are uninstalled.

sandboxed: false

start

Specifies if the app should start automatically at start-up: "auto" sets the app to start automatically by the Supervisor. "manual" sets the app to start through a manual prompt to the Supervisor. Default is auto.

start: auto

numProcs

Specifies the maximum number of processes and threads allowed to run at one time: an integer number.

If fork() calls or pthread_create() calls start failing with error code EAGAIN (seen in strace output as clone() system calls), then you are probably running into this limit.

Default is 20.

numProcs: 4

mqueueSize

Specifies the maximum number of bytes that can be allocated for POSIX MQueues. Default is 512.

mqueueSize: 22

rtSignalQueueSize

Specifies the maximum number of real-time signals that can be queued (waiting for delivery) to processes. This can be per thread in the app.

Default is 100.

rtSignalQueueSize: 10

memLimit

Specifies the maximum amount of memory (in kilobytes) that all processes in an app can share. Default is 40960.

memLimit: 4000

cpuShare

Specifies the relative cpu share for an application.

Cpu share is used to calculate the cpu percentage for a process relative to all other processes in the system. New cgroups and processes default value of 1024 if not otherwise configured. The actual percentage of the cpu allocated to a process is calculated like this:

(share value of process) / (sum of shares from all processes contending for the cpu)

All processes within a cgroup share the available cpu percentage share for that cgroup like this:

cgroupA is configured with the default share value, 1024. cgroupB is configured with 512 as its share value. cgroupC is configured with 2048 as its share value.

cgroupA has one process running. cgroupB has two processes running. cgroupC has one process running.

This assumes all processes in cgroupA, cgroupB and cgroupC are running and not blocked waiting for an I/O or timer event, and another system process is also running.

Sum of all shares (including the one system process) is 1024 + 512 + 2048 + 1024 = 4608

The process in cgroupA will get 1024/4608 = 22% of the cpu. The two processes in cgroupB will share 512/4608 = 11% of the cpu, each process getting 5.5%. The process in cgroupC will get 2048/4608 = 44% of the cpu. The system process will get 1024/4608 = 22% of the cpu.

cpuShare: 512

fileSystemSize

Specifies the maximum amount of RAM that can be consumed by an app's temporary (volatile) file system at runtime. Default is 128K

fileSystemSize: 120K

files

Lists additional files or directories to be included in an app so they’re available at runtime (e.g., audio files, web pages, executable scripts or programs from external build system).

Three things need to be specified for each file:

  • access permissions
  • build system path
  • target path

Access permissions - any combination of one or more of the following letters, enclosed in square brackets:

  • r = readable
  • w = writeable
  • x = executable

If permissions values are not specified, then read-only ([r]) is the default.

Note
Access permissions aren't implemented yet. For now, everything that gets installed in the application's "bin" directory on target gets "rx" permission, and all other files get "r" while all directories get "rx".

Build system path - file system path on the build PC where the file is located at build time.

The path can be relative to the directory where the .adef file is located.

Target path - file system path on the target where the file will appear at runtime.

Paths of files included in the apps will be automatically installed on-target under "/opt/legato/apps/xxxx", where "xxxx" is replaced by the app name. If the application runs inside a sandbox, it will appear

File paths can be enclosed in quotation marks (either single ' or double "). This is required when the file path contains spaces.

files:

    [r]     audio/alert.wav     /usr/share/sounds/
    [rx]  third-party/foobar/bin/foobar   /bin/
    htdocs/index.html   /var/www/
    "stuff/file name with spaces"  /usr/share/stuff/
    'stuff/another file'   /usr/share/stuff/

File Ownership and Set-UID Bits

When the application is installed on a target:

  • the owner and group are set to root on all files in the app.
  • the setuid bit is cleared on everything in the application.

executables

Lists executables to be constructed and moved to the “bin” directory inside the app.

An executable’s content is specified inside parentheses after the name, and can be one of these:

  • relative file system path to source code file (e.g., a .c, .java, or .lua file)
  • component
  • relative file system path to library file (e.g., .a or .so file).

Only C/C++ source files, components, and libraries are currently supported.

executables:
myexe1 ( file1.c libgoodstuff.so )
myexe2 ( foobar toto )

If a component is included in an executable, then that component will be built and linked into the executable, and its COMPONENT_INIT function will be run at process start-up. Furthermore, that component’s runtime files (shared libraries, Lua source code, etc.) will be packaged inside the application for installation on the target.

If a source file is included in an executable, the build tools will search for it in the file system according to the source search path. When found, it will be compiled (if written in a compiled language) and linked into the executable. Note that all the source files specified for an executable will together be considered a component (called "default"), and one of those source files will be expected to implement a COMPONENT_INIT function, which will get called at start-up.

If a library is “included in” an executable in this way, that library is expected to be found in the “import” or “files” section of the application’s .adef file or in the “files” section of the Component.cdef file of a component that appears in the the .adef file. When the executable is linked, it will be linked with these “included” libraries in the order in which they are listed. Note that it's permitted to list the same library more than once, as is sometimes necessary in order to satisfy all unresolved symbols, due to the single-pass nature of the linker.)

The mechanism by which the executable is constructed will depend on the type of content and the target device. For example, C files will be compiled and linked using the appropriate compiler tool chain, depending on what target device the application is being built for. The same goes for components written in C. Java code will be compiled to Java bytecode. Lua code will be simply copied into the application.

Note
In some cases, there may be incompatibilities between components or source code files that prevent them from being included in the same executable. For example, you may not be able to put Java sources and C sources into the same executable together. If you do violate one of these restrictions, the build tools will tell you about it.

import

The import section lists things imported to the app’s sandbox at runtime from outside of the sandbox. The contents appear similar to the "files" section’s content, but meanings are different: Things listed in the “import” section are expected to be found on the target at runtime. They are not copied into the app at build time; they're made accessible to the app inside of its sandbox at runtime.

Currently, only virtual file system objects (files, directories, named sockets and pipes, device files, etc.) are explicitly imported. (Note: IPC interfaces are imported by components using the Component.cdef file’s “import” section.)

This section is ignored if the app is not sandboxed (if sandboxed set to false).

Items in the import section have essentially the same format as items in the files section, except the first path must be an absolute path (beginning with ‘/’).

The first path is the object to be imported. This is an absolute path in the target’s file system, outside of the sandbox (beginning with ‘/’).

The second path is the absolute file system path inside the app’s sandbox where the object will appear at runtime.

File paths can be enclosed in quotation marks (either single ' or double "). This is required when the file path contains spaces.

import:
    // I get character stream input from outside via a named pipe (read-only)
    /var/run/someNamedPipe  /var/run/

    // I need read and write access to UART2.
    /dev/ttyS1  /dev/

    // I need to be able to play back audio files installed in /usr/local/share/audio.
    "/usr/local/share/audio/error message.wav" /usr/share/audio/
    '/usr/local/share/audio/success message.wav' /usr/share/audio/

Permissions settings in import can't override permissions on the object in the target’s file system. If an object is read-only for the app’s user account in the root file system, it'll still be read-only accessible inside the app’s sandbox (even if imported “[rw]” in the app’s .adef file).

File permissions and ownership (group and user) on the original file in the target system remain in effect inside the sandbox.

groups

Add an unsandboxed app's user to groups on the target system. Not permitted for sandboxed apps.

groups:
www-data
modem

watchdogTimeout

The watchdogTimeout section sets the default timeout in milliseconds for processes in this application. This value will be used if there is no value set in the processes section for a given process. See watchdogTimeout in the processes section.

watchdogAction

The watchdogAction section sets the recovery action to take if a process in this application expires its watchdog. This value will be used if there is no value set in the processes section for a given process. See watchdogAction in the processes section.

bindings

This section allows IPC imports (listed in the “import” sections of Component.cdef files) to be "bound" to IPC exports (listed in the "export" sections of Component.cdef files).

This allows direct control over how IPC interfaces are interconnected, thereby allowing reusable components and/or apps to be "wired" together to form a working system.

Bindings can be between two interfaces inside the same app (an "internal binding"), or can be between a client-side interface in this app and a server-side interface "provided" by another app (or non-app user).

Interface instances inside the app are identified using the executable name, component name, and the service instance name. These different parts of the interface instance identifier are separated by a period (‘.’).

The client interface always appears first, and an arrow ( -> ) is used to separate the client interface from the server interface.

For example, to bind "clientExe.clientComponent.api" to "serverExe.serverComponent.api":

bindings:

    clientExe.clientComponent.api -> serverExe.serverComponent.api

External services provided by other apps are identified using the app name and the service name, separated by a period ('.').

bindings:

    clientExe.clientComponent.api -> otherApp.api

To bind to a service provided by a non-app user, the app name is replaced by a user name inside angle brackets.

bindings:

    clientExe.clientComponent.api -> <root>.api

requires

The "requires:" section is used to specify things that the application needs from its runtime environment.

Eventually, this will support "file:", "dir:", "api:", and "configTree" subsections, but for now, only "api:" and "configTree:" subsections are supported.

api

Declares that a client-side (imported) IPC API interface needs to be bound to a service provided by another app (or non-app user).

For example, the following declares that the "temperature" interface on the "tempInput" component in the "controller" executable should be made into a bindable external interface called "airTemp":

requires:

    api: airTemp {controller.tempInput.temperature}

Interface instances are identified using the executable name, component name, and the service instance name. These different parts of the interface instance identifier are separated by a period (‘.’).

configTree

Declares that the application requires access to a given configuration tree. Each application has its own configuration tree named after the application. In addition, there's a "system" configuration tree that contains privileged system data.

Applications can be granted read access or both read and write access to trees.

By default, an application only has read access to its own configuration tree.

If access is granted to a tree, but the access mode ("[r]" or "[w]") is not specified, then only read permission will be granted.

requires:

    configTree: { [w] myApp }   // I need write access to my configuration data.
    configTree: { otherApp }    // I need read access to another app's configuration data.

provides

The "provides:" section is used to specify things that the application provides to other apps (or non-app processes) in its runtime environment.

For now, only "api:" subsections are supported.

api

This subsection declares that a server-side (exported) IPC API interface is available for other apps (or non-app users) to use via bindings.

For example, the following declares that the "temperature" interface on the "thermistor" component in the "sensor" executable should be made into a bindable external interface called "spaceTemp":

provides:

    api: spaceTemp {sensor.thermistor.temperature}

Interface instances are identified using the executable name, component name, and the service instance name. These different parts of the interface instance identifier are separated by a period (‘.’).

processes

A processes section specifies processes to run when the app is started, along with their environment variables, command-line arguments, limits, and fault handling actions.

Content in the processes section is divided into .adef processes.

If different processes have different variables, they must be in separate "processes:" sections.

For example,

processes:
// Start up these processes when the app starts
run: myProc1 ( myExe --foo -b 43 )
run: myProc2 ( myExe –bar --b 92 )
run: ( myExe2 "Hello, world." ) // If no proc name is specified, uses the exe name by default.
// Env var settings (name = value) for all processes in this section.
envVars:
LE_LOG_LEVEL = DEBUG
priority: medium // Starting (and maximum) scheduling priority. Process can only lower its priority from here.
coreFileSize: 100K // Maximum size of core dump files.
maxFileSize: 50K // Files are not allowed to grow bigger than this.
memLockSize: 32K // Maximum number of bytes allowed to be locked into physical memory using mlock().
numFds: 20 // Maximum number of file descriptors allowed to be open at the same time.
processes:
run: ( realTimeExe )
priority: rt10 // Allow real-time scheduling (max priority 10) for processes in this section.
/*-- Exception handling policy for processes in this section. --*/
faultAction: restart // Restart the process if it fails.

The processes section of the .adef also has sub-sections, see .adef processes.


Copyright (C) Sierra Wireless, Inc. 2014. All rights reserved. Use of this work is subject to license.