Unity library is missing?

I am trying to run a simple unit test but it fails because Unity.h is missing. If I add unity to my lib_dep, the test does work, but then my normal build fails.

Any suggestions? I had the impression that platformio is supposed to identify automatically the test’s dependency on Unity.

Platformio.ini:

[env:my_env]
build_type = debug
; build_type = release
platform = ststm32
; test_filter = serial_packets/test_serial_packets_client
; debug_test = serial_packets/test_serial_packets_client
test_filter = test_trivial
debug_test = test_trivial
extra_scripts = extra_script.py
board = my_genericSTM32H750VBT6
; Linker file is from cube ide.
board_build.ldscript = STM32H750VBTX_FLASH.ld
debug_tool = stlink
upload_protocol = stlink
; debug_build_flags = -O0 -ggdb3 -g3
; debug_build_flags = -Og -ggdb3 -g3
debug_build_flags = -Os -g3 -ggdb3
; debug_init_break = tbreak app_main
debug_init_break = tbreak none
test_framework = custom
; test_port = COM6
monitor_port = COM6
lib_archive = no
check_skip_packages = yes
lib_deps = 
  adc
  data_recorder
  host_link
  io
  misc
  printer_link
  controller
  cube_ide
  serial_packets
  system
  ; unity
build_flags =
  -fmax-errors=5
  -Werror
  -mfpu=fpv5-sp-d16 
  -mfloat-abi=hard 
  -Wl,-Map,${BUILD_DIR}/firmware.map
  -mthumb 
  -D DEBUG
  -D USE_HAL_DRIVER
  -DSTM32_THREAD_SAFE_STRATEGY=4
  -fstack-usage
  -std=gnu11
  -Ilib/cube_ide/Core/Inc
  -Ilib/cube_ide/Core/ThreadSafe
  -Ilib/cube_ide/Drivers/CMSIS/Device/ST/STM32H7xx/Include
  -Ilib/cube_ide/Drivers/CMSIS/Include
  -Ilib/cube_ide/Drivers/STM32H7xx_HAL_Driver/Inc
  -Ilib/cube_ide/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
  -Ilib/cube_ide/Middlewares/ST/STM32_USB_Device_Library/Core/Inc
  -Ilib/cube_ide/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS
  -Ilib/cube_ide/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/Include
  -Ilib/cube_ide/Middlewares/Third_Party/FreeRTOS/Source/include
  -Ilib/cube_ide/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F
  -Ilib/cube_ide/Middlewares/Third_Party/FatFs/src
  -Ilib/cube_ide/USB_DEVICE/App
  -Ilib/cube_ide/USB_DEVICE/Target
  -Ilib/cube_ide/FATFS/App
  -Ilib/cube_ide/FATFS/Target
  -D CONFIG_MAX_PACKET_DATA_LEN=1000
  -D CONFIG_MAX_PENDING_COMMANDS=5

test/test_trivial/test.cpp: (app_main() is called from main() in my startup file, which first stats FreeRTOS)

#include "Unity.h"
#include "time_util.h"
#include "io.h"

void setUp() {}

void tearDown() {}

void test_sample() { TEST_ASSERT_TRUE(true); }

void app_main() {
  // LEt the USB/Serial time to settle down.
  time_util::delay_millis(3000);

  UNITY_BEGIN();
  RUN_TEST(test_sample);
  UNITY_END();

  for (;;) {
    time_util::delay_millis(100);
    io::LED.toggle();
  }
}

Test failure (lib_dep doesn’t contain Unity, running a verbose test after a Full Clean):

 *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --verbose --environment my_env 

Collected 10 tests (misc/test_static_string, misc/test_time_util, sd/test_rw, serial_packets/test_serial_packets_client, serial_packets/test_serial_packets_crc, serial_packets/test_serial_packets_data, serial_packets/test_serial_packets_decoder, serial_packets/test_serial_packets_encoder, test_sample, test_trivial)        

