Skip to content

Publish flattened headers for Compiler Explorer - #98

Merged
jll63 merged 4 commits into
boostorg:developfrom
jll63:feature/develop-ce
Sep 4, 2026
Merged

Publish flattened headers for Compiler Explorer#98
jll63 merged 4 commits into
boostorg:developfrom
jll63:feature/develop-ce

Conversation

@jll63

@jll63 jll63 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

(Written by Claude Code, on behalf of @jll63.)

Brings back the flattened headers that were published for the review, and has
CI deploy them again. The scripts that produced them went away with the old
main.yml in 83c8ab9 ("CI: adopt boost-cli GHA"); what was left in dev/ had
gone stale - flatten.sh still named compiler.hpp, shared_ptr.hpp and
unique_ptr.hpp.

What is generated

Compiler Explorer can include a header from a URL, but only one file at a time:
it does not resolve the includes inside the file it fetches, and it does the
fetching client-side, so the host must send CORS headers - GitHub Pages does.

dev/flatten.py therefore rewrites every public header into a self-sufficient
file, so that a CE example's include list is the same as a local example's, one
line per header, in the same order:

#include <https://jll63.github.io/openmethod/boost/openmethod.hpp>
#include <https://jll63.github.io/openmethod/boost/openmethod/initialize.hpp>

boost/openmethod.hpp is the root and carries its whole closure. Every other
header carries only what the root does not provide - its detail/ headers, and
interop/virtual_any.hpp, which nothing includes directly - and turns the rest
into a check on the include guard:

#ifndef BOOST_OPENMETHOD_CORE_HPP
#error "<boost/openmethod/initialize.hpp>: #include <.../boost/openmethod.hpp> first"
#endif

so using one without the root fails on a single #error instead of a wall of
undeclared identifiers. Guard names are read from the header being flattened,
never hardcoded - several are legacy and do not match their path.

Deployment

The antora job regenerates the headers into the Pages artifact, at the root of
the site, next to the documentation. They are live now, from this branch:
https://jll63.github.io/openmethod/boost/openmethod.hpp. Switching the source
to develop later is just a merge - the deploy step is not branch-specific.

Checks

