arduino / ArduinoCore-samd

Arduino Core for SAMD21 CPU
GNU Lesser General Public License v2.1
467 stars 715 forks source link

GNU ARM toolchain update request #313

Closed VioletGiraffe closed 5 years ago

VioletGiraffe commented 6 years ago

The current toolchain (based on GCC 4.8) is significantly outdated, it lacks many C++14 features. C++14 is an important update to C++ because it expands on template metaprogramming, which is a very useful technique for embedded programming: it allows writing nicely looking, convenient code that does a lot of stuff at compile-time, with zero run-time overhead. Most notably, GCC 4.8 lacks extended constexpr and generic lambdas - the latter is exactly what I'm missing right now and can't compile my project without.

I tried this release, just dropped it into the toolchain-gccarmnoneeabi folder, and it seems to work just fine!

There are much newer toolchain versions available, but that's not as important as getting full c++14 support. So I'm only asking for a minor upgrade from GCC 4.8 to 4.9, because 4.9 supports -std=c++14.

P. S. Even the AVR compiler is based on GCC 4.9.3 and supports c++14. Its standard library is lacking (nearly non-existent, even), but that's not such a big problem because there are c++11/14 stdlib implementations for Arduino AVR.

facchinm commented 6 years ago

Hi @VioletGiraffe , I agree on updating the toolchain, it's not an immediate issue but, as you noticed, C++14 is simply not achievable with the current one, so if we raise the bar for AVR we'll need to update this too.

PaulStoffregen commented 6 years ago

We've been using gcc-arm-none-eabi 5.4.1 (2016q3) on Teensy for some time, compiling everything with -std=gnu++14. It's working quite well, very good compatibility. Believe me, I was a bit nervous about the jump to C++14, but it went very very smoothly.

Turns out constexpr constructors allow for much more efficient compile results, and they solve long-standing static initialization order problems. If you need a reason to update, being able to use constexpr constructors in the Print & Stream classes is pretty compelling!

If you decide to jump to the 2016q3 release, I can contribute well tested 64 bit x86 and 32 bit ARM Linux builds which aren't on launchpad.net.

If Linux 64 bit ARM ( https://github.com/arduino/Arduino/issues/7302 ) eventually moves forward, I can help there too with a build of the ARM toolchain. Just ping me if you decide to move in that direction. I'm not planning to touch Google Go, so waiting until you guys at least port arduino-builder and the new preprocessor.

facchinm commented 6 years ago

I agree with 2016q3 which is almost synced with the latest avr-gcc (5.3.0). I can compile by myself, no problem, for all the supported platforms. The constexpr stuff is very very compelling, so I think we should start the switch quite soon :slightly_smiling_face:

PaulStoffregen commented 6 years ago

I recently built 2016q3 on Jetson TX2. Ran into a couple small issues, mostly missing "makeinfo". Here's modified build scripts with a makeinfo workaround. If you haven't already done this, hope it saves you a little time. :-)

https://github.com/PaulStoffregen/ARM_Toolchain_2016q3_Source

facchinm commented 6 years ago

Thanks Paul :slightly_smiling_face: Here is the json to test the new toolchain http://downloads.arduino.cc/packages/package_samd_newtoolchain_index.json

It provides an update of samd core directly (so it can be tested as almost production ready). Setting -Wall produces a bunch of portability warnings on CMISIS-Atmel so it may be worth to update it before shipping officially.

Please test and report if anything is broken, thanks!

VioletGiraffe commented 6 years ago

@facchinm Can I test it on my machine, and if so, where do I put the file? Or is it only for Arduino project maintainers ?

facchinm commented 6 years ago

@VioletGiraffe you can test it directly on your machine, simply paste the link in Additional sources under File/Preferences, reload the board manager and you should see the update for samd core

PaulStoffregen commented 6 years ago

For just a bit more detail, click File > Preferences. Then click this button in the preferences dialog.

sc

Then add the json link into the text box. Here you can see I already had 4 of these, so I just added it to the end. If the box is empty on your copy of Arduino, just paste the link into the first line.

