Including headers and src from other directories with PIO

Hi, I have my project on vscode in a PIO generated folder, with all that is required to run individually. Everything works fine.
I have a bunch of .cpp and .h files in a different directory. I want to be able to add them to my project by including them, but it has not been successful so far. Here is what I do:

In my platformio.ini, I specified the additional directories where my .cpp and .h files are:

[env:ATmega328P]
platform = atmelavr
board = ATmega328P
framework = arduino
upload_protocol = atmelice_isp
upload_flags = -e
upload_port = usb
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xFF
board_fuses.efuse = 0x05
build_flags =
  -I/Users/jcbsk/OneDrive/Documents/Github/Atmega328p_Addons/include
  -I/Users/jcbsk/OneDrive/Documents/Arduino/custom_files/header_files
  -L/Users/jcbsk/OneDrive/Documents/Github/Atmega328p_Addons/src
  -L/Users/jcbsk/OneDrive/Documents/Arduino/custom_files/src

Then, I have a main.h that includes all of my header files needed for my project. There I #include <> the header files from my external directory. (Then I add this main.h in my main.cpp).

#ifndef MAIN_H
#define MAIN_H

#include "app_config.h"
#include <Arduino.h>
#include <SPI.h>

#include "74HC165.h"
#include "tact.h"
#include "tact_functions.h"
#include "FSM_config.h"
#include "menu.h"
#include "Timers.h"
#include "sleep.h"

/*##################################################################

ADDONS : external headers included if defined in app_config

##################################################################*/

#if FOUR_LCD_CONFIG
// Add PIO libraries
#include <LCD.h>
#include <LiquidCrystal_I2C.h> // F Malpartida's NewLiquidCrystal library
// Addon (external) library
#include <4x20_LCD.h>
#endif

#if ST7789_CONFIG
// Add PIO libraries
#include <Adafruit_ST7789.h>    //includes Adafruit_GFX.h
// Addon library
#include <ST7789_oled.h>
#endif

#if DS1307_CONFIG
// Add external libraries
#include <RTClib.h>
// Addon library
#include <DS1307.h>
#endif

#endif // MAIN_H

You see, the ADDONS section at the end of my main.h is supposed to let me work with those header files from my external directory (I called them DS1307.h, ST7789_oled.h and 4x20_LCD.h)

I think so far this works because I am able to access the functions from my external .h files when typing (the intellisense recognizes them). I also can compile when these functions are in my main.cpp, but as soon as the linking starts, an error occurs saying that

