Skip to content

Iwyu staging#823

Open
robertlipe wants to merge 6 commits intoPlummersSoftwareLLC:mainfrom
robertlipe:iwyu_staging
Open

Iwyu staging#823
robertlipe wants to merge 6 commits intoPlummersSoftwareLLC:mainfrom
robertlipe:iwyu_staging

Conversation

@robertlipe
Copy link
Collaborator

Description

I realize that seeing "+193 files" in a PR is usually a reason to go for a long walk and never come back. This note is intended to
explain why this was necessary, why it’s safe, and why some things (like GetEffectManager) had to change.

  1. The Disease: Implicit Include Chaos
    Previously, our headers were "anesthetized" by a lucky include order. Target A would build because Header B happened to include Header
    C, which defined a type needed by Header D.

In Arduino v3 (GCC 15), this luck ran out. The include order changed just enough that demo would build, but ledstrip would
spontaneously fail. Our implicit dependencies were literal "build killers."

  1. The Cure: IWYU and Implementation Migration
    To fix this, I followed "Include What You Use" (IWYU) dogma:
  • Implementations live in .cpp files. It is simply good taste to have code exist in one place. This separates the definition,
    declaration, and usage trees.
  • Headers are for declarations. If a header only needs a pointer to a struct, we now use a forward declaration (class Foo;) instead of
    dragging in the whole world.
  • globals.h Precedence. We now strictly insist that globals.h is the first local include. This is enforced via new audit tools in
    /tools.
  1. The "Why" behind the Renames

EffectManager() → GetEffectManager()
This wasn't a stylistic choice; it was a compiler requirement for decoupling.

  1. Name Hiding: In C++, a member function with the same name as a type hides that type. If SystemContainer had a method named
    EffectManager(), we couldn't easily forward-declare the class without the compiler getting confused between the function and the
    type.
  2. Disambiguation: Standardizing on GetEffectManager() allows us to use lean headers with forward declarations, significantly reducing
    the "recompile the world" effect when effect logic changes.

network.h → nd_network.h
Arduino v3 introduced a system <Network.h>. Our local network.h was causing "poisonous" collisions. I surrendered and renamed ours to
nd_network.h to break the circle.

  1. Notable Optimizations
  • byte_utils.h: Replaced ByteswapU64 and friends with more traditional versions. The previous versions were reading source memory
    far too many times; the new versions decay to std::memcpy on our LE architecture, which is significantly faster and handles
    unaligned access better.
  • Palette Offloading: Moved large palettes to colordata.cpp to ensure they reside in rodata (Flash) rather than consuming precious RAM
    at runtime.
  1. Completeness and "Sawdust"
  • 53/53 Builds: Every single target in the project builds and runs.
  • Arduino v3 Proof: Added demo_v3, m5plusdemo_v3, and spectrum2_v3 targets. While not yet fully "supported" (partition
    tables/filesystems will change), they prove the core logic is now v3-ready.
  • Fidelity: I used a mix of automation (Perl/Sed/Gemini-CLI) and manual care. I tried to retain every meaningful comment and bit of
    technical "lore" (like Stefan Petrick’s notes). If a comment fell between the floorboards, it was "sawdust" from the heavy
    lifting—not intentional removal.
  1. How to Review
    The vast majority of this PR is Code Motion. If you see a function disappear from a .h and appear in a .cpp, it is the same logic
    you’ve already approved—just living in its proper home.

Van dik hout zaagt men planken. We had to saw some thick planks to get here, but the resulting frame is much stronger.

  • robertl

Ultimately to make it run on compilers of the last ten years and on chips from the last six.

Contributing requirements

  • I read the contribution guidelines in CONTRIBUTING.md.
  • I understand the BlinkenPerBit metric, and maximized it in this PR.
  • I selected main as the target branch.
  • All code herein is subjected to the license terms in COPYING.txt.

rbergen and others added 4 commits February 26, 2026 04:15
…re documentation

Core technical changes:
- Migrated 30+ core class implementations from headers to .cpp files to improve build times and follow IWYU best practices.
- Pruned redundant implementations and redefinitions across the codebase (EffectManager, TaskManager, LEDBuffer, etc.).
- Restored extensive technical documentation, historical 'lore', and debugX instrumentation lost during initial migration.
- Kept performance-critical XY() mapping logic inline in headers (GFXBase, HUB75GFX, HexagonGFX) to minimize register pressure on ESP32.
- Resolved build failures and link errors in Mesmerizer and other environments.
- Corrected various dormant bugs:
  - Fixed dangling palette references in particle and spectrum effects by changing members from reference to value storage.
  - Fixed floating-point truncation bug in SimpleColorBeat::Draw.
  - Corrected visibility and redefinition of EffectTaskParams in NightDriverTaskManager.
