Problem with "PROJECT_DIR" variable

I’m trying to use the PROJECT_DIR variable, but it seems to get corrupted if I
use a specific path for my project folder.

I am using Window 10.

I created two separate projects in different folders and only one shows the problem

First project folder:
D:\Projects\PlatformIO\ESP32\CYD\CYD_EEZ_Demo_B
Prints out as:
D:/Projects/PlatformIO/1/CYD/CYD_EEZ_Demo_B

It has deleted “ESP32” from the path and replaced it with “1”

Second project folder:
D:\Projects\PlatformIO\ESP32_DEV\CYD\CYD_EEZ_Demo_C
prints out as:
D:/Projects/PlatformIO/ESP32_DEV/CYD/CYD_EEZ_Demo_C

In this location is works perfectly.

This a baffling to me. Maybe ESP32 is a reserved word or something, but I wouldn’t expect that to effect a file system path?

1 Like

Hi @grubble !

Can you please show which variable and where you have set it? That’s not quite clear to me yet.

I add this to my platformio.ini, so I have access to PROECT_DIR’s value in my main.cpp.

build_flags =
  -D SHOW_PROJECT_DIR="${PROJECT_DIR}"

Then in my Arduino code main.cpp I print out the value to the serial port:

#define __MY_TO_STR_AUX(x) #x
#define __MY_TO_STR(x) __MY_TO_STR_AUX(x)

void setup() {
  Serial.begin(115200);
  Serial.println( __MY_TO_STR(SHOW_PROJECT_DIR) );
}
void loop(){}

This is not what I’m actually trying to do with the variable, but it was the easiest way to prove to myself there was some weirdness happening.

You’re not string escaping the macro correctly.

There’s a macro active with -D ESP32, and defined macros like this will have a default value of “1”.

What you’re doing is you’re building a macro with the identifier

#define SHOW_PROJECT_DIR D:\Projects\PlatformIO\ESP32\CYD\CYD_EEZ_Demo_B

which you then try to post-stringify with your

#define __MY_TO_STR_AUX(x) #x
#define __MY_TO_STR(x) __MY_TO_STR_AUX(x)

trick. But by then, the ESP32 part of that macro will already have been expanded (global activated macro), and so it screws up the whole thing.

So what you want is to be able to do a direct string definition like

#define SHOW_PROJECT_DIR "D:\Projects\PlatformIO\ESP32\CYD\CYD_EEZ_Demo_B"

So, don’t post-stringifiy your macro, follow the documentation directly to already stringify it in the build_flags.

https://docs.platformio.org/en/latest/projectconf/sections/env/options/build/build_flags.html#stringification

So you need

build_flags =
  -D'SHOW_PROJECT_DIR="${PROJECT_DIR}"'

And then just

void setup() {
  Serial.begin(115200);
  Serial.println(SHOW_PROJECT_DIR);
}
void loop(){}

grafik

1 Like

Thanks @maxgerhardt, that worked perfectly. However I think maybe it needs to be post-stringifyable to satisfy the way the LVGL library expects a macro definition for where to find the master config file if not placed in the default location, which would be “[project folder]/.pio/libdeps/[my board]lv_conf.h.”

This file has to be hand crafted per project, so I want it located in the “src” folder with the rest of my code.

The LVGL library has a way to tell it the location of the config file, by defining a macro: LV_CONF_PATH.

In the LVGL library file “lv_conf_internal.h”, this section of code handles finding lv_conf.h:

/*If lv_conf.h is not skipped include it*/
#if !defined(LV_CONF_SKIP) || defined(LV_CONF_PATH)
    #ifdef LV_CONF_PATH                           /*If there is a path defined for lv_conf.h use it*/
        #define __LV_TO_STR_AUX(x) #x
        #define __LV_TO_STR(x) __LV_TO_STR_AUX(x)
        #include __LV_TO_STR(LV_CONF_PATH)
        #undef __LV_TO_STR_AUX
        #undef __LV_TO_STR
    #elif defined(LV_CONF_INCLUDE_SIMPLE)         /*Or simply include lv_conf.h is enabled*/
        #include "lv_conf.h"
    #else
        #include "../../lv_conf.h"                /*Else assume lv_conf.h is next to the lvgl folder*/
    #endif
    #if !defined(LV_CONF_H) && !defined(LV_CONF_SUPPRESS_DEFINE_CHECK)
        /* #include will sometimes silently fail when __has_include is used */
        /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80753 */
        #pragma message("Possible failure to include lv_conf.h, please read the comment in this file if you get errors")
    #endif
#endif

But if I add this to my platformio.ini:

build_flags =
  -D'SHOW_PROJECT_DIR="${PROJECT_DIR}/src/lv_conf.h"'
  -D'LV_CONF_PATH="${PROJECT_DIR}/src/lv_conf.h"'                       

The compiler throws the error:

In file included from .pio/libdeps/my_esp32-2432S028R/lvgl/src/lv_init.h:16,
                 from .pio/libdeps/my_esp32-2432S028R/lvgl/lvgl.h:21,
                 from src/main.cpp:1:
.pio/libdeps/my_esp32-2432S028R/lvgl/src/lv_conf_internal.h:54:42: fatal error: \"D:/Projects/PlatformIO/ESP32/CYD/CYD_EEZ_Demo_B/src/lv_conf.h\": Invalid argument
         #include __LV_TO_STR(LV_CONF_PATH)
                                          ^
compilation terminated.

My knowledge of complicated macros like this is minimal, and I’m struggling to figure out how to solve it, or even if it can be done.

1 Like

If the stringified value of the LV_CONF_PATH variable is just #included, then you can take al ot of complexity out of this variable’s value by simply first adding the path where your wanted include file is with -I (global include search path) and then only saying -DLV_CONF_PATH="lv_conf.h".

In fact, this simplifies further with this code path

If lv_conf.h is not in the library itself, you can simple say

build_flags =
  ; make LVGL code try to include "lv_conf.h"
  -DLV_CONF_INCLUDE_SIMPLE
  ; this folder has the lv_conf.h. Add it to the global include path
  -Isrc/

Thanks @maxgerhardt for all your help. I got stuck down the rabbit hole trying to solve it the first way, I hadn’t noticed the LV_CONF_INCLUDE_SIMPLE method, which worked perfectly.
I now have:

build_flags =
  -Isrc/
  -DLV_CONF_INCLUDE_SIMPLE

Thanks.

2 Likes