Understanding dependency compilation order

Hello, I’m slowly getting familiar with PIO and trying to learn a little bit of how it works under the hood.

Is it possible to understand how the Library Dependency Finder (LDF) led the compiler to a library that caused a missing dependency error? In other words, the dependency chain of who included who until it broke?

For example, my project has a dependency on the Adafruit GFX Library which causes a know dependency error. I now understand how to fix the error thanks to this post and this post. My understanding is that Adafruit GFX Library has an #include <Adafruit_I2CDevice.h> that is not picked up by the LDF by default (lib_ldf_mode = chain) since it’s in the source file Adafruit_GrayOLED.cpp (rather than being in a header file).

The error generated is the following:

Processing mkrwifi1010 (platform: atmelsam; board: mkrwifi1010; framework: arduino)
------------------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelsam/mkrwifi1010.html
PLATFORM: Atmel SAM (6.3.0) > Arduino MKR WiFi 1010
HARDWARE: SAMD21G18A 48MHz, 32KB RAM, 256KB Flash
DEBUG: Current (atmel-ice) External (atmel-ice, blackmagic, jlink)
PACKAGES:
 - framework-arduino-samd 1.8.11
 - framework-cmsis 1.40500.0 (4.5.0)
 - framework-cmsis-atmel 1.2.2
 - toolchain-gccarmnoneeabi 1.70201.0 (7.2.1)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain+, Compatibility ~ soft
Found 36 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <Arduino_MKRIoTCarrier> 1.0.2
|   |-- <Wire> 1.0
|   |-- <Arduino_BQ24195> 0.9.1
|   |   |-- <Wire> 1.0
|   |-- <Arduino_APDS9960> 1.0.3
|   |   |-- <Wire> 1.0
|   |-- <Arduino_LPS22HB> 1.0.1
|   |   |-- <Wire> 1.0
|   |-- <Arduino_LSM6DS3> 1.0.0
|   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <SPI> 1.0
|   |-- <Arduino_HTS221> 1.0.0
|   |   |-- <Wire> 1.0
|   |-- <Arduino_MCHPTouch> 1.2.1
|   |-- <SD> 0.0.0-alpha+sha.041f788250
|   |   |-- <SPI> 1.0
|   |-- <Adafruit GFX Library> 1.10.10
|   |   |-- <SPI> 1.0
|   |   |-- <Wire> 1.0
|   |-- <Adafruit ST7735 and ST7789 Library> 1.7.3
|   |   |-- <Adafruit GFX Library> 1.10.10
|   |   |   |-- <SPI> 1.0
|   |   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <Adafruit DotStar> 1.1.4
|   |   |-- <SPI> 1.0
|-- <ArduinoIoTCloud> 1.1.1
|   |-- <ArduinoECCX08> 1.3.5
|   |   |-- <Wire> 1.0
|   |-- <Wire> 1.0
|   |-- <Arduino_DebugUtils> 1.1.0
|   |-- <Arduino_ConnectionHandler> 0.6.4
|   |   |-- <WiFiNINA> 1.8.13
|   |   |   |-- <SPI> 1.0
|   |   |-- <Arduino_DebugUtils> 1.1.0
|   |-- <WiFiNINA> 1.8.13
|   |   |-- <SPI> 1.0
|   |-- <RTCZero> 1.6.0
|   |-- <ArduinoMqttClient> 0.1.5
|-- <Arduino_ConnectionHandler> 0.6.4
|   |-- <WiFiNINA> 1.8.13
|   |   |-- <SPI> 1.0
|   |-- <Arduino_DebugUtils> 1.1.0
|-- <WiFiNINA> 1.8.13
|   |-- <SPI> 1.0
|-- <Arduino_DebugUtils> 1.1.0
|-- <RTCZero> 1.6.0
|-- <ArduinoMqttClient> 0.1.5
|-- <Wire> 1.0
|-- <Arduino_BQ24195> 0.9.1
|   |-- <Wire> 1.0
|-- <Arduino_APDS9960> 1.0.3
|   |-- <Wire> 1.0
|-- <Arduino_LPS22HB> 1.0.1
|   |-- <Wire> 1.0
|-- <Arduino_LSM6DS3> 1.0.0
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <SPI> 1.0
|-- <Arduino_HTS221> 1.0.0
|   |-- <Wire> 1.0
|-- <Arduino_MCHPTouch> 1.2.1
|-- <SD> 0.0.0-alpha+sha.041f788250
|   |-- <SPI> 1.0
|-- <Adafruit GFX Library> 1.10.10
|   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|-- <Adafruit ST7735 and ST7789 Library> 1.7.3
|   |-- <Adafruit GFX Library> 1.10.10
|   |   |-- <SPI> 1.0
|   |   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <Adafruit DotStar> 1.1.4
|   |-- <SPI> 1.0
Building in release mode
Compiling .pio\build\mkrwifi1010\lib581\Adafruit GFX Library\Adafruit_GrayOLED.cpp.o
In file included from .pio\libdeps\mkrwifi1010\Adafruit GFX Library\Adafruit_GrayOLED.cpp:20:0:
.pio\libdeps\mkrwifi1010\Adafruit GFX Library\Adafruit_GrayOLED.h:30:10: fatal error: Adafruit_I2CDevice.h: No such file or directory

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

 #include <Adafruit_I2CDevice.h>
          ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Archiving .pio\build\mkrwifi1010\lib74d\libArduinoECCX08.a
