SPLED is a Software Product Line (SPL) demonstrating variant-based configuration management. Each variant (Disco, Sleep, Spa, etc.) compiles into separate binaries using shared components with different feature configurations.
Key architectural concepts:
- Variants: Product configurations in
variants/<VariantName>/containingconfig.txt(KConfig features),parts.cmake(component selection), andconfig.cmake(CMake settings) - Components: Modular C code in
components/<name>/with CMakeLists.txt using SPL-specific macros - Build Kits:
prod(production C code) vstest(C++ with GoogleTest for unit testing) - Feature Configuration: KConfig system (
KConfigfile) drives conditional compilation via CMake variables
Windows:
- Run
.\build.ps1 -installto install dependencies - Start VS Code with
.\build.ps1 -startVSCode
Linux/macOS:
- Run
./build.sh --installormake installto install dependencies - Start VS Code with
./build.sh --start-vscodeormake vscode - See BUILD_LINUX.md for detailed Linux instructions
When to re-run installation:
- First cloning the repository
- Switching branches (dependencies may have changed)
- After pulling updates
This ensures proper environment variables and Python virtual environment activation (.venv with Poetry dependencies).
VS Code users can build directly using the CMake extension via .vscode configuration files:
- Build Kit selection (
.vscode/cmake-kits.json): Choose betweenprod(production C code) andtest(GTest C++ unit tests) - Variant selection (
.vscode/cmake-variants.json): Select variant (Disco, Spa, Sleep, Base/Dev, IDEA/Sloemada) and build type (Debug/Release) - CMake settings (
.vscode/settings.json): Configures build directory patternbuild/${variant}/${buildKit}/${buildType}, Ninja generator, and passes BUILD_KIT/BUILD_TYPE variables to CMake - Use CMake extension's status bar to select kit/variant/build type, then build using CMake commands or tasks
Windows (PowerShell):
# Interactive variant selection
.\build.ps1 -build
# Specific variant
.\build.ps1 -build -variants Disco
# Clean build
.\build.ps1 -build -variants Spa -clean
# Test build (includes unit tests)
.\build.ps1 -build -buildKit test -buildType DebugLinux/macOS (Bash/Make):
# Using bash script (same as PowerShell)
./build.sh --build --variants Disco
./build.sh --build --variants Spa --clean
./build.sh --build --build-kit test --build-type Debug
# Using Makefile (shortcuts)
make disco # Build Disco variant
make build VARIANT=Spa # Build Spa variant
make build-clean VARIANT=Spa # Clean build
make test-build VARIANT=Disco # Build with test kitBuild outputs: build/<VariantName>/<BuildKit>/<BuildType?>/
Tests are Python-based using pytest for build validation and report checks:
Windows:
# Run all tests
.\build.ps1 -selftests
# Filtered tests
.\build.ps1 -selftests -filter "Disco"
# Specific markers (see pytest.ini)
.\build.ps1 -selftests -marker "build_debug"Linux/macOS:
# Using bash script
./build.sh --selftests --filter "Disco"
# Using Makefile
make test # All tests
make test-disco # Disco tests only
make test-filter FILTER="Disco" # Custom filterComponent unit tests: GTest/GMock in components/*/test/*.cc files, run via test build kit.
View reports: Use tasks "Open variant test report" / "Open variant coverage report" from VS Code.
Component CMakeLists.txt files use spl-core macros (not standard CMake):
# Add source files (production code)
spl_add_source(src/my_component.c)
# Add test files (GTest, only in test build kit)
spl_add_test_source(test/test_my_component.cc)
# Declare dependencies on other components
spl_add_required_interface(components/rte)
# Finalize component (must be last)
spl_create_component(LONG_NAME "My Component")Conditional dependencies use KConfig variables from config.txt:
if(AUTO_OFF STREQUAL "True")
spl_add_required_interface(components/auto_off)
endif()Variant's parts.cmake lists components with spl_add_component(components/<name>).
Features defined in KConfig (menuconfig syntax) generate CMake variables via config.txt:
CONFIG_BLINKING=y→ CMake variableBLINKING="True"# CONFIG_AUTO_OFF is not set→ CMake variableAUTO_OFF="False"
Edit feature config: .\build.ps1 -command "guiconfig" (requires KCONFIG_CONFIG env var set to variant's config.txt).
Check feature values in source code via generated autoconf.h header.
- No direct CMake invocation: Always use build wrapper (
build.ps1on Windows,build.shormakeon Linux) - handles variant selection, environment, Poetry, etc. - Component isolation: Each component has own CMakeLists.txt, must declare all dependencies explicitly
- Test location: Python integration tests in
test/<VariantName>/, C++ unit tests incomponents/*/test/ - Dependency management: Python deps via Poetry (
pyproject.toml), C/C++ external deps fetched by CMake FetchContent
- RTE (Runtime Environment):
components/rte- shared interfaces, all components depend on it - Main entry:
components/main/src/main.c- calls OS scheduler - OS abstraction:
components/os- simple task scheduler (configurable period via KConfig) - Platform types:
components/platform_types- standard types (uint8_t, etc.)
Components communicate via RTE signals/runnable interfaces (see rte.h for patterns).
- build.ps1 - Windows build/test wrapper
- build.sh - Linux/macOS build/test wrapper
- Makefile - Convenient shortcuts for common tasks (Linux/macOS)
- BUILD_LINUX.md - Linux-specific build instructions
- CMakeLists.txt - Includes variant config and spl-core framework
- KConfig - Feature model definition
- variants/Disco/parts.cmake - Example component selection
- components/spled/CMakeLists.txt - Example conditional dependencies
- test/Disco/test_Disco.py - Example pytest structure using
SplBuildhelper