7. Build Process¶
foxBMS uses waf The meta build system
for building binaries for the
foxBMS MCUs and the documentation.
For detailed information on waf
see waf.io. A short
introcution to waf
is given at
waf.io/apidocs/tutorial.
The more detailed version of how to use waf
is found at
waf.io/book.
7.1. General¶
7.1.1. Where to find the toolchain?¶
The waf
toolchain is located in directory foxbms-setup\tools
, and is
`waf
. This archive is automatically unpacked in a directory named
something like waf-{{X}}-{{X}}-{{X}}-{{some-hash-value}}
containing the waf
library, where {{X}}
is the waf version. It is unpacked into foxbms\tools
.
It is assumed that all commands are run from directory foxbms
.
Therefore waf
has to be always called by python tools\waf some-command
where some-command
is an argument defined in the wscript
.
Additional build tools are located in foxbms-setup\tools\waftools
. These are
the tooles needed for building the documentation, i.e., doxygen
and
sphinx
.
7.1.2. Where are the build steps described?¶
The build process is described in files named wscript
, that can be found
nearly everywhere inside the different directories inside the foxBMS project.
Later in this documentation this is explained in detail.
7.1.3. General¶
waf
needs always to be run form the top level of the repository and the path
to waf must be given relative to that directory. This path is tools\waf
.
cd path\to\foxbms
python tools\waf {{some command}}
7.1.4. What commands can be used?¶
To get an overview of support commands run --help
on the waf
library:
python tools\waf --help
waf [commands] [options]
Main commands (example: ./waf build -j4)
build : executes the build
build_primary : executes the build of primary
build_secondary : executes the build of secondary
clean : cleans the project
clean_primary : cleans the project primary
clean_secondary : cleans the project secondary
configure : configures the project
dist : creates an archive containing the project source code
distcheck : checks if the project compiles (tarball from 'dist')
distclean : removes the build directory
doxygen : creates doxygen documentation
doxygen_primary : creates the doxygen documentation of primary
doxygen_secondary : creates the doxygen documentation of secondary
list : lists the targets to execute
list_primary : lists the targets to execute for primary
list_secondary : lists the targets to execute for secondary
sphinx : creates the sphinx documentation of the project
step : executes tasks in a step-by-step fashion, for debugging
step_primary : executes tasks in a step-by-step fashion, for debugging of primary
step_secondary : executes tasks in a step-by-step fashion, for debugging of secondary
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-c COLORS, --color=COLORS
whether to use colors (yes/no/auto) [default: auto]
-j JOBS, --jobs=JOBS amount of parallel jobs (8)
-v, --verbose verbosity level -v -vv or -vvv [default: 0]
-t TARGET, --target=TARGET
build target: debug (default)/release
Configuration options:
Build and installation options:
-p, --progress -p: progress bar; -pp: ide output
Step options:
--files=FILES files to process, by regexp, e.g. "*/main.c,*/test/main.o"
Installation and uninstallation options:
--distcheck-args=ARGS
arguments to pass to distcheck
Before building any binaries or documentation is possible, the project needs to
be configured. A successfull configure
command and its ouput is shown below:
python tools\waf configure
(...)
'configure' finished successfully (0.340s)
Note
This configuration step is automaticcaly performed when using the bootstrap
script bootstrap.py
.
After the project has been configured, a build can be triggered and it is
generally exectued by the build
command, but as foxBMS requries building
variants, one has to use e.g., build_primary
in order to build binaries
for the primary MCU.
python tools\waf build
Waf: Entering directory `.\foxbms-setup\build'
A build variant must be specified, run 'python tools\waf --help'
python tools\waf build_primary
(...)
'build_primary' finished successfully (8.800s)
The possible build
commands, the definition of the and corresponding targets
and the targets itself is listet below:
- Primary MCU
python tools\waf build_primary
The targets are defined at:
foxbms-setup\embedded-software\mcu-primary\src\application\wscript
foxbms-setup\embedded-software\mcu-common\src\engine\wscript
foxbms-setup\embedded-software\mcu-common\src\module\wscript
foxbms-setup\embedded-software\mcu-primary\src\engine\wscript
foxbms-setup\embedded-software\mcu-primary\src\module\wscript
foxbms-setup\embedded-software\mcu-freertos\wscript
foxbms-setup\embedded-software\mcu-hal\STM32F4xx_HAL_Driver\wscript
foxbms-setup\embedded-software\mcu-primary\src\general\wscript
foxbms-application foxbms-common-engine foxbms-common-module foxbms-engine foxbms-module foxbms-os foxbms-stmhal foxbms_primary.elf 'list_primary' finished successfully (0.040s)
- Secondary MCU
python tools\waf build_secondary
The targets are defined at:
foxbms-setup\embedded-software\mcu-secondary\src\application\wscript
foxbms-setup\embedded-software\mcu-common\src\engine\wscript
foxbms-setup\embedded-software\mcu-common\src\module\wscript
foxbms-setup\embedded-software\mcu-secondary\src\engine\wscript
foxbms-setup\embedded-software\mcu-secondary\src\module\wscript
foxbms-setup\embedded-software\mcu-freertos\wscript
foxbms-setup\embedded-software\mcu-hal\STM32F4xx_HAL_Driver\wscript
foxbms-setup\embedded-software\mcu-secondary\src\general\wscript
foxbms-application foxbms-common-engine foxbms-common-module foxbms-engine foxbms-module foxbms-os foxbms-stmhal foxbms_secondary.elf 'list_secondary' finished successfully (0.070s)
- General documentation
The general documenation is build by
python tools\waf sphinx
- API documentation
The API documentation is build using the
doxygen_{{variant}}
, thereforepython tools\waf doxygen_primary python tools\waf doxygen_secondary
- Cleaning
It is also possible to clean the binaries and Doxygen documentation. This step is performed by the
clean
command.As seen from
--help
the possibleclean
commands areclean_primary
clean_secondary
distclean
Cleaning the general sphinx documentation alone is currently not supported. However it is possible to make a complete clean by
distclean
. After distclean the entire build direcory and all lock files etc. are deleted and the project needs to be configured again.
7.2. Targets¶
As stated above thetargets and subtargets of the build process are shown by
list_x
where x
is the specified target. The main target is the *.elf
file. However some targets are build afterwards. After successfully linking the
map file is generated.
These logging files are found in build
and build\{{target}}
.
Addiotional to the *.elf
file a *.hex
of the binary is generated.
The *.hex
is needed, as it is used to calculate the checksum of the binary.
Afterwards the calculted checksum is written back into the *.elf
and
*.hex
files. Based on this binary the flash
and flashheader
are
generated by gcc’s objcopy
. The implementation of this can be found in
foxbms-setup\\tools\\chksum\*
: All files in are neeedfoxbms-setup\\wscript
: See implementation ofdef add_chksum_task(self)
andclass chksum(Task.Task)
.
In a post build step the size
is run on all binaries and generates a
logfile.
7.3. Build Process¶
Note
For testing the following explanations it is assumed that
python tools\waf configure
has been run.
This sections gives an overview how the build process is defined. All features
are generally defined in the top wscript
located at
foxbms-setup\wscript
.
The minimum of functions that need to be defined to build are in waf
configure
andbuild
.
As the toolchain needs more targets the following functions need to be
implemented: options
, size
, dist
, doxygen
, sphinx
.
Furthermore functions and classes for calculataing the checksum (chksum
,
add_chksum_task
), stripping debug symbols in release mode (strip
,
add_strip_task
), creating a hex
file from the elf
file (hexgen
,
add_hexgen_task
), generating bin
files from elf
files
(binflashheadergen
, binflashgen
, add_bingen_task
) and compiling
assembler files (Sasm
, asm_hook
).
For implemenation details see the wscript
itself.
Some of these functionalities require scripts from foxbms-setup\tools
.

