Skip to content

Strip duplicate typedefs from vendored common.h (ship 36.0.0.1.1)#62

Draft
lloeki wants to merge 2 commits into
mainfrom
lloeki/header-dedup-postprocess
Draft

Strip duplicate typedefs from vendored common.h (ship 36.0.0.1.1)#62
lloeki wants to merge 2 commits into
mainfrom
lloeki/header-dedup-postprocess

Conversation

@lloeki

@lloeki lloeki commented Jun 22, 2026

Copy link
Copy Markdown
Member

Why

libdatadog v36's generated common.h (as shipped in 36.0.0.1.0) declares several profiling typedefs twice:

  • Forward-decl + full-struct collisions: ddog_prof_EncodedProfile, ddog_prof_StringId, OpaqueStringId (a typedef struct X X; forward decl coexisting with the full typedef struct X { ... } X;).
  • Opaque pointer typedefs emitted verbatim twice: ddog_prof_StringId2, ddog_prof_MappingId2, ddog_prof_FunctionId2.

These are legal under C11, but consumers compiling with -Werror -Wtypedef-redefinition (e.g. dd-trace-rb CI with DATADOG_GEM_CI=true) treat them as fatal -Wtypedef-redefinition errors. libdatadog's own dedup_headers tool only strips child-vs-base header duplicates, not these intra-common.h ones.

This lets us ship a clean 36.0.0.1.1 gem without waiting for a new libdatadog release.

What

  • Add Helpers.dedup_common_headers (in Rakefile): a build-time post-processing step that removes the duplicate typedefs from every vendored common.h after the headers are placed.
    • Removes multiline typedef struct X X; forward decls when the full } X; body is present (either order).
    • Removes exact-duplicate single-line typedef ...; lines, keeping the first occurrence.
    • Idempotent and safe: only genuine duplicates are removed; unique typedefs are never touched. Logs how many were stripped.
  • Hook it into both header-vendoring paths:
    • rake extract (download/extract release flow) — the release-gem path.
    • rake libdatadog:build (from-source flow).
  • Bump GEM_MINOR_VERSION 0 -> 1 (LIB_VERSION stays 36.0.0), yielding gem 36.0.0.1.1.

Validation

Against the real published header (libdatadog 36.0.0.1.0, x86_64-linux and x86_64-linux-musl):

cc/clang -std=gnu99 -Werror -Wtypedef-redefinition -fsyntax-only on a TU that #includes datadog/common.h:

  • Before: 6 errors (redefinition of typedef ... is a C11 feature).
  • After: compiles cleanly (both platforms).

Each of ddog_prof_EncodedProfile, ddog_prof_StringId, OpaqueStringId, ddog_prof_StringId2, ddog_prof_MappingId2, ddog_prof_FunctionId2 now appears exactly once as a typedef. Re-running the step removes nothing (idempotent). rake spec passes (19 examples, 0 failures).

Note

One of three coordinated changes for the libdatadog v36 duplicate-typedef header issue (increasing order of permanence):

  • dd-trace-rb#5928 — immediate CI mitigation: bump dd-trace-rb to v36 plus a temporary -Wno-error=typedef-redefinition stopgap.
  • This PR (libdatadog-rb#62) — gem-level fix: strip the duplicate typedefs during vendoring and ship 36.0.0.1.1, without waiting for a libdatadog release.
  • libdatadog#2149 — upstream fix in dedup_headers: makes common.h clean by construction and obsoletes this post-processing once released.

Draft pending review of this post-processing approach vs. the upstream libdatadog header fix (libdatadog#2149).

lloeki added 2 commits June 22, 2026 17:31
libdatadog v36's generated common.h declares several profiling typedefs
twice: forward "typedef struct X X;" declarations that coexist with the
full "typedef struct X { ... } X;" body (ddog_prof_EncodedProfile,
ddog_prof_StringId, OpaqueStringId) and opaque pointer typedefs emitted
verbatim twice (ddog_prof_StringId2, ddog_prof_MappingId2,
ddog_prof_FunctionId2).

These are legal under C11 but consumers compiling with
-Werror -Wtypedef-redefinition (e.g. dd-trace-rb CI with
DATADOG_GEM_CI=true) treat them as fatal errors. libdatadog's own
dedup_headers tool only removes child-vs-base header duplicates, not
these intra-common.h ones.

Add BuildFromSource::Headers.dedup_common_headers, a build-time
post-processing step that removes the duplicate typedefs from every
vendored common.h after the headers are placed. It runs in the
from-source build flow (rake libdatadog:build) right after the headers
are copied and their permissions fixed. The step is idempotent and only
removes genuine duplicates, logging how many were stripped.
Ship the common.h duplicate-typedef fix without waiting for a new
libdatadog release. The packaged library stays at LIB_VERSION 36.0.0;
only GEM_MINOR_VERSION is bumped from 0 to 1, yielding gem version
36.0.0.1.1 per the lib_version.gem_major.gem_minor scheme.
@lloeki lloeki force-pushed the lloeki/header-dedup-postprocess branch from c5336d1 to 7c5e97c Compare June 22, 2026 15:33
@lloeki lloeki changed the title feat: strip duplicate typedefs from vendored common.h (ship 36.0.0.1.1) Strip duplicate typedefs from vendored common.h (ship 36.0.0.1.1) Jun 22, 2026
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