V5 branch - local build fails due to circular dependancy on wled_metadata.cpp.o
When trying to compile the "V5" branch locally, the build fails with "Don't know how to build from a source file with suffix `.o'." The same V5 build on github works.
I have asked an AI to help me analyze the problem, below is the solution that works in my environment:
Problem:
Build fails with error Don't know how to build from a source file with suffix '.o'
|-- SPI @ 3.3.4
|-- WiFi @ 3.3.4
|-- NeoESP32RmtHI
|-- ESP32 Async UDP @ 3.3.4
|-- WebServer @ 3.3.4
*** Applied include path shortening for 232 framework paths ***
*** Path length reduced from 33262 to ~11333 characters ***
*** Estimated savings: 21576 characters ***
*** While building `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']' from `['C:\\ARDUINO_Work\\WLED_upstream_new_0.16\\.pio\\build\\esp32dev\\src\\wled_metadata.cpp.o']': Don't know how to build from a source file with suffix `.o'. Expected a suffix in this list: ['.c', '.m', '.C', '.cpp', '.cc', '.cxx', '.c++', '.C++', '.mm', '.s', '.asm', '.ASM', '.spp', '.SPP', '.sx', '.S'].
File "C:\Users\frank\.platformio\platforms\espressif32\builder\frameworks\arduino.py", line 786, in apply_include_shortening
========================================================================================= [FAILED] Took 7.55 seconds =========================================================================================
Suspected Root Cause:
The AddBuildMiddleware function in set_metadata.py was returning the result of env.Object(), which creates a build target (.o file). This causes SCons to treat the .o file as a source file, creating a circular dependency where it tries to build wled_metadata.cpp.o FROM wled_metadata.cpp.o.
https://github.com/wled/WLED/blob/8ea41cf2d2606477af573134fbc19c85000f67b9/pio-scripts/set_metadata.py#L108-L112
Impact: Prevents successful compilation on ESP32 platforms using the Tasmota platform-espressif32 with include path shortening enabled.
suggested fix
The middleware should return the original node and modify the environment's CPPDEFINES in-place, rather than creating a new Object target.
def add_wled_metadata_flags(env, node):
cdefs = env["CPPDEFINES"].copy()
if not has_def(cdefs, "WLED_REPO"):
repo = get_github_repo()
if repo:
cdefs.append(("WLED_REPO", f"\\\"{repo}\\\""))
cdefs.append(("WLED_VERSION", WLED_VERSION))
# BEFORE (incorrect - causes circular dependency):
# return env.Object(node, CPPDEFINES=cdefs)
# AFTER (correct - modifies environment in-place):
env["CPPDEFINES"] = cdefs
return node
The fix modifies the environment's CPPDEFINES directly and returns the original node, allowing SCons to properly handle the build dependency chain without creating duplicate targets.
Your AI has missed the entire purpose of that module, which was to ensure that the define was passed solely to the one source file, so it would not break build caching on the rest of the tree. Modifying "env" affects all files. If that was what I'd wanted to do, none of that logic is necessary at all - a simple pre-script would have sufficed.
Can you fix it? I have no idea how pio scripts work (and not good at python coding) - needed to un-block my local compile, that's why I asked the AI 😅
This circular dependency is real, do you know how that could happen?
I'll take a look tonight. Offhand, my best guess is that it's caused by pioarduino's "path shortening" feature -- I suspect they ran in to the same challenge I did, namely that you can modify a per-file build environment in SCons exactly once, when it is promoted to a Builder object. Likely they aren't handling the case that that transformation was done earlier.
Seems like pioarduino has a bunch of breakage with respect to the baseline platformio - first it was the short git hash handling, now this. The middleware approach I used is literally the example in the platformio documentation.
fixed with https://github.com/pioarduino/platform-espressif32/pull/358 in branch develop