avr-gcc supports modern C++, but does not ship a C++ standard library. avr-libstdcpp provides the libstdc++ headers of GCC, adapted for avr-libc, for avr-gcc 8 to 15 and C++17 to C++26.
#include <algorithm>
#include <array>
#include <chrono>
#include <optional>
#include <string_view>
#include <variant>
using namespace std::chrono_literals;
constexpr std::array<uint16_t, 4> thresholds{100, 200, 400, 800};
constexpr auto level = std::ranges::lower_bound(thresholds, 300) - thresholds.begin();
static_assert(level == 2);
std::optional<std::chrono::milliseconds> timeout = 1500ms;
std::variant<int16_t, float, std::string_view> value = "hello";Everything implemented in the headers is available: containers, strings,
algorithms, ranges, optional, variant, function, smart pointers,
<chrono>, <cmath>, <random>, <atomic>, coroutines and much more.
I/O streams, locales and <format> require the compiled library, which is
not provided. See the limitations for details.
Add the include directory to the include path and compile the src
directory with your application:
LIB=avr-libstdcpp
avr-g++ -std=c++23 -Os -mmcu=atmega328p -fno-exceptions -fno-rtti -fno-threadsafe-statics \
-ffunction-sections -fdata-sections -Wl,--gc-sections \
-I$LIB/include main.cpp $LIB/src/*.cc $LIB/runtime/*.cpp -o main.elf -lmThis works with avr-gcc 8 to 15: The headers and sources select the header
set for your compiler version themselves (see compatibility).
With Make, avr-libstdcpp.mk also provides the newest
C++ standard supported by your compiler:
AVR_CXX := avr-g++
include avr-libstdcpp/avr-libstdcpp.mk
CXXFLAGS += -std=$(AVR_LIBSTDCPP_STD) -I$(AVR_LIBSTDCPP_INCLUDE)
SOURCES += $(AVR_LIBSTDCPP_SOURCES)See getting started for the details, CMake, the required compiler flags and the runtime functions you may need to provide.
- Getting started: setup, compiler flags, runtime
- Compatibility: supported compilers and why there are four header sets
- Limitations: what works and what does not
- Guide: using the standard library on tiny bare-metal systems
- Generating: how the headers are generated from GCC
- Testing: integration tests and CI
The examples run on an Arduino Uno and print via the serial port:
| Example | Shows |
|---|---|
blink |
<chrono> durations, clocks and hh_mm_ss |
interrupt_counter |
std::atomic shared between an interrupt and the main loop |
sensor_filter |
median and moving average filters with <algorithm>, <numeric> and <cmath> |
command_shell |
a serial command line with string_view, from_chars, map and function |
state_machine |
a traffic light with std::variant states and std::visit |
lookup_table |
a sine table computed at compile time with constexpr and std::array |
ranges |
a data logger with C++20 ranges, span, concepts and <random> |
chrono |
a custom high_resolution_clock driven by Timer0 |
cmath |
floating-point functions of <cmath> |
numeric |
constexpr algorithms of <numeric> |
vector |
std::vector with dynamic memory |
cd examples/blink
make # build with avr-g++
make sim # run in simavr
make program # flash via avrdudeThe chrono, cmath, numeric and vector examples use their own Makefiles
and C++17 by default.
| Path | Content |
|---|---|
include, src |
Redirect every file to the header set of your avr-gcc version |
gcc10, gcc12, gcc13, gcc15 |
The generated header sets, each with include and src |
avr-libstdcpp.mk |
Paths and the newest C++ standard for Make |
runtime |
Optional implementations of new, delete, the C++ ABI and atomics |
tools |
The generator and the library sources |
tests |
Integration tests running in simavr |
examples |
Examples for the Arduino Uno |
docs |
Documentation |
Do not edit the header sets directly, they are regenerated by
tools/generate.py.
avr-libstdcpp began in 2018 with an import of the libstdc++ headers of GCC 8, from which unsupported parts were removed by hand. A second import from GCC 10 in 2020 added many C++20 features. Since 2026, the headers are generated automatically from four GCC versions, which provides the complete library up to C++26 and makes supporting new GCC versions much easier.
The generated headers and library sources in gcc*/ and the files in
tools/src are part of GCC and
licensed under the GNU General Public License Version 3 or higher
with the GCC Runtime Library Exception, except for functexcept.cc and
math.cc.
The examples, tests, runtime, scripts, functexcept.cc and math.cc are
subject to the terms of the Mozilla Public License Version 2.0.