sc2

Then you'll need to click Tools > Boards > Boards Manager...

Find the "Arduino SAMD Boards" and update to the version 1.6.19. It shows which version you have already installed (if any) in the name, but there isn't any apparent way to update. Just click on it and the invisible button will appear. (the usability impact of these buttons being invisible might be a question for @00alis to consider...) If you already had any version, you'll get a drop-down on the left to select the version you want. If you didn't have it, an install button appears on the right.

Then make sure you have the right board selected in Tools > Boards. I used Arduino Zero for a quick test right now. Here's a simple sketch to quickly test.

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print("Compiled by gcc ");
  Serial.print(__GNUC__);
  Serial.print(".");
  Serial.print(__GNUC_MINOR__);
  Serial.print(".");
  Serial.print(__GNUC_PATCHLEVEL__);
  Serial.println();
  delay(500);
}

Much to my surprise, it's printing 7.2.1, rather than 5.4.1. Is that really the intention, to jump all the way to the newest?

facchinm commented 6 years ago

@PaulStoffregen it is, just to avoid getting stuck in the "too old again" loop. Support for C++17 is almost complete on gcc7 so it is a good future proof candidate. About the board manager, have you tried the beta (or the hourly)? The mouse on-hover should solve most of the usability issues of bard/lib manager.

PaulStoffregen commented 6 years ago

I used 1.8.5 for testing just now.

Regarding the latest version, I've advise caution. Already a couple users who tried version 6 have reported some code that compiles in version 5 but not 6, where certain C++ checks have become more strict. Here's one of them: https://github.com/PaulStoffregen/Wire/issues/9

Letting the AVR and ARM toolchains diverge too much is probably going to bring you a lot more pain than people complaining that version 5 is outdated...

PaulStoffregen commented 6 years ago

Also, as part of your transition from gcc 4.8.3 to anything version 5 or newer, I'd recommend adding "-Wno-error=narrowing" to the compiler flags in platform.txt. You want this when compiling C++ code, but not C or ASM.

VioletGiraffe commented 6 years ago

@PaulStoffregen , sounds like a problem with the code, not the toolchain. Those people were probably writing non-standard, non-portable code. I would advocate against allowing them to keep writing such code, but on the other hand, I understand the need to maintain compatibility with countless existing libraries.

PaulStoffregen commented 6 years ago

Those people were probably writing non-standard, non-portable code.

Trouble is "those people" are companies like Sparkfun who only test their libraries on Arduino Uno... or their clones of Arduino's products. Their (highly successful) business model is heavy on selling new hardware and light on maintaining older libraries, especially if they still work fine on the most popular AVR boards.

But "those people" you get to hear from and you have to explain the issue are the novice end users who already bought the hardware and just want it to work, or even people who bought similar cheap Asian clone hardware but downloaded the library from a well known website. When it worked in the older Arduino IDE but now fails, "those people" blame Arduino, not the original library authors!

PaulStoffregen commented 6 years ago

However, that issue on Teensy's version of the Wire lib is entirely my fault. I accepted a contribution for constexpr constructors. It works really well. But I was unaware of this very subtle point. It wasn't mention on any of the many tutorials I read about constexpr.

This is what tends to happen when you jump to the much newer toolchains. Within each major version they usually do a pretty good job of keeping things compatible. But when you go from 5 to 6, or 6 to 7, you're looking at likely having to deal with imperfect libraries that used to compile.

It's painful even when you're the library author. But when it's countless end users suffering and library authors who do little or no ongoing maintenance, compatibility issues are very painful. That's why I rarely update.

stevenj commented 6 years ago

@PaulStoffregen that's an argument for keeping an old toolchain "as an option" but not an argument for not updating. Otherwise, one can NEVER update because one is always weighed down by the libraries of the past (which will never be fixed). You are perpetually frozen in time. Not a great outcome.

PaulStoffregen commented 6 years ago

