Build_cache_dir = ... will not share object files between envs?

Based on this quote from the documentation:
https://docs.platformio.org/en/latest/projectconf/section_platformio.html#build-cache-dir

The cached object will not be used if the original source file was modified or build environment has a different configuration (new build flags, etc):

I was under the impression that it would share framework object files between envs, not just cache future builds of the same environment. e.g. having this .ini:

[platformio]
build_cache_dir = cache

[env]
board = esp32dev

[env:one]
platform = espressif32
framework = arduino

[env:two]
platform = espressif32
framework = arduino

Building two after building one will not share the framework files, even if board = … stays the same.
If env was built at least once before, removing .pio/build/* will retrieve framework & libs from the cache (‘Retrieved … from cache’ instead of ‘Compiling …’)
Adding src_build_flags = -DSOMETHING to any env will do the same.

Not yet sure if this is intended or not.

The main uses cases for environments I can think of are to support multiple boards and multiple build settings. In both cases, the commands to generate the object files will differ and the resulting object files are likely to differ as well. Therefore, the object files cannot be reused for another enviroment.

Do you have a frequent use case with multiple environemnts using the same boards and build settings?

1 Like

The idea was to have a different app build flags, like -DFEATURE_AAA -DFEATURE_BBB in one and -DFEATURE_CCC -D… etc. in the other.
Using a single environment that would mean I need to use some external means to give pio those flags, which I do right now via bash script that runs the pio run multiple times with a different env PLATFORMIO_SRC_BUILD_FLAGS=…, successfuly using caching as a means to speed things up.
Or what I was previously doing is using a single env and periodically replacing configuration header contents that the app uses.

Underlying implementation does indeed use a different paths for output .o, since every env is a separate directory under .pio/build/…

It makes perfect sense to use two different environments for the two different build flags. However, the different build flags will result in different objects files so the .o files cannot be shared.

In your case you might know that the majority of object files will be the same. But PlatformIO (or any other tool) cannot know this before compiling all the codes. So it’s correct that the .o files are not shared.

You will have to look into other means of of improving build times.

2 Likes

So while we can’t make assumptions between envs, maybe recompilation condition for a single env should be more relaxed than it is now?

It feels like it should keep the existing framework & libs and just rebuild the app when using src_build_flags = …, since we are not introducing any new global build flags that way. Even when such configuration changes introduce new libraries for LDF, only app and lib would be built

Is that across the board though, or just for certain object files? Perhaps the cache mechanism just isn’t as well tuned as it could be… after all … this is a new feature for PIOv4. For the same board,platform,framework… i.e. just two differently named environments… with the same board… nothing was cached between environments… which seemed a bit at odds with the behaviour suggested in the docs.

[platformio]
build_cache_dir = cache

[env]
platform = espressif32
framework = arduino

[env:one]
board = esp32dev

[env:two]
board = esp32dev

But sometimes it seems the cache successfully works for when it identified

Retrieved `.pio/build/one/partitions.bin' from cache
Retrieved `.pio/build/one/libFrameworkArduinoVariant.a' from cache
Retrieved `.pio/build/one/FrameworkArduino/HardwareSerial.cpp.o' from cache

But then goes and compiles virtually every other part of the build e.g.

Compiling .pio/build/one/FrameworkArduino/Esp.cpp.o
Compiling .pio/build/one/FrameworkArduino/FunctionalInterrupt.cpp.o
Compiling .pio/build/one/FrameworkArduino/IPAddress.cpp.o

Where I can see the cache working surprisingly well is when you ‘clean’ the project… it basically retrieves everything from the cache on the next build… which seems a bit… pointless… since I don’t view that to be a strictly clean build … and when you change platformio.ini parameters other than build_flags… i.e. a change to upload_port will trigger a retrieve for all objects, rather than a compile for all… so 2 second build instead of a 20 second build in that case. So for some changes to the platformio.ini file… probably anything not directly part of the compile process… it prevents a complete rebuild when the file is changed… which is nice… no wait for that total rebuild after mistyping that OTA name or changing the upload port. :slight_smile:

You can if they have the same build flags. Try to run pio run --verbose. You will see build flags. If flags match, PlatformIO will cache these objects in a cached folder.

In terms of user-configurable build flags, they stay the same. Only thing that changes is -o ... parameter, which includes an env: name, but scons uses a full cmdline as a hash for cache storage.

gh action log url
Flow is set run the env, move cache dir, run a different env and then compare both directories
Caches for env:one and env:two are completely different.
Cache for env:one ran the second time is a bit different, but mostly the same (framework.a file has a different timestamps inside)