Skip to content

Wrap the library in the ABI-versioning inline namespace - #360

Merged
Bronek merged 8 commits into
mainfrom
bronek/add_version_macro
Jul 20, 2026
Merged

Wrap the library in the ABI-versioning inline namespace#360
Bronek merged 8 commits into
mainfrom
bronek/add_version_macro

Conversation

@Bronek

@Bronek Bronek commented Jul 20, 2026

Copy link
Copy Markdown
Member

Resolves #352.

Everything in fn and pfn now lives in inline namespace LIBFN_VERSION — spelled v0_0_9 today, staged to v0_1 at the 0.1.0 tag — so different library lines fail loud at link time instead of silently ODR-colliding. Three commits:

  1. Stop the FWD and DEDUCED_RETURN macros leaking from fn headers. The standalone macro headers are folded into a guard-less bracketing pair fn/detail/macro_begin.hpp/macro_end.hpp (push_macro/define on entry, undef/pop_macro on exit — nesting-safe, and a user's own prior definition survives). Every per-header sentinel TU now #errors if FWD, DEDUCED_RETURN or ASSERT survives an include: the only macros a libfn header leaves behind are its include guard and LIBFN_VERSION. Tests that relied on the leak include the pair explicitly; the examples define their own one-line FWD, the idiom a user would write.

  2. Add include/libfn_version.hpp, synced from VERSION. A new root header — below both fn and pfn, the only header either may reach outside its own tree — defining LIBFN_VERSION per branch (v0_0_9, or v0_0_9_cxx26 under the user-defined LIBFN_CXX26, reserved for the C++26 std::type_order mode). Never hand-edited: scripts/sync_versions.py derives both spellings from VERSION (now 0.0.9) exactly as it mirrors the packaging literals — v0_<y> once a 0.y line is tagged, v0_0_<z> on the 0.0 line, a SemVer prerelease appended (-dev_dev), _cxx26 last. Packaging: exported CMake target libfn::version (FILE_SET, same EXPORT; carried by both libraries), Bazel :version; conan and nix pick the header up through their existing recursive copies.

  3. Wrap fn and pfn in the inline namespace. All 35 namespace openings (the six fn/detail nested forms as namespace fn::inline LIBFN_VERSION::detail), each wrapped header self-containedly including <libfn_version.hpp>. A new pre-commit hook (scripts/check_namespace_wrap.py) refuses any unwrapped opening — a missed wrap compiles green while its entities silently escape the versioned ABI namespace, so the invariant is enforced textually. tests/fn/libfn_version.cpp pins fn::LIBFN_VERSION::… ≡ fn::… version-agnostically via the macro.

Empirical findings worth reviewing:

  • Sortkey: GCC and MSVC spell the inline namespace in the pretty-printed type key; clang omits it. The version is deliberately kept in the key where the compiler spells it — truthful to the mangled reality and to what std::type_order will reflect — and the uniform insertion cannot flip any relative ordering, so copack canonical order is unchanged. Pinned per-compiler in tests/fn/detail/meta.cpp, version-agnostic via a stringized macro.
  • Docs: doxygen dual-indexes inline-namespace members under both spellings (probed locally on 1.16.1), so the fn::… references in docs/ keep resolving; cmake/Docs.cmake additionally expands LIBFN_VERSION to the real spelling, parsed from the header. The docs CI job is the authority for the container's doxygen.

On the issue's open points: pfn receives the same treatment (one shared version header, one ABI story); docs are handled as above; the abigo baseline needs nothing here — the wrapped tree at the 0.1.0 tag becomes the baseline the 0.1 line's z-bumps classify against. The LIBFN_CXX26 wiring (CMake VALIDATE_CXX26, gcc-16 workflow lane, meta.hpp std::type_order) is deliberately deferred; its spelling is already reserved.

🤖 Generated with Claude Code

https://claude.ai/code/session_0198ikYYxtCqwNG54SS1b249

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@augmentcode

augmentcode Bot commented Jul 20, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR introduces ABI versioning for libfn by wrapping all public APIs in fn and pfn inside inline namespace LIBFN_VERSION, so different library lines collide loudly at link time instead of via silent ODR mismatches.

Changes:

  • Added include/libfn_version.hpp defining the LIBFN_VERSION macro (plus a LIBFN_CXX26 variant) and wired it into CMake and Bazel exports.
  • Updated scripts/sync_versions.py to derive/update the namespace spelling from VERSION and keep packaging literals in sync.
  • Wrapped all fn/pfn namespace openings with the versioned inline namespace; added a pre-commit hook (scripts/check_namespace_wrap.py) to enforce the invariant.
  • Reworked internal macro handling: replaced standalone macro headers with fn/detail/macro_begin.hpp/macro_end.hpp bracketing to prevent FWD/DEDUCED_RETURN/ASSERT leakage.
  • Adjusted documentation generation to stage a namespace-stripped copy of include/ for doxygen via cmake/StripNamespaceWrap.cmake and a new docs_stage_include target.
  • Added/updated tests to validate the inline-namespace aliasing behavior and keep compiler-specific sortkey pins version-agnostic.

Technical Notes: Consumers should continue using fn::X/pfn::X; the inline namespace keeps source names stable while embedding the ABI version into symbol names.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread cmake/Docs.cmake Outdated
Comment thread scripts/check_namespace_wrap.py
@Bronek

Bronek commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

augment review

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread cmake/StripNamespaceWrap.cmake
Comment thread cmake/Docs.cmake Outdated
@Bronek

Bronek commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

augment review

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread cmake/StripNamespaceWrap.cmake
Comment thread cmake/StripNamespaceWrap.cmake
@Bronek

Bronek commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

augment review

@sonarqubecloud

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

@Bronek
Bronek merged commit c8fd50c into main Jul 20, 2026
64 checks passed
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.

Wrap the public API in inline namespace v0_1

1 participant