System Definition .sdef

This topic provides details about Legato's System Definition files.

See Manage Sandboxes and Security for details on how to Sandbox Config Sample and understand app and process limits.

.sdef files can contain these sections:

apps

An apps: section declares one or more apps to be deployed to the target system.

apps:
{
webserver
}

This looks for an app definition file called webserver.adef and includes it in the system. You can also optionally include the .adef extension.

Alternatively you can include the full path and adef extension on the declaration and bypass the app search paths.

apps:
{
/full/path/to/my/app/webserver.adef
}

In addition to including applications in source for to your system builds. You can also add binary application packages.

Binary app packages are apps distributed without their source code. You include these apps in your .sdef file apps: section just like .adef files.

apps:
{
webserver.wp85.app
}

Binary app files are named for the target architecture they are built against. This way it's hard to mix up builds for incompatible target architectures. The same pathing and search rules apply to binary apps as do for .adef files.

The apps: section can override limits and other app settings.

Here's a code sample to deploy a web server limiting its share of the CPU under heavy load to 500 (see cpuShare):

apps:
{
webServer
{
cpuShare: 500
}
}

Any of the following subsections can be used in an .sdef apps: section, and will override the .adef setting for all processes in that app:

maxPriority

interfaceSearch

This section is used to specify directories in which mksys should look for interface files, such as .api files and .h files, when building components in the system.

interfaceSearch:
{
    $LEGATO_ROOT/interfaces/modemServices   // Dir containing Legato modem services APIs.

    interfaces  // Dir containing custom interfaces belonging to this system.
}

To allow components to be relocated in the build host file system, components should not specify interface file search paths outside of their own directories. But, to truly separate interfaces from implementation, interfaces should be kept outside of components. This can be accomplished by adding interface search directory paths to the interfaceSearch section in the .sdef file.

