Genode Porting Guide: Native Genode port of a library

Porting a library to be used natively on Genode is similar to porting an application to run natively on Genode. The source codes have to be obtained and, if needed, patched to run on Genode. As an example on how to port a library to natively run on Genode, we will describe the porting of SDL_net in more detail. Ported libraries are placed in the libports repository of Genode. But this is just a convention. Feel free to host your library port in a custom repository of your's.

Checking requirements/dependencies

We will proceed as we did when we ported DosBox to run natively on Genode. First we build SDL_net on Linux to obtain a log file of the whole build process:

 $ wget http://www.libsdl.org/projects/SDL_net/release/SDL_net-1.2.8.tar.gz
 $ tar xvzf SDL_net-1.2.8.tar.gz
 $ cd SDL_net-1.2.8
 $ ./configure
 $ make > build.log 2>&1

Creating the port file

We start by creating _<genode-dir>/libports/ports/sdl_net.port:

 LICENSE   := BSD
 VERSION   := 1.2.8
 DOWNLOADS := sdl_net.archive

 URL(sdl_net) := http://www.libsdl.org/projects/SDL_net/release/SDL_net-$(VERSION).tar.gz
 SHA(sdl_net) := fd393059fef8d9925dc20662baa3b25e02b8405d
 DIR(sdl_net) := src/lib/sdl_net

 PATCHES := src/lib/sdl_net/SDLnet.patch src/lib/sdl_net/SDL_net.h.patch

In addition to the URL the SHA1 checksum of the SDL_net archive needs to specified because tool/prepare_port validates the downloaded archive by using this hash.

Applications that want to use SDL_net have to include the SDL_net.h header file. Hence it is necessary to make this file visible to applications. This is done by populating the <genode-dir>/contrib/sdl-<hash>/include directory:

 DIRS := include/SDL
 DIR_CONTENT(include/SDL) := src/lib/sdl_net/SDL_net.h

For now, we also use a dummy hash in the sdl_net.hash file like it was done while porting DosBox. We will replace the dummy hash with the proper one at the end.

Creating the build Makefile

We create the build rules in libports/lib/mk/sdl_net.mk:

 SDL_NET_DIR := $(call select_from_ports,sdl_net)/src/lib/sdl_net

 SRC_C = $(notdir $(wildcard $(SDL_NET_DIR)/SDLnet*.c))

 vpath %.c $(SDL_NET_DIR)

 INC_DIR += $(SDL_NET_DIR)

 LIBS += libc sdl

SDL_net should be used as shared library. To achieve this, we have to add the following statement to the mk file:

 SHARED_LIB = yes

If we omit this statement, Genode's build system will automatically build SDL_net as a static library called sdl_net.lib.a that is linked directly into the application.

It is reasonable to create a dummy application that uses the library because it is only possible to build libraries automatically as a dependency of an application.

Therefore we create libports/src/test/libports/sdl_net/target.mk with the following content:

 TARGET = test-sdl_net
 LIBS   = libc sdl_net
 SRC_CC = main.cc
 vpath main.cc $(PRG_DIR)/..

At this point we also create lib/import/import-sdl_net.mk with the following content:

 SDL_NET_PORT_DIR := $(call select_from_ports,sdl_net)
 INC_DIR += $(SDL_NET_PORT_DIR)/include $(SDL_NET_PORT_DIR)/include/SDL

Each port that depends on SDL_net and has added it to its LIBS variable will automatically include the import-sdl_net.mk file and therefore will use the specified include directory to find the SDL_net.h header.

Compiling the library

We compile the SDL_net library as a side effect of building our dummy test program by executing

 $ make test/libports/sdl_net

All source files are compiled fine but unfortunately the linking of the library does not succeed:

 /src/genodebuild/foc_x86_32/var/libcache/sdl_net/sdl_net.lib.so:
     undefined reference to `gethostbyaddr'

The symbol gethostbyaddr is missing, which is often a clear sign of a missing dependency. In this case however gethostbyaddr(3) is missing because this function does not exist in Genode's libc (*). But getaddrinfo(3) exists. We are now facing the choice of implementing gethostbyaddr(3) or changing the code of SDL_net to use getaddrinfo(3). Porting applications or libraries to Genode always may involve this kind of choice. Which way is the best has to be decided by closely examining the matter at hand. Sometimes it is better to implement the missing functions and sometimes it is more beneficial to change the contributed code. In this case, we opt for changing SDL_net because the former function is obsolete anyway and implementing gethostbyaddr(3) involves changes to several libraries in Genode, namely libc and the network related libc plugin. Although we have to keep in mind that it is likely to encounter another application or library that also uses this function in the future.

With this change in place, SDL_net compiles fine.

(*) Actually this function is implemented in the Genode's libc but is only available by using libc_resolv which we did not do for the sake of this example.

Testing the library

The freshly ported library is best tested with the application, which was the reason the library was ported in the first place, since it is unlikely that we port a library just for fun and no profit. Therefore, it is not necessary to write a run script for a library alone.

For the records, here is a list of all files that were created by porting SDL_net to Genode:

 libports/lib/mk/sdl_net.mk
 libports/lib/mk/import/import-sdl_net.mk
 libports/ports/sdl_net.hash
 libports/ports/sdl_net.port
 libports/src/lib/sdl_net/SDLnet.patch
 libports/test/libports/sdl_net/target.mk