Skip to content

refactor(ec): generate ECCodes.h / ECTagTypes.h only, drop the committed copies - #716

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:refactor/ec-headers-generated-only
Jul 30, 2026
Merged

refactor(ec): generate ECCodes.h / ECTagTypes.h only, drop the committed copies#716
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:refactor/ec-headers-generated-only

Conversation

@got3nks

@got3nks got3nks commented Jul 30, 2026

Copy link
Copy Markdown

Summary

The EC headers existed twice: generated from their .abstract sources into the build tree, and committed under src/libs/ec/cpp/ where they were hand-maintained. Adding a tag meant editing the abstract and hand-adding the matching enum entry and name-string case to the committed header, with nothing enforcing that the two agreed.

They already disagreed in one respect: #include <cstdint> was added to the committed header by 5a6f5e86d and the generator never learned about it.

The reason this matters beyond the chore: both copies reached the same binary. Measured with ninja's dependency data on master, 24 TUs compiled against the committed ECCodes.h and 3 (Api.cpp, PrefsSchema.cpp, Refresher.cpp) against the generated one, with amuleapi linking objects of both kinds — Api.cpp.o pulls in both. Divergence there would not have been a compile error. It would have linked cleanly and put two different values for the same tag on the EC wire.

This makes the generated header the only one, so the abstract is the single source of truth: edit it and the enum entry, the DEBUG_EC_IMPLEMENTATION name string and the documentation all follow.

The generator had to learn three things first

So that the output is not a regression on the header it replaces:

  • #include <cstdint> when the abstract has a TypeDef section (those emit typedef uint8_t ec_opcode_t). ECTagTypes has none and uses aMule's own uint8, so it deliberately does not get the include.
  • ## is a documentation comment, emitted into the header above the entry that follows it. Plain # keeps its existing meaning of an abstract-only note (section headings, commented-out *_UNUSED placeholders). The 28 comment lines the committed header carried move into the abstract and come out byte-identical.
  • A literal ; no longer corrupts the output. The file is turned into a CMake list by swapping newlines for ;, so a semicolon in prose split one line into several and the fragments were then parsed as entries. The same unquoted-variable bug was silently eating semicolons in the licence block — "free software; you can" was being emitted as "free software you can".

src/libs/ec/java/ goes too: nothing built, shipped or referenced those files, and they were only ever updated by hand alongside the headers. The now-dead ECCodes.h / ECTagTypes.h entries in whitespace_fixer's exclusion list are removed with them.

For contributors

@LSalami @ngosang @danim7 @mrjimenez — heads-up, since this changes the workflow for anyone adding an EC tag.

Adding an EC tag is now one edit. In ECCodes.abstract:

## Optional. Explains what the tag carries and who reads it.
EC_TAG_SOMETHING                          0x1234

The ## lines become // comments above the entry in the generated header. Nothing else to touch.

Test plan

Equivalence against the header being deleted — enum NAME = 0xVALUE pairs identical (521 in ECCodes.h, 11 in ECTagTypes.h), typedefs identical, and every one of the 28 documentation comment lines preserved verbatim. The only remaining differences are cosmetic: brace placement and the switch-case layout inside the debug block, neither of which any consumer sees now that the file lives solely in the build tree.

Single source confirmed — from ninja's dependency data after a full build, all 86 TUs that include ECCodes.h and all 84 that include ECTagTypes.h resolve to the generated copy. None to a source-tree one.

Round trip — adding a tag plus a ## comment to the abstract and nothing else regenerates the header with the enum entry, the documentation comment and the DEBUG_EC_IMPLEMENTATION name-string case, and a TU compiles against it with the correct value.

Cold parallel builds from an empty tree, so the generate-before-compile ordering holds without a race:

Platform Build ctest
macOS 15 ARM64 0 errors 29/29
Ubuntu 26.04 ARM64 0 errors 29/29
Windows 11 ARM64 (CLANGARM64) 0 errors 29/29

macOS covered the full target set (MONOLITHIC + DAEMON + REMOTEGUI + AMULECMD + WEBSERVER + TESTING + AMULEAPI).

Lint gatesgit clang-format origin/master reports nothing to format, and diff-scoped clang-tidy is clean against both .clang-tidy-new-code and .clang-tidy. Both analysed 0 TUs, which is honest rather than a false pass: this diff changes CMake and the abstract only, with no C++ source touched.

Note

src/libs/ec/cpp/gen_ECVersion reads the committed ECCodes.h, so this leaves that reference stale. It was already dead before this change — nothing invokes it, and the mkFileSum it pipes into does not exist in the tree — so removing it felt like a separate decision rather than something to fold in here.

…ted copies

The EC headers existed twice: generated from their .abstract sources into
the build tree, and committed under src/libs/ec/cpp/ where they were
hand-maintained. Adding a tag meant editing the abstract AND hand-adding
the matching enum entry and name-string case to the committed header, with
nothing enforcing that the two agreed.

They did not agree in one respect already: `#include <cstdint>` was added
to the committed header by 5a6f5e8, and the generator never learned
about it.

Worse, both copies reached the same binary. Measured with ninja's
dependency data on master, 24 TUs compiled against the committed ECCodes.h
and 3 (Api.cpp, PrefsSchema.cpp, Refresher.cpp) against the generated one,
with amuleapi linking objects of both kinds. Divergence there would not
have been a compile error -- it would have linked cleanly and put two
different values for the same tag on the EC wire.

Make the generated header the only one. The abstract becomes the single
source of truth: edit it and the enum entry, the DEBUG_EC_IMPLEMENTATION
name string and the documentation all follow.

The generator had to learn three things first, so the output is not a
regression on the header it replaces:

  * emit `#include <cstdint>` when the abstract has a TypeDef section
    (those emit `typedef uint8_t ec_opcode_t`). ECTagTypes has none and
    uses aMule's own uint8, so it does not get the include.
  * `##` is a documentation comment, emitted into the header above the
    entry that follows it. Plain `#` keeps its meaning of an
    abstract-only note. The 28 comment lines the committed header carried
    move into the abstract, and come out byte-identical.
  * a literal `;` no longer corrupts the output. The file is turned into
    a CMake list by swapping newlines for `;`, so a semicolon in prose
    split one line into several and the fragments were parsed as entries.
    The same unquoted-variable bug was silently eating semicolons in the
    licence block ("free software; you can" -> "free software you can").

Verified against the header being deleted: enum name=value pairs and
typedefs are identical, and every documentation comment is preserved
verbatim. The only remaining differences are cosmetic -- brace placement
and the switch-case layout in the debug block, neither of which any
consumer sees now that the file lives solely in the build tree.

All 86 TUs that include ECCodes.h and all 84 that include ECTagTypes.h now
resolve to the generated copy; none to a source-tree one. A cold parallel
build from an empty tree succeeds, so the ordering holds without a race.

The ec/java/ counterparts are deleted too: nothing built, shipped or
referenced them, and they were only ever updated by hand alongside the
headers.
@got3nks
got3nks merged commit e86646c into amule-org:master Jul 30, 2026
15 checks passed
@got3nks
got3nks deleted the refactor/ec-headers-generated-only branch July 30, 2026 18:48
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.

1 participant