Monthly Archives: September 2012

Using C++ on the Arduino: a mainstream C++ Standard Library port for the AVR!

The Arduino development environment (and more generally, the avr-gcc/avr-libc/avr-binutils toolchain) supports, and in the Arduino core library, uses C++ language features.  However, a C++ standard library is not included, which makes using other C++ libraries (even just the header-only libraries in Boost) a challenge, and can result in less effectively-C++ code.  Among my goals in seeking C++ standard libraries for the Arduino include the ability to use the excellent Eigen matrix-math library and some of the header-only Boost libraries.

(tl;dr version: visit !)

A number of individuals have worked on ports of (partial – at least the Arduino IDE disables RTTI and exceptions, and fstream is little use without a filesystem) C++ standard library implementations. (Keep in mind that the C++ standard library is more than just the STL – the string library is sometimes considered part of the STL but is technically its own thing, as well as the streams library.)  The following are the previous attempts I’ve found:

  • Andy Brown ported the original SGI STL (not a full C++ standard library) but with some additions to bring it closer to a full standard library. He considered libstdc++ (too embedded with the desktop GCC toolchain) as well as uSTL (which he eliminated due to larger generated code size) before porting the SGI STL. He made a number of customizations to it that, while making it less standards-conforming, made it more suitable to use on AVR devices. He supplemented it with a streams implementation based on  uClibc++, as well as some custom features for the AVR and Arduino environment. (For instance, iostream implementations for HardwareSerial and character LCDs.) The library is header-only, so you only pay in compile time for what you use. However, the SGI STL precedes the standardization of the C++ standard library with STL (it’s an [the?] initial implementation…), so compiler and library compatibility are sometimes a bit sketchy.
    • The SGI STL license is a fairly liberal, non-copyleft license that Debian’s won’t identify for me :-). The portions from uClibc++ are LGPL 2.1+, and the headers written by Andy specifically for the arduino (lcdostream and serstream) are under a three-clause BSD license.
  • “maniacbug” started the Arduino library StandardCplusplus, a fairly direct port of uClibc++ . uClibc++ is a more modern implementation than the SGI STL (that is, it’s a post-standardization implementation) and aims to be a full C++ standard library.  I found that to use for my purposes, I had to make a number of modifications (particularly in implementing the limits header), which are on my GitHub fork of StandardCplusplus. It’s concise and easy to read, but its relative incompleteness in the areas I needed made it some effort to maintain.
    • License-wise, uClibc++ is LGPL 2.1+ which keeps it easy to move code in, but harder to move code out, and a bit confusing for embedded. (avr-libc uses, and seems to recommend, an MIT-style non-copyleft liberal license – presumably to avoid potential complexities over requirements and definitions of linking, derivative works, etc. given the nature of embedded code as being flashed into hardware.) The stream classes by Andy Brown were also added to this library, under the same three-clause BSD license mentioned earlier.

While I had gotten StandardCplusplus to a state where I could mostly use it, I found myself hitting a number of issues bit-by-bit. Furthermore, a number of the fixes/needed implementations were because of gaps in upstream, rather than porting issues, and the break between the upstream uClibc++ and the Arduino-layout, Arduino-specialized version made it harder to justify fixing issues that would be bothersome to port upstream and/or marginally likely to be accepted (AVR-specific code somewhat scattered, and behind ifdef __AVR__ or ifdef ARDUINO guards).

With this background, I’d like to introduce my new development, and what I’m using now: the addition of an AVR port to the STLport project, which I’ve posted on GitHub.  STLport is liberally-licensed, and evolutionarily, it descends from the SGI STL that served as Andy Brown’s starting point. However, STLport, despite its name, can be configured as a full C++ standard library. It has been extended, expanded to include newer C++ standards and TR1, and (as suggested by the name) ported to work with many compilers. This porting was done smartly, by limiting platform-specific macro checks to configuration headers, which define feature-focused configuration macros as needed for use in the rest of the library. This meant that my changes could be fairly limited in files touched: primarily adding a config header for AVR, modifying the GCC config header to avoid assumptions that are untrue on AVR, and creating/applying a few more feature-focused config defines to reduce the library’s size and porting overhead. While the last tagged release was in 2008, the project has been moved to a Git repository and has been under some development since then. For instance, changes to the STLport-5.2 (stable) branch are as recent as April 2012, and the master branch in fact is (working toward being) a C++11 standard library.

I’ve made ports for both the 5.2 stable branch and the master branch. The library can be built using the STLport build system if you prefer, though if you’re using Arduino, all you’ll need is one of the “arduino-installed” branches: these are generated by a script rearranging the sources/headers from the mainline branches. This way, they won’t fall (much) behind and can easily be reproduced. (I could have claimed success without these branches, however, I find it convenient to keep Arduino libraries in Git submodules, and the branch solution provides a straightforward, nontechnical way to use the library directly with the Arduino IDE.) Both the C++11 and stable 5.2 versions work with the Arduino core library, though note that you’ll need to put your compiler into C++11 mode for the master branch. As far as I can tell, this can’t be done with the Arduino IDE.

I’ve verified that both versions compile as a static library on their own. I’ve also verified that C++ Standard Library-using Arduino sketches build using (my branch of) Arduino-Makefile (with appropriate EXTRA_CXXFLAGS as needed) on both the master and 5.2 branches, and that sketches build successfully using the Arduino IDE and the 5.2 branch. My test system for this has been an Ubuntu Lucid x86_64 machine, with the following package versions updated from Debian Testing:

  • arduino and arduino-core  – 1:1.0.1+dfsg-6
  • gcc-avr – 1:4.7.0-2
  • binutils-avr – 2.20.1-3
  • avr-libc – 1:1.8.0-2

On Windows, I’ve been using the Arduino 1.0.1 IDE upgraded with Windows binaries of gcc-avr 4.7.0 and avr-libc 1.8.0 from Andy Brown (caveat: save your original avr-size.exe and put it back in place after). As this updated  is substantially the same as what I use on Linux, I’m pleased that as expected, building on Windows with the 5.2 branch in the IDE works just fine.  Remarkably, though the toolchain bundled with 1.0.1 on Windows is very very old (gcc 4.3.3) and contains some annoying-to-really-bad bugs for AVR, it at least built my (complicated template metaprogramming and STL algorithm-based) test app, only being slightly more picky about my nested template syntax.

So, give it a try! Let me know if it works for you – and if you have improvements, or find things that don’t work, please feel free to send an issue or pull request on my STLport for AVR/Arduino GitHub repository.