L4Re Support

The L4Re build system is based on Makefiles, and the mk directory within the idl4re software distribution contains a collection of make-compatible files that integrate the idl tool and interface files with the L4Re build system so that the tool is invoked automatically when necessary.

  1. Basic Makefile Structure
  2. Interface-Related Settings
  3. Filename Transformations
  4. Interface Definitions

To write or adapt a package Makefile, some additional definitions and statements are needed to introduce the additional processing steps that take interface descriptions and generate source code from them when needed.

processingInterface:file.idlGenerated sources:file_server.cfile_client.c...idlOutput programExisting sources

This document describes the form a package Makefile should take and introduces the required elements to integrate interface code generation into the package build process.

Basic Makefile Structure

The general form of a suitable Makefile employing interface generation follows that broadly used within L4Re, with a top-level package employing the following definitions:

PKGDIR ?= .
L4DIR  ?= $(PKGDIR)/../..

Appropriate target and build mode definitions may be specified. For example, for a program:

TARGET = myserver
MODE   = shared

For a library:

TARGET = libserver.a libserver.so

Various locations and the inclusion of some rules are useful to define at this point:

IDL_DIR         = $(L4DIR)/pkg/libsystypes/idl
IDL_MK_DIR      = $(L4DIR)/idl4re/mk
IDL_BUILD_DIR   = .
IDL_EXPORT_DIR  = .

include $(IDL_MK_DIR)/idl.mk

(These are described below.)

Usage of interface descriptions should be defined. For example, for some interfaces employed by client programs in the C language:

CLIENT_INTERFACES_C = file mapped_file

For interfaces used by C++ server programs:

SERVER_INTERFACES_CC = dataspace dataspace_factory

These interface definitions are then complemented with definitions that expand to the source files involved. For example:

CLIENT_INTERFACES_SRC_C = $(call interfaces_to_client_c,$(CLIENT_INTERFACES_C))

Or:

SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC))

After these definitions, it is convenient to provide the plain source files that are present in the package. For example:

PLAIN_SRC_C = routines.c main.c

With this, it is possible to provide the normal source file definitions which will be a combination of the plain source files with the ones providing support for interfaces.

For example, for a client program employing generated C language files:

SRC_C = $(PLAIN_SRC_C) $(CLIENT_INTERFACES_SRC_C)

To make sure that any required headers are generated before attempts are made to compile the source files, a special rule is required at the end of the file. This is mentioned below.

Library-related and header-related definitions are typically needed. For example:

REQUIRES_LIBS   = libipc libsystypes
PRIVATE_INCDIR  = $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)

As usual, the Makefile ends with the appropriate role-specific rule inclusion. For example, for programs:

include $(L4DIR)/mk/prog.mk

For interface-driven file generation, an accompanying statement is also required:

include $(IDL_MK_DIR)/interface_rules.mk

This must appear after the role-specific inclusion statement.

Finally, to coordinate the generation of header files with compilation, a rule must be added after the L4Re build system include statements. This must make the plain source files dependent on generated files. For example:

$(PLAIN_SRC_C): $(CLIENT_INTERFACES_SRC_C)

Or, for C++ server code, using the above naming conventions:

$(PLAIN_SRC_CC): $(SERVER_INTERFACES_SRC_CC)

The following sections describe the different elements of this basic arrangement in more detail.

In a Makefile used to build a L4Re component, the following settings can be used to configure the generation of code from interfaces.

Variable Purpose
IDL_DIR Finding .idl files to be processed
IDL_MK_DIR Finding the idl4re/mk directory and rule files
IDL_BUILD_DIR The location of generated code for this component
IDL_EXPORT_DIR Exporting interface headers

The roles of the variables can be summarised in a diagram:

variablesIDL_DIRfile.idl...idlIDL_BUILD_DIRfile_client.c...IDL_EXPORT_DIRfile_interface.h...IDL_MK_DIRidl.mk...

Typically, the following kinds of values will be used:

Variable Value
IDL_DIR A directory containing interfaces
IDL_MK_DIR $(L4DIR)/idl4re/mk
IDL_BUILD_DIR .
IDL_EXPORT_DIR (See below for discussion.)

In the case of IDL_EXPORT_DIR, the variable needs to indicate the location of interface header files that can be referenced by code needing to use the component interfaces. Where such code resides in the same package, the current directory (.) can be used. Where such code resides in other packages, a location is required to export the generated files to those packages.

To avoid mixing up any exported generated interface headers with original non-generated headers, a value of the following form can be used:

$(OBJ_BASE)/include/contrib/$(CONTRIB_INCDIR)

Here, a header called file_interface.h would be exported and included using just this simple name. However, in some cases, there may be other packages exporting headers of the same name, and this may result in confusion.

The solution to this is to organise headers (of any kind) in collections. Here, the header could be placed inside a directory called fsserver and be included as fsserver/file_interface.h. This would be achieved by using a location of the following form:

$(OBJ_BASE)/include/contrib/$(CONTRIB_INCDIR)/fsserver

Filename Transformations

Immediately after the settings, it is typically useful to define some filename transformations:

include $(IDL_MK_DIR)/idl.mk

These make it easier to define the various interfaces used by a component and to derive the filenames involved using transformation functions such as the following:

$(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))

Remember that a conventional package Makefile will be concerned with source files and their compilation. Since interface files will be used to generate files that do not initially exist, knowledge about the names of these generated source files needs to be applied to tell the build system which files it will ultimately need to compile.

transformationsfile.idlfile_client.cinterfaces_to_client_cfile_server.cinterfaces_to_server_c

Various rules are applied in the build system to make sure that source files are then handled appropriately.

Interface Definitions

After the settings and the inclusion of the idl.mk file, it is appropriate to define certain variables describing the use of individual interfaces:

Variable Interface Usage
CLIENT_INTERFACES_C C language client code
CLIENT_INTERFACES_CC C++ language client code
SERVER_INTERFACES_C C language server code
SERVER_INTERFACES_CC C++ language server code

These variables reference .idl files containing interface descriptions. For example:

SERVER_INTERFACES_CC = dataspace mapped_file

This indicates that server code in C++ will need to be generated from dataspace.idl and mapped_file.idl, and rules are generated to ensure that make becomes aware of this need.

The variables are then employed in filename transformations, described in more detail elsewhere in this document.