A flat-headers job runs dev/check-flat.sh on every push and PR: each
generated header must compile after the root, each must fail on its own with
our own diagnostic, and the ce/*.cpp examples must build and run against the
generated tree. 50 checks.

ce/ is now part of the CMake build as well. It was referenced from nowhere,
its CMakeLists.txt carried mangled identifiers from a bad sed, and two sources
had been missing using boost::openmethod::virtual_; long enough to stop
compiling.

Reflection example

ce/reflection.cpp registers Animal, Dog, Cat and Bulldog by C++26 reflection -
one BOOST_OPENMETHOD_REGISTER_CLASSES() instead of BOOST_OPENMETHOD_CLASSES.
Bulldog is the point: no overrider mentions it and no class list names it, yet
the scan finds it deriving from Dog, registers it, and poke dispatches it to
Dog's overrider.

It has no C++17 fallback, so CMake builds it only when
BOOST_OPENMETHOD_ENABLE_REFLECTION is on, and dev/check-flat.sh probes for a
P2996 compiler (CXX_REFLECTION, $CXX, then g++-16) and reports it skipped
when there is none. The flat-headers job installs GCC 16 so CI compiles it -
confirmed in the job log:

note   C++26 reflection: g++-16 -std=c++26 -freflection
ok     ce/reflection.cpp

Live on Compiler Explorer: https://godbolt.org/z/1eTx5f13z (x86-64 gcc 16.2,
-std=c++26 -freflection -O3 -DNDEBUG, Boost 1.90). Checked through godbolt's
own compile API, with the fetched flat headers pasted in place of the URL
includes the way CE's client does: exit 0, and the program prints
Snoopy barks. / Felix hisses. / Hector barks.

🤖 Generated with Claude Code

https://claude.ai/code/session_011HmyQexbZAWZk6BDkHSbdQ

jll63 and others added 3 commits September 4, 2026 12:03
Compiler Explorer can include a header from a URL, but only one file at a
time: it does not resolve the includes inside the file it fetches. The
scripts that produced single-file headers for the review went away with the
old main.yml in 83c8ab9 ("CI: adopt boost-cli GHA"), and what was left in
dev/ had gone stale - flatten.sh still named compiler.hpp, shared_ptr.hpp and
unique_ptr.hpp.

dev/flatten.py now rewrites *every* public header into a self-sufficient
file, so a CE example's include list matches a local one line for line:

    #include <https://jll63.github.io/openmethod/boost/openmethod.hpp>
    #include <https://jll63.github.io/openmethod/boost/openmethod/initialize.hpp>

boost/openmethod.hpp is the root and carries its whole closure. Every other
header carries only what the root does not provide - its detail/ headers, and
interop/virtual_any.hpp - and turns the rest into a check on the include
guard, so that using one without the root fails on a single #error instead of
a wall of undeclared identifiers. Guard names are read from the header being
flattened: several are legacy and do not match their path.

The antora job regenerates them into the Pages artifact, at the root of the
site, next to the documentation. CE fetches URL includes client-side, so the
host must send CORS headers; GitHub Pages does.

dev/check-flat.sh, run by the new flat-headers job, compiles each generated
header after the root, checks that each one fails on its own, and builds and
runs the ce/ examples against the generated tree. Those examples are now part
of the CMake build too - ce/CMakeLists.txt was referenced from nowhere and
carried mangled identifiers from a bad sed, and two of the sources had been
missing `using boost::openmethod::virtual_;` long enough to stop compiling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011HmyQexbZAWZk6BDkHSbdQ
Registers Animal, Dog, Cat and Bulldog by C++26 reflection - one
BOOST_OPENMETHOD_REGISTER_CLASSES() instead of BOOST_OPENMETHOD_CLASSES.
Bulldog is what the example is about: no overrider mentions it and no class
list names it, yet the scan finds it deriving from Dog, registers it, and
poke dispatches it to Dog's overrider.

It needs a compiler that implements P2996 - x86-64 gcc (trunk) on Compiler
Explorer, with -std=c++26 -freflection - and has no C++17 fallback, so
ce/CMakeLists.txt builds it only when BOOST_OPENMETHOD_ENABLE_REFLECTION is
on, and dev/check-flat.sh probes for such a compiler (CXX_REFLECTION, $CXX,
then g++-16) and reports the example as skipped when there is none. The
flat-headers job installs GCC 16 so that CI compiles it rather than skips it.

Checked against the deployed headers the way CE consumes them: fetch
boost/openmethod.hpp and boost/openmethod/initialize.hpp from the Pages site,
paste each in place of its #include line, compile the result with
g++-16 -std=c++26 -freflection -O3 -DNDEBUG.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011HmyQexbZAWZk6BDkHSbdQ
x86-64 gcc 16.2, -std=c++26 -freflection -O3 -DNDEBUG, Boost 1.90, and the
two headers fetched from the Pages site. Checked through godbolt's own API:
the compiler accepts the flags, and the example - with the flat headers
pasted in place of the URL includes, as CE's client does - runs there and
prints the expected three lines.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011HmyQexbZAWZk6BDkHSbdQ
@cppalliance-bot

cppalliance-bot commented Sep 4, 2026

Copy link
Copy Markdown

An automated preview of the documentation is available at https://98.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-09-04 21:58:15 UTC

The deploy step was gated on the fork, so merging this upstream would build
the headers and then skip publishing them: boostorg.github.io/openmethod
would keep 404ing on boost/openmethod.hpp. Upstream now deploys from develop
- and only develop, since any other branch would clobber the site - while the
fork keeps deploying from any branch, which is where a branch is tried out
before it is merged. Upstream's Antora site starts being refreshed by this
workflow again as a result; it has not been since 2026-07-15.

The base URL is derived from github.repository_owner rather than hardcoded:
it is baked into the banner and the guard-check message of every generated
header, so it has to name the site the artifact is about to be deployed to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011HmyQexbZAWZk6BDkHSbdQ
@jll63
jll63 merged commit 5ec487c into boostorg:develop Sep 4, 2026
6 of 7 checks passed
@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.46%. Comparing base (92e720c) to head (5ec487c).
⚠️ Report is 19 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop      #98      +/-   ##
===========================================
+ Coverage    93.02%   93.46%   +0.44%     
===========================================
  Files           22       22              
  Lines         1634     1653      +19     
  Branches       504      500       -4     
===========================================
+ Hits          1520     1545      +25     
+ Misses          66       64       -2     
+ Partials        48       44       -4     

see 5 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 767d6a5...5ec487c. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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