Skip to content

Make the published libcvc bundle actually consumable (xmlrpc, version, CGAL 6, windows-debug) - #324

Merged
transfix merged 4 commits into
masterfrom
fix/sdf-error-macro-leak
Sep 4, 2026
Merged

transfix merged 4 commits into
masterfrom
fix/sdf-error-macro-leak

Conversation

@transfix

@transfix transfix commented Sep 3, 2026

Copy link
Copy Markdown
Owner

src/cvc/geometry/SDF/SignDistanceFunction_v2/reg3data.h:12 defined, at file scope in a header:

#define error(x) {fprintf(stderr, "%s\n", x); exit(1);}

A function-like macro with that name rewrites any later declaration using the identifier — and error() matches a one-parameter macro with an empty argument — so any header parsed afterwards that declares a member or function called error becomes a syntax error.

This is already costing us

Three call sites carry workarounds for it today:

File Workaround
utility/algorithm.cpp // CGAL headers must come before SDF headers due to macro conflicts
SDF/.../DistanceTransform.cpp // Include app.h BEFORE DistanceTransform.h ... reg3data.h defines error() as a macro which conflicts with cvc::app
tests/mtxlib_test.cpp seventeen lines explaining #undef barriers positioned to stop clang-format's IncludeBlocks:Regroup from reordering the includes back into a broken state, ending "Do not merge these blocks"

And CGAL 6 broke it

Include ordering is not a fix. In CGAL 6, CGAL/AABB_traits.h is deprecated and forwards to AABB_traits_3.h, which pulls in Filtered_kernel/internal/Static_filters/Static_filter_error.h and its double error() const. algorithm.cpp includes AABB_traits.h at line 63, after reg3data.h at line 40 — outside what the ordering workaround covers.

Homebrew and vcpkg both ship CGAL 6.2 now, so every macOS and Windows build of libcvc fails there. It surfaced as six red jobs on transfix/F2Dock#35, which builds libcvc from source:

CGAL/.../Static_filter_error.h:110:10: error: expected member name or ';' after declaration specifiers
  110 |   double error()  const { return _e; }
note: expanded from macro 'error'
  reg3data.h:12:18

On MSVC the macro body shows up in the diagnostics verbatim — 'fprintf': is not a member of 'CGAL::internal::Static_filter_error', '__acrt_iob_func' (that's stderr).

Reduced repro against the pre-fix header, no CGAL needed:

#include "reg3data.h"
struct Static_filter_error { double _e; double error() const { return _e; } };
reg3data.h:12: error: expected unqualified-id before '{' token

Same file on this branch: compiles.

The change

The macro had exactly two users, both in RawivParser.cpp. Replaced with a file-local function of identical behaviour — exit(1) included, so nothing changes at runtime — which keeps the name inside that translation unit.

All three workarounds are then dead and removed. mtxlib_test.cpp now takes clang-format's natural include order (the SDF headers first, which its comment said would re-break the build) and compiles.

Adds Reg3DataHeaderHygiene.ErrorIsNotAMacro to mtxlib_test, declaring a struct that mirrors CGAL's. Reintroducing the macro anywhere reg3data.h can reach now fails to compile, instead of waiting for the next CGAL bump on a platform our Linux CI does not cover.

Verification

  • libcvc builds clean (RelWithDebInfo, SDF on).
  • mtxlib_test 43/43, algorithm_test 10/10.
  • check_test_targets.py: all 119 test executables reach TEST_TARGETS.
  • clang-format --dry-run --Werror clean on every touched file.
  • Reduced repro fails before / passes after, as above.

Local CGAL here is 5.6, so the CGAL 6 path itself is verified by the reduced repro rather than by compiling against CGAL 6.

transfix added a commit to transfix/F2Dock that referenced this pull request Sep 3, 2026
Every macOS and Windows job fails while compiling libcvc, not F2Dock:

  CGAL/.../Static_filters/Static_filter_error.h:110:10: error: expected
    member name or ';' after declaration specifiers
    110 |   double error()  const { return _e; }
  note: expanded from macro 'error'
    libcvc-src/src/cvc/SDF/SignDistanceFunction_v2/reg3data.h:12

libcvc's reg3data.h defines a function-like `error(x)` macro at file scope.
CGAL 6 deprecated AABB_traits.h into AABB_traits_3.h, which now pulls in
Static_filter_error and its `double error() const`; `error()` matches the
one-parameter macro with an empty argument. Homebrew and vcpkg both ship
CGAL 6.2 now, so libcvc stopped compiling on both platforms. Fixed upstream
in transfix/libcvc#324.

Picking the fix up means moving off the v3.2.1-era pin. Two consequences for
F2Dock, both confined to src/vol/RAWIV.cpp, the only file here that touches
libcvc:

  - 3.3.0 moved the public headers into subdirectories: cvc/app.h ->
    cvc/core/app.h, cvc/types.h -> cvc/core/types.h, and bounding_box /
    dimension / volume / volume_file_info under cvc/volume/.
  - CVC_NAMESPACE is gone; cvc/core/namespace.h now just declares
    `namespace cvc {}`. The 17 CVC_NAMESPACE:: qualifiers become cvc::.

LIBCVC_VERSION moves to 3.3.0 as well, so it acts as a compatibility floor:
an older installed or prebuilt libcvc now fails the find_package() version
check and falls through to the source build, instead of being accepted and
then failing to compile against the new include paths. There is no v3.3.0
GitHub release, so the prebuilt strategy misses and the source path is what
runs -- same as it already did for v3.2.1.

The SHA is pinned one commit past v3.3.0 because the tag itself still has
the macro.

Verified locally: configures, builds, 187/187 unit tests, and a 1A2K docking
run produces output identical to the same run against the old pin.
@transfix transfix changed the title fix(sdf): stop reg3data.h leaking an error macro out of the header Make the published libcvc bundle actually consumable (xmlrpc, version, CGAL 6, windows-debug) Sep 4, 2026
transfix added a commit that referenced this pull request Sep 4, 2026
…325)