Processing test_trivial in my_env environment
------------------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
test\test_trivial\test.cpp:1:10: fatal error: Unity.h: No such file or directory

***************************************************************
* Looking for Unity.h dependency? Check our library registry!   
*
* CLI  > platformio lib search "header:Unity.h"
* Web  > https://registry.platformio.org/search?q=header:Unity.h
*
*************************************************************** 

 #include "Unity.h"
          ^~~~~~~~~
compilation terminated.
*** [.pio\build\my_env\test\test_trivial\test.o] Error 1
Uploading stage has failed, see errors above. Use `pio test -vvv` option to enable verbose output.
-------------------------------------------------------- my_env:test_trivial [ERRORED] Took 25.12 seconds --------------------------------------------------------

============================================================================ SUMMARY ============================================================================ 
Environment    Test                                        Status    Duration
-------------  ------------------------------------------  --------  ------------
my_env         misc/test_static_string                     SKIPPED
my_env         misc/test_time_util                         SKIPPED
my_env         sd/test_rw                                  SKIPPED
my_env         serial_packets/test_serial_packets_client   SKIPPED
my_env         serial_packets/test_serial_packets_crc      SKIPPED
my_env         serial_packets/test_serial_packets_data     SKIPPED
my_env         serial_packets/test_serial_packets_decoder  SKIPPED
my_env         serial_packets/test_serial_packets_encoder  SKIPPED
my_env         test_sample                                 SKIPPED
my_env         test_trivial                                ERRORED   00:00:25.125
=========================================================== 1 test cases: 0 succeeded in 00:00:25.125 =========================================================== 

 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'test', '--verbose', '--environment', 'my_env'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it.

Successful test, when I include unity in platformio.ini lib_dep:

 *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe test --verbose --environment my_env 

Collected 10 tests (misc/test_static_string, misc/test_time_util, sd/test_rw, serial_packets/test_serial_packets_client, serial_packets/test_serial_packets_crc, serial_packets/test_serial_packets_data, serial_packets/test_serial_packets_decoder, serial_packets/test_serial_packets_encoder, test_sample, test_trivial)        

Processing test_trivial in my_env environment
------------------------------------------------------------------------------------------------------------------------------------------------------------------

Building & Uploading...
xPack Open On-Chip Debugger 0.12.0-01004-g9ea7f3d64-dirty (2023-01-30-15:04)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

hla_swd
[stm32h7x.cpu0] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08001994 msp: 0x24080000
** Programming Started **
Warn : Adding extra erase range, 0x0800c560 .. 0x0801ffff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **  
shutdown command invoked

Testing...
If you don't see any output for the first 10 secs, please reset board (press reset button)

I: Task Main started successfully
I: Task Logger started successfully
I: Serial USB started
I: &uxTopUsedPriority = 0x800c1b8
test\test_trivial\test.cpp:16:test_sample:PASS

-----------------------
1 Tests 0 Failures 0 Ignored
OK

-------------------------------------------------------- my_env:test_trivial [PASSED] Took 32.59 seconds -------------------------------------------------------- 

============================================================================ SUMMARY ============================================================================ 
Environment    Test                                        Status    Duration
-------------  ------------------------------------------  --------  ------------
my_env         misc/test_static_string                     SKIPPED
my_env         misc/test_time_util                         SKIPPED
my_env         sd/test_rw                                  SKIPPED
my_env         serial_packets/test_serial_packets_client   SKIPPED
my_env         serial_packets/test_serial_packets_crc      SKIPPED
my_env         serial_packets/test_serial_packets_data     SKIPPED
my_env         serial_packets/test_serial_packets_decoder  SKIPPED
my_env         serial_packets/test_serial_packets_encoder  SKIPPED
my_env         test_sample                                 SKIPPED
my_env         test_trivial                                PASSED    00:00:32.594
=========================================================== 1 test cases: 1 succeeded in 00:00:32.594 =========================================================== 
 *  Terminal will be reused by tasks, press any key to close it. 

