mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Includes C++26 related infrastructure macros. Fixes compile errors when compiling under C++26. Initially supported C++26 features: - [[indeterminate]] - new 2022 ISO prefixes in ratio.h - atomic fetch_max() and fetch_min() - is_virtual_base_of - is_trivially_relocatable and trivially_relocate - saturation arithmetic: add_sat, sub_sat, mul_sat, div_sat, saturate_cast
268 lines
12 KiB
Markdown
268 lines
12 KiB
Markdown
#  Embedded Template Library (ETL)
|
||
|
||

|
||
[](https://img.shields.io/github/release-date/jwellbelove/etl?color=%231182c3)
|
||
[](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)
|
||
[](https://opensource.org/licenses/MIT)
|
||

|
||

|
||

|
||
|
||

|
||
|
||

|
||

|
||

|
||

|
||

|
||

|
||

|
||
|
||

|
||

|
||

|
||

|
||

|
||

|
||

|
||
|
||
[](https://www.codacy.com/manual/jwellbelove/etl?utm_source=github.com&utm_medium=referral&utm_content=ETLCPP/etl&utm_campaign=Badge_Grade)
|
||
|
||
[](https://www.etlcpp.com/sponsor.html)
|
||
|
||
[Project documentation](https://www.etlcpp.com/)
|
||
|
||
## Motivation
|
||
|
||
C++ is a powerful language for embedded systems development, with templates offering a great deal of flexibility and type safety. While the C++ Standard Library provides a wealth of well-tested functionality, it’s often not well suited to environments with strict deterministic behavior and limited resources.
|
||
|
||
In many embedded applications, dynamic memory allocation is discouraged or outright prohibited, making standard STL containers and many other components impractical or unusable.
|
||
|
||
What’s needed is a template library specifically designed for embedded systems — one that allows developers to define fixed or maximum sizes for containers and other objects at compile time. Additionally, since many embedded toolchains still lack full support for standards beyond C++03, it's valuable to have access to a library that backports select features from later versions of the C++ Standard Library.
|
||
|
||
## About the ETL
|
||
|
||
The Embedded Template Library (ETL) is not intended as a full replacement for the C++ Standard Template Library (STL), but rather as a complementary solution tailored specifically for embedded systems.
|
||
|
||
Its design goals include:
|
||
|
||
- Providing a set of containers with fixed or maximum sizes defined at compile-time.
|
||
|
||
- Offering APIs that closely resemble those of the STL, enabling familiar and consistent usage.
|
||
|
||
- Maintaining compatibility with C++98 while implementing many features introduced in later standards
|
||
(C++11/14/17/20/23/26) where possible.
|
||
|
||
- Ensuring deterministic behavior, which is critical in real-time and resource-constrained environments.
|
||
|
||
- Introducing additional components and utilities useful in embedded contexts but absent from the STL.
|
||
|
||
The ETL avoids dynamic memory allocation entirely; the heap is never used. All non-intrusive containers have a fixed capacity, allowing memory requirements to be fully determined at compile-time. This makes the ETL ideal for lower-resource embedded applications where predictability, performance, and memory control are essential.
|
||
|
||
The library is compatible with any compiler that supports C++03 or later.
|
||
|
||
Help on integrating the ETL with your project may be found here.
|
||
|
||
|
||
## Key features of the ETL
|
||
|
||
- Actively Maintained: Developed and maintained on GitHub since 2014.
|
||
|
||
- Open Source: MIT licensed.
|
||
|
||
- No STL Dependency: Designed to operate independently of the C++ Standard Template Library.
|
||
|
||
- No Dynamic Memory Allocation: All storage is allocated either at compile-time or on the stack; heap usage is entirely avoided.
|
||
|
||
- RTTI and Virtual Functions: No runtime type information (RTTI) is required. Virtual functions are used sparingly and only when strictly necessary.
|
||
|
||
- Header-Only Library: All functionality is provided via header files; No separate compilation needed.
|
||
|
||
- Fixed-Capacity Containers: Offers STL-like containers with fixed or maximum capacity, plus additional non-standard container types.
|
||
|
||
- Cache Efficiency: Containers use contiguous memory layouts for optimal cache performance.
|
||
|
||
- Compact Codebase: Shared base classes (based on type) help reduce overall container code size.
|
||
|
||
- Compile-Time Features:
|
||
- Templated compile-time constants
|
||
- Template-based design pattern base classes (e.g., Visitor, Observer)
|
||
- Type-safe smart enumerations
|
||
- Type-safe typedefs and constants
|
||
|
||
- Embedded System Frameworks:
|
||
- Message routing
|
||
- Finite state machines
|
||
- Task scheduling
|
||
|
||
- C++11 Backports: Implements many C++11 features (type traits, algorithms, containers) for use in C++03 environments.
|
||
|
||
- Utilities:
|
||
- CRC calculations (8, 16, 32 & 64-bit)
|
||
- Checksums and hash functions
|
||
- Variants (type-safe unions)
|
||
- Extensive template support utilities
|
||
|
||
- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; user’s choice.
|
||
|
||
- Thoroughly Tested:
|
||
- Over 10,000 unit tests
|
||
- Tested with Visual Studio 2022, GCC 12, and Clang 14
|
||
- Continuous integration via GitHub Actions.
|
||
|
||
- Readable and Well-Documented: Clean, maintainable source code with clear documentation.
|
||
|
||
- Support: Free email support available. A Slack group is available. Paid support on request.
|
||
|
||
- Archived: A snapshot of the ETL is preserved in the Arctic Code Vault for long-term digital preservation.
|
||
|
||
Any help porting the library to work under different platforms and compilers would be gratefully received.
|
||
I am especially interested in people who are using Keil, IAR, Green Hills, TI Code Composer etc, bare metal or RTOS, and DSPs.
|
||
|
||
See (https://www.etlcpp.com) for up-to-date information.
|
||
|
||
## Installing this library
|
||
|
||
You can find the setup steps [here](https://www.etlcpp.com/setup.html).
|
||
|
||
### CMake
|
||
|
||
One way to use this library is to drop it somewhere in your project directory
|
||
and then make the library available by using `add_subdirectory`
|
||
|
||
```cmake
|
||
add_subdirectory(etl)
|
||
add_executable(foo main.cpp)
|
||
target_link_libraries(foo PRIVATE etl::etl)
|
||
```
|
||
|
||
If ETL library is used as a Git submodule it may require additional configuration for proper ETL version resolution by allowing the lookup for Git folder outside of the library root directory.
|
||
|
||
```cmake
|
||
set(GIT_DIR_LOOKUP_POLICY ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||
add_subdirectory(etl)
|
||
```
|
||
|
||
If you want to install this library with CMake, you can perform the following steps. On Linux,
|
||
super user rights might be required to install the library, so it might be necessary to add
|
||
`sudo` before the last command:
|
||
|
||
```sh
|
||
git clone https://github.com/ETLCPP/etl.git
|
||
cd etl
|
||
git checkout <targetVersion>
|
||
cmake -B build .
|
||
cmake --install build/
|
||
```
|
||
|
||
After the library has been installed, you can use
|
||
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html) to use the library.
|
||
Replace `<majorVersionRequirement>` with your desired major version:
|
||
|
||
```cmake
|
||
find_package(etl <majorVersionRequirement>)
|
||
add_executable(foo main.cpp)
|
||
target_link_libraries(foo PRIVATE etl::etl)
|
||
```
|
||
|
||
|
||
Alternatively you can use [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html),
|
||
replacing `<targetVersion>` with the version to install based on a git tag:
|
||
|
||
```sh
|
||
Include(FetchContent)
|
||
|
||
FetchContent_Declare(
|
||
etl
|
||
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
||
GIT_TAG <targetVersion>
|
||
)
|
||
|
||
FetchContent_MakeAvailable(etl)
|
||
|
||
add_executable(foo main.cpp)
|
||
target_link_libraries(foo PRIVATE etl::etl)
|
||
```
|
||
|
||
## Profile definition
|
||
|
||
When using ETL in a project, there is typically an `etl_profile.h` defined to
|
||
adjust ETL to the project needs. ETL will automatically find `etl_profile.h`
|
||
if it is available in the include path(s). If it's not available, ETL will
|
||
work with default values.
|
||
|
||
### Example
|
||
|
||
```
|
||
#ifndef __ETL_PROFILE_H__
|
||
#define __ETL_PROFILE_H__
|
||
|
||
#define ETL_TARGET_DEVICE_GENERIC
|
||
#define ETL_TARGET_OS_NONE
|
||
|
||
#define ETL_NO_STL
|
||
|
||
#endif
|
||
```
|
||
|
||
## Platform specific implementation
|
||
|
||
Although ETL is generally a self-contained header-only library, some interfaces need to be
|
||
implemented in every project or platform, at least if those interfaces are actually being
|
||
used, due to project specifics:
|
||
|
||
| ETL header | Platform specific API to be implemented | Needed when using |
|
||
|------------|-----------------------------------------|-------------------------------------|
|
||
| `chrono.h` | `etl_get_high_resolution_clock()` | `etl::high_resolution_clock::now()` |
|
||
| | `etl_get_system_clock()` | `etl::system_clock::now()` |
|
||
| | `etl_get_steady_clock()` | `etl::steady_clock::now()` |
|
||
| `print.h` | `etl_putchar()` | `etl::print()` |
|
||
| | | `etl::println()` |
|
||
|
||
### Example
|
||
|
||
```
|
||
#include <etl/chrono.h>
|
||
#include <etl/print.h>
|
||
|
||
extern "C"
|
||
{
|
||
|
||
etl::chrono::high_resolution_clock::rep etl_get_high_resolution_clock()
|
||
{
|
||
return etl::chrono::high_resolution_clock::rep(static_cast<int64_t>(getSystemTimeNs()));
|
||
}
|
||
|
||
etl::chrono::system_clock::rep etl_get_system_clock()
|
||
{
|
||
return etl::chrono::system_clock::rep(static_cast<int64_t>(getSystemTimeNs()));
|
||
}
|
||
|
||
etl::chrono::system_clock::rep etl_get_steady_clock()
|
||
{
|
||
return etl::chrono::system_clock::rep(static_cast<int64_t>(getSystemTimeNs()));
|
||
}
|
||
|
||
void etl_putchar(int c)
|
||
{
|
||
putByteToStdout(static_cast<uint8_t>(c));
|
||
}
|
||
|
||
}
|
||
```
|
||
|
||
The following default values apply if the respective macros are not defined
|
||
(e.g. in `etl_profile.h`):
|
||
|
||
| Macro | Default |
|
||
|-----------------------------------------------|----------------------------|
|
||
| `ETL_CHRONO_SYSTEM_CLOCK_DURATION` | `etl::chrono::nanoseconds` |
|
||
| `ETL_CHRONO_SYSTEM_CLOCK_IS_STEADY` | `true` |
|
||
| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION` | `etl::chrono::nanoseconds` |
|
||
| `ETL_CHRONO_HIGH_RESOLUTION_CLOCK_IS_STEADY` | `true` |
|
||
| `ETL_CHRONO_STEADY_CLOCK_DURATION` | `etl::chrono::nanoseconds` |
|
||
|
||
## Arduino library
|
||
|
||
The content of this repo is available as a library in the Arduino IDE (search for the "Embedded Template Library" in the IDE library manager). The Arduino library repository is available at ```https://github.com/ETLCPP/etl-arduino```, see there for more details.
|