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.
- Services
- Support
- string_constant - Compile-time string library with support for formatting similar to fmt/python format specifiers.
- log (wip) - Logging library.
The main branch of cib currently uses C 20 and is tested with:
- Clang 14 thru 18
- GCC 12 thru 13
An older version of cib that uses C 17 is tagged at v1.7.0. It is tested with:
- Clang 9 thru 15
- GCC 9 thru 12
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
- Compose modular firmware systems with high-level abstractions
- Perform registration of components at compile-time
- 🏎 Optimize runtime-performance and memory usage
- 🦺 Catch undefined behavior during initialization
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
- Repository: https://github.com/intel/compile-time-init-build/
- Issue tracker: https://github.com/intel/compile-time-init-build/issues
- In case of sensitive bugs like security vulnerabilities, please contact one or more of the project maintainers directly instead of using issue tracker. We value your effort to improve the security and privacy of this project!
The code in this project is licensed under the BSL-1.0 license. See LICENSE for more details.