Linker Error when using compiler optimization flags

Hi !
I followed these instructions to use compiler optimization flags when compiling from the Arduino IDE.

When I set the optimization level to fast (using the argument -Ofast), I get the following error when compliling my code, which is using the following Library:

In function `global constructors keyed to 65535_0_Device.cpp.o.6022':
<artificial>:(.text.startup+0x7d4): undefined reference to `Adafruit_CharacterOLED::command(unsigned char)'

Does anybody understand why this happens and how to fix it?
kind regards,
Flub

I found a line of code which i can comment out to make the error disappear. Perhaps someone can understand why this line is a problem:
The problem occurs when using the LCD::command method from inside the class method first time.
When i uncomment the line where it is used, the compiling works. I think it is because command method of the LCD (or Adafruit_CharacterOLED) is inlined only when using optimization flags other than -Os. So inline is ignored when using -Os and starts to do something when I use -Ofast.
So why could the inline of the LCD::command Method be a problem here:

I created an example sketch which reproduces the error:
(Note: I renamed the library from Adafruit_CharacterOLED to LCD)

#include "LCD.h"
LCD lcd(OLED_V2, A13, A12, A14, A8, A9, A10, A11);

void setup() {
  lcd.print("test");
  lcd.command(LCD_FUNCTIONSET | LCD_EUROPEAN_I);
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
}

Edit: I just found this post on the forums here:

But i think removing the inline directive in the Library is somehow not a solution as it just disables the intended optimization.

I now just edited the Libray, i renamed the command function to _command and put it in the private scope. Then I added a non inlined function in the public space called command which just calls the _command function. I am not sure but perhaps the positive effect of inlining is kept like this. and a call to command from outside is happening only once when choosing the characterset anyways...

void LCD::command(uint8_t value) {
  _command(value);
}
inline void LCD::_command(uint8_t value)
{
  send(value, LOW);
  waitForReady();
}

I found a really helpful video on this:

He says:

It does not compile since inline requires the function body to be visible for the caller. And we have to move the function body to the header.

Considering this, I think the Library's use of inline is wrong.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.