Home · All Classes · Main Classes · Deprecated

How to write launchable applications

Launcher enables starting up various types of applications very fast. Launcher uses different booster for each of the application types. This page concentrates on launching MeeGo Touch applications with the MeeGo Touch booster, but also other boosters are briefly introduced at the bottom of the page.

Introduction

In order to be started up with the launcher, an application needs to

In the following we will explain how the launcher works and then explain how to fulfill the requirements above.

How the launcher works

Applauncherd daemon helps launching applications faster by two means. First, it preloads a number of libraries, including MeeGo Touch and Qt libraries. This allows faster loading of application binaries when needed. Second, it initializes certain components before an application is loaded and makes the results available to applications when they start.

More technically, applauncherd forks a will-be-application process, a.k.a booster, before knowing which application is going to be launched next. Booster processes do application-type specific initializations. For instance, the MeeGo Touch booster instantiates MApplication and MApplicationWindow objects and stores them to MComponentCache. Then the booster process waits for a connection from the invoker.

An application is invoked with the invoker. The invoker sends the booster process the name and location of the application binary and data on its running environment. This triggers the booster process to load the binary, to initialize its environment, and finally to call the main() function in the binary.

Boosted MeeGo Touch applications pick up and use the already instantiated MApplication and MApplicationWindow objects from MComponentCache instead of creating new ones.

Source code modifications

MApplication instance must be taken from the MComponentCache. It is recommended to take MApplicationWindow from the cache as well. That is, the main program should have:

MApplication* application = MComponentCache::mApplication(argc, argv);
MApplicationWindow* window = MComponentCache::mApplicationWindow();

Note that applications that use MComponentCache can be run without the launcher/invoker as well. In that case MComponentCache will instantiate new MApplication and MApplicationWindow objects on the fly.

The launcher needs to find the symbol main in an application binary in order to start executing the application. However, unnecessary symbols in the application binary cause unnecessary overhead, so the recommended flags for compiling for the launcher make symbols hidden by default. When the flags are used, the main function must be explicitly exported. It can be done as follows:

#include <MExport>

M_EXPORT int main(int argc, char **argv)
{
...
}

Compilation and Linking

Binaries intended to be run with applauncherd should be compiled with -fPIC option to produce position independent code. In order to produce a position independent executable, -pie option and -rdynamic options can be used in linking. This allows the result to be executed both traditionally and with the invoker.

To improve linking and load times of shared object libraries the size of dynamic export table it is encouraged to hide the unnecessary symbols from the resulting binary by using -fvisibility=hidden and -fvisibility-inlines-hidden flags in compilation as well.

Building with QMake

The preferred way

Once you have installed the libmeegotouch-dev package, you can simply use QMake configuration option meegotouch-boostable:

CONFIG += meegotouch-boostable

This tells qmake to use the meegotouch-boostable feature, which includes the meegotouch feature and ultimately uses pkg-config for the flags. Unfortunately qmake does not complain if you add the line but have not installed libmeegotouch-dev, so if the QMake magic does not seem to work, double check that the package is indeed installed.

The pkg-config way

You can also use pkg-config to get the correct flags:

QMAKE_CXXFLAGS += `pkg-config --cflags meegotouch-boostable`
QMAKE_LFLAGS += `pkg-config --libs meegotouch-boostable`

If libmeegotouch-dev is not installed, pkg-config will complain when you run make.

The last resort

It's also possible to manually define the following variables in the .pro file:

QMAKE_CXXFLAGS += -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
QMAKE_LFLAGS += -pie -rdynamic

It is then up to you to modify the .pro file if there are changes to the required compiler and linker flags.

Building with CMake

You can utilize pkg-config in CMake by including FindPkgConfig in CMakeLists.txt:

include(FindPkgConfig) 

To obtain the compiler and linker flags, add the following lines:

pkg_check_modules(MEEGOTOUCH_BOOSTABLE REQUIRED meegotouch-boostable)
add_definitions(${MEEGOTOUCH_BOOSTABLE_CFLAGS})
link_libraries(${MEEGOTOUCH_BOOSTABLE_LDFLAGS})

In order to install the application binary with a .launch filename extension, use the following line:

install(PROGRAMS myapplication DESTINATION /usr/bin RENAME myapplication.launch)

If you do not want to use pkg-config for some reason, you can manually add the compiler and linker flags like this:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -fvisibility-inlines-hidden")
set(CMAKE_EXE_LINKER_FLAGS "-pie -rdynamic")

Again, this requires you to update the flags if something changes.

Obtaining flags with pkg-config

The package libmeegotouch-dev provides the necessary files for pkg-config to get the appropriate compiler and linker flags. To get the compiler flags, use

pkg-config --cflags meegotouch-boostable

and to get the linker flags use

pkg-config --libs meegotouch-boostable

Running boosted application

Check that applauncherd package is installed and applancherd daemon is running. You can now run your application as usual like /usr/bin/application_binary, or use the mboosted launching by running:

invoker --type=m /usr/bin/application_binary

Debugging

In order to debug launched application, the debugger must be attached to already running booster process. For instance, first run

gdb /usr/bin/applauncherd.bin $(pgrep booster-m)

then set a breakpoint to the application code and let the process continue to that point

(gdb) break main.cpp:42
No source file named main.cpp.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (main.cpp:42) pending.
(gdb) c
Continuing.

