Build system

Build directories

The build system is supposed to never touch the source tree. The procedure of building components and integrating them into system scenarios is performed within a distinct build directory. One build directory targets a specific kernel and hardware platform. Because the source tree is decoupled from the build directory, one source tree can have many different build directories associated, each targeted at a different platform.

The recommended way for creating a build directory is the use of the create_builddir tool located at <genode-dir>/tool/. The tool prints usage information along with a list of supported base platforms when started without arguments. For creating a new build directory, one of the listed target platforms must be specified. By default, the new build directory is created at <genode-dir>/build/<platform>/ where <platform> corresponds to the specified argument. Alternatively, the default location can be overridden via the optional BUILD_DIR= argument. For example:

 cd <genode-dir>
 ./tool/create_builddir x86_64 BUILD_DIR=/tmp/build.x86_64

This command creates a new build directory for the 64-bit x86 platform at /tmp/build.x86_64/. For the basic operations available from within the build directory, please refer to Section Using the build system.

Configuration

Each build directory contains a Makefile, which is a symbolic link to tool/builddir/build.mk. The makefile is the front end of the build system and not supposed to be edited. Besides the makefile, there is an etc/ subdirectory that contains the build-directory configuration. For most platforms, there exists merely a single build.conf file, which defines the source-code repositories to be incorporated into the build process along with the parameters for the run tool explained in Section Run tool.

The selection of source-code repositories is defined by the REPOSITORIES declaration, which contains a list of directories. The etc/build.conf file as found in a freshly created build directory is preconfigured to select the source-code repositories base-<platform>, base, os, and demo. There are a number of commented-out lines that can be uncommented for enabling additional repositories.

Cleaning

To remove all but kernel-related generated files, use

 make clean

To remove all generated files, use

 make cleanall

Both clean and cleanall won't remove any files from the bin/ subdirectory. This makes the bin/ a safe place for files that are unrelated to the build process, yet are required for the integration stage, e.g., binary data.

Controlling the verbosity

To understand the inner workings of the build process in more detail, you can tell the build system to display each directory change by specifying

 make VERBOSE_DIR=

If you are interested in the arguments that are passed to each invocation of make, you can make them visible via

 make VERBOSE_MK=

Furthermore, you can observe each single shell-command invocation by specifying

 make VERBOSE=

Of course, you can combine these verboseness toggles for maximizing the noise.

Target descriptions

Each build target is represented by a corresponding target.mk file within the src/ subdirectory of a source-code repository. This file declares the name of the target, the source codes to be incorporated into the target, and the libraries the target depends on. The build system evaluates target descriptions using make. Hence, the syntax corresponds to the syntax of makefiles and the principle functionality of make is available for target.mk files. For example, it is possible to define custom rules as done in Section Building tools to be executed on the host platform.

Target declarations

TARGET

is the name of the binary to be created. This is the only mandatory variable to be defined in each target.mk file.

LIBS

is the list of libraries that are used by the target.

SRC_CC

contains the list of .cc source files. The default search location for source codes is the directory where the target.mk file resides.

SRC_C

contains the list of .c source files.

SRC_S

contains the list of assembly .s source files.

SRC_BIN

contains binary data files to be linked to the target.

INC_DIR

is the list of include search locations. Directories should always be appended by using +=.

REQUIRES

expresses the requirements that must be satisfied in order to build the target. More details about the underlying mechanism is provided by Section Platform specifications.

CC_OPT

contains additional compiler options to be used for .c as well as for .cc files.

CC_CXX_OPT

contains additional compiler options to be used for the C++ compiler only.

CC_C_OPT

contains additional compiler options to be used for the C compiler only.

EXT_OBJECTS

is a list of external objects or libraries. This declaration is merely used for interfacing Genode with legacy software components.

Specifying search locations

When specifying search locations for header files via the INC_DIR variable or for source files via vpath, the use of relative pathnames is illegal. Instead, the following variables can be used to reference locations within the source-code repository where the target resides:

REP_DIR

is the base directory of the target's source-code repository. Normally, specifying locations relative to the base of the repository is rarely used by target.mk files but needed by library descriptions.

PRG_DIR

is the directory where the target.mk file resides. This variable is always to be used when specifying a relative path.

$(call select_from_repositories,path/relative/to/repo)

This function returns the absolute path for the given repository-relative path by looking at all source-code repositories in their configured order. Hereby, it is possible to access files or directories that are outside the target's source-code repository.

$(call select_from_ports,<port-name>)

This function returns the absolute path for the contrib directory of the specified <port-name>. The contrib directory is located at <genode-dir>/contrib/<port-name>-<fingerprint> whereby <fingerprint> uniquely identifies the version of the port as expected by the current state of the Genode source tree.

