doc: update porting guide to new port mechanism

This commit is contained in:
Josef Söntgen 2014-05-27 16:06:42 +02:00 committed by Norman Feske
parent f2d38443f7
commit bdfe634fdf
1 changed files with 204 additions and 229 deletions

View File

@ -31,8 +31,14 @@ sections:
:[http:porting_device_drivers - Porting devices drivers]:
This chapter describes the concepts of how to port a device driver to the
Genode framework. It requires the basic knowledge introduced in the previous
chapters and should be read last. Before reading this guide, it is strongly
advised to read the "The Genode Build System" documentation.
chapters and should be read last.
Before reading this guide, it is strongly advised to read the "The Genode
Build System" documentation:
:Build-system manual:
[http://genode.org/documentation/developer-resources/build_system]
Porting third-party code to Genode
@ -55,22 +61,22 @@ Steps in porting applications to Genode
e.g. what functionality needs to be provided by the target system and
which libraries does it use.
# Create a port Makefile
# Create a port file
Prepare the source code of the application for the use within Genode. The
Genode build-system infrastructure uses fetch rules, so called port-files,
which describe how the source is obtained, what patches are applied to the
source code, if needed, and where the source code will be stored and
Genode build-system infrastructure uses fetch rules, so called port files,
which declare where the source is obtained from, what patches are applied
to the source code, and where the source code will be stored and
configured.
# Check platform dependent code and create stub code
This step may require changes to the original source code
of the application to be compilable to Genode. At this point, it
of the application to be compilable for Genode. At this point, it
is not necessary to provide a working implementation for required
functions. Just creating stubs of the various functions is fine.
# Create build Makefile
# Create build-description file
To compile the application we need build rules. Within these rules
we also declare all dependencies (e.g. libraries) that are needed
@ -176,61 +182,75 @@ libraries are already available on Genode. For now all we have to do is to
keep them in mind.
Creating the port Makefile
==========================
Creating the port file
======================
Since DosBox is an application, which depends on several ported
libraries (e.g., libSDL), the 'ports' repository within the Genode
source tree is a natural fit. On that account, the port Makefile
_ports/ports/dosbox.mk_ is created. It is often reasonable to also
create a corresponding _ports/ports/dosbox.inc_ file that contains
the used version of the program which is included by _dosbox.mk_ as
well as by the associated build Makefile. Through this approach it is
easier to update ports whose structures stays the same but varies only
in its version string.
libraries (e.g., libSDL), the _ports_ repository within the Genode
source tree is a natural fit. On that account, the port file
_ports/ports/dosbox.port_ is created.
For DosBox the _dosbox.inc_ looks as follows:
For DosBox the _dosbox.port_ looks as follows:
! DOSBOX_REV := 3837
! DOSBOX_VERSION := svn-$(DOSBOX_REV)
! DOSBOX := dosbox-$(DOSBOX_VERSION)
In addition, the corresponding _dosbox.mk_ contains:
! include ports/dosbox.inc
! LICENSE := GPLv2
! VERSION := svn
! DOWNLOADS := dosbox.svn
!
! DOSBOX_SVN_URL = http://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk
!
! #
! # Interface to top-level prepare Makefile
! #
! PORTS += $(DOSBOX)
!
! prepare:: $(CONTRIB_DIR)/$(DOSBOX)
!
! #
! # Port-specific local rules
! #
! $(CONTRIB_DIR)/$(DOSBOX):
! $(ECHO) "checking out 'dosbox rev. $(DOSBOX_REV)' to '$@'"
! $(VERBOSE)svn export $(DOSBOX_SVN_URL)@$(DOSBOX_REV) $@
! URL(dosbox) := http://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk
! DIR(dosbox) := src/app/dosbox
! REV(dosbox) := 3837
_The variable_ 'CONTRIB_DIR' _always contains the path to the directory_
_that holds the contributed source code relatively to the particular_
_Genode repository (e.g., ports/contrib)._
First, we define the license, the version and the type of the source code
origin. In case of DosBox, we checkout the source code from a Subversion
repository. This is denoted by the '.svn' suffix of the item specified in
the 'DOWNLOADS' declaration. Other valid types are 'file' (a plain file),
'archive' (an archive of the types tar.gz, tar.xz, tgz, tar.bz2, or zip)
or 'git' (a Git repository).
To checkout the source code out from the Subversion repository, we also need
its URL, the revision we want to check out and the destination directory
that will contain the sources afterwards. These declarations are mandatory and
must always be specified. Otherwise the preparation of the port will fail.
! PATCHES := $(addprefix src/app/dosbox/patches/,\
! $(notdir $(wildcard $(REP_DIR)/src/app/dosbox/patches/*.patch)))
!
! PATCH_OPT := -p2 -d src/app/dosbox
As next step, we declare all patches that are needed for the DosBox port.
Since in this case, the patches are using a different path format, we have
to override the default patch settings by defining the _PATCH_OPT_ variable.
Each port file comes along with a hash file. This hash is generated by taking
several sources into account. For one, the port file, each patch and the
port preparation tool (_tool/ports/prepare_port_) are the ingredients for
the hash value. If any of these files is changed, a new hash will be generated,
For now, we just write "dummy" in the '_ports/ports/dosbox.hash_ file.
The DosBox port can now be prepared by executing
! $ make PKG=dosbox prepare
! $ <genode-dir>/tool/ports/prepare_port dosbox
from within Genode's 'ports' repository. The 'prepare::' rule is evaluated
and the checkout will be triggered.
However, we get the following error message:
Error: <rep-dir>/ports/dosbox.port is out of date, expected <fingerprint>
We get this message because we had specified the "dummy" hash value in
the _dosbox.hash_ file. The prepare_port tool computes a fingerprint
of the actual version of the port and compares this fingerprint with the
hash value specified in _dosbox.hash_. The computed fingerprint can
be found at _<genode-dir>/contrib/dosbox-dummy/dosbox.hash_. In the final
step of the port, we will replace the dummy fingerprint with the actual
fingerprint of the port. But before finalizing the porting work, it is
practical to keep using the dummy hash and suppress the fingerprint check.
This can be done by adding 'CHECK_HASH=no' as argument to the prepare_port tool:
! $ <genode-dir>/tool/ports/prepare-port dosbox CHECK_HASH=no
Check platform-dependent code
=============================
At this point, it is important to spot platform dependent source files or
At this point, it is important to spot platform-dependent source files or
rather certain functions that are not yet available on Genode. These source
files should be omitted. Of course they may be used as a guidance when
implementing the functionality for Genode later on, when creating the
@ -249,11 +269,18 @@ we assemble a list of needed source files. If an application just
uses a simple Makefile and not a build tool, it might be easier to just
reuse the contents of this Makefile instead.
First we include _dosbox.inc_ and for convenience set the source directory
of DosBox:
First of all, we create a shortcut for the source directory of DosBox by calling
the 'select_from_ports' function:
! include $(REP_DIR)/ports/dosbox.inc
! DOSBOX_DIR = $(REP_DIR)/contrib/$(DOSBOX)
! DOSBOX_DIR := $(call select_from_ports,dosbox)/src/app/dosbox
Under the hood, the 'select_from_ports' function looks up the
fingerprint of the specified port by reading the corresponding
<port-name>.hash file. It then uses this hash value to construct the
directory path within the _<genode-dir>contrib/_ directory that belongs to
the matching version of the port. If there is no hash file that matches the
port name, or if the port directory does not exist, the build system
will back out with an error message.
Examining the log file leaves us with the following list of source files:
@ -274,7 +301,7 @@ Examining the log file leaves us with the following list of source files:
! […]
_The only variable here that is actually evaluated by Genode's build-system is_
'SRC_CC' _. The rest of the variables are little helpers that make our_
'SRC_CC'. _The rest of the variables are little helpers that make our_
_life more comfortable._
In this case, it is mandatory to use GNUMake's 'notdir' file name function
@ -286,7 +313,7 @@ why you have to use a build directory for each platform. The Genode build
system will create the needed directory hierarchy within the build directory
automatically. By combining GNUMake's 'notdir' and 'wildcard' function, we
can assemble a list of all needed source files without much effort. We then
use 'vpath' to point GNUMake to the right source file within the _contrib_
use 'vpath' to point GNUMake to the right source file within the dosbox
directory.
The remaining thing to do now is setting the right include directories and proper
@ -324,7 +351,7 @@ environment. Below is a skimmed diff of these changes:
!
! […]
Thereafter we specify the compiler flags:
Thereafter, we specify the compiler flags:
! CC_OPT = -DHAVE_CONFIG_H -D_GNU_SOURCE=1 -D_REENTRANT
! ifeq ($(filter-out $(SPECS),x86_32),)
@ -343,7 +370,7 @@ As noted in the commentary seen in the diff we define 'C_TARGETCPU'
and adjust the include directories ourselves according to the target
architecture.
While debugging compiler warnings for 3rd-party code are really helpful but
While debugging, compiler warnings for 3rd-party code are really helpful but
tend to be annoying after the porting work is finished, we can
remove the hashmark to keep the compiler from complaining too
much.
@ -351,13 +378,13 @@ much.
Lastly, we need to add the required libraries, which we acquired in step 1:
! LIBS += libc libm libpng sdl stdcxx zlib
! LIBS += libc_log libc_fs libc_lwip_nic_dhcp config_args
! LIBS += libc_lwip_nic_dhcp config_args
In addition to the required libraries, a few Genode specific
libraries are also needed. These libraries implement certain
functions in the libc via the libc's plugin mechanism.
libc_log, for example, is used to print message on stdout via
Genode's LOG service.
libc_lwip_nic_dhcp, for example, is used to connect the BSD socket interface
to a NIC service such as a network device driver.
Creating the run script
@ -418,18 +445,16 @@ Nextm we provide the scenario's configuration 'config':
! <resource name="RAM" quantum="1M"/>
! <provides><service name="Timer"/></provides>
! </start>
! <start name="tar_fs">
! <resource name="RAM" quantum="4M"/>
! <provides> <service name="File_system"/> </provides>
! <config>
! <archive name="dosbox.tar" />
! <policy label="" root="/" />
! </config>
! </start>
! <start name="dosbox">
! <resource name="RAM" quantum="128M"/>
! <config>
! <sdl_audio_volume value="100"/>
! <libc stdout="/dev/log" stderr="/dev/log">
! <vfs>
! <tar name="dosbox.tar"/>
! <dir name="dev"> <log/> </dir>
! </vfs>
! </libc>
! </config>
! </start>
! </config>}
@ -442,9 +467,9 @@ Thereafter we declare all boot modules:
! set boot_modules {
! core init timer audio_out_drv fb_drv ps2_drv ld.lib.so
! libc_fs.lib.so libc.lib.so libc_log.lib.so libm.lib.so
! libc.lib.so libm.lib.so
! lwip.lib.so libpng.lib.so stdcxx.lib.so sdl.lib.so
! pthread.lib.so zlib.lib.so tar_fs dosbox dosbox.tar
! pthread.lib.so zlib.lib.so dosbox dosbox.tar
! }
! build_boot_image $boot_modules
@ -496,19 +521,15 @@ application that is ported.
Since 'ftime(3)' is a deprecated function anyway we change the code of
DosBox to use 'gettimeofday(2)'.
After this was fixed we face another problem:
After this was fixed, we face another problem:
! /src/genode/ports/contrib/dosbox-svn-3837/src/ints/int10_vesa.cpp:48:33: error:
! unable to find string literal operator operator"" VERSION
The fix is quite simple and the compile error was due to the fact
that Genode uses C++11 by now. It often happens that 3rd party code
is not well tested with a C++11 enabled compiler. In any case a patch file
should be created which will be applied when executing the fetch-rules:
! $(CONTRIB_DIR)/$(DOSBOX):
! […]
! $(VERBOSE)patch -N -p0 < src/app/dosbox/int10_vesa.patch
is not well tested with a C++11 enabled compiler. In any case, a patch file
should be created which will be applied when preparing the port.
Furthermore it would be reasonable to report the bug to the DosBox
developers so it can be fixed upstream. We can then get rid of our
@ -537,13 +558,13 @@ Debugging the application
DosBox was successfully compiled but unfortunately it did not run.
To be honest that was expected and here the fun begins.
At this point there are several options to chose from. By running
Genode/Fiasco.OC within Qemu we can use the kernel debugger (JDB)
to take a deeper look at what went wrong (e.g. backtraces of the
At this point, there are several options to chose from. By running
Genode/Fiasco.OC within Qemu, we can use the kernel debugger (JDB)
to take a deeper look at what went wrong (e.g., backtraces of the
running processes, memory dumps of the faulted DosBox process etc.).
Doing this can be quite taxing but fortunately Genode runs on multiple
kernels and often problems on one kernel can be reproduced on another
kernel. For this reason we choose Genode/Linux where we can use all
kernel. For this reason, we choose Genode/Linux where we can use all
the normal debugging tools like 'gdb(1)', 'valgrind(1)' and so on. Luckily
for us, DosBox also fails to run on Genode/Linux. The debugging steps
are naturally dependent on the ported software. In the case of DosBox,
@ -553,8 +574,8 @@ Linux as a host platform.
For the sake of completeness here is a list of all files that were created by
porting DosBox to Genode:
! ports/ports/dosbox.inc
! ports/ports/dosbox.mk
! ports/ports/dosbox.hash
! ports/ports/dosbox.port
! ports/run/dosbox.run
! ports/src/app/dosbox/config.h
! ports/src/app/dosbox/patches/bios.patch
@ -566,16 +587,32 @@ porting DosBox to Genode:
[image dosbox]
DosBox ported to Genode
Finally, after having tested that both the preparation-step and the
build of DosBox work as expected, it is time to
finalize the fingerprint stored in the _<genode-dir>/ports/ports/dosbox.hash_
file. This can be done by copying the content of the
_<genode-dir>/contrib/dosbox-dummy/dosbox.hash file_.
Alternatively, you may invoke the _tool/ports/update_hash_ tool with the
port name "dosbox" as argument. The next time, you
invoke the prepare_port tool, do not specify the 'CHECK_HASH=no' argument.
So the fingerprint check will validate that the _dosbox.hash_ file
corresponds to your _dosbox.port_ file. From now on, the
_<genode-dir>/contrib/dosbox-dummy_ directory will no longer be used because
the _dosbox.hash_ file points to the port directory named after the real
fingerprint.
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 has to be
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.
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
@ -592,85 +629,43 @@ process:
! $ make > build.log 2>&1
Creating the port Makefile
==========================
Creating the port file
======================
We start by creating 'libports/ports/sdl_net.inc':
We start by creating _<genode-dir>/libports/ports/sdl_net.port:
! SDL_NET_VERSION = 1.2.8
! SDL_NET = SDL_net-$(SDL_NET_VERSION)
Following this we create the actual fetch-rules
in _libports/ports/sdl_net.mk_
! include ports/sdl_net.inc
! LICENSE := BSD
! VERSION := 1.2.8
! DOWNLOADS := sdl_net.archive
!
! SDL_NET_TGZ = $(SDL_NET).tar.gz
! SDL_NET_URL = http://www.libsdl.org/projects/SDL_net/release/$(SDL_NET_TGZ)
! 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
!
! #
! # Interface to top-level prepare Makefile
! #
! # Register SDL_net port as lower case to be consistent with the
! # other libraries.
! #
! PORTS += sdl_net-$(SDL_NET_VERSION)
!
! prepare-sdl_net: $(CONTRIB_DIR)/$(SDL_NET) include/SDL/SDL_net.h
!
! $(CONTRIB_DIR)/$(SDL_NET): clean-sdl_net
! PATCHES := src/lib/sdl_net/SDLnet.patch src/lib/sdl_net/SDL_net.h.patch
While extracting the archive, we omit certain directories and files that we
do not need and that otherwise would only pollute the 'contrib' directory:
! #
! # Port-specific local rules
! #
! $(DOWNLOAD_DIR)/$(SDL_NET_TGZ):
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(SDL_NET_URL) && touch $@
!
! $(CONTRIB_DIR)/$(SDL_NET): $(DOWNLOAD_DIR)/$(SDL_NET_TGZ)
! $(VERBOSE)tar xfz $< \
! --exclude Xcode --exclude VisualC --exclude Xcode-iOS \
! --exclude VisualCE --exclude Watcom-OS2.zip --exclude debian \
! -C $(CONTRIB_DIR) && touch $@
! $(VERBOSE)patch -N -p0 < src/lib/sdl_net/SDLnet.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 file visible to applications. This is
done by creating a symbolic link from the original location to
_libports/include/SDL/SDL_net.h_
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:
! #
! # Install SDL_net headers
! #
! include/SDL/SDL_net.h:
! $(VERBOSE)mkdir -p $(dir $@)
! $(VERBOSE)ln -fs ../../$(CONTRIB_DIR)/$(SDL_NET)/SDL_net.h include/SDL/
! DIRS := include/SDL
! DIR_CONTENT(include/SDL) := src/lib/sdl_net/SDL_net.h
Since we created a symbolic link that is placed in Genode's _libports_
repository,
we have to provide a 'clean' rule. This rule is responsible for removing all
extracted files and the link we created:
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.
! clean-sdl_net:
! $(VERBOSE)rm -rf include/SDL/SDL_net.h
! $(VERBOSE)rmdir include/SDL 2>/dev/null || true
! $(VERBOSE)rm -rf $(CONTRIB_DIR)/$(SDL_NET)
_It is important to write the_ 'clean' _rule in way that does not remove_
_files that are still needed by other components of Genode or ported_
_applications. In this example we only delete include/SDL if it is_
_empty. Otherwise_ 'rmdir(1)' _will not remove the directory and we_
_simply ignore it._
Creating the build Makefile
===========================
We create the build rules in _libports/lib/mk/sdl_net.mk_:
! include $(REP_DIR)/ports/sdl_net.inc
! SDL_NET_DIR = $(REP_DIR)/contrib/$(SDL_NET)
! SDL_NET_DIR := $(call select_from_ports,sdl_net)/src/lib/sdl_net
!
! SRC_C = $(notdir $(wildcard $(SDL_NET_DIR)/SDLnet*.c))
!
@ -685,11 +680,11 @@ have to add the following statement to the 'mk' file:
! SHARED_LIB = yes
_If we omit this statement, Genode's build-system will automatically_
_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 a reasonable to create a dummy application that uses the
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.
@ -702,16 +697,15 @@ _libports/src/test/libports/sdl_net/target.mk_ with the following content:
! vpath main.cc $(PRG_DIR)/..
At this point we normally would also create _lib/import/import-sdl_net.mk_
At this point we also create _lib/import/import-sdl_net.mk_
with the following content:
! REP_INC_DIR += include/SDL
! SDL_NET_PORT_DIR := $(call select_from_ports,sdl_net)
! INC_DIR += $(SDL_NET_PORT_DIR)/include $(SDL_NET_PORT_DIR)/include/SDL
However in this case this is not necessary because _SDL_net_ depends on
libSDL which already provides its own _import-sdl.mk_ file with exactly
the same content. While preparing SDL_net we placed a symbolic link in
just this directory and therefore every user of SDL_net already knows
about this directory.
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
@ -737,13 +731,13 @@ 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
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 is likely to encounter
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.
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_
@ -755,15 +749,16 @@ 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 profit. Therefore, it is not necessary to
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/ports/sdl_net.inc
! libports/ports/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
@ -774,14 +769,14 @@ Porting an application to Genode's Noux runtime
Porting an application to Genode's Noux runtime is basically the same as
porting a program to natively run on Genode. The source code has to be
prepared and, if needed, patched to run in Noux. However in contrast to
this there are Noux build rules (_ports/mk/noux.mk_) that enable us to use
this, there are Noux build rules (_ports/mk/noux.mk_) that enable us to use
the original build-tool if it is based upon Autotools. Building the
application is done within a cross-compile environment. In this environment
all needed variables like 'CC', 'LD', 'CFLAGS' and so on are set to their
proper values. In addition to these precautions, using _noux.mk_ simplifies certain things.
The system-call handling/functions is/are implemented in the libc plugin
_libc_noux_ (the source code is found in _ports/src/lib/libc_noux_). All
application running in Noux have to be linked against this library which is
applications running in Noux have to be linked against this library which is
done implicitly by using the build rules of Noux.
As an example on how to port an application to Genode's Noux runtime, we
@ -801,58 +796,33 @@ process:
! $ make > build.log 2>&1
Creating the port Makefile
==========================
Creating the port file
======================
We start by creating the port Makefile _ports/ports/tar.mk_:
! GNUTAR = tar-1.27
! GNUTAR_TXZ = $(GNUTAR).tar.xz
! GNUTAR_SIG = $(GNUTAR_TXZ).sig
! GNUTAR_URL = http://ftp.gnu.org/gnu/tar
! GNUTAR_KEY = GNU
! LICENSE := GPLv3
! VERSION := 1.27
! DOWNLOADS := tar.archive
!
! URL(tar) := http://ftp.gnu.org/gnu/tar/tar-$(VERSION).tar.xz
! SHA(tar) := 790cf784589a9fcc1ced33517e71051e3642642f
! SIG(tar) := ${URL(tar)}.sig
! KEY(tar) := GNU
! DIR(tar) := src/noux-pkg/tar
_As of release 13.08 Genode includes integrity checks for downloaded_
_3rd-party software. The signature of the downloaded archive will be_
_checked prior to extraction. New ports to Genode should always use_
_this checks if it is possible. Unfortunately not all projects provide signature_
_files though._
_As of version 14.05, Genode does not check the signature specified via_
_the SIG and KEY declaration but relies the SHA checksum only. However,_
_as signature checks are planned in the future, we use to include the_
_respective declarations if signature files are available._
The remaining part of the port Makefile looks like this:
! #
! # Interface to top-level prepare Makefile
! #
! PORTS += $(GNUTAR)
!
! prepare:: $(CONTRIB_DIR)/$(GNUTAR)
!
! #
! # Port-specific local rules
! #
! $(DOWNLOAD_DIR)/$(GNUTAR_TXZ):
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(GNUTAR_URL)/$(GNUTAR_TXZ) && touch $@
!
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG):
! $(VERBOSE)wget -c -P $(DOWNLOAD_DIR) $(GNUTAR_URL)/$(GNUTAR_SIG) && touch $@
!
! $(CONTRIB_DIR)/$(GNUTAR): $(DOWNLOAD_DIR)/$(GNUTAR_TXZ).verified
! $(VERBOSE)tar xfJ $(<:.verified=) -C $(CONTRIB_DIR) && touch $@
!
! $(DOWNLOAD_DIR)/$(GNUTAR_TXZ).verified: $(DOWNLOAD_DIR)/$(GNUTAR_TXZ) \
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG)
! $(VERBOSE)$(SIGVERIFIER) $(DOWNLOAD_DIR)/$(GNUTAR_TXZ) \
! $(DOWNLOAD_DIR)/$(GNUTAR_SIG) $(GNUTAR_KEY)
! $(VERBOSE)touch $@
Its almost the same as the previous shown port Makefile but adds rules for
verifying the archive signature.
While porting GNU tar we will use a dummy hash as well.
Creating the build rule
=======================
Build rules for Noux packages are located in _ports/src/noux-pkgs_.
Build rules for Noux packages are located in _<genode-dir>/ports/src/noux-pkgs_.
The _tar/target.mk_ corresponding to GNU tar looks like this:
@ -964,13 +934,8 @@ Now we can trigger the compilation of tar by executing
_At least on the first compilation attempt, it is wise to unset_ 'VERBOSE'
_because it enables us to see the whole output of the_ 'configure' _process._
If configure is not able to find a particular header file the first place
to look is generally _libports/include/libc_. This directory is populated by
the rules in _libports/ports/libc.mk_. So if a header file is indeed
missing, adding the relevant header there is necessary.
By now Genode provides almost all libc header files that are used by
typical POSIX programs. In most cases it is rather a matter of enabling
By now, Genode provides almost all libc header files that are used by
typical POSIX programs. In most cases, it is rather a matter of enabling
the right definitions and compilation flags. It might be worth to take a
look at FreeBSD's ports tree because Genode's libc is based upon the one
of FreeBSD 8.2.0 and if certain changes to the contributed code are needed,
@ -1060,7 +1025,7 @@ system call and it is difficult to see in which.
Anyhow, 'fstatat' is not properly implemented. At this point, we either have
to add this function to the Genode's libc or rather add it to libc_noux.
If we add it to the libc not only applications running in Noux will
If we add it to the libc, not only applications running in Noux will
benefit but all applications using the libc. Implementing it in
libc_noux is the preferred way if there are special circumstances because
we have to treat the function differently when used in Noux (e.g. 'fork').
@ -1068,10 +1033,12 @@ we have to treat the function differently when used in Noux (e.g. 'fork').
For the sake of completeness here is a list of all files that were created by
porting GNU tar to Genode's Noux runtime:
! ports/ports/tar.mk
! ports/ports/tar.hash
! ports/ports/tar.port
! ports/run/noux_tar.run
! ports/src/noux-pkg/tar/target.mk
Extensive build rules example
=============================
@ -1091,7 +1058,7 @@ porting a program to Noux:
! --sbindir=/bin \
! --libexecdir=/bin
In addition to the normal configure options we have to also define the
In addition to the normal configure options, we have to also define the
path prefixes. The OpenSSH build system embeds certain paths in the
ssh binary, which need to be changed for Noux.
@ -1106,7 +1073,7 @@ Noux build rules.
! LIBS += libcrypto libssl zlib libc_resolv
As OpenSSH depends on several libraries we need to include these in the
As OpenSSH depends on several libraries, we need to include these in the
build Makefile. These libraries are runtime dependencies and need to be
present when running OpenSSH in Noux.
@ -1138,7 +1105,7 @@ way is to do it before building the Noux package:
The target _noux_built.tag_ is a special target defined by the Noux build
rules. It will be used by the build rules when building the Noux package.
We add the 'Makefile_patch' target as a dependency to it. So after configure
is executed the generated Makefile will be patched.
is executed, the generated Makefile will be patched.
Autoconf's configure script checks if all requirements are fulfilled and
therefore, tests if all required libraries are installed on the host system.
@ -1162,6 +1129,7 @@ script by providing dummy libraries:
! libz.a:
! $(VERBOSE)$(AR) -rc $@
Porting devices drivers
#######################
@ -1194,14 +1162,15 @@ Basic driver structure
The first step in porting a driver is to identify the driver code that has to be
ported. Once the code is located, we usually create a new Genode repository and
write a Makefile that downloads and extracts the code to a directory called
_contrib_ (see 'dde_linux/Makefile') thus implementing the 'make prepare'
command for the repository. Having the source code ready, there are three main
tasks the environment must implement. The first is the driver back end, which is
responsible for raw device access using Genode primitives, the actual
environment that emulates Linux function calls the driver code is using, and the
front end, which exposes for example some Genode-session interface (like NIC or
block session) that client applications can connect to.
write a port file to download and extract the code. It is good practice to name
the port and the hash file like the new repository, e.g. _dde_linux.port_ if
the repository directory is called _<genode-dir>/repos/dde_linux_.
Having the source code ready, there are three main tasks the environment must
implement. The first is the driver back end, which is responsible for raw device
access using Genode primitives, the actual environment that emulates Linux
function calls the driver code is using, and the front end, which exposes for
example some Genode-session interface (like NIC or block session) that client
applications can connect to.
Further preparations
@ -1241,14 +1210,14 @@ following code snippet in your _*.mk_ file which does the trick:
!# Determine the header files included by the contrib code. For each
!# of these header files we create a symlink to _lx_emul.h_.
!#
!GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
!GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(DRIVER_CONTRIB_DIR) |\
! sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | \
! sort | uniq)
!
!#
!# Filter out original Linux headers that exist in the contrib directory
!#
!NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | \
!NO_GEN_INCLUDES := $(shell cd $(DRIVER_CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | \
! sed "s/.*include\///")
!GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
!
@ -1275,6 +1244,12 @@ following code snippet in your _*.mk_ file which does the trick:
Make sure 'LX_INC_DIR' is the directory containing the _lx_emul.h_ file. Note
that 'GEN_INC' is added to your 'INC_DIR' variable.
The 'DRIVER_CONTRIB_DIR' variable is defined by calling the _select_from_port_
function at the beginning of a Makefile or a include file, which is used by
all other Makefiles:
! DRIVER_CONTRIB_DIR := $(call select_from_ports,driver_repo)/src/lib/driver_repo
The process of function definition and type declaration continues until the code
compiles. This process can be quite tiresome. When the driver code finally compiles, the
next stage is linking. This will of course lead to another whole set of errors
@ -1428,7 +1403,7 @@ When 'probe' returns successful, you may either test other driver functions by
hand or start building the front-end.
The front-end
The front end
=============
An important design question is how the front end is attached to the driver. In