Archiving .pio\build\mkrwifi1010\libb8d\libArduino_DebugUtils.a
Compiling .pio\build\mkrwifi1010\libc61\WiFiNINA\utility\WiFiSocketBuffer.cpp.o
Compiling .pio\build\mkrwifi1010\libc61\WiFiNINA\utility\nano_rp2040_support.cpp.o
Compiling .pio\build\mkrwifi1010\libc61\WiFiNINA\utility\server_drv.cpp.o
Compiling .pio\build\mkrwifi1010\libc61\WiFiNINA\utility\spi_drv.cpp.o
Compiling .pio\build\mkrwifi1010\libc61\WiFiNINA\utility\wifi_drv.cpp.o
Compiling .pio\build\mkrwifi1010\liba7c\Arduino_ConnectionHandler\Arduino_ConnectionHandler.cpp.o
Compiling .pio\build\mkrwifi1010\liba7c\Arduino_ConnectionHandler\Arduino_GSMConnectionHandler.cpp.o
Compiling .pio\build\mkrwifi1010\liba7c\Arduino_ConnectionHandler\Arduino_LoRaConnectionHandler.cpp.o
Compiling .pio\build\mkrwifi1010\liba7c\Arduino_ConnectionHandler\Arduino_NBConnectionHandler.cpp.o
*** [.pio\build\mkrwifi1010\lib581\Adafruit GFX Library\Adafruit_GrayOLED.cpp.o] Error 1
================================ [FAILED] Took 19.31 seconds ================================

How can I know which file included Adafruit_GrayOLED.cpp or Adafruit_GrayOLED.h? I did a global search and could not find such references.

Because I could not find any references to one of these two files from any other library, I’m suspecting that PIO is compiling all the files inside /libdeps/Adafruit GFX Library (rather than just the files listed in a #include statement). Is my suspicion correct? (library’s github repo)

Any references to documentation or related articles would be greatly appreciated. Thanks.

Does your platformio.ini explicitly have

lib_deps =
     adafruit/Adafruit BusIO @ ^1.8.3
     #.. other libs

in lib_deps?

Thanks for the reply!
No. If I include adafruit/Adafruit BusIO @ ^1.8.3 in lib_deps then it fixes the dependency error but that doesn’t help me trace the dependency chain that caused the error.

Here is my platformio.ini file (intentionally leaving Adafruit BusIO out):

[env:mkrwifi1010]
platform = atmelsam
board = mkrwifi1010
framework = arduino
build_flags =
    -L"$PROJECT_LIBDEPS_DIR/$PIOENV/Arduino_MCHPTouch/src/cortex-m0plus"
    -lsamd21_qt_gcc
lib_deps = 
	arduino-libraries/Arduino_MKRIoTCarrier@^1.0.2
	arduino-libraries/ArduinoIoTCloud@^1.1.1
	adafruit/Adafruit SleepyDog Library @ ^1.4.0

I think the answer from @ivankravets in another post brings me a little closer to the answer:

PlatformIO uses chain+ mode for library.properties dependencies.
[It] parses ALL C/C++ source files of the project and follows only by nested includes ( #include ... , chain…) from the libraries. It also parses C, CC, CPP files from libraries which have the same name as included header file.

Does this means that, similarly to the project’s files in the /src folder, all source files inside the library’s root directory are also parsed?

Consider the following scenario:

  • my main.cpp has #include <Adafruit_GFX.h>
  • Adadruit GFX library has the structure illustrated in my first post

Will Adafruit_GrayOLED.cpp be parsed even thought #include <Adafruit_GFX.h> is not found anywhere in the library’s contents, in my main.cpp or in my lib_deps ?