Finally invoke the application with the booster to which the debugger is attached to

invoker --type=m /usr/bin/application_binary

PIE binaries and debugging

Using pkg-config when building your binaries makes them linked with the -pie flag. The -pie flag makes your binaries position independent executables. This means that the executables can be either used as a normal shared library or run from e.g. the command line.

This creates problems when debugging your application with gdb older than version 7.1 which introduced the support for PIE binaries.

The solution when using gdb 7.0 or earlier is to link your binaries as libraries i.e. using -shared instead of -pie. After this, you can't execute your binaries directly, you have to use invoker.

Setting correct linker flags with QMake:

QMAKE_CXXFLAGS += -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
QMAKE_LFLAGS += -shared -rdynamic

Remember to remove the CONFIG += meegotouch-boostable, if used.

Packaging and distributing

It is recommended to rename application binary to <application_name>.launch and replace original binary by a script that executes invoker with correct application type and the name of application binary as a parameter. Launch script example for typical application is:

#!/bin/sh
exec /usr/bin/invoker --type=m $0.launch "$@"

Note that even if the binary is renamed to <application_name>.launch, application identifier does not change (optional parameter of MComponentCache::mApplication).

.desktop and D-Bus .service files can be modified so that instead of normal execution there is

Exec=/usr/bin/invoker --delay <seconds> --type=m /usr/bin/<application_name>.launch

Note 1: when launching through D-Bus, it is important to add enough delay to invoker so that it won't exit before the launched application gets its D-Bus service registered. Otherwise D-Bus daemon may think that the application just died. Another option is to use --wait-term which forces invoker to wait until the launched application exits.

Note 2: There is a slight difference in application startup time if using script instead of the actual binary in Exec-field of .desktop and .service files. Therefore it is recommended always use the actual invoker call with the binary name as presented above.

Note 3: When .desktop file contains X-Maemo-Service -field application will be started by default through D-Bus. This might cause some delay for application startup time. Therefore it is recommended not to have X-Maemo-Service -field inside .desktop files with launched applications, unless it is really needed for some other reason.

Application packages that use the launcher depend on the applauncherd package.

Platform security

If an application does not have an aegis manifest file, no actions are needed for platform security.

If an application has a manifest file, an addition needs to be made there: everything that is requested for the application binary must be requested to the application launcher binary as well.

For instance, manifest file for an application that needs only an automatically generated application ID:

<aegis>
  <request>
    <for path="/usr/bin/application_name.launch" />
    <for path="applauncherd-launcher::/usr/bin/applauncherd.bin" id="" />
  </request>
</aegis>

If an application has a user-defined ID:

<aegis>
  <request>
    <for path="/usr/bin/application_name.launch" id="myownid" />
    <for path="applauncherd-launcher::/usr/bin/applauncherd.bin" id="myownid" />
  </request>
</aegis>

Finally, if an application has some security tokens:

<aegis>
  <request>
    <credential name="GlobalToken" />
    <credential name="OwnToken" />
    <credential name="package::OtherToken" />
    <for path="/usr/bin/application_name.launch" />
    <for path="applauncherd-launcher::/usr/bin/applauncherd.bin" id="" />
  </request>
</aegis>

Limitations and known issues

Issues with command line arguments

Current launcher implementation does not support following Qt and MeeGo Touch command line options (see QApplication and MApplication docs for more information about command options usage):

QCoreApplication::arguments() returns a QStringList that containing at most 32 arguments and drops the rest. The full list of arguments is accessible through argc and argv. They can be converted into QStringList similar to returned by QCoreApplication::arguments() as follows:

M_EXPORT int main(int argc, char **argv) {
    QStringList arguments;
    for (int a = 0; a < argc; ++a) {
        arguments << QString::fromLocal8Bit(argv[a]);
    }
    ...

Issues with scripts, D-Bus, and process monitoring

By default, invoker processes terminate before or right after booster processes have called main(). This may confuse shell scripts and process monitoring in D-Bus daemon and Upstart, for instance. To help solving these issues invoker accepts parameters

Sample MeeGo Touch launchable application

#include <MApplication>
#include <MApplicationPage>
#include <MApplicationWindow>
#include <MComponentCache>
#include <MExport>

M_EXPORT int main(int argc, char ** argv)
{
    MApplication *app = MComponentCache::mApplication(argc, argv);
    MApplicationWindow* window = MComponentCache::mApplicationWindow();
    MApplicationPage mainPage;

    window->show();

    mainPage.setTitle("Hello World! (Now supports Launcher)");
    mainPage.appear();
  
    return app->exec();
}

Other boosters

Warning: behavior of these boosters is subject to change.

Qt booster is a no-operation booster. It can be used by calling invoker --type=qt. Qt booster requires only the M_EXPORT source modification. Any MeeGo Touch boostable application can be launched with this booster type as well, but it will result in a slower start up because of empty cache.

Wrt booster, used with invoker --type=wrt, populates MComponentCache with MApplication and MApplicationWindow, just like the MeeGo Touch booster. However, in this case MApplication uses a graphics system which suits better for rendering web content.


Copyright © 2010 Nokia Corporation Generated on Thu Nov 4 2010 18:14:23 (PDT)
Doxygen 1.7.1
MeeGo Touch