Compiler differences

I am using Arduino 1.8.12. I have been using the Arduino Uno for some time now, but lately I have included the Teensy 4.1 into my projects, so I have started compiling code using both boards. I have noticed that I get more warnings when I compile for Teensy by changing the Tools|Board option in the IDE.
Here's an example, this code:

/* Test Library code for compile errors */
#include <Wire.h>
#include <Testmcp3424.h>
void setup() {
  // put your setup code here, to run once:

  // Reset device
  if (generalCallReset()) 
    Serial.println ("Device reset successful");
   else { Serial.println ("Bus Error"); }

   //find device address and create instance of MCP3424
   uint8_t adcAddress = getAddress();
   if (adcAddress != 0) {
    Serial.print ("Found device at ");
    Serial.println (adcAddress, HEX);
    MCP3424 adc = MCP3424 (adcAddress);
   else {
    Serial.println ("No device found");

generates no warning when compiled for Arduino Uno. But generates the following warning when compiled for Teensy 4.1;
C:...\Testmcp3424.ino\Testmcp3424.ino.ino:22:13: warning: variable 'adc' set but not used [-Wunused-but-set-variable]

 MCP3424 adc = MCP3424 (adcAddress);

This is not the first instance either. The Teensy compiler is much better at catching logical mistakes than the compiler used for Arduino.
The question is: if I want to make good open source code, should I use a mix of different boards when compiling? Does anyone have any idea how many really different compilers there are now?

Some platforms like the AVR platform hide warnings.
Always seemed silly to me.
I recommend that you enable all warnings.
Then change "Compiler Warnings" to "All"

--- bill

1 Like

This is compiler option. Teensy set it, UNO didnt

I think it is a very good idea. One of the cornerstones of the Arduino project is portability. It is really wonderful that we can often compile the same sketch for a wide variety of microcontrollers with significantly different architectures. But that portability is often achieved only through care by the developer.

My advice is to set up an automated compilation of the example sketches for representative boards of each of the architectures you want to support as a basic "smoke test". This is often done using an automation service, the most popular of which at this time is GitHub Actions.

You can see a demonstration of that in one of the official Arduino libraries here:
In this case, they are compiling for boards of the samd, mbed, esp8266, and mbed_nano architectures. There is more thorough coverage of the SAMD boards both due to them being the primary target of the library as well as because the library supports the different network interfaces provided by the various MKR boards.

For portability, if you stick to the Arduino core API functions to do i/o (i.e. don't do things like use AVR port i/o) and do not abuse API functions (use them only as documented) you will have very few if any issues related to portability with respect to compiling.
That said, I have run into many portability issues in the Arduino environment across boards & platforms over the past 10+ years.
Many of the s/w related ones, I've worked with the platform developers to fix them.
These days most of issues are either timing related or the core platform is incomplete or incorrectly implemented some of the Arduino APIs.
One of the biggest ones is that some platforms do not properly create the Arduino defines in their variant file.
i.e. missing or incorrectly declared symbols like LEDBUILTIN, SDA, SCL, etc...
(they MUST be #define vs const int)
Or things like ESP32 didn't implement analogWrite(), or
ESP8266 and ESP32 boards use active low on their LED vs active high on all the other boards.
To get maximum portability for these types things requires using conditionals, to detect these issues at compile time and work around them with different code.

Timing related issues can show up because there can be as much as 100x or even 200x difference in the speed of certain i/o between platforms for certain applications.
Timing issues can be frustrating and occasionally difficult to discover and resolve.
A recent one that I've run into is that using shiftOut() will no longer work in some situations due to it being so fast on certain platforms that it violates the maximum clock rate of the device on the other end.
This is case where the code itself is 100% portable, it just does not work due to it running too fast.

Another one is mixing 3v and 5v devices.
A 5v device can often properly interpret 3v logic levels without using a proper level shifter.
There can be issues since the 3v high levels are often boarder line.
For example, if a 5v device needs a high pulse to trigger.
The code may have t leave the 3v signal high for a longer period of time than a 5v signal to ensure that the 5v device sees the high signal
This is because the 3v signal high is very borderline and requires extra time to fully rise up to be seen as high by the 5v devices.
i.e. the slew rate time for a 3v signal to be seen as high is longer than the time for a 5v signal.

For timing related things, I use a logic analyzer to look at the signals to verify that signals are behaving properly.

--- bill