7.3.1. General Documentation¶
This build target uses the function def sphinx(bld)
. Since this
definition of a function called sphinx
, it is accepted as command to waf.
This general documentation is generated by running
python tools\waf sphinx
The implementation details of the sphinx
command can be found in
foxbms-setup\tools\waftools\sphinx_build.py
.
7.3.2. Primary and Secondary Binaries and Doxygen Documentation¶
In order to have different build variants, these variants have to be defined.
This is done at the top of the main wscript
at foxbms-setup\wscript
. The
variants have to be defined for the binary build and Doxygen documentation.
from waflib.Build import BuildContext, CleanContext, InstallContext, \
UninstallContext, ListContext, StepContext
for x in variants:
for y in (
BuildContext,
CleanContext,
InstallContext,
UninstallContext,
ListContext,
StepContext
):
name = y.__name__.replace('Context','').lower()
class tmp(y):
if name == 'build':
__doc__ = '''executes the {} of {}'''.format(name, x)
elif name == 'clean':
__doc__ = '''cleans the project {}'''.format(x)
elif name == 'install' or name == 'uninstall':
__doc__ = '''CURRENTLY NOT SUPPORTED:{}s the project {}'''.format(name, x)
elif name == 'list':
__doc__ = '''lists the targets to execute for {}'''.format(x)
elif name == 'step':
__doc__ = '''executes tasks in a step-by-step fashion, for \
debugging of {}'''.format(x)
cmd = name + '_' + x
variant = x
dox = 'doxygen'
class tmp(BuildContext):
__doc__ = '''creates the {} documentation of {}'''.format(dox, x)
cmd = dox + '_' + x
fun = dox
variant = x
In the function build and doxygen the build variant is checked, the the correct sources are selected. If no build variant is specified, an error message is displayed, telling to specify a variant. This is generally implemented something like this:
def build(bld):
import sys
import logging
from waflib import Logs
if not bld.variant:
bld.fatal('A {} variant must be specified, run \'{} {} --help\'\
'.format(bld.cmd, sys.executable, sys.argv[0]))
bld.env.__sw_dir = os.path.normpath('embedded-software')
src_dir = os.path.normpath('mcu-{}'.format(bld.variant))
ldscript = os.path.join(bld.env.__sw_dir, src_dir, 'src', bld.env.ldscript_filename)
For doxygen it is implemented very similar:
def doxygen(bld):
import sys
import logging
from waflib import Logs
if not bld.variant:
bld.fatal('A build variant must be specified, run \'{} {} --help\'\
'.format(sys.executable, sys.argv[0]))
if not bld.env.DOXYGEN:
bld.fatal('Doxygen was not configured. Run \'{} {} --help\'\
'.format(sys.executable, sys.argv[0]))
_docbuilddir = os.path.normpath(bld.bldnode.abspath())
doxygen_conf_dir = os.path.join('documentation', 'doxygen')
os.makedirs(_docbuilddir, exist_ok=True)
conf_file = 'doxygen-{}.conf'.format(bld.variant)
doxygenconf = os.path.join(doxygen_conf_dir, conf_file)
7.4. wscripts¶
As mentioned above, the build process is described in wscript
s, which are
itself valid python scripts.
The top is foxbms-setup\wscript
which defines the functions needed for the
build, e.g., configure
, build
etc.
From the top wscript
the other wscript
s are called recursive by
bld.recurse(..)
.
To get a detailed view on the single build steps, see these files.