FEATURE is a mean of specifying valid/invalid dependencies and configurations.
FEATURE is used there should be at some level a hardware requirement, whether this is a radio, a bus of a specific core architecture.
This is not a hard line, in some cases the line can be harder to establish than others. There are complicated cases like
netif since a network interface could be fully implemented in software as a loop-back.
It's also important to note that a
FEATURE does not mean there is a
MODULE with the same name. There could be many implementations for the same
FEATURE. The fact that many
FEATURES translate directly into a
MODULE is only by convenience.
# all periph features correspond to a periph submodule USEMODULE += $(filter periph_%,$(FEATURES_USED))
FEATURE to be provided by a
board it must meet 2 criteria, and for
periph_% and other hw (hardware) related
FEATURES it must follow a 3rd criteria.
stm32l152rehas an SPI peripheral
riotbootneeds to be able to link and flash at an offset
cpu/stm32_common/periph/spi.cis implemented for
riotbootneeds an implementation of
nucleo-l152re/include/periph_conf.hspecified wiring between
FEATURES_PROVIDEDare available hardware (including BSP) features (e.g.:
periph_uart) or characteristics (e.g:
arch_32bits) of a board.
FEATURES_CONFLICTare a series of
FEATURESthat can't be used at the same time for a particular
FEATURESthat are needed by a
FEATURES_OPTIONALare "nice to have"
FEATURES, not needed but useful. If available they are always included.
FEATURESthat can't be used by a
APPLCIATION. They are usually used for hw characteristics like
arch_to easily resolve unsupported configurations for a group.
FEATURES_USEDare the final list of
FEATURESthat will be used by an
FEATURES_CONFLICT_MSGare defined in
FEATURES_BLACKLISTare defined by the application
tests/%/Makfile, etc.) or in
CPU_MODEL refer to the soc or mcu (microcontroller) present in a
BOARD. The variables
CPU_FAM, etc. are just arbitrary groupings to avoid code duplication. How this grouping is done depends on every implementation and the way each manufacturer groups there products.
These variables allows declaring the
FEATURES that the mcu/soc provides as well as resolving dependencies.
FEATURES provided by a
CPU/CPU_MODEL should not depend on the wiring of a specific
BOARD but be intrinsic to the soc/mcu.
CPU/CPU_MODEL might support
FEATURES that will depend on the
BOARD wiring, e.g.: bus (
spi) mappings. In this cases the
FEATURE should be provided by the
In RIOTs build-system, a
BOARD is a grouping of:
b-l072z-lrwan1leds and buttons
board can have all the required
FEATURES to interact with a radio or sensor/actuator, but it doesn't necessarily provide that
at86rf233radio as well as the necessary
periph_*features to use
sx1272, and even a default configuration for the
SX1272MB2xAshield, but not doesn't provide the radio.
/boards is connected to a radio shield, sensors, actuators, etc. then it is a different
board than the one provided by default. Whenever you need to have a device mapping (in linux-arm, it would require a different device tree), then it is a different board and would need a different
nucleo-* with a
SX1272MB2xA is a different board in RIOT sense.
devicetree is implemented this concept will change.
This page contains basic guidelines about
make variable declaration, it summarizes some of the pros and cons as well as specifies good and bad patterns in our build system. You might want to refer to
gnu make documentation regarding these subjects.
Exporting a variable means it will be evaluated on every
target call, which slows down the build system. Always avoid exporting a variable if unneeded.
If an export is actually needed by a
sub-make then export the variable only for the needed targets using
target-export-variables (more in
Exported variables ("global variable") are hard to remove, specially when badly documented. If no one knows why it's there and no one knows where it can be used then no one knows if it's safe to remove since it's present for every target. This is why global variables need clear documentation.
=the value of the variable is only declared, but not set, therefore the variable will only be evaluated when expanded (used) somewhere in the makefile. If
is never expanded,
some-commandis never executed and
some-commandis executed every time
OUTPUTis expanded, same for
some-commandis slow this introduced unneeded overhead.
:=the value is only expanded once, expanding any reference to other variables or functions. If
OUTPUTis always used at least once and evaluates a costly function (
some command) then use
:=the variable will be evaluated even if not needed, which introduces unnecessary delay, in particular
some commandor functions evaluated by
ANOTHER_VARIABLEare slow. It can also cause a failure in a worst-case scenario (think what happens if a tool is defined with
:=but you don't have the tool and you don't need it either).
:=depend on the order of definition.
memoizedis a RIOT defined function that combines characteristics from both
:=. The variable expansion will be deferred until its first usage, but further usage will consider it as a simply expanded variable, so it will use the already evaluated value. In the example
some-commandwould be executed once or not at all (more in