Differences between revisions 1 and 2
Revision 1 as of 2014-11-01 19:06:11
Size: 7660
Editor: bbb
Comment:
Revision 2 as of 2014-11-01 19:07:16
Size: 7661
Editor: bbb
Comment:
Deletions are marked like this. Additions are marked like this.
Line 152: Line 152:
 4. Add the target for `myapp`, like this: `myapp: ${obj-myapp}.  4. Add the target for `myapp`, like this: `myapp: ${obj-myapp}`.

Overview

liblitmus is the userspace library of LITMUSRT. When you compile liblitmus, a static library file named liblitmus.a is created. Userspace applications can and should link against this library like any other shared library.

When creating userspace test tools, it may be tempting to create new tools within the liblitmus repository. However, this is not recommended as it is difficult to maintain when newer liblitmus versions become available. Instead, project-specific userspace tools should be maintained in separate repositories and explicitly link against liblitmus.

To simplify this setup, liblitmus generates an include file (at $LIBLITMUS/inc/config.makefile) that is intended to be used in the Makefiles of projects that depend on liblitmus. The following tutorial shows how to use these include files.

Tutorial

In the following, we assume that you want to create a tool that depends on the LITMUSRT userspace interface.

The tutorial assumes that you have checked out and compiled liblitmus to a directory $DIR/liblitmus (where $DIR is arbitrary).

Step 1: Create a New Directory

Create a new directory in $DIR, say $DIR/mytools/, and create a sub-directory $DIR/mytools/src/.

$ cd $DIR
$ mkdir -p mytools/src

Step 2: Create a Source File

For testing purposes, we'll create a simple dummy app that links against liblitmus. To this end, create a file mytool.c in mytools/src with the following contents.

   1 #include <stdio.h>
   2 #include <stdlib.h>
   3 
   4 /* include the main liblitmus header */
   5 #include <litmus.h>
   6 
   7 
   8 int main(int argc, char** argv)
   9 {
  10         struct rt_task param;
  11         int ready_rt_tasks, all_rt_tasks;
  12 
  13         init_litmus();
  14         init_rt_task_param(&param);
  15 
  16         /* Normally you would configure the task here, enter real-time mode, and start
  17          * the real-time computation, but we'll simply call a liblitmus function and
  18          * quit here as the goal is simply to test whether we can successfully link
  19          * against liblitmus.
  20          */
  21 
  22         /* query the LITMUS^RT proc interface */
  23         if (!read_litmus_stats(&ready_rt_tasks, &all_rt_tasks)) {
  24                 perror("read_litmus_stats");
  25                 exit(1);
  26         }
  27 
  28         printf("There are %d real-time tasks waiting for a synchronous "
  29                 "task system release.\n", ready_rt_tasks);
  30         printf("There are %d real-time tasks in total.\n", all_rt_tasks);
  31 
  32         return 0;
  33 }

Step 3: Create a Makefile

Next, we'll setup the new project to link against liblitmus by reusing the build framework of liblitmus.

To this end, create a Makefile in mytools/ with the following contents.

   1 # ##############################################################################
   2 # User variables
   3 
   4 # user variables can be specified in the environment or in the local make.conf file
   5 -include make.conf
   6 
   7 # Where is the LITMUS^RT userspace library source tree?
   8 # By default, we assume that it resides in a sibling directory named 'liblitmus'.
   9 LIBLITMUS ?= ../liblitmus
  10 
  11 # Include default configuration from liblitmus.
  12 # IMPORTANT: Liblitmus must have been built before this file exists.
  13 include ${LIBLITMUS}/inc/config.makefile
  14 
  15 # all sources
  16 vpath %.c src/
  17 
  18 # local include files
  19 CPPFLAGS += -Iinclude/
  20 
  21 # ##############################################################################
  22 # Targets
  23 
  24 all = mytool
  25 
  26 .PHONY: all clean
  27 all: ${all}
  28 clean:
  29         rm -f ${all} *.o *.d
  30 
  31 obj-mytool = mytool.o
  32 mytool: ${obj-mytool}
  33 
  34 
  35 # dependency discovery
  36 include ${LIBLITMUS}/inc/depend.makefile
  37 

This completes the setup.

Testing

You should now be able to compile mytool and link against liblitmus, which should look similar to this.

$ make
/usr/bin/gcc         -O2 -Wall -Werror -g -Wdeclaration-after-statement -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -m64 -DARCH=x86_64 -I../liblitmus/include -I../liblitmus/arch/x86/include -I../liblitmus/arch/x86/include/uapi -I../liblitmus/arch/x86/include/generated/uapi -Iinclude/  -c -o mytool.o src/mytool.c
/usr/bin/gcc         -m64                  mytool.o  -L../liblitmus -llitmus -o mytool

You should now be able to run ./mytool.

$ file mytool
mytool: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

On a non-LITMUSRT kernel, you'll see a bunch of error messages because the task initialization fails.

$ ./mytool 
mlockall(): Cannot allocate memory
Warning: Could not initialize LITMUS^RT, mlockall() failed.
init_kernel_iface: cannot open LITMUS^RT control page (No such file or directory)
kernel <-> user space interface initialization: No such file or directory
Warning: Could not initialize LITMUS^RT, kernel <-> user space interface initialization failed.
read_litmus_stats: No such file or directory

On a LITMUSRT kernel, the tool should run without error messages if executed as root.

Adding Additional Build Targets

To add additional build targets, you can simply add them to the all list.

For example, suppose you wanted to add a second application called myapp, and further suppose that myapp also needs to link against librt (Linux's POSIX real-time library) to get access to clock_gettime(). This can be realized with the following steps:

  1. Add a target myapp to all. This should look now like:  all = mytool myapp

  2. Add -lrt to LDFLAGS, like this: LDFLAG += -lrt. It's important that you use += (and not =) to ensure that the settings of liblitmus are not removed.

  3. Add the list obj-myapp to list all object files needed for myapp. For example: obj-myapp = myapp.o if there is a file mytools/src/myapp.c

  4. Add the target for myapp, like this: myapp: ${obj-myapp}.

As a result, the Makefile should now look as follows.

   1 [...]
   2 # ##############################################################################
   3 # Targets
   4 
   5 all = mytool myapp
   6 
   7 LDFLAGS += -lrt
   8 
   9 .PHONY: all clean
  10 all: ${all}
  11 clean:
  12         rm -f ${all} *.o *.d
  13 
  14 obj-mytool = mytool.o
  15 mytool: ${obj-mytool}
  16 
  17 obj-myapp = myapp.o
  18 myapp: ${obj-myapp}
  19 
  20 [...]

Cleanup

The makefile automatically includes a clean target to remove all build products.

$ make clean
rm -f mytool myapp *.o *.d

Discussion

The method described in this tutorial is the preferred way to link against liblitmus, as it prevents the accumulation of cruft in liblitmus. Even though liblitmus already contains a bunch of tools in bin/, it should not accumulate further project-specific tools and applications. Further, it ensures that clients of liblitus are compiled with compatible flags.

If you use a cross-compiler to build liblitmus (e.g., to build binaries for an ARM target), then any project using /inc/config.makefile will by default also be built using the cross-compiler. In our experience, this simplifies cross-compilation setups considerably.

Optionally including the local file make.conf (which doesn't have to exist) makes it possible include local settings that are never committed to git. It's not strictly needed, but if you plan on collaborating with others (who, for example, might have checked out liblitmus at a different path), this is a useful feature and we recommend that you always provide this functionality in LITMUSRT-related Makefiles.

LinkAgainstLiblitmusTutorial (last edited 2014-11-01 19:18:47 by bbb)