Custom targets accompanying a library or program

There are cases that call for building custom targets in addition to a regular library or or program. For example, the executable binary of an application may be accompanied by generated data files. The creation of such build artifacts can be expressed by custom make rules. However, a rule is triggered only if it is a dependency of the build target. This can be achieved by adding the rule to the CUSTOM_TARGET_DEPS variable. For example,

 CUSTOM_TARGET_DEPS += menu_view_styles.tar

 menu_view_styles.tar:
    $(VERBOSE)cd $(PRG_DIR); tar cf $(PWD)/bin/$@ styles

Library descriptions

In contrast to target descriptions that are scattered across the whole source tree, library descriptions are located at the central place lib/mk. Each library corresponds to a <libname>.mk file. The base of the description file is the name of the library. Therefore, no TARGET variable needs to be defined. The location of source-code files is usually defined relative to $(REP_DIR). Library-description files support the following additional declaration:

SHARED_LIB = yes

declares that the library should be built as a shared object rather than a static library. The resulting object will be called <libname>.lib.so.

Platform specifications

Building components for different platforms likely implicates that portions of code are tied to certain aspects of the target platform. For example, target platforms may differ in the following respects:

Each of those aspects may influence the build process in different ways. The build system provides a generic mechanism to steer the build process according to such aspects. Each aspect is represented by a tag called spec value. Any platform targeted by Genode can be characterized by a set of such spec values.

The developer of a software component knows the constraints of his software and thus specifies these requirements in the build-description file of the component. The system integrator defines the platform the software will be built for by specifying the targeted platform in the SPECS declaration in the build directory's etc/specs.conf file. In addition to the (optional) etc/specs.conf file within the build directory, the build system incorporates all etc/specs.conf files found in the enabled repositories. For example, when using the Linux kernel as a platform, the base-linux/etc/specs.conf file is picked up automatically. The build directory's specs.conf file can still be used to extend the SPECS declarations, for example to enable special features.

Each <spec> in the SPECS variable instructs the build system to

Before a target or library gets built, the build system checks if the REQUIRES entries of the build description file are satisfied by entries of the SPECS variable. The compilation is executed only if each entry in the REQUIRES variable is present in the SPECS variable as supplied by the build directory configuration.

Building tools to be executed on the host platform

Sometimes, software requires custom tools that are used to generate source code or other ingredients for the build process, for example IDL compilers. Such tools won't be executed on top of Genode but on the host platform during the build process. Hence, they must be compiled with the tool chain installed on the host, not the Genode tool chain.

The build system accommodates the building of such host tools as a side effect of building a library or a target. Even though it is possible to add the tool-compilation step to a regular build description file, it is recommended to introduce a dedicated pseudo library for building such tools. This way, the rules for building host tools are kept separate from rules that refer to regular targets. By convention, the pseudo library should be named <package>_host_tools and the host tools should be built at <build-dir>/tool/<package>/ where <package> refers to the name of the software package the tool belongs to, e.g., qt5 or mupdf. To build a tool named <tool>, the pseudo library contains a custom make rule like the following:

 $(BUILD_BASE_DIR)/tool/<package>/<tool>:
     $(MSG_BUILD)$(notdir $@)
     $(VERBOSE)mkdir -p $(dir $@)
     $(VERBOSE)...build commands...

To let the build system trigger the rule, add the custom target to the HOST_TOOLS variable:

 HOST_TOOLS += $(BUILD_BASE_DIR)/tool/<package>/<tool>

Once the pseudo library for building the host tools is in place, it can be referenced by each target or library that relies on the respective tools via the LIBS declaration. The tool can be invoked by referring to $(BUILD_BASE_DIR)/tool/<package>/tool.

For an example of using custom host tools, please refer to the mupdf package found within the libports repository. During the build of the mupdf library, two custom tools fontdump and cmapdump are invoked. The tools are built via the lib/mk/mupdf_host_tools.mk library description file. The actual mupdf library (lib/mk/mupdf.mk) has the pseudo library mupdf_host_tools listed in its LIBS declaration and refers to the tools relative to $(BUILD_BASE_DIR).

Building 3rd-party software

The source code of 3rd-party software is managed by the mechanism presented in Section Integration of 3rd-party software. Once prepared, such source codes resides in a subdirectory of <genode-dir>/contrib/.

If the build system encounters a target that incorporates ported source code (that is, a build-description file that calls the select_from_ports function), it looks up the respective <port-name>.hash file in the repositories as specified in the build configuration. The fingerprint found in the hash file is used to construct the path to the port directory under contrib/. If that lookup fails, a meaningful error is printed. Any number of versions of the same port can be installed at the same time. I.e., when switching Git branches that use different versions of the same port, the build system automatically finds the right port version as expected by the currently active branch.