Simple Arduino project has undefined reference error to default constructor during linking stage in build

I’ve been scouring the internet trying to find a solution and done a ton of tinkering myself, but at this point, I’ve lost all my hair and feel no closer to solving this problem.

Here’s the error:

Linking .pio\build\megaatmega2560\firmware.elf
C:\Users\matth\AppData\Local\Temp\cclHZ2N6.ltrans0.ltrans.o: In function `_GLOBAL__sub_I_selectWheel':
<artificial>:(.text.startup+0xf6): undefined reference to `SelectWheel::SelectWheel()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\megaatmega2560\firmware.elf] Error 1

Here’s the terminal output for pio run -t clean and platformio run --verbose: Platformio Clean and Build Terminal -

Here’s the project structure:

| -- .pio
| -- .vscode
| -- include
|     | -- Adafruit_BusIO
|     | -- Adafruit_EPD
|     | -- Adafruit_GFX_Library
|     | -- Adafruit_SSD1306
|     | -- ArduinoSTL
| -- lib
|     | -- SelectWheel
|     |    | -- SelectWheel.h
|     |    | -- SelectWheel.cpp
| -- src
|    | -- main.cpp
| -- platformio.ini

Here’s platformio.ini

platform = atmelavr
board = megaatmega2560
framework = arduino

Here’s /src/main.cpp

#include <Arduino.h>
#include "SelectWheel/SelectWheel.h"

SelectWheel* selectWheel = new SelectWheel();

void setup() {}
void loop() {}

Here’s /lib/SelectWheel/SelectWheel.h

#ifndef SelectWheel_h
#define SelectWheel_h

#include "Arduino.h"

class SelectWheel {
        int pinA, pinB;
        SelectWheel(int, int);


Here’s /lib/SelectWheel/SelectWheel.cpp

#include "SelectWheel.h"

SelectWheel::SelectWheel() {}
SelectWheel::SelectWheel(int pinA, int pinB) {
    this->pinA = pinA;
    this->pinB = pinB;
    pinMode(this->pinA, INPUT);
    pinMode(this->pinB, INPUT);

Let me know if there is any additional information I can supply to help as I’ve already tried a bunch of way to fix this.

The build log indicates that SelectWheel.cpp is neither compiled nor included. Your project structure shows a strange organization for third-party libraries.

The preferred setup for third-party libraries is to NOT download or install them, but rather to declare them in platformio.ini. PlatformIO will then take care of the rest:

lib_deps =
    Adafruit BusIO
    Adafruit EPD
    Adafruit GFX Library
    Adafruit SSD1306

Third-party libraries certainly do not belong into the include directory. Delete everything in that directory. If you need local copies of third-party libraries (e.g. because you need to modify them), put them into the lib directory.

I’m not sure this will solve the problem entirely. But it’s a first step to take.

Thank you @manuelbl for the reply! I’ve done what you suggested and am now able to reference header and cpp files in the /lib/ directory by #include "SelectWheel.h".

What I’d really like is to be able to nest folders in my /lib/ directory. Ex:

|  -- InputDevices
|     | -- SelectWheel
|     |    | -- SelectWheel.h
|     |    | -- SelectWheel.cpp
|     | -- Slider
|     |    | -- Slider.h
|     |    | -- Slider.cpp
|     | -- Button
|     |    | -- Button.h
|     |    | -- Button.cpp

If I want to still be able to include these files in /src/main.cpp, is there a way I can still use this nested structure?

As i understand, if you use the platformio.ini to add third party libraries to your project, you would generally use pointy brackets (#include <my_3rd_party_lib.h>) to include them. Using “” indicates you’re giving a relative path to the project sources root, although you seem to get away with it somehow.

You can include any files from nested directories by using this to actually give them the full path: #include "../lib/SelectWheel/SelectWheel.h".
Of course you have to make sure no not move your files around a lot (although most IDEs take care of changing relative paths to the file within the project) but when you found a structure you’d stick to it anyway so that should not be that big of an issue.