It is possible to have an out-of-tree build of parts of the crazyflie firmware. This enables developers to work on elements without worrying about merging it with the full code base.
General out-of-tree build process
In a separate folder create a Makefile which contain the following content:
CRAZYFLIE_BASE := [LOCATION OF THE CRAZYFLIE FIRMWARE]
#
# We override the default OOT_CONFIG here, we could also name our config
# to oot-config and that would be the default.
#
OOT_CONFIG := $(PWD)/config
include $(CRAZYFLIE_BASE)/tools/make/oot.mk
This will make the crazyflie-firmware build system look for a Kbuild file in your folder.
The following variables are understood by oot.mk:
| Variable | Function | Default |
|---|---|---|
OOT |
Specify where your code (Kbuild file) is located. |
$(PWD) (Your current directory) |
OOT_CONFIG |
Location of your OOT specific Kconfig file, will be merged with the default config. |
$(OOT)/oot-config |
EXTRA_CFLAGS |
Extra CFLAGS needed by your app | Empty. |
And oot.mk also expects $(CRAZYFLIE_BASE) to be set to the path to the crazyflie-firmware repository.
The Kbuild file in the $(OOT) folder should point out your source files:
obj-y += your_estimator_out_of_tree.o
It can also point out another folder where the code resides:
obj-y += src/
If you have header files in another folder, use EXTRA_CFLAGS in the Makefile to let the compiler know where to find them:
EXTRA_CFLAGS += -I$(PWD)/src/inc
Overriding in-tree headers
If you need to override a header that lives inside the main firmware tree
(for example to tweak the PID gains or physical constants in
platform_defaults_cf2.h for your build, without editing the in-tree file),
place your replacement in an overrides folder next to your OOT Makefile.
$(OOT)/overrides is searched before every other include path, so a file
placed there is picked up instead of its in-tree namesake, for the whole
firmware build — not just your own OOT sources.
This only works for a header that is #included (with quotes) from a file
outside the directory the header itself lives in — the C preprocessor
always checks the includer’s own directory first, before any -I path, so a
header included by a neighbour in the same directory can never be shadowed
this way.
platform_defaults_cf2.h (and its sibling platform headers) is not
directly shadowable by this rule: it’s only ever included from
platform_defaults.h, which lives right next to it in
src/platform/interface. Overriding it therefore requires overriding
both files together:
your_oot_folder/
├── Makefile
├── overrides/
│ ├── platform_defaults.h # unmodified copy of the in-tree file
│ └── platform_defaults_cf2.h # your changes go here
└── ...
platform_defaults.h itself is directly shadowable, since it’s included
from files spread across src/hal, src/drivers, src/modules, etc. — none
of which live in src/platform/interface. Once your copy of it is the one
being compiled, its own #include "platform_defaults_cf2.h" resolves
relative to its location (overrides/), which is what lets your copy of
platform_defaults_cf2.h be found in turn.
OOT builds can be configured with Kbuild using terminal interfaces like make menuconfig or by loading a default configuration, such as with make cf2_defconfig. Any definitions in $(OOT_CONFIG) will override conflicting settings.
Note: If you are using macOS you may encounter errors when trying to build your app, such as:
readlink: illegal option -- m sed: invalid command code . cp: illegal option -- TThis happens because the app-layer build expects the GNU versions of
readlink,sedandcp. To fix the errors, install and use the GNU utilities:brew install coreutils gnu-sed
OOT estimators
The config file needs to enable ESTIMATOR_OOT, and can also set other config options:
CONFIG_ESTIMATOR_OOT=y
in [your_estimator_out_of_tree].c in the src folder you will just need to make sure that the following functions are implemented:
init = estimatorOutOfTreeInittest = estimatorOutOfTreeTestupdate = estimatorOutOfTree
OOT Controllers
The config file needs to enable CONTROLLER_OOT, and can also set other config options:
CONFIG_CONTROLLER_OOT=y
in [your_controller_out_of_tree].c in the src folder you will just need to make sure that the following functions are implemented:
init = controllerOutOfTreeInittest = controllerOutOfTreeTestupdate = controllerOutOfTree
App layer
Technically the app layer is an example of an out of tree build. Follow the app layer instructions for this.