To successfully compile Zeke, you'll need the following packages/tools:
Zeke
- GNU
make
>3.8 llvm
3.3 or 3.4clang
3.3 or 3.4binutils
2.24arm-none-eabi
mipsel-sde-elf
bash
mkdosfs
andmtools
for creating a rootfs imagecloc
for source code statsncurses-devel
Documentation
- Doxygen
man
for viewing man pages
The easiest way to build and run Zeke is by using the ready built Docker image and dmk.
The Docker image is built by using the this Dockerfile, see Zekedoc documentation for more information.
When in the root directory of the Zeke repository:
$ dmk
you@abc:/build$ KBUILD_DEFCONFIG=qemu_rpi_headless_testing.defconfig ./configure defconfig
you@abc:/build$ make all -j5
you@abc:/build$ make qemu
After making the defconfig you can change the configuration knobs by running
./configure menuconfig
. More information regarding configure
script can be
found here.
The userland unit tests must be built by specifying a special target opttest
as all
doesn't include tests. The tests can be found under opt/test
when
running Zeke, which means the tests must be run inside Zeke as thebinaries are
compiled for Zeke using its libc.
The unit tests for the kernel (kunit) can be executed by writing the name of
each test to /proc/kunit
and available tests can be listed by reading the
same file.
The Docker image comes with a GCC version specially built for debugging the Zeke kernel. Debugging with GDB has some documentation about how to debug Zeke.
configure
- Set defaults for files in config dirmake all rootfs
- Compile the kernel, user space and create a rootfs imagemake kernel.img
- Compile the kernelmake world
- Compile only the user space without creating a rootfs imagemake opttest
- Compile on target testsmake clean
- Clean all compilation targets
Run make help
for full list of targets and compilation flags.
Configure script accepts following commands as an argument:
config
Update current config utilising a line-oriented programnconfig
Update current config utilising a ncurses menu based programmenuconfig
Update current config utilising a menu based programxconfig
Update current config utilising a QT based front-endgconfig
Update current config utilising a GTK based front-endoldconfig
Update current config utilising a provided .config as baselocalmodconfig
Update current config disabling modules not loadedlocalyesconfig
Update current config converting local mods to coresilentoldconfig
Same as oldconfig, but quietly, additionally update depsdefconfig
New config with default from ARCH supplied defconfigsavedefconfig
Save current config as ./defconfig (minimal config)allnoconfig
New config where all options are answered with noallyesconfig
New config where all options are accepted with yesallmodconfig
New config selecting modules when possiblealldefconfig
New config with all symbols set to defaultrandconfig
New config with random answer to all optionslistnewconfig
List new optionsolddefconfig
Same as silentoldconfig but sets new symbols to their default value
To use defconfig you must set KBUILD_DEFCONFIG
environment variable to any of the
filenames seen under defconfigs
directory.
For example:
$ KBUILD_DEFCONFIG=qemu_rpi_headless_testing.defconfig ./configure defconfig
kern/Makefile
is responsible of compiling the kernel and parsing kmod
makefiles. Module makefiles are following the naming convention
<module>.mk
and are located under kern/kmodmakefiles
directory.
Module makefiles are parsed like normal makefiles but care should be
taken when changing global variables in these makefiles. Module
makefiles are mainly allowed to only append IDIR
variable and all
other variables should be more or less specific to the module makefile
itself and should begin with the name of the module.
A valid module makefile could look something like the following listing:
# Module example
# Mandatory file
# If any source files are declared like this the whole module becomes
# mandatory and won't be dropped even if its configuration is set to zero.
module-SRC-1 += src/module/test.c
# Optional file
# If all files are declared like this then the module is optional and can be
# enabled or disabled in the `config.mk`.
module-SRC-$(configMODULE_CONFIGURABLE) += src/module/source.c
# Assembly file
module-ASRC$(configMODULE_CONFIGURABLE) += src/module/lowlevel.S
The kernel makefile will automatically discover test-SRC-1
list and
will compile a new static library based on the compilation units in the
list. Name of the library is derived from the makefile’s name and so
should be the first word of the source file list name.
TODO
Userland makefiles are constructed from user_head.mk
, user_tail.mk
and the actual targets between includes. A good example of a user space
makefile is bin/Makefile
that compiles tools under /bin
. A manifest
file is automatically generated by the make system and it will be used
for creating a rootfs image with tools/mkrootfs.sh
script.
Userland program sources are mostly located under directories close to
the final location in rootfs image. Currently we only have bin
and
sbin
directories in the build but our intention is to follow FHS as
far as possible. So for example sources for init is located in
/sbin/src/sinit
directory and the final elf binary is created to
/sbin
. However if the final executable is compiled from one file
it's ok to omit the final level of the directory structure in source tree.
The build system for user programs is "fully" automated, meaning that there shouldn't be need to write any new makefiles to build new binaries.
Adding a new program to the build
-
Assuming that you have your source code files in the correct directory go to the top directory of the build tree eg.
/bin
and openMakefile
with your favorite editor. -
Add the final binary name to the list of name in
BIN
variable. -
Create a list of source file as a variable named
BINFILENAME-SRC-y
, wherey
can be replaced with$(configSOMETHING)
if compilation of the binary should be controlled by a Kconfig option.
Libc is linked by default and any other needed libraries or linker arguments
can be passed by setting BINFILENAME-LDFLAGS
in the makefile.
TODO
TODO