Linker error: undefined reference (reproducible)

I have 2 Arduino Teensy projects: basicTestLibrary and legacyTest

basicTestLibrary is is a simple cpp and header combo with a Foo class inside Bar namespace. It has a single method: doSomething.

The legacyTest uses basicTestLibrary as a dependency linked via file://

The doSomething method is invoked in the default loop area of main.cpp in legacyTest

When I attempt to build the project, it fails with a linker error and undefined reference to Bar::Foo::doSomething(int)

I’ve had this same error on a larger project, which is why I created this test environment with a fresh install of VS Code and PlatformIO extension on a new Windows 10 VM. The issue persists.

Project download: Microsoft OneDrive

basicTestLibrary

platformio.ini
[env:teensy41]
platform = teensy
board = teensy41
framework = arduino
library.json
{
  "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json",
  "name": "basicTestLibrary",
  "version": "0.1.0",
  "authors": {
    "name": "Matthew Baker",
    "email": "",
    "maintainer": true
  },
  "dependencies": {
  },
  "frameworks": ["arduino"],
	"platforms": "*",
  "build": {
    "flags": [
      
    ],
    "srcFilter": [
      "-<main.cpp>"
    ]
  }
}

legacyTest

platformio.ini
[common]
lib_deps_builtin = 

lib_deps_external = 
  basicTestLibrary=file://C:/platform_io_projects/basicTestLibrary

[env]
platform = teensy
board = teensy40
framework = arduino
lib_deps = ${common.lib_deps_builtin}
  ${common.lib_deps_external}

monitor_speed = 115200
build_flags =  -Wall

[env:teensy41]
platform = teensy
board = teensy41
framework = arduino

Any ideas why this is happening?

#include "foo.h"

namespace Bar
{

  Foo::Foo() {};
  int doSomething(int x)
  {
    return x + 10;
  }
}

Wrong.

The doSomething function is declared inside the namespace Bar, but not as a member method of the Foo class, as the header file declares.

namespace Bar
{
  class Foo
  {
  public:
    Foo();
    int doSomething(int x);
  };
}

So the foo.cpp has to be

#include "foo.h"

namespace Bar
{

  Foo::Foo() {};
  int Foo::doSomething(int x)
  {
    return x + 10;
  }
}

Further, the libray.json is wrong. The srcFilter

  "build": {
    "flags": [
      
    ],
    "srcFilter": [
      "-<main.cpp>"
    ]
  }

prevents all files of the library to be built. If you meant to say “build all files but the main.cpp” (which doesn’t even exist in that library’s folder?), then that’s

 "+<*> -<main.cpp>"

Apply these fixes and you get

Linking .pio\build\teensy41\firmware.elf
Checking size .pio\build\teensy41\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
Calculating size .pio\build\teensy41\firmware.elf
teensy_size: Memory Usage on Teensy 4.1:
teensy_size:   FLASH: code:8984, data:3016, headers:8476   free for files:8105988
teensy_size:    RAM1: variables:3808, code:6288, padding:26480   free for local variables:487712
teensy_size:    RAM2: variables:12416  free for malloc/new:511872
Building .pio\build\teensy41\firmware.hex
========= [SUCCESS] Took 2.59 seconds =========
1 Like

You’re right, I completely missed the Foo prefix for the definition of doSomething. The odd thing was that intellisense was accepting the foo.soSomething() call and was even pointing to the same declaration when Alt clicking it.
Code_m0DyARt15S

It’s been a long day :man_facepalming:

As for the library.json, that must have been the issue all along. I’ve now changed it to "srcFilter": "+<*> -<.git/> -<.svn/> -<main.cpp>". Thanks for clarifying this! main.cpp was in another library as a test, but I didn’t want it being included / compiled when used as an external library.