cib is a C++ header-only library for building embedded firmware with reusable components. It implements the compile-time initialization and build pattern. Instead of initializing components and registering callbacks at runtime, this process is executed at compile-time using constexpr or consteval functions.
Firmware using cib is implemented as a collection of components. Each component provides services and features to the build. Component features extend and provide new functionality to services.
There are multiple sub-projects contained within cib. Some of them are used to implement cib and others extend cib.
The main branch of cib currently uses C++20 and is tested with:
An older version of cib that uses C++17 is tagged at v1.7.0. It is tested with:
For the older version see this repo at that tag.
The recommended way to use cib is with CMake and CPM. With this method,add the following to your CMakeLists.txt:
CPMAddPackage("gh:intel/compile-time-init-build#047aab6")
target_link_libraries(your_target PRIVATE cib)
Where 047aab6
is the git hash (or tag, or branch) that you want to use.
cib is also released as a single header file as well as the zipped github repo. To get started quickly, download the cib.hpp header from the release area:
wget https://github.com/intel/compile-time-init-build/releases/download/v1.0.0/cib.hpp
Another option is to include cib as a git submodule in your repo and add the cib directory in your CMakeLists.txt file:
add_subdirectory(extern/compile-time-init-build)
target_link_libraries(your_target PRIVATE cib)
With any of these methods, include the cib.hpp header in your code to use it.
Since cib is a library for efficiently building firmware through composition a simple example takes a few more lines than a typical "Hello, world!"
#include <cib/cib.hpp>
#include <iostream>
struct say_message : public cib::callback_meta<>{};
// the 'core' component exposes the 'say_message' service for others to extend
struct core {
constexpr static auto config = cib::exports<say_message>;
};
// the 'say_hello_world' component extends 'say_message' with its own functionality
struct say_hello_world {
constexpr static auto config =
cib::extend<say_message>([](){
std::cout << "Hello, world!" << std::endl;
});
};
// the 'hello_world' project composes 'core' and 'say_hello_world'
struct hello_world {
constexpr static auto config =
cib::components<core, say_hello_world>;
};
// the nexus instantiates the project
cib::nexus<hello_world> nexus{};
int main() {
// the fully extended and built services are ready to be used
nexus.service<say_message>();
return 0;
}
Try out this example live at Compiler Explorer.
A larger and more illustrative example can be found in this repo at examples/hello_world.
For more details on how to use cib, see the User Guide.
cib is built with CMake. The single header is built with the
release_header
target:
git clone https://github.com/intel/compile-time-init-build.git
cmake -B build
cmake --build build -t release_header
ls build/include/cib/ | grep cib.hpp
This combines all the cib header files in the include
tree by recursively
including the #include
directives and ignoring all other macros.
NOTE: cib uses CPM.cmake to
fetch its dependencies. When first running cmake
, the dependencies will be
downloaded. To avoid re-downloading dependencies when reconfiguring cmake, it's
recommended to designate a cache directory and set the CPM_SOURCE_CACHE
environment variable.
Unit tests are registered with CTest, and will build and run as part of the
built-in all
target.
cmake -B build
cmake --build build
This will build and run all the unit tests with Catch2 and GTest. To re-run them:
ctest --test-dir build
See the full documentation.
If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.
For more details on contributing, please see CONTRIBUTING.md
The code in this project is licensed under the BSL-1.0 license. See LICENSE for more details.