Learn

Fixing "undefined reference to" in Arduino

Beginner

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: blink, ready to breaklive0.000 s 0.00x
Click to open it in the editor
An LED on pin 13 and a working sketch. Open it, rename loop to Loop, and press Run to see the linker error.

undefined reference to 'loop' is a linker error. The sketch compiled, and then the linker, which joins the compiled pieces into one program, could not find the code for a name the program uses. For setup or loop it means the sketch has no function by exactly that name, often because it is written Loop() or Setup(). For a function of your own it means the function was declared but never written out, or written with different parameter types from the declaration. For a library function, the library’s .cpp file is not in the build.

Mokxi links with LLVM’s linker, which words it undefined symbol: loop(). The circuit above is an LED blinking on pin 13. Open it, rename loop to Loop and press Run: the build stops with undefined symbol: loop(), and the build tab names the line that has Loop() and says "Arduino calls loop(), spelled exactly that way in lower case."

No setup() or no loop()

The Arduino core has the program’s real starting point, main(), and it calls setup() once and then loop() for ever. So every sketch needs both, even when one of them has nothing to do. Leave one out and nothing is wrong in the sketch itself, which is why the compiler is happy and the linker is not. A sketch with only setup() stopped with undefined symbol: loop(), and the build tab said "The sketch has no loop() function. Every Arduino sketch needs both setup() and loop()." An empty void loop() { } is enough.

An empty sketch fails with both: undefined symbol: setup() and undefined symbol: loop(). Mokxi’s build tab says "sketch.ino is empty, so there is nothing to build" rather than naming the two functions, and the same for a file that is not built at all, such as a sketch.py, which it calls Python.

The smallest sketch that builds: both functions, one of them empty
void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
}

void loop() {
}

Loop(), Setup() and other near misses

The names have to match exactly, lower case included. void Loop() is a perfectly good function that nothing calls, so the sketch compiles and the link fails. In a sketch with void Loop() on line 5, Mokxi’s build tab said "sketch.ino line 5 has Loop(), but Arduino calls loop(), spelled exactly that way in lower case. Rename Loop to loop." The same goes for setUp(), Setup() and void loop1().

Broken: Loop() with a capital L
void setup() {
  pinMode(13, OUTPUT);
}

void Loop() {
  digitalWrite(13, HIGH);
}

Your own function: declared, but not written

A declaration such as void blinkTimes(int count); promises the function exists somewhere. Call it and never write the body, and the link fails: undefined symbol: blinkTimes(int) in Mokxi, undefined reference to 'blinkTimes(int)' from GCC. Mokxi’s build tab says "blinkTimes is used, but its code is in no file of the build."

The same error comes when the body is there with different parameter types. With the declaration taking an int and the function written as void blinkTimes(byte count), the sketch had two different functions to C++: the one it called, which takes an int and has no body, and another one nobody called. The link failed with the same undefined symbol: blinkTimes(int). Make the declaration and the definition match, word for word.

The declaration and the definition, matching
void blinkTimes(int count);

void setup() {
  pinMode(13, OUTPUT);
  blinkTimes(3);
}

void loop() {
}

void blinkTimes(int count) {
  for (int i = 0; i < count; i++) {
    digitalWrite(13, HIGH);
    delay(200);
    digitalWrite(13, LOW);
    delay(200);
  }
}

A .h with no .cpp, an extern, a static member

A header tab sensor.h that declares int readSensor();, with no .cpp tab that writes it, gave undefined symbol: readSensor(). The header is the promise and the .cpp is the code: add the .cpp tab, starting with #include <Arduino.h> and #include "sensor.h".

extern int threshold; says the variable is defined in another file, and if no file defines it the link fails with undefined symbol: threshold. Write int threshold = 500; in exactly one file. And a static int total; inside a class only declares it: the link failed with undefined symbol: Counter::total until one line outside the class, int Counter::total = 0;, defined it.

A .c tab and extern "C"

A sketch is C++, and C++ adds a function’s parameter types to the name it hands the linker. A .c tab is compiled as C, which does not. So a mathutil.c that writes int addTwo(int a, int b), with a mathutil.h that only declares it, compiles cleanly and then fails with undefined symbol: addTwo(int, int). The code is there under its plain C name, and the sketch asks for the C++ one. The linker’s next line, >>> referenced by sketch.ino:5, names the line that calls it, and Mokxi’s build tab says "addTwo is used, but its code is in no file of the build."

There are two fixes, and both built. Rename the tab mathutil.cpp, so both sides are C++, or wrap the header’s declarations in extern "C", as below, so the sketch asks for the C name. Keep the #ifdef __cplusplus lines: C has no extern "C", and the .c tab includes the same header.

mathutil.h, for a sketch and a .c tab alike
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

int addTwo(int a, int b);

#ifdef __cplusplus
}
#endif

A library whose .cpp is not in the build

A library is usually a .h and a .cpp. Copy only the .h into a sketch, or install a library by hand into the wrong folder, and every call into it is an undefined reference, even though the sketch compiles. In the Arduino IDE, install it from the Library Manager or with Sketch, Include Library, Add .ZIP Library. In Mokxi, Add library takes the library’s .zip, or its .h and .cpp files together.

Questions

What does "undefined reference to setup" mean in Arduino?

The sketch has no setup() function, or has one spelled differently, such as Setup(). Every sketch needs a setup() and a loop() in lower case, even if one is empty.

Is "undefined reference" a compiler error?

No, a linker error. The code compiled; the linker could not find the code for a name to join into the program. So the line it names is often not in your sketch at all.

Is "undefined symbol" the same error?

Yes. "undefined reference to" is the wording of GCC’s linker, which the Arduino IDE uses; Mokxi links with LLVM’s linker, which says "undefined symbol".

My function is right there. Why is it an undefined reference?

Its parameters probably differ from the declaration at the top, such as byte in one and int in the other. C++ treats those as two different functions. Make the two lines match.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.