- Ensured IJSONSerializable resides exclusively in interfaces.h to decouple core logic from heavy JSON headers.
- Cleaned up branch by removing all scratch files, build logs, and unintended artifacts from the PR.
@robertlipe robertlipe requested a review from rbergen March 8, 2026 10:45
@robertlipe
Copy link
Collaborator Author

Heads-up Rutger/Dave: Once this IWYU refactor is landed, I have a second submarine arriving immediately behind it that replaces the RemoteDebug library with a native socket-based implementation (TelnetServer and Console classes).

I’ve kept that work separate to avoid complicating this IWYU review, but be aware that many of the files I just moved logic into (like network.cpp and main.cpp) will see logic changes in the very next PR to rip out the abandoned debugger. If you'd prefer to see those together (you really don't...), let me know, but my plan is to land the structural change first. That will make the second one look much more mechanical - plus, it'll make the inevetible collisions my problem and not yours, though it may be handy to zoom out and see future direction.

Let's focus on this one now. (If you want to toss/edit any of this doc, feel free.) I'll get the abandonded RemoteDebug work found and uploaded next. It's comparatively small...but also in the "it'll only hurt for a little while" category.

@robertlipe robertlipe marked this pull request as ready for review March 8, 2026 11:13
@robertlipe
Copy link
Collaborator Author

In case you care what Gemini says:

robertlipe#40 (comment)

Copy link
Collaborator

@rbergen rbergen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done! Sonnet agrees with Gemini, and my manual review (yes, I did one) only yielded a few things that I would like you to look at before we proceed.

I am duty-bound to ask if you actually ran this branch on a number of devices we're targeting, including Mesmerizer...?

And yes, thank you for isolating your next PR from this one.

Ultimately to make it run on compilers of the last ten years and on chips from the last six.

Haha, couldn't help yourself! Congrats on holding it in until the very end. ;)

@@ -1,3 +1,6 @@
#pragma once

#include "random_utils.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we put this under the file header.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit surprised by this file showing up in the diff. Why would you downgrade specific packages in the package-lock.json for the on-board web app, while package.json apparently is unchanged?

Comment on lines +45 to +67
// SystemContainer
//
// Holds a number of system-wide objects that take care of core/supportive functions on the chip.
// The objects are added to this class in an "enriched property" style. This means that for each object, the class
// contains:
// - A declaration of the member variable (using SC_DECLARE)
// - A Setup method that creates and returns the object in question (mostly through SC_SIMPLE_SETUP_FOR or
// SC_FORWARDING_SETUP_FOR)
// - A Has method that returns true if the object has been Setup, and a property getter that returns a reference to
// the actual object (both using SC_GETTERS_FOR)
//
// The difference between SC_SIMPLE_SETUP_FOR and SC_FORWARDING_SETUP_FOR is that the former invokes a parameterless
// constructor when creating the object, and the latter forwards any arguments passed to it on to the constructor.
//
// SC_SIMPLE_PROPERTY and SC_FORWARDING_PROPERTY are provided for convenience; they combine a declaration, simple or
// forwarding Setup method, and the Has and getter methods.
//
// Most macros accept two parameters:
// - The name of the property, as used in the Setup, Has and getter methods
// - The type of the property, as held/returned by this class
//
// The actual composition of this class is largely driven by the macros mentioned, only irregular Setup methods are
// coded manually.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you've done here is unroll the macros across systemcontainer.h and systemcontainer.cpp. As much as I hate repetitive code I can see how this is defendable; for one the macro solution was extremely ugly in itself.

However, please update the documentation as well, then. (I think a select of 23 lines & Delete will do, here).

Comment on lines +447 to +454
[env:demo_v2]
extends = env:demo
platform = platformio/espressif32 @ ^6.12.0

[env:demo_v3]
extends = env:demo
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.30-2/platform-espressif32.zip
board_build.partitions = config/partitions_custom_noota_v3.csv
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave a comment in platformio.ini or the PR that explains the purpose of the new _v2 and _v3 envs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants