Toolchain


#1

How can I use the standart Linux toolchain to compile the source… I’d love to use the Legato as an API support… NO COMPONENT_INIT will be needed and my own main will have to be started…


#2

Here are some instructions on how to take a legacy program, with its own main(), and get it going on the WP7. These instructions should apply to other Legato modules too.

I have broken it into several stages, beginning with the most basic cross-compiling and copying onto the target.

NOTE: printf() output will go to /dev/console, so it will appear on your UART console. The on-target command-line used in the examples below is the UART console.

We plan to add this documentation and some complete working samples to the framework in the next release (15.04).

Cheers,

–Jen

===================================================================

To make a legacy app executable on target, simply build it using the cross tool chain provided.

$ /opt/swi/y16-ext/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc -o legacyProgram main.c $ 

You can copy it onto the target using a tool like scp.

$ scp legacyProgram 192.168.1.2:
legacyProgram                                100% 9366     9.2KB/s   00:00
$ 

Then run it from the target command-line.

root@swi-mdm9x15:~# ./legacyProgram
Hello world.
root@swi-mdm9x15:~# 

===================================================================

To make use of the application life cycle management tools that we provide, create a simple .adef file that bundles the cross-compiled executable into an application.

legacyProgram.adef:

// Disable the sandbox security to make things a little easier.
sandboxed: false

// Put the cross-compiled legacy program in the app's bin directory.
// [x] = make it executable.
bundles:
{
    file:
    {
        [x] legacyProgram /bin/
    }
}

// Tell the Supervisor to start this program when the application is started.
processes:
{
    run:
    {
        ( legacyProgram )
    }
}

Then you can run mkapp to generate an application bundle for your target.

$ mkapp -t wp7 legacyProgram.adef
$ 

This can be installed on the target using instapp.

$ instapp legacyProgram.wp7
Installing application 'legacyProgram' from file 'legacyProgram.wp7'.
Installing app 'legacyProgram'...
Created user 'applegacyProgram' (uid 1011, gid 1011).
DONE
$ 

From the target’s command line, use app start to run the program.

root@swi-mdm9x15:~# app start legacyProgram Starting app 'legacyProgram'...
Hello world.
DONE
root@swi-mdm9x15:~# 

===================================================================

To use a Legato modem service API, such as the “le_info” API, you need to do a few things:

  1. #include “legato.h” and “interfaces.h”.

  2. Connect to the service by calling le_info_ConnectService(). At runtime, if the “le_info” service is not up, this will block until it comes up. In the meantime, you will see your app in the “WAITING CLIENTS” list if you run sdir list.

  3. Add a call to one of the “le_info” API functions, such as le_info_GetDeviceModel().

  4. Create a “stand-alone” Legato component that “requires” the “le_info” API.

api_client/Component.cdef:

requires:
{
    api:
    {
        le_info.api
    }
}
  1. Build the component using mkcomp --stand-alone.
$ mkcomp --stand-alone -t wp7 -i $LEGATO_ROOT/interfaces/modemServices api_client
  1. Compile and link your executable with the header files and library generated by mkcomp.
$ export CC=/opt/swi/y16-ext/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc
$ $CC -c main.c -I_build -I$LEGATO_ROOT/framework/c/inc
$ $CC -o legacyProgram main.o libIF_le_info_client.so -L$LEGATO_ROOT/build/wp7/bin/lib -llegato
  1. Update your .adef file to bundle into your app the libraries generated by mkcomp.
bundles:
{
    file:
    {
        [x] legacyProgram /bin/
        [r] libIF_le_info_client.so /lib/
    }
}
  1. Specify which instance of the “le_info” service your app should use (and implicitly grant permission to use it) by adding a “binding” to your .adef file.
bindings:
{
    *.le_info -> modemService.le_info
}
  1. Re-generate your application bundle and install it on target.
$ mkapp -t wp7 legacyProgram.adef
$ instapp legacyProgram.wp7 192.168.1.2
Installing application 'legacyProgram' from file 'legacyProgram.wp7'.
Removing app 'legacyProgram'...
Deleted user 'applegacyProgram'.
Installing app 'legacyProgram'...
Created user 'applegacyProgram' (uid 1011, gid 1011).
DONE
$ 

===================================================================

Adding a second or subsequent API is simpler.

  1. Add the API to the list “required” by your “stand-alone” component.

api_client/Component.cdef:

requires:
{
    api:
    {
        le_info.api
        le_data.api
    }
}
  1. Build the component using mkcomp --stand-alone.
$ mkcomp --stand-alone -t wp7 -i $LEGATO_ROOT/interfaces/modemServices -i $LEGATO_ROOT/interfaces/dataConnectionService api_client
  1. Compile and link your executable with the header files and library generated by mkcomp.
$ export CC=/opt/swi/y16-ext/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc
$ $CC -c main.c -I_build -I$LEGATO_ROOT/framework/c/inc
$ $CC -o legacyProgram main.o libIF_le_info_client.so libIF_le_data_client.so -L$LEGATO_ROOT/build/wp7/bin/lib -llegato
  1. Update your .adef file to bundle into your app the additional library generated by mkcomp.
bundles:
{
    file:
    {
        [x] legacyProgram /bin/
        [r] libIF_le_info_client.so /lib/
        [r] libIF_le_data_client.so /lib/
    }
}
  1. Specify which instance of the new service your app should use (and implicitly grant permission to use it) by adding a “binding” to your .adef file.
bindings:
{
    *.le_info -> modemService.le_info
    *.le_data -> dataConnectionService.le_data
}
  1. Re-generate your application bundle and install it on target.
$ mkapp -t wp7 legacyProgram.adef
$ instapp legacyProgram.wp7 192.168.1.2
Installing application 'legacyProgram' from file 'legacyProgram.wp7'.
Removing app 'legacyProgram'...
Deleted user 'applegacyProgram'.
Installing app 'legacyProgram'...
Created user 'applegacyProgram' (uid 1011, gid 1011).
DONE
$ 

===================================================================

If you need to handle asynchronous callbacks (aka “handlers”), you need le_event_GetFd() and le_event_ServiceLoop().

They are documented under the heading “Integrating with Legacy POSIX Code” under the Legato C Runtime Library’s “Event Loop API” page in the Legato framework documentation (legato.io/legato-docs/15_01_ … egacyPosix).

Here’s an example:

// Register a callback function to be called when an SMS arrives.
le_sms_AddRxMessageHandler(MySmsRxHandlerFunc, NULL);

// Get the Legato event loop "readyness" file descriptor and put it in a pollfd struct
// configured to detect "ready to read".
struct pollfd pollControl;
pollControl.fd = le_event_GetFd();
pollControl.events = POLLIN;

while (true)
{
    // Block until the file descriptor is "ready to read".
    int result = poll(&pollControl, 1, -1);

    if (result > 0)
    {
        // The Legato event loop needs servicing. Keep servicing it until there's nothing left.
        while (le_event_ServiceLoop() == LE_OK)
        {
            /* le_event_ServiceLoop() has more to do.  Need to call it again. */
        }
    }
    else
    {
        LE_FATAL("poll() failed with errno %m.");
    }
}

#3

Note: If you are running your app unsandboxed and trying to use libraries that you have bundled into your app, you may need to set the LD_LIBRARY_PATH environment variable so your executable can find those libraries.

Your app is installed under “/opt/legato/apps/appName”, so if you bundled a library “libfoo.so” under “/lib” inside your app, then it will appear to an unsandboxed app as “/opt/legato/apps/appName/lib/libfoo.so”.

legacyProgram.adef:

sandboxed: false

bundles:
{
    file:
    {
        [x] legacyProgram /bin/
        [r] libIF_le_info_client.so /lib/
        [r] libIF_le_data_client.so /lib/
    }
}

processes:
{
    envVars:
    {
        LD_LIBRARY_PATH = /opt/legato/apps/legacyProgram/lib
    }

    run:
    {
        ( legacyProgram )
    }
}

bindings:
{
    *.le_info -> modemService.le_info
    *.le_data -> dataConnectionService.le_data
}

But, if you are running sandboxed, “/lib” inside your sandbox will automatically be in your library search path, so you won’t need to set LD_LIBRARY_PATH if you put your libraries in your sandboxed app’s “/lib” directory.