Note
mksys command-line arguments (-i or --interface-search) could also be used to solve this problem, but that forces the developer to use a build script to launch mksys (so they don't have to remember all the right interface directory paths and type them on the command line each time they run mksys).

maxPriority

Sets the maximum priority level the app it permitted to use.

Acts as a ceiling only. Lowers the priority level if an app would otherwise be allowed to use a higher priority. It won't raise the priority level for any processes in the app.

Here's a code sample where a process in the app's .adef is configured to start at high priority, and the .sdef section for that app has maxPriority set to medium so the process will start at medium priority.

apps:
{
foo
{
maxPriority: high
}
}

Another process in the same .adef configured to start at low priority will still start at low priority.

preloaded

Indicates whether or not an app must be preloaded onto the target device separately from the rest of the system.

If you are not sure whether or not you need this feature, you probably don't. Use of this feature is intended for very specific use cases. It is encouraged that delta updates of systems be used instead, whenever practical.

The legato AF supports being installed in a read-only partition, mounted as /mnt/legato in the target file system. Writeable files will be kept in another file system mounted as /legato in the target file system.

If the read-only partition must be updated, but there are other (possibly very large) apps in the writeable file system, it may be impossible to deliver an update containing the apps over-the-air at the same time that the read-only partition is updated.

Usually, the read-only partition does not need to be updated, but in some cases, it may be desireable, and this feature can help.

For example, a customer has a giant app containing pictures and audio files. In the factory, the framework and a few apps are loaded into the read-only /mnt/legato, and other apps, including the huge app, are installed in the writeable /legato. Later, when the device is in the field, a change needs to be made to both the modem firmware and the Legato framework, and must be delivered together, as a single FOTA (firmware over the air) update. A new system is built using mksys. But, the resulting system update file is too large to fit in the FOTA update image (and likely very expensive to deliver over the air to hundreds of thousands of devices). Fortunately, the audio files don't need to be updated at the same time, and the audio app can be marked "preloaded" in the .sdef file to exclude it from the system update file. After the FOTA update, the new system will use the audio file that already exists on the target's writeable file system.

apps:
{
modemService
audioService
dataConnectionService
controller
userInterface { preloaded: true }
}

After you have built the new system, verify that the app that was marked "preloaded" in the .sdef file has the same MD5 hash as the app that is actually installed on the target. You can do this by comparing the contents of the symlink in /legato/systems/current/apps/ on the target with the contents of the symlink in the staging/apps/ directory of the system's build directory on the build host.

$ ssh root@192.168.2.2 'readlink /legato/systems/current/apps/userInterface'
/legato/apps/a60357d912ff3b4b28e080580b34fff3
$ readlink build/wp85/system/staging/apps/userInterface
/legato/apps/a60357d912ff3b4b28e080580b34fff3

If these are different, then something has changed that has resulted in the built version of your app to be different in the context of your new system. If you continue to install your new system on the target, the "preloaded" app will not start. But, if you find yourself in this situation, and you are absolutely certain that the version of the preloaded app that is on your target is still compatible with the new system you are about to install, and you can't afford to install the new version of your app, then you have another option: Change the "true" in your "preloaded: true" statement in your .sdef file to the MD5 hash of the old version of the app installed on your target.

apps:
{
modemService
audioService
dataConnectionService
controller
userInterface { preloaded: a60357d912ff3b4b28e080580b34fff3 }
}

bindings

Lists IPC bindings that connect apps’ external IPC interfaces. They're listed in the extern section of their .adef files. Each binding connects one client-side interface to one server-side interface.

Interfaces use the app name and the interface name, separated by a period (‘.’). The two bound-together interfaces are separated by an arrow ("->").

For example,

apps:
{
vavController
thermostat
airHandlerProxy
}
 
bindings:
{
// Connect the VAV controller to the thermostat
vavController.temp -> thermostat.temp
vavController.setpoint -> thermostat.setpoint
 
// Connect the VAV controller to the supply air duct temperature sensor
vavController.ductTemp -> ductTemperatureSensor.temp
 
// Hook up the VAV control outputs to the damper actuators.
vavController.supplyDamper -> supplyAirDamper.damper
vavController.returnDamper -> returnAirDamper.damper
 
// Use a network proxy to request duct temperature changes from the Air Handling Unit.
vavController.airHandler -> airHandlerProxy.airHandler
}

For security reasons, binding between apps is never performed unless explicitly specified in the .sdef or .adef files.

buildVars

Build environment variables can be defined inside the .sdef file using "buildVars:" sections. This will define variables in the build tools' process environment at build time.

buildVars:
{
    PRODUCT_VERSION = "0.2.3 - beta"
    HARDWARE_REV = 4
    DEBUG = 1
}

These are defined using "name = value" pairs, where the value can be a quoted string and may contain the values of other environment variables that were previously defined.

All buildVars: sections will be evaluated before processing any other sections. So, even if a buildVars: section appears after another section that uses it, the variables will be available in that other section.

Note
This is necessary to allow the sharing of components between apps. If two apps contained the same component, but each app were built with a different set of environment variables, it would be hard to tell which set of environment variables were used to build the shared component, and the component may behave in an unexpected way for one of the apps.
apps:
{
    $APP_PATH
}

buildVars:
{
    APP_PATH = path/to/app
}

Within the buildVars: sections, the order of the definitions matters.

buildVars:
{
    X = foo  // X is now "foo"

    X = bar  // X has been changed to "bar"

    X = foo${X}  // X has been changed to "foobar"

    X = "$X baz" // X has been changed to "foobar baz"
}

cflags

Provides a way to specify command-line arguments to pass to the compiler when compiling C source code files. These flags will be added to the flags specified on the command-line and in other definition files.

Flags are separated by whitespace.

cflags:
{
-g -O0
-DDEBUG=1
}

cxxflags

Provides a way to specify command-line arguments to pass to the compiler when compiling C++ source code files. These flags will be added to the flags specified on the command-line and in other definition files.

Flags are separated by whitespace.

cxxflags:
{
-std=c++0x
-g -O0
}

ldflags

Linker flags provide a way to specify command-line arguments to pass to the compiler when linking C/C++ object (.o) files together into a component shared library (.so) file. These flags will be added to the flags specified on the command-line and in other definition files.

Flags are separated by whitespace.

ldflags:
{
-Lfoo/bar
}

kernelModules

The optional kernelModules: section declares a list of pre-built kernel modules to be bundled and installed with Legato.

Each entry represents a path to the .mdef definition file that describes how the module is installed on the target.

This code sample shows the section declaring the "/path/to/kernel/module/hello.mdef" be bundled with Legato:

kernelModules:
{
/path/to/kernel/module/hello
}

commands

To make a command-line tool available to a root user who is logged-in to a shell on a target device tty (e.g., through secure shell [ssh] or a serial console):

  1. Build an app containing the executable.
  2. Add the executable to the "commands:" section of the .sdef file.

Each entry in the commands section looks like this:

commandName = appName:/path/to/exe

The path to the executable must be an absolute path within the application's read-only installed files. For example, if the executable is a script that was bundled into the app "myApp" to appear at "/usr/share/exe" inside the myApp's sandbox at runtime, then the command would be specified as

commandName = myApp:/usr/share/exe

If the executable is built using an "executables" section in a .adef file, then the executable will appear in the app's bin directory. For example,

apps:
{
myTools // This app's .adef builds an exe called "led" that can be used to turn LEDs on and off.
}
 
commands:
{
led = myTools:/bin/led // When I login via ssh, I can run "led 1 on" to turn on LED 1.
}
Warning
When the command runs, it runs with the full privileges of the user that runs it. If you login as root and run a command, the command executes with root user privileges.