My point is making too big a jump at once (3 major versions), and especially getting the AVR and ARM toolchains out of sync is a recipe for lots of unhappy Arduino users.

stevenj commented 6 years ago

@PaulStoffregen I understand your point completely, that's why I say its an argument for keeping the current version available, as an option, for the possible instances where the new GCC will not successfully build the old libraries. Its not an argument for not updating the compiler.

All I have seen so far is excessive and overly pedantic warnings about case statements that fall through, and #if BLAH type constructs. Both of which do not actually change the code, it still compiles correctly. Both can be suppressed with appropriate switches, and I think at least initially, they should be. Are there ANY code breaking changes?

However, there is an actual instance of new library code which can not be used with Arduino because of it's ancient compiler. That being FreeRTOS 10 which won't build with the Arduino GCC for Cortex-M0. That's an actual problem because of this "frozen" compiler mentality. Not a "maybe" problem that some old library won't compile. And that is going to get worse as people start moving their code to use the new features of compilers. Not better.

I also don't see any value in a small incremental upgrade, that's just kicking the can down the road. If you want to hold the compiler stable for a few years, and i can understand why you would, then you should jump to the latest compiler you can, so that you have more longevity before you start to go obsolete.

The benefits of upgrading as I have seen in my code are:

  1. Smaller, tighter binaries = better code generation.
  2. Better and more modern language standards compliance = better to teach good software engineering.
  3. An ability to use modern libraries which rely on these more modern language standards.
  4. Support for more processor architectures, especially Cortex-M7 (now), Cortex-M23 and Cortex-M33 (near future).

The negatives are:

  1. Old libraries throw ignorable warnings.
  2. Maybe an old library won't actually build properly, but we don't know of one.

Negative 1. Is easily solved with a command line switch or 2. Negative 2. Is easily solved by having the old compiler available for people who find they need it.

Your other issue of keeping the compilers in sync has some merit, so upgrade the AVR compiler as well. There are GCC 8.1 AVR binaries in the wild, so it will be able to be built and work with 7.2.1. Seriously there is a bigger need to upgrade the AVR GCC because of the HUGE number of chips that the current version just doesn't support. V8.1 adds all these cores: ATtiny212, ATtiny214, ATtiny412, ATtiny414, ATtiny416, ATtiny417, ATtiny814, ATtiny816, ATtiny817, ATtiny1614, ATtiny1616, ATtiny1617, ATtiny3214, ATtiny3216, ATtiny3217

That alone should be a reason to upgrade AVR GCC to 8.1, and then bring ARM up to parity when its released by arm (or just build it now from source)

But, keep the current versions around (as a fallback option) for a couple of years so people can migrate without undue pain. Then all answers to support queries about old broken libraries becomes "Either use the old compiler, or fix the library."

facchinm commented 6 years ago

@stevenj the AVR toolchain we are now going to ship (which is already bundled in Hourly) is the latest one officially supported by Microchip, with the latest ATPACK for ATMEGA included.