And if I perform my normal build with unity listed in lib_dep I get this error:

 *  Executing task: C:\Users\user\.platformio\penv\Scripts\platformio.exe run 

Processing my_env (platform: ststm32; board: my_genericSTM32H750VBT6)
-----------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/ststm32/my_genericSTM32H750VBT6.html
PLATFORM: ST STM32 (16.1.0) > STM32H750VBT6 (1024k RAM. 128k Flash)
HARDWARE: STM32H750VBT6 480MHz, 1MB RAM, 128KB Flash
DEBUG: Current (stlink) External (blackmagic, jlink, stlink)       
PACKAGES:
 - toolchain-gccarmnoneeabi @ 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf 
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 11 compatible libraries
Scanning dependencies...
Dependency Graph
|-- adc
|-- data_recorder 
|-- host_link     
|-- io
|-- misc
|-- printer_link  
|-- controller    
|-- cube_ide      
|-- serial_packets
|-- system        
|-- Unity @ 2.5.2 
Building in debug mode
Compiling .pio\build\my_env\lib50d\io\cdc_serial.o
Compiling .pio\build\my_env\lib50d\io\io.o
Compiling .pio\build\my_env\lib50d\io\serial.o
Compiling .pio\build\my_env\lib2be\misc\error_handler.o
Compiling .pio\build\my_env\lib2be\misc\logger.o
Compiling .pio\build\my_env\lib2be\misc\session.o
Compiling .pio\build\my_env\libee8\serial_packets\serial_packets_client.o
Compiling .pio\build\my_env\libee8\serial_packets\serial_packets_crc.o
Compiling .pio\build\my_env\libee8\serial_packets\serial_packets_decoder.o
Compiling .pio\build\my_env\libee8\serial_packets\serial_packets_encoder.o
Compiling .pio\build\my_env\libd5d\data_recorder\data_recorder.o
Compiling .pio\build\my_env\lib48e\host_link\host_link.o
Compiling .pio\build\my_env\lib4fd\controller\controller.o
Compiling .pio\build\my_env\lib465\adc\adc.o
Compiling .pio\build\my_env\lib9d9\printer_link\printer_link.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\dma.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\freertos.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\gpio.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\main.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\rng.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\sdmmc.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\spi.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\stm32h7xx_hal_msp.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\stm32h7xx_it.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\syscalls.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\sysmem.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\system_stm32h7xx.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\tim.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Src\usart.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\Startup\startup_stm32h750vbtx.o
Compiling .pio\build\my_env\libe47\cube_ide\Core\ThreadSafe\newlib_lock_glue.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pcd.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pcd_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rng_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_spi.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_spi_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.o
Compiling .pio\build\my_env\libe47\cube_ide\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_usb.o
Compiling .pio\build\my_env\libe47\cube_ide\FATFS\App\fatfs.o
Compiling .pio\build\my_env\libe47\cube_ide\FATFS\Target\bsp_driver_sd.o
Compiling .pio\build\my_env\libe47\cube_ide\FATFS\Target\fatfs_platform.o
Compiling .pio\build\my_env\libe47\cube_ide\FATFS\Target\sd_diskio.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Src\usbd_cdc.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_core.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ctlreq.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\ST\STM32_USB_Device_Library\Core\Src\usbd_ioreq.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FatFs\src\diskio.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FatFs\src\ff.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FatFs\src\ff_gen_drv.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FatFs\src\option\ccsbcs.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FatFs\src\option\syscall.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\CMSIS_RTOS\cmsis_os.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\croutine.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\event_groups.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\list.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\portable\GCC\ARM_CM4F\port.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\queue.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\stream_buffer.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\tasks.o
Compiling .pio\build\my_env\libe47\cube_ide\Middlewares\Third_Party\FreeRTOS\Source\timers.o
Compiling .pio\build\my_env\libe47\cube_ide\USB_DEVICE\App\usb_device.o
Compiling .pio\build\my_env\libe47\cube_ide\USB_DEVICE\App\usbd_cdc_if.o
Compiling .pio\build\my_env\libe47\cube_ide\USB_DEVICE\App\usbd_desc.o
Compiling .pio\build\my_env\libe47\cube_ide\USB_DEVICE\Target\usbd_conf.o
Compiling .pio\build\my_env\lib0db\system\startup.o
Compiling .pio\build\my_env\lib924\Unity\unity.o
Compiling .pio\build\my_env\src\main.o
In file included from .pio\libdeps\my_env\Unity\src\unity.h:21:0,
                 from .pio\libdeps\my_env\Unity\src\unity.c:7:
