Linker issues with unit tests - Cannot use source files?

I am trying to clean up my projects and their unit tests. I am running into a weird linkage issue I cannot seem to solve.

I have earlier used only header files for my classes. The unit tests can test these fine. But now when I moved the class definitions to the src-directory, the unit tests cannot be build due to undefined reference errors. No methods of my classes are found by the linker while building the tests. Building the project (the check mark symbol) builds fine.

I have tried forcing rebuilding source files in the tests with test_build_project_src set to true, but it does not work. It just adds another error message (multiple definitions of 'main'). How am I supposed to use that option? Remove any main file from the source directory? (I am currently only using it to check for compilation errors when building).

Minimal example:

File structure:

.
+-- .pio
|    +-- ...
+-- .vscode
|    +-- ...
+-- include
|    +-- tClass.h
+-- src
|    +-- tClass.cpp
|    +-- main.cpp          (has an 'int main()' function)
+-- test
|    +-- test_embedded
|         +-- ...
|    +-- test_desktop
|         +-- mainTest.cpp (has an 'int main()' function also)
|         +-- test_tClass.h
|         +-- test_tClass.cpp
+-- platformio.ini

Content of platformio.ini:

[env:native]
platform = native
test_ignore = test_embedded
test_build_project_src = false
src_filter = -<.git/> -<test/> +<main.cpp>

Note: I have one class that cannot be tested in the native environment , so I had to make sure it was not included when building native. Thus, using a custom src_filter.

Note: I have tried with test_build_project_src = true, but it did not solve my linking issue.

Running Tests:

>> platformio test -e native

...

.pio\build\native\test\test_desktop\test_tClass.o:test_tClass.cpp:(.text+0x102): undefined reference to `tClass::tClass()'
.pio\build\native\test\test_desktop\test_tClass.o:test_tClass.cpp:(.text+0x10e): undefined reference to `tClass::someMethod(const bool)'
.pio\build\native\test\test_desktop\test_tClass.o:test_tClass.cpp:(.text+0x135): undefined reference to `tClass::anotherMethod(unsigned char&)'

...

collect2.exe: error: ld returned 1 exit status
*** [.pio\build\native\program.exe] Error 1

Note: I would rather not use a solution where I put my code in the lib folder, since I really do not want to manually copy code around. I am writing reusable libraries stored on GitHub that I want to use with the lib_deps option in platformio.ini. I have not had any luck using the lib folder for this in the past.

I ended up wrapping the content of src/main.cpp in C style macros, verifying that UNIT_TEST is not defined.

I did not want to start defining C style macros, that was the reason I did not do this from the start. However, it seems I chose the exact symbol that PlatformIO is already setting when running platformio test.

// main.cpp
#ifndef UNIT_TEST
int main() {...}    
#endif

I then set test_build_project_src = true and skipped the src_filter part. Instead of defining which files I wanted to use, I wrapped the few files not working with the native build in #ifdef ARDUINO macros.

Iā€™m not totally happy with the results, but it works.

1 Like