SBS (Skyward Build System) is the build system used in Skyward Experimental Rocketry to compile its firmwares, which are written for Miosix (the in-house OS) and need to be built for specific boards.
SBS is based on CMake: it is made of CMake modules that include the necessary dependencies and define functions that allow to specify SBS targets and their respective target boards.
Creating a new SBS project
An SBS project is first of all a CMake project, therefore you need to create a file CMakeLists.txt
in the project root folder.
In order to use SBS in the CMake project, you need to add Skyward Boardcore as a recursive Git submodule:
git clone --recursive https://git.skywarder.eu/scs/skyward-boardcore.git <skyward_boardcore_path>
The placeholder
<skyward_boardcore_path>
refers to the relative path of the folder of Skyward Boardcore. It is common practice to place Skyward Boardcore into the subfolderlibs
of the project root folder.
Once you cloned Skyward Boardcore, you need to include the SBS CMake module sbs.cmake
, located in the folder cmake
of Skyward Boardcore, in the file CMakeLists.txt
of your project:
include(<skyward_boardcore_path>/cmake/sbs.cmake)
As a reference for how to structure the file
CMakeLists.txt
, you can take a look at the file used for Skyward Boardcore.
cmake/dependencies.cmake
An optional file dependencies.cmake
can be added into the subfolder cmake
of the project root folder in order to define variables and targets on which the targets of the project depend. Module sbs.cmake
first includes dependencies.cmake
inside Skyward Boardcore and then it automatically includes dependencies.cmake
in the subfolder cmake
of the project root folder, if it exists.
In CMake you use add_subdirectory()
to load a CMake-based external library:
add_subdirectory(<lib_directory> EXCLUDE_FROM_ALL)
It is common practice to add libraries as Git submodules into the subfolder
libs
of the project root folder.
You can use CMake variables to define groups of sources that refer to a common purpose, so that they can be referred to when defining targets:
set(<NAME_OF_THE_GROUP>_SOURCES
file1
file2
...
)
CMakeLists.txt
The file CMakeLists.txt
in the project root folder defines how to compile each target.
In CMake you use:
-
add_executable()
to define an executable target -
target_include_directories()
to specify its include directories -
target_link_libraries()
to specify the libraries to which to link it -
target_compile_definitions()
to specify its compile definitions
SBS adds the function sbs_target()
that defines an executable as SBS target, i.e. a board firmware linked to Skyward Boardcore (and recursively to Miosix and its other dependencies).
add_executable(<executable_name> <sources...>)
target_include_directories(<executable_name> PRIVATE <directories...>)
target_link_libraries(<executable_name> PRIVATE <libraries...>)
target_compile_definitions(<executable_name> PRIVATE <definitions...>)
sbs_target(<executable_name> <board_id>)
It is common practice to categorize SBS targets as either entrypoints (located in
src/entrypoints
) or tests (located insrc/tests
).
Note
A typical folder structure for an SBS project is:
your-project/
|_ build/
|_ libs/
| |_ skyward-boardcore/
|_ src/
| |_ entrypoints/
| |_ tests/
|_ CMakeLists.txt
Building
To build the targets of an SBS project you use CMake:
mkdir build
cd build
cmake -DCMAKE_TOOLCHAIN_FILE=<skyward_boardcore_path>/libs/miosix-kernel/miosix/_tools/toolchain.cmake ..
cmake --build .
To simplify the steps necessary to build the targets and lint the code, an SBS script written in Bash is provided that wraps the CMake commands.
Prompting ./sbs -h
will print the help message.
To build all the targets with the SBS script you just need to do:
./sbs
To build a specific target (not necessarily a board firmware) you can do:
./sbs -b <target>
The SBS script automatically looks for Ccache and Ninja and in case it finds them it sets the appropriate options of the CMake configure command to use them, speeding up the build phase.
To get a list of the available entrypoints you can use the -l
option. To get a list of the available boards you can use the -r
option.
SBS Internals
Normally, to compile code with Miosix you would have to choose the target board in miosix/config
and execute Miosix's Makefile (see the Miosix Guide).
Standard MIOSIX build
-
Makefile: main Makefile, used to compile the main.cpp. Lists the files to compile (
SRC:=
), the libraries to include (INCLUDE:=
) and the directories to include (INCLUDE_DIRS:=
). - miosix/Makefile: Makefile for the kernel sources.
- miosix/config/Makefile.inc: specifies compiler flags, the target board and all board-specific configurations (Clock speed, linker script location, XRAM etc...).
graph TD;
subgraph miosix-kernel
subgraph miosix
miosixMakefile[Makefile]
subgraph config
configMakefile.inc[Makefile.inc]
end
end
Makefile -- execute --> miosixMakefile
Makefile -- include --> configMakefile.inc
end
SBS Build
The SBS build works as follows:
- From your project folder, you execute the SBS script
<skyward_boardcore_path>/sbs
(or a calling script./sbs
) - The SBS script executes
cmake
specifying the Miosix Toolchain File and the appropriate options - CMake configures the project by loading
CMakeLists.txt
-
CMakeLists.txt
includes<skyward_boardcore_path>/cmake/sbs.cmake
, which recursively configures the project of Skyward Boardcore by loading its fileCMakeLists.txt
- The project of Skyward Boardcore includes
<skyward_boardcore_path>/cmake/boardcore.cmake
, which includes<skyward_boardcore_path>/cmake/dependencies.cmake
-
<skyward_boardcore_path>/cmake/dependencies.cmake
recursively configures the project of Miosix by loading its fileCMakeLists.txt
and other external libraries - The project of Miosix configures a library for each board, by loading the options defined in
<skyward_boardcore_path>/libs/miosix-kernel/miosix/config/options.cmake
-
<skyward_boardcore_path>/cmake/sbs.cmake
includescmake/dependencies.cmake
in the root project folder - CMake builds each target of the project, including the entrypoints and the tests defined with
sbs_target()
graph TD;
subgraph CMake
cmake
end
subgraph Project
sbs
CMakeLists.txt
subgraph proj/cmake[cmake]
dependencies.cmake
end
subgraph src
entrypoint1
entrypoint2
src...[...]
end
subgraph build
entrypoint1.bin
entrypoint2.bin
build...[...]
end
subgraph libs/skyward-boardcore
b/sbs[sbs]
b/CMakeLists.txt[CMakeLists.txt]
subgraph b/cmake[cmake]
b/boardcore.cmake[boardcore.cmake]
b/dependencies.cmake[dependencies.cmake]
b/sbs.cmake[sbs.cmake]
end
subgraph libs/miosix-kernel/miosix
m/CMakeLists.txt[CMakeLists.txt]
m/options.cmake[config/options.cmake]
m/toolchain.cmake[_tools/toolchain.cmake]
end
end
end
sbs -- execute --> b/sbs
b/sbs -- execute --> cmake
cmake -- use --> m/toolchain.cmake
cmake -- configure --> CMakeLists.txt
CMakeLists.txt -- include --> b/sbs.cmake
b/sbs.cmake -- add_subdirectory --> b/CMakeLists.txt
b/CMakeLists.txt -- include --> b/boardcore.cmake
b/boardcore.cmake -- include --> b/dependencies.cmake
b/dependencies.cmake -- add_subdirectory --> m/CMakeLists.txt
m/CMakeLists.txt -- ... for each board ... --> m/options.cmake
b/sbs.cmake -- include --> dependencies.cmake
CMakeLists.txt -- sbs_target --> entrypoint1
CMakeLists.txt -- sbs_target --> entrypoint2
cmake -- build --> entrypoint1
entrypoint1 --> entrypoint1.bin
cmake -- build --> entrypoint2
entrypoint2 --> entrypoint2.bin