<artificial>:(.text.startup+0x2a4): undefined reference to `whatever the function name()'

This means it must be an include problem but I just can’t find it. I include main.h in all of my external headers like so:

#ifndef LCD_FOUR_H
#define LCD_FOUR_H

#include <main.h>      //RED SQUIGGLY LINE HERE

/*##################################################
            MACROS
##################################################*/

//LCD to I2C pinout

#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
#define LED_OFF 1 
#define LED_ON 0

/*##################################################
            DECLARATION
##################################################*/

extern LiquidCrystal_I2C lcd;

void lcd_setup();

#endif

And there is a red squiggly line on my #include <main.h> in my external files, Saying

#include errors detected. 
Please update your includePath. Squiggles are disabled for this translation unit
cannot open source file "main.h

On my external .cpp files I include their respective .h files like so: (and the same red squiggle appears on the #include <> shown below:

#include <4x20_LCD.h>     //RED SQUIGGLY LINE HERE

LiquidCrystal_I2C lcd(LCD_I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);

void lcd_setup() {

  lcd.begin(20, 4); // initialize the lcd
  //lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(LED_OFF);  //turn on backlight
  lcd.backlight(); //Backlight ON if under program control
  lcd.setCursor(0, 0); //character 1 on line 0

}

I am almost there, because I can access everything from main.cpp, they just cannot link the libraries?! What am I doing wrong? Thanks!
here is main.cpp:
#include “main.h” //NO SQUIGGLY LINE HERE :slight_smile:

void setup() {
lcd_setup(); //Intellisense finds this function! just cannot link after compiling
}

void loop() {
}

As you have just added include folders via the -I flag, it is able to resolve the names and headers and everything, but the source code from the source file isn’t compiled in. Also the

Flag is wrong here if there are source code files inside these folders. -L adds a search path for precompiled library files (.a / .so) .

You might try a different approach: Try using lib_extra_dirs. This does compile in the code and also include the library headers, but only if they obey the library folder format (include files in the inc/ or include folder).

So you might try

[env:ATmega328P]
platform = atmelavr
board = ATmega328P
framework = arduino
upload_protocol = atmelice_isp
upload_flags = -e
upload_port = usb
board_fuses.hfuse = 0xDE
board_fuses.lfuse = 0xFF
board_fuses.efuse = 0x05
; add non-standard include
build_flags =
  -I/Users/jcbsk/OneDrive/Documents/Arduino/custom_files/header_files
lib_extra_dirs = 
    /Users/jcbsk/OneDrive/Documents/Github/Atmega328p_Addons/
    /Users/jcbsk/OneDrive/Documents/Arduino/custom_files/

as the platformio.ini.

2 Likes

I use lib_extra_dirs as indicated:

lib_extra_dirs =
    ..\Library\EnvironmentParamSensor\lib,

with the structure as follows

EnvironmentParamSensor
└───lib
    ├───BMP280
    ├───MCP3008
    ├───SensorBase
    └───SHTC3

each subfolder having its *.h and *.cpp files. All is compiled and linked. The only inconvenience:
the headers in includes in main.cpp are squiggled and not clickable and no code completion for the respective classes. Can I get rid of this?

#include <SimpleAnalogSensor.h>
#include <BMP280Temperature.h>

Ctrl+Shift+P → Rebuild Intellisense in VSCode.

Yes, it worked.
Thank you, Max!

The above solution is not working.
My directory structure is

ESP32_Projects

├───project1
├ … …└─── src
├ . … … . . … └─── my_lib1.cpp
├───project2
├───shared_libs
… … …└─── my_lib1
… … … … … …├─── my_lib1.h
… … … … … …└─── my_lib1.cpp

In platformio I wrote

lib_extra_dirs = 
       C:/Users/johnk/Documents/ESP32Projects/shared_libs

lib_deps =
  heltecautomation/Heltec ESP32 Dev-Boards@^1.1.0
  olikraus/U8g2@^2.28.8

lib_ldf_mode=chain+

In src/main I have:
#include <my_lib1.h>

During compile, I get:
src\main.cpp:6:22: fatal error: my_lib1.h: No such file or directory

Please Help

The above solution is absolutely working with the folder structure you’ve shown. See GitHub - maxgerhardt/pio-test-libextra-repro.

Scanning dependencies...
Dependency Graph
|-- <my_lib1>
Building in release mode
[...]
RAM:   [          ]   4.1% (used 13488 bytes from 327680 bytes)
Flash: [==        ]  15.9% (used 208262 bytes from 1310720 bytes)
Building .pio\build\esp32dev\firmware.bin
esptool.py v3.1
Merged 1 ELF section
============================================= [SUCCESS] Took 8.90 seconds =============================================

@maxgerhardt
Thank you for responding.
My apologies, I should not have said your solution did not work, I should have said it was not working for me.
Your very complete and detailed example was what I needed.
The problem was that I do not have a good understanding of platformio.ini and python.
The absolute patch I had was the problem.
lib_extra_dirs =
C:/Users/johnk/Documents/ESP32Projects/shared_libs
But without your kind and complete example showing the relative path on the same line as
lib_extra_dirs = , I might have still failed because would not have thought I needed it on the same line because many other of my parameters have settings on the next line. I thought it was just a preference not a requirement.
When I typed
lib_extra_dirs =
…/…/sb_libs
It still did not work, with I typed
lib_extra_dirs = …/…/sb_libs
like your example. It worked.
Again, thank you for all the hard work you did to help me with a stupid mistake.

1 Like