#121 moved the fork()+IPC multiprocess tests off the parallel ctest
scheduler because their socket and replication windows get starved under
load, producing failures that say nothing about the code. It covered
state_exec_multiprocess_test and state_multiprocess_ipc_test.

state_transport_ipc_test has the same profile -- real Unix-domain sockets
driven with poll() timeouts -- and was left on the parallel scheduler.
It still flakes: StateTransportIpcTest.TwoEndpointConvergence was the single
failure out of 2739 tests on an unrelated PR (#324, an SDF header fix that
touches nothing near state or IPC), which is what surfaced the gap.

Same one-line treatment as its two siblings.
reg3data.h defined

    #define error(x) {fprintf(stderr, "%s\n", x); exit(1);}

at file scope in a header. A function-like macro with that name rewrites any
later declaration that uses the identifier, and `error()` matches a
one-parameter macro with an empty argument, so any header parsed afterwards
that declares a member or function called `error` becomes a syntax error.

Three call sites already carried workarounds for it:

  algorithm.cpp        "CGAL headers must come before SDF headers due to
                       macro conflicts"
  DistanceTransform.cpp "Include app.h BEFORE DistanceTransform.h ... reg3data.h
                       defines error() as a macro which conflicts with cvc::app"
  mtxlib_test.cpp      seventeen lines explaining #undef barriers placed to stop
                       clang-format's IncludeBlocks:Regroup from reordering the
                       includes back into a broken state, ending "Do not merge
                       these blocks"

Include ordering is not a fix, and CGAL 6 broke it. CGAL/AABB_traits.h is now
deprecated and forwards to AABB_traits_3.h, which pulls in
Static_filters/Static_filter_error.h and its `double error() const`.
algorithm.cpp includes AABB_traits.h *after* reg3data.h, so the ordering
workaround does not cover it, and every macOS and Windows build fails there
once the package managers ship CGAL 6.2 (Homebrew and vcpkg both do now).
Reduced repro against the pre-fix header:

    struct Static_filter_error { double _e; double error() const { return _e; } };
    reg3data.h:12: error: expected unqualified-id before '{' token

The macro had exactly two users, both in RawivParser.cpp. Replaced with a
file-local function of the same behaviour, including the exit(1), so the name
cannot leave that translation unit. All three workarounds are then dead and
are removed; mtxlib_test.cpp now takes clang-format's natural include order --
the order its comment said would break the build -- and compiles.

Adds Reg3DataHeaderHygiene.ErrorIsNotAMacro to mtxlib_test, which declares a
struct mirroring CGAL's, so reintroducing the macro anywhere reg3data.h can
reach fails to compile rather than waiting for the next CGAL bump.

mtxlib_test 43/43 and algorithm_test 10/10 pass.
…c::xmlrpc

