Legato? cdef? adef? apis? interfaces.h? Components? Applications? All these are strange terms for someone used to developing programs to run on a conventional Linux system.
Key Points
- "Legato" is a system that crosses between a host and target environments
- A Component is the basic element of a Legato Application and is described by the Component.cdef file
- Debug and Error output is always sent to the system log (syslogd)
- An ".adef" file is used to describe all the resources required to build a Legato Application
- Use the Legato build tools to construct your Application.
Overview
The key point to remember is that "Legato" is not just an application, but is an integrated system that contains:
- build tools that run on a host PC (Linux or Windows)
- target tools that run on the mangOH/WP85 platform
- an application framework that provides safe and secure access to modules integrated into the WP85 processor
- a management supervisor that simplifies control of your client application on the mangOH/WP85 platform
So what is a Legato Application?
At a very high level, a Legato application consists of the following elements:
- one or more source files to build a component;
- links to some external APIs;
- definition files to describe to the build tools how everything fits together
The ultimate output of the build process is an 'update' file - this is a bundle of all the files and configuration information that is uploaded to the mangOH/WP85 platform.
A more general diagram of the elements of a Legato application is presented below:

Components, .cdefs and source files
A Component is the basic 'container' for a Legato application. It contains the source files (in C, C++ or Java ), any additional files (such as audio or graphics files) required by the component.
Note:
Java is available as a development language from Legato 16.07.0 onwards. But this article will only concentrate on using C/C++ as the primary development languages.
Critically, if developing in C or C++, one source file must contain the Component constructor - called COMPONENT_INIT - which is the entry point to all the code in the Component. Note that unlike 'main()', COMPONENT_INIT must run to completion (and return) or the rest of your Application will not run.
Note:
A component doesn’t actually have a ‘main()’ function as it is actually built as a shared library (.so) that is managed by the Legato Supervisor on the target platform. But if it contains executable code it does need an entry point – so thinking of ‘COMPONENT_INIT’ as the equivalent of ‘main()’ is sort of OK. And as is the case of a standard program only having one ‘main()’, a Legato Component can only have one ‘COMPONENT_INIT’
It is a requirement to put all the files pertaining to a component into a separate subdirectory. Developer Studio uses the convention
In this article, the example application to flashes a led is called flashled
, and for clarity the component source files will be in a directory called flashledComponent
. The actual name is not important, but the directory name must be known as it is required by the .adef file to build the application correctly.
Component.cdef
Component.cdef (and it must be called 'Component.cdef') is the definition file that ties the Component together and describes to the build tools how to build the Component. Component.cdef is a plain text file easily editable by a normal text editor.
The Component.cdef file is built up of a number of sections that each describe various elements that make up the component. There are many other sections other than those described below that can be added to the Component.cdef file - see http://legato.io/legato-docs/latest/defFilesCdef.html for the canonical list and examples.
sources:
For a Component that is going to be 'executed' by an Application, the Component.cdef file must contain a 'sources:' section to describe the source files that are required to build the Component. Remember, if developing in C or C++, one of the source files must contain the COMPONENT_INIT Component constructor.
Note:
As of Legato 16.07.0 it’s possible to build Components that only contain resources such as libraries or audio files and are not executable. For the purposes of this article, it’s assumed that you’re building an Application that does something and in this case will require a ‘sources:’ section.
requires:
The 'requires:' section is similar to adding 'include' directories when compiling a conventional Linux application. But instead of include files, the 'requires:' section lists the 'Inter Process Communication' (IPC) APIs required by this Component to function. Each API can be a reference to a Legato framework API (these are usually name-spaced with a leading 'le_'), or can refer to your own or other third party APIs. By listing an API in the 'requires:' section, the build tools will expose the constants and functions of the API to your program (see also #include "interfaces.h", below).
Example Component.cdef
Below is an example Component.cdef file to support our flashledComponent:
/*
* sources section:
* list of source files required to build this component
* One file per line, case sensitive, including file extension
* One file MUST have the COMPONENT_INIT{ } definition (the main(){} equivalent)
*/
sources:
{
main.c
}
/*
* requires section:
* specify external 'things' this component requires from the external
* environment
*/
requires:
{
apis:
{
GPIO1 = le_gpio.api // create an instance of the le_gpio.api
// called GPIO1
}
}
Source Files
As with a normal Linux application, a Component can consist of multiple source files as required by the developer. The name (including extension) of each source file must be listed in the 'sources:' section of Component.cdef or it will not be included in the build. C and C++ source files should follow the naming conventions' for GCC (.c for C source files, .cc, cxx, .cpp or .c++ for C++ files).
Header files (.h, .hxx, .hpp etc) to share constants or function declarations between source files in a Component are also allowed, but header files are not to be listed in the 'sources:' section.
There is no requirement for a particular name for the source file that contains COMPONENT_INIT, although it is a good idea to follow a common naming convention across all your Components. By default, Developer Studio names the 'main' file of a Component after the name of the Component - so for the flashled example given above, the source containing COMPONENT_INIT would be called flashled.c, in the directory flashledComponent. But if you are more comfortable naming this source file 'main.c' or 'init.c' then this will cause no problems to the build tools - as long as the correct name is in the 'sources:' section of Component.cdef.
#include "legato.h"
Nearly every source file will require "legato.h" as an include file. This contains the commonly used Legato API header files and some standard system header files.
#include "interfaces.h"
The Legato build system generates a number of files and interfaces in the background to manage the IPC between Components and System services. These files are built from the 'requires:' section in the Component.cdef file (see above) and the Legato build system also builds an 'interfaces.h' header file to export system constants and function declarations to user source files.
If you have a 'requires:' section in your Component.cdef file, then you will be required to #include "interfaces.h" in your source files.
Sample source file (main.c) for Component.cdef above
#include "legato.h"
#include "interfaces.h" /* include auto-generated api interfaces from Component.cdef */
/*
* NOTE: GPIO1 is 'created' as an instance of le_gpio using requires: api:
* section in Component.cdef
*/
COMPONENT_INIT
{
le_result_t result = LE_OK;
LE_INFO( "Component Init" );
// configure GPIO - use WP85 pin GPIO25
// constant renamed from LE_GPIO_ACTIVE_HIGH via binding in adef
result = GPIO1_SetPushPullOutput( GPIO1_ACTIVE_HIGH, true );
if ( result != LE_OK )
{
LE_INFO("SetPushPullOutput returned [%d]", result );
}
// turn on GPIO (set 'high')
result = GPIO1_Activate();
if ( result != LE_OK )
{
LE_INFO( "GPIO1_Activate returns [%d:%s]",
result, LE_RESULT_TXT(result) );
}
}
Where's my debug output?
All standard and error output from a Legato application is redirected behind the scenes to the system logger (syslogd) - so even if you have a serial connection to the 'console' port you won't see any messages. There are two ways to see the system logger output:
- Using Developer Studio
The system log is available in Developer Studio in the 'Device Management' perspective under the 'Legato Console' tab at the bottom of the screen. The Legato Console tab also has some filtering capability to allow you to filter the output to only show log information from your application of interest.
- Using command line
After logging into the mangOH/WP85 platform, use the command 'logread -f' to continuously scroll the system log on the console. There is no native filtering capability, but the output can be paused by pressing <CTRL>S
and restarted by pressing <CTRL>Q
.
Note:
unlike a conventional Linux system, the syslog is not stored to disk, but instead uses a circular RAM buffer to store log information. The upshot of this is that:
- The log information does not survive across a power cycle or reboot
- The log space is limited and older entries will be overwritten in time
LE_INFO() and friends
The Legato framework introduces some custom log output macros such as LE_INFO(), LE_DEBUG() and others . These macros are designed to take the place of using printf() to output debug information to the system log.
The advantage of using LE_INFO() and friends is that the output can be controlled from the command line so that various levels of debug information can be controlled remotely from the console or other login method without having to rebuild the application.
For full information about LE_INFO() and friends and the Legato logging system, please see http://legato.io/legato-docs/latest/c_logging.html.
Applications and the adef file
A Legato Application consists of one (or more) Components, and links to the required Services files as 'require:'d in each Component.cdef file. The instructions for how to construct an Application is done using an '.adef' file.
As with the Component.cdef, an .adef file is a plain text file easily editable by a normal text editor.
By convention, each Application is in its own directory, and Components that are used by an Application are located in subdirectories underneath the Application directory. So for the example 'flashled' application referenced above, the entire application directory tree would look something like this:
/home/developer/workspace/
flashled/
flashled.adef
flashledComponent/
Component.cdef
main.c
Application.adef
Each application requires an adef file to describe all the resources required to build the Legato Application. Unlike the Component definition file, there is no requirement for a fixed name for the adef file - although the convention is to name the adef file after the name of the Application. As an example, the 'flashled' Application referred to above would have an adef filed named 'flashled.adef'.
Note:
The name of the adef file is used as the name of both the generated .update install file, and as the name of the application inside the Legato Supervisor on the mangOH/WP85 platform.
As with the Component.cdef file, the .adef file is built up of a number of sections that each describe the various resources required by the Application. As a minimum an .adef file requires at least an 'executables:' and 'processes:' sections, and if there are entries in the Component.cdef 'requires:' section then a 'bindings:' section will also be required.
There are many other sections that can be added to an .adef file, and each section has multiple options. The full list of sections and options for .adef files can be found here: http://legato.io/legato-docs/latest/defFilesAdef.html
executables:
The 'executables:' section defines a list of executable processes for the Application. In a typical Application there is only one executable as defined by the Component list, but in advanced Applications there can both be the same Component started more than once (with different names); or multiple different executables each configured in their own 'processes:' section.
A typical minimal 'executables:' section is as follows:
executables:
{
flashled = ( flashledComponent )
}
where:
- flashled is the target executable (name of the Application)
- flashledComponent is the Component that contains the source for the flashled executable
Each component listed as source for an executable will be linked into the executable and COMPONENT_INIT will be called for each component in the list.
processes:
The 'processes:' section describes the parameters for an executable defined in the 'executables:' section. There must be a separate 'processes:' section for each different executable as defined in the 'executables:' section.
At a minimum, a 'processes:' section must contain a 'run:' subsection that describes the executable (defined in the 'executables:' section) to be run when the Legato Supervisor on the mangOH/WP85 platform is commanded to start the Application.
A typical minimum 'processes:' section to run the flashled executable defined above is as follows:
processes:
{
run:
{
( flashled )
}
}
bindings:
If the 'requires:' section in a Component.cdef file is like adding include directories at the compile step when building a conventional Linux application, then the 'bindings:' section in the .adef file is like adding libraries to the link step.
For every API in the Component.cdef 'requires:' section, there must be a corresponding entry in the .adef 'bindings:' section. If there are no entries in the Component.cdef 'requires:' section (or the section is not present in the Component.cdef file) then the 'bindings:' section is not required in the .adef file.
Each entry in the 'bindings:' section is a key = value pair of the following format:
<executable>.<component>.<component_api> = service.service_api
Where:
- executable is the name of the executable as defined as a target in the 'executables:' section
- component is the name of the component as defined in the target sources list in the 'executables:' section
- component_api is the API as defined in the Component.cdef 'requires:' section
- service is the name of the 'Legato' framework service (or 'daemon' in Linux speak) that provides the desired API
- service_api is the name of the endpoint API that needs to be linked to the Component API. Note that this is usually but not always the same as component_api
Sample flashled.adef file
/*
* executables section
* define executable processes for this application
*/
executables:
{
flashled = ( flashledComponent )
}
/*
* processes section:
* describe to Legato Supervisor what processes to run when Application
* is started
*/
processes:
{
run:
{
( flashled )
}
}
/*
* bindings section:
* connect internal interfaces to external services
*/
bindings:
{
flashled.flashledComponent.GPIO1 -> gpioService.le_gpioPin25
}
So how does this all come together as an .update file
Well, that really depends on the development environment that you are using. Developer Studio will automate pretty much everything for you and 'automagically' work, whereas if you are working on the command line you may need to run a couple of commands to get things together.
No matter which tool you are using, underneath everything is the Legato toolkit and gcc cross compiler. The Legato tools take care of managing all the dependencies and the intricacies of cross-compiling so there's one less thing to worry about.
The official Legato 'Develop Apps' information is here: http://legato.io/legato-docs/latest/basicApps.html
There are some other getting started guides coming shortly on 'A little slice of mangOH' that will go into this in more detail.
FAQ
What's this 'sandbox' stuff all about?
Legato Applications have been designed to be as 'Secure by Default' as possible. To achieve this all Legato Applications run inside a secure 'sandbox' environment unless explicitly configured otherwise by the application developer. This means that a Legato Application cannot (by default) contact, corrupt or otherwise interfere with either other Legato Applications or the underlying Linux kernel and root file system.
This may become an issue for some applications that need direct access to particular hardware, and there is an option to 'un-sandbox' an Application by modifying the .adef file.
WARNING:
Unless you know what you are doing, running an Application un-sandboxed is probably a BAD thing!
For information on controlling the sandbox state of an Application, please see the Legato documentation here: http://legato.io/legato-docs/latest/defFilesAdef.html#defFilesAdef_sandboxed
How do I stop my application from starting automatically?
By default, a Legato Application is configured to start automatically after being uploaded to the mangOH/WP85 platform, or when the Legato Supervisor on the mangOH/WP85 platform starts. Sometimes this autostart behaviour is not desired - especially when debugging an application that is crashing.
To stop an Application from starting automatically, add the following line to the top of the Application .adef file:
start: manual
For more information on managing the startup state of an application, please see the Tip Controlling Application Startup and the Legato documentation here: http://legato.io/legato-docs/latest/defFilesAdef.html#defFilesAdef_start
Comments in definition files
It is possible to add comments to both the Component.cdef and Application.adef files. Comments take the form of 'C' comments:
/*
to start a (multiline) block comment*/
to end a (multiline) block comment//
for a single (to end of line) line comment