Adding the ATtinies pack as an external dependencies should be easy enough for any third party developer (adding -B to tell gcc where to look for device specific information, see http://distribute.atmel.no/tools/opensource/Atmel-AVR-GNU-Toolchain/3.5.4/).

Latest AVR-GCC (8.1) produces suboptimal code in a lot of cases (I am on Arch so I occasionally "benchmark" the bleeding edge version on Makefile-based projects)

PaulStoffregen commented 6 years ago

I downloaded the latest hourly. Its avr-gcc seems to be version 5.4.0.

PaulStoffregen commented 6 years ago

Going with anything but the newest seems to be an unpopular idea here.

Speaking as someone who answers end user questions 4+ hours a day, and who regularly fixes library compatibility problems reported by those users, I feel shipping significantly different toolchain versions for AVR vs ARM is a terrible mistake.

If an option is somehow implemented to choose different toolchain versions, I sincerely hope the default for ARM would be to use the version which most closely matches that used by AVR.

stevenj commented 6 years ago

@facchinm thats a good reason not use 8.1 for AVR, but if it is producing sub optimal code compared to an earlier version that's a bug. It should be reported upstream. But I agree until that was fixed its a good reason not to use it.

facchinm commented 6 years ago

I downloaded the latest hourly. Its avr-gcc seems to be version 5.4.0.

In Atmel standard toolchain 3.5.4 contains avr-gcc 5.4.0 , don't know what they were thinking when they chose that numbering scheme :slightly_smiling_face:

ryan-feeley commented 6 years ago

I'm interesting in helping this move forward. I'm agnostic as to the version, but gcc 4.8.2 is pretty ancient. I'm not convinced that it is a meaningful goal to keep the avr and arm toolchains in sync w.r.t. gcc version. Have they ever been? I think "close" is good enough, and I'm with @PaulStoffregen that latest and greatest is pushing too hard.

What would be needed to verify and test everything? Is there a list of say either the top N libraries in terms of downloads, or in terms of user questions that consume the time of developers or maintainers?

I recommend bumping to at least 6.4 to get this bug fix. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728

One user-facing advantage to going to version 7 is that the diagnostics and suggestions for common "newbie" errors like mis-spelled identifiers and the like are greatly improved.

Are there any sets of standardized hardware test beds? For example, hardware appropriate for the various examples in arduino/hardware/samd/1.6.19/libraries/

Onno-Dirkzwager commented 5 years ago

Any news on when the "new" toolchain gets released? I want to port some of my esp libraries to these briliant boards (MKR 1010) but keep running into problems with the old compiler.

facchinm commented 5 years ago

Hi @Onno-Dirkzwager , the beta branch already ships with the new toolchain. Since there are a lot of changes we decided to deactivate all the other boards except MKRVidor4000, but restoring them is a matter of renaming boards.txt.disabled into boards.txt (https://github.com/arduino/ArduinoCore-samd/blob/beta/boards.txt.disabled). You can safely download the beta using the board manager.

Onno-Dirkzwager commented 5 years ago

@facchinm thankyou for your reply. This sounds good! Ill give it a try tonight.

paloscsaba commented 5 years ago

Hi @facchinm, is there a way to use a newer GCC for Arduino Due also? As far as I see, the SAMD beta does not cover Due. I would be very thankful if you could tell me how to do it myself.

PaulStoffregen commented 5 years ago

The specific steps vary somewhat, depending on whether you use Windows, Macintosh, or Linux.

facchinm commented 5 years ago

@paloscsaba the easiest way is:

paloscsaba commented 5 years ago

Thanks for the quick replies! @PaulStoffregen : I am using Windows @facchinm : Thanks, I will try this, and give feedback.

paloscsaba commented 5 years ago

Well, it works the way you described, but raises new problems. I am still investigating but maybe you already know the solution: the #define max() and min() macro functions collide with several different max and min identifiers in STL include files (stl_algobase.h, algorithmfwd.h, limits, etc.)

I am tempted to comment out the macros in Arduino.h, but maybe there is a more beautiful solution you already know that does not cause problems in legacy libraries. I don't fear editing those libraries, but this might hard for newbies.

paloscsaba commented 5 years ago

OK, I managed to compile my small sketch. Needed to write #undef max #undef min after every #include <Arduino.h>. Watch out: the .ino file implicitly includes Arduino.h, so these lines are also needed at the top of the sketch. If this is the price for modern C++, then OK.

paloscsaba commented 5 years ago

Another note: When I enable -std=c++14, I need to add these lines to new.cpp:

// C++14 additional delete operators

#if __cplusplus >= 201402L

void operator delete(void * ptr, std::size_t) 
{
    ::operator delete(ptr);
}

void operator delete[](void * ptr, std::size_t) 
{
    ::operator delete(ptr);
}

#endif
VioletGiraffe commented 5 years ago

@paloscsaba : looks like a problem with the stdlibc++, something the toolchain maintainers should look into.

facchinm commented 5 years ago

Core 1.8.x ships with gcc7, closing as solved