Build System Basics
FEATURES
Section titled “FEATURES”What is a FEATURE?
Section titled “What is a FEATURE?”A FEATURE is a mean of specifying valid/invalid dependencies and configurations.
Whenever a 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.
e.g.
# all periph features correspond to a periph submoduleUSEMODULE += $(filter periph_%,$(FEATURES_USED))Providing a FEATURE
Section titled “Providing a FEATURE”For a 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.
- Needs the “hardware” or BSP support (toolchain, build system, flasher, etc.)
- e.g.:
stm32l152rehas an SPI peripheralriotbootneeds to be able to link and flash at an offset
- e.g.:
- Needs support in RIOT, an implementation of an api to interact with the hw
- e.g.:
cpu/stm32_common/periph/spi.cis implemented forstm32l1riotbootneeds an implementation ofcpu_jump_to_image
- e.g.:
- Wiring between the cpu/soc(system on a chip) a bus and other cpu/hw components.
- e.g.:
nucleo-l152re/include/periph_conf.hspecified wiring betweenPORT_AxandSPI1
- e.g.:
All the FEATURES_%
Section titled “All the FEATURES_%”-
FEATURES_PROVIDEDare available hardware (including BSP) features (e.g.:periph_hwrng,periph_uart) or characteristics (e.g:arch_32bits) of a board. -
FEATURES_CONFLICTare a series ofFEATURESthat can’t be used at the same time for a particularBOARD. -
FEATURES_REQUIREDareFEATURESthat are needed by aMODULEorAPPLICATIONto work. -
FEATURES_OPTIONALare “nice to have”FEATURES, not needed but useful. If available they are always included. -
FEATURES_REQUIRED_ANYareFEATURESof which (at least) one of is needed by aMODULEorAPPLICATION. Alternatives are separated by a pipe (|) in order of preference, e.g.:FEATURES_REQUIRED_ANY += arch_avr8|arch_nativeif both are provide thenarch_avr8will be used. -
FEATURES_BLACKLISTareFEATURESthat can’t be used by aMODULEorAPPLICATION. They are usually used for hw characteristics likearch_to easily resolve unsupported configurations for a group. -
FEATURES_USEDare the final list ofFEATURESthat will be used by anAPPLICATION
Where to define FEATURES_%
Section titled “Where to define FEATURES_%”-
FEATURES_PROVIDED,FEATURES_CONFLICTandFEATURES_CONFLICT_MSGare defined inMakefile.features -
FEATURES_REQUIRED,FEATURES_OPTIONAL,FEATURES_REQUIRED_ANY, andFEATURES_BLACKLISTare defined by the applicationMakefile(examples/%/Makefile,tests/%/Makefile, etc.) or inMakefile.dep
CPU/CPU_MODEL
Section titled “CPU/CPU_MODEL”CPU and CPU_MODEL refer to the soc or mcu (microcontroller)
present in a BOARD. The variables CPU, 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.
A CPU/CPU_MODEL might support FEATURES that will depend on the BOARD wiring,
e.g.: bus (uart, spi) mappings. In this cases the FEATURE should be provided
by the BOARD.
In RIOTs build-system, a BOARD is a grouping of:
- soc/mcu (
CPU/CPU_MODEL)- e.g.:
b-l072z-lrwan1stm32l072cz
- e.g.:
- sensor/actuators (buttons and leds included) (
drivers)- e.g.:
b-l072z-lrwan1leds and buttons
- e.g.:
- radios, ethernet, etc. devices (
drivers)- e.g.:
b-l072z-lrwan1sx1276
- e.g.:
- programming/debugging tools
- e.g.:
b-l072z-lrwan1stlink
- e.g.:
- configuration mapping cpu support capabilities to availability
- e.g.:
b-l072z-lrwan1periph_conf.h,gpio_params
- e.g.:
A board can have all the required FEATURES to interact with a radio or
sensor/actuator, but it doesn’t necessarily provide that FEATURE.
e.g.: - samr21-xpro provides a at86rf233 radio as well as the necessary
periph_* features. - nucleo-* provide all periph_* features to use sx1272, and
even a default configuration for the SX1272MB2xA shield, but not
doesn’t provide the radio.
If a board in $(RIOTBASE)/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 board/periph_conf.
A nucleo-* with a SX1272MB2xA is a different board in RIOT sense.
note: if devicetree is implemented this concept will change.
Printing Infos, Warnings and Error Messages
Section titled “Printing Infos, Warnings and Error Messages”Many Makefiles perform checks of parameters, variables and other settings during the build process to ensure a proper operation. To inform and help the user, these messages are printed to the terminal.
The CI (Continuous Integration) and other scripts used during build process and
deployment of RIOT interpret the output of Make printed to stdout.
This output is used to determine if a compilation was successful or how big the
compiled binary file is.
To avoid confusing these scripts, informative messages and colored warnings and
errors should be printed to stderr instead.
To make printing colored messages easy, the helper functions defined in
$(RIOTBASE)/makefiles/color.inc.mk can and should be used.
Generally you have to distinguish between two function types: One can be used
during the initial phase of the Make process and the other one can be used in
recipes. The latter has to be prefixed with sh_.
# Remember to include the Makefile that defines the helpers!include $(RIOTBASE)/makefiles/color.inc.mk
# During the execution of the Makefile, you have to use `echoinfo`, `echowarn`,# ...ifeq (,$(filter periph_spi,$(FEATURES_USED))) $(call echoerr,("Can\'t proceed with the build!"\ "The feature \"periph_spi\" is required for this"\ "operation. \(You can add it to FEATURES_REQUIRED.\)"))endif
# You can colorize parts of your text with the `c_red`, `c_yellow`, `c_green`# and `c_purple` functions, but be aware that this can become difficult to write.# If you want to have white text, always start with `echoinfo`.ifneq (,$(DEPRECATED_MODULES_USED)) $(call echoinfo,($(call c_red,"Deprecated modules are in use:")\ "$(DEPRECATED_MODULES_USED)"))endif
# In recipes you have to use the `sh_` prefixed functions.clean: $(call sh_echowarn,("Deleting all your data now!"))Available Functions
Section titled “Available Functions”echoinfo- Prints information in white text to the terminal.echowarn- Prints warnings in yellow text to the terminal. Warnings should be used for everything that does not break the build.echoerr- Prints errors in red text to the terminal. Errors should be used for everything that compromises the build process or the resulting binary.echored- Prints in red text.echoyellow- Prints in yellow text.echogreen- Prints in green text.echopurple- Prints in purple text.sh_echoinfo- Same asechoinfo, but to be used in recipes.sh_...c_red,c_yellow,c_green,c_purple- Colorize part of a message.
Variables Declaration Guidelines
Section titled “Variables Declaration Guidelines”This section 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.
Avoid Unnecessary Export
Section titled “Avoid Unnecessary Export”export OUTPUT = $(shell some-command)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
makefiles/utils/variables.mk).
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.
Use Memoized for Variables Referencing a Function or Command
Section titled “Use Memoized for Variables Referencing a Function or Command”Recursively Expanded Variable
Section titled “Recursively Expanded Variable”OUTPUT = $(shell some-command $(ANOTHER_VARIABLE))-
When using
=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$(OUTPUT)is never expanded,some-commandis never executed andANOTHER_VARIABLEnot expanded. -
All variables or functions referenced by the declared variable will will be evaluated every time the variable is expanded. In the example
some-commandis executed every timeOUTPUTis expanded, same forANOTHER_VARIABLE. Ifsome-commandis slow this introduced unneeded overhead. -
If the variable expansion doesn’t involve evaluating a function the overhead is none.
Simply Expanded Variable
Section titled “Simply Expanded Variable”OUTPUT := $(shell some-command $(ANOTHER_VARIABLE))-
When using
:=the value is only expanded once, expanding any reference to other variables or functions. IfOUTPUTis always used at least once and evaluates a costly function (some command) then use:=. -
When using
:=the variable will be evaluated even if not needed, which introduces unnecessary delay, in particularsome commandor functions evaluated byANOTHER_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). -
The values of variables declared with
:=depend on the order of definition.
Memoized
Section titled “Memoized”OUTPUT = $(call memoized,OUTPUT,$(shell some-command))memoizedis a RIOT defined function that combines characteristics from both=and:=. 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 examplesome-commandwould be executed once or not at all (more inmakefiles/utils/variables.mk).
Additional Documentation
Section titled “Additional Documentation”- Deferred vs. simple expansion: http://make.mad-scientist.net/deferred-simple-variable-expansion/
- Tracking issue: #10850