Create Apps
These are the basic steps to build an app written in C that logs Hello World.
when the process it's in starts up:
Then you're ready for the next level: Add Things, Use IPC, and Deploy Multiple Components.
Sample Directories and Files
Typical apps have directories and files that look this:
helloWorld/ ├── helloComp │ ├── Component.cdef │ └── hello.c └── helloWorld.adef
Create Component
Complete these steps to create a component: Create Directory, Create C Source File, and Create cdef File
Create Directory
1
. Create a directory: the directory name will become the component name:
$ mkdir helloComp
Create C Source File
2
. Create source (implementation) file hello.c:
$ gedit helloComp/hello.c
It should contain the following:
#include "legato.h"{LE_INFO("Hello world.\n");}
This looks similar to the original C hello
, world program from Kernighan's and Richie's "The C Programming Language", except that:
- #include <stdio.h> is replaced with #include "legato.h"
- main() is replaced with COMPONENT_INIT
In fact, legato.h will include stdio.h, along with a bunch of other system headers and Legato framework headers. This reduces the amount of time you have to spend including header files to get access to the functions and data types you need.
The build tools figure out what language the source code is written in by looking at the filename extension. So, because our file hello.c
ends in .c, the build tools will try to use a C compiler to compile it into a library when it gets included in an executable.
Component Initializer
The COMPONENT_INIT
macro is used to identify your component initializer. Every component must have a component initializer.
By using component initializers instead of having each component implement their own main() function, it's possible to run multiple components in the same executable and even share a thread between those components.
The main process thread (the main() function auto-generated by the build tools) will automatically call the component's initializer at the appropriate time during the process start-up sequence (based on the inter-dependencies between components). If component A is used by component B, then component A's initializer will be run before component B's initializer. Then component B can safely call the API functions of component A knowing that component A has already been initialized. This won't work if both components depend on each other (directly or indirectly through other components). That's one reason why dependency loops are not permitted between components. The framework will detect inter-component dependency loops at build time and terminate the build.
Component initializers don't take any parameters and don't return anything, but they must always return . Unless they experience a fatal error, in which case they must terminate the process with a non-zero exit code (which can be done using LE_FATAL()
, LE_ASSERT()
, etc. ).
- Note
- If a component's initializer doesn't return, the process will not be able to finish initializing all the components that have been deployed to it and the process's main thread will never process any events that are queued to it.
In our "Hello World" example, we just use our component initializer to print Hello
world to the log using LE_INFO()
.
Create cdef File
3
. Create a cdef
file called Component.cdef
like this:
$ gedit helloComp/Component.cdef
sources:{hello.c}
See Definition Files for complete info.
Create App
You need to create an adef
file before you can build you app.
4
. Create an adef
file called helloWorld.adef
like this:
executables:{helloWorld = ( helloComp )}processes:{run:{(helloWorld)}}
This defines one executable called helloWorld
implemented by helloComp
and then starts one instance of the helloWorld executable.
If your executable has multiple components, add more components inside the parentheses after the executable name: "helloWorld = ( helloComp foo bar )".
Build App
5
. Run mkapp
to build the executable and bundle it into an app:
Use the -t
option to build for a target other than the default "localhost" target.
This is how to build the helloWorld app to install on the Sierra Wireless WP85 module:
$ mkapp -t wp85 helloWorld.adef
- Note
- If you're building an AR7, substitute
ar7
in the mkapp run command.
Install App to Target
6
. Use instapp
to install the app on your target:
$ instapp helloWorld.wp85.update <ip addr>
The second argument is the target device's IP address where to install the app. This will connect to the target and install the app.
Usage
These usage tips are based on running a secure shell (SSH) to interface with the target. See mangoh.io if you need to setup your target device.
Target Login
Login to your target using a secure shell connection:
$ ssh root@192.168.2.2
Target Start App
Start your application using the app start
command:
$ app start helloWorld
View Logs
Your installed app's LE_INFO
log message will appear in the system log ("syslog") on the target device.
Run logread
(on the target) to view the system log.
# logread
Use logread's -f option to start monitoring the logs and display messages as they are logged.
# logread -f
Here's a code sample accessing the logs on a target device with IP address 192.168.2.2 through an ssh connection:
$ ssh root@192.168.2.2 '/sbin/logread -f'
Remove App
From the host PC, run rmapp
to uninstall the app:
$ rmapp helloWorld.wp85 <ip addr>
From the target run:
# app remove <app name>
List App
Use lsapp
to list the apps installed on a target.
$ lsapp <ip addr>
Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.