The published 3.3.0+cvc.3 bundle still has no cvc::xmlrpc. Verified by
installing it from the live catalog:

    cvcpkg install libcvc --prefix p --config release --link shared
    grep -c cvc::xmlrpc p/lib/cmake/cvc/cvcTargets.cmake   ->  0
    ls p/lib | grep -i xmlrpc                              ->  (nothing)
    ls p/include/xmlrpc                                    ->  headers present

publish-cvcpkg.yml already passes -DCVC_USING_XMLRPC=ON on every lane and
hard-fails when the archive or the exported target is missing, but +cvc.3
predates those guards, so no artifact ever carried them. Only a republish
can fix it, and only at a revision above the catalog's max -- 3, not the
recipe's stale 2 -- so this goes straight to 4. At or below the published
max the publish is a silent no-op / 409.

Why this matters beyond libcvc: transfix/F2Dock hard-requires cvc::xmlrpc.
Its _libcvc_check_usable() rejects any libcvc package that lacks the target
and src/CMakeLists.txt FATAL_ERRORs without it, so both catalog strategies
have always been rejected and F2Dock has always fallen through to building
libcvc FROM SOURCE. Demonstrated with a cvcpkg prefix on CMAKE_PREFIX_PATH:

    -- Prebuilt libcvc download failed: 22;"HTTP response code said error"
    -- Building libcvc v3.3.0 from source

That source build is the only reason CGAL and the platform toolchains enter
F2Dock's compile at all -- and therefore the only reason CGAL 6.2 broke its
macOS jobs and the VS18 v180 CL.exe crash broke its Windows jobs. A bundle
that actually exports cvc::xmlrpc removes the source build and both failure
modes with it.

Pairs with the reg3data.h fix in this PR: the +cvc.4 republish carries both.
src/cvc/CMakeLists.txt pinned CVC_VERSION_MAJOR/MINOR at 3/0 while the
top-level project() said 3.3.0. CVC_VERSION feeds write_basic_package_version_file,
so every published bundle exported a cvcConfigVersion.cmake reading

    set(PACKAGE_VERSION "3.0")

with COMPATIBILITY SameMajorVersion. Any downstream find_package(cvc 3.x.y)
with y > 0 failed the version check against every bundle ever published --
the requested version is simply greater than 3.0.

transfix/F2Dock is the case in hand: it asked for 3.2.0, never matched, and
fell through to building libcvc from source. Together with the missing
cvc::xmlrpc target (previous commit) that is two independent reasons a
consumer could not use a published bundle, and the source build is what put
CGAL and the host toolchain into F2Dock's compile.

SOVERSION still comes from CVC_VERSION_MAJOR, so the runtime link name is
unchanged and nothing relinks -- verified:

    lib/libcvc.so   -> libcvc.so.3        (unchanged)
    lib/libcvc.so.3 -> libcvc.so.3.3.0    (was libcvc.so.3.0)

Only the full VERSION suffix and the exported package version move. Both
still match the recipe's `lib/libcvc*` pack glob.
The matrix excluded config=debug on windows-2022 because the catalog had no
windows-debug dep bundles, so a Debug libcvc would have linked Release MSVC
deps -- a debug/release CRT mismatch producing a broken artifact. That was
the right call at the time; the fix is to close the gap, not keep excluding.

Measured it across libcvc's 34 runtime deps by querying the catalog for
platform=windows build-type=debug. Twenty-three already had bundles; ten did
not: gmp, mpfr, gsl, tiff, libiimod, assimp, levmar, grpc, cgal, imagemagick.
(fontconfig also came back missing but is scoped platforms: [linux, macos] in
this recipe, so it never applied to a Windows build.) Those ten are building
now via libcvc-deps' windows-build.yml with config=debug, dispatched in
dependency order so each publishes before the next installs it.

Downstream this is what lets a consumer run a Debug lane at all:
transfix/F2Dock builds Debug and Release on all three platforms and now takes
libcvc from the catalog instead of compiling it, so a missing windows-debug
bundle would leave that lane with nothing to link.

Do not merge ahead of the dep builds -- without them the lane produces
exactly the mismatched artifact the exclusion was guarding against.
@transfix
transfix force-pushed the fix/sdf-error-macro-leak branch from 3bb67fb to f37762a Compare September 4, 2026 03:05
@transfix
transfix merged commit f6393eb into master Sep 4, 2026
13 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.

1 participant