.pio\libdeps\my_env\Unity\src\unity_internals.h:11:10: fatal error: unity_config.h: No such file or directory

**********************************************************************
* Looking for unity_config.h dependency? Check our library registry!
*
* CLI  > platformio lib search "header:unity_config.h"
* Web  > https://registry.platformio.org/search?q=header:unity_config.h
*
**********************************************************************

 #include "unity_config.h"
          ^~~~~~~~~~~~~~~~
compilation terminated.
*** [.pio\build\my_env\lib924\Unity\unity.o] Error 1
=============================================================== [FAILED] Took 27.59 seconds ===============================================================
 *  The terminal process "C:\Users\user\.platformio\penv\Scripts\platformio.exe 'run'" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it.

Anybody has any idea why the Unity dependency is not detected automatically as it should?

OK, found it. My platformio.ini has test_platform=custom. Should be test_platform=unity (default).

I actually just ran into the same issue…

In my current project I do not have any main.cpp, because there is no implementation - just headers and inline implementations (ipp files).

I can confirm, that the unity_config.h and unity_config.c files do not exist before pio run anywhere in the .pio/build/* directory. Once I run pio test, they do exist, but even then pio run fails with the unity_config.h-related error message instead of the anticipated one.

Adding lib_ignore = Unity the build fails with the expected error, but Unity is absent entirely and pio test does not work.

What I would expect if I run pio run -v is something along the lines of:

ld: Undefined symbols:
  _main, referenced from:
      <initial-undefines>
clang: error: linker command failed with exit code 1 (use -v to see invocation)
*** [.pio/build/native/program] Error 1

However: what I get is:

In file included from .pio/libdeps/native/Unity/src/unity.c:7:
In file included from .pio/libdeps/native/Unity/src/unity.h:21:
.pio/libdeps/native/Unity/src/unity_internals.h:11:10: fatal error: 'unity_config.h' file not found
#include "unity_config.h"
         ^~~~~~~~~~~~~~~~
1 error generated.
*** [.pio/build/native/libe7b/Unity/unity.o] Error 1

My platformio.ini looks like this:

[platformio]
name = "LibName"
description = LibDescription
default_envs = native

[env]
build_flags = -std=gnu++17
build_unflags = -std=gnu++11

[env:native]
platform = native
lib_deps = voronii/Dial2AbstractSensors@^1.0.9
           throwtheswitch/Unity@^2.5.2

I do not currently need pio run -v for this project, but I might want to have tests and implementation in the same project at some point and this would be an issue.

It seems, that Unity is not excluded during regular build (in Java / Maven/Gradle one can use testImplementation or <scope>test</scope>, but I haven’t found anything similar in PlatformIO). Is there a way to do that?

Edit:
I just figured out, that not adding throwtheswitch/Unity@^2.5.2 to lib_deps at all works - I can run pio run as well as pio test. However: CLion goes nuts, because it cannot find Unity at all. This shouldn’t happen though - or should it?

Edit 2:
Weird, it seems to find some pieces, but not others. It looks like it’s possible to work around it, but it’s not really smooth.

There is no reason to do this. When testing the project for the first time, PlatformIO will pull all dependencies required by the unit testing engine.

1 Like

Thank you. Yes, it seems, that just setting up tests ensures, that Unity is pulled and included and used in pio test only.

1 Like