Ceres asks for Eigen with a version range - find_package(Eigen3 3.3.4...5
NO_MODULE) - and Eigen's own Eigen3ConfigVersion.cmake rejects any range whose
endpoints differ in major version. A 3.4 Eigen therefore declares itself
INCOMPATIBLE with Ceres' query, the search falls through, and Ceres binds whatever
older Eigen comes next on the prefix path. Where a distro eigen3-devel 3.3.4 is
installed alongside a 3.4 one, Ceres created Eigen3::Eigen first, in its own
directory scope, pointing at the older headers, and exported it publicly; the
project's own find_package then ran afterwards and made a second target pointing at
the newer ones. Targets linking both - the geometry refinement and the scale/merge
libraries - took the older Eigen first.
The result was a binary holding Eigen 3.3.4 and 3.4.90 template instantiations at
once. Identically mangled, they are merged at link time with disagreeing evaluator
layouts, so the program is undefined: at -O2 it segfaulted inside an Eigen product
under the lattice reduction, nine runs out of nine, and at -O3 it happened not to,
which is luck rather than correctness.
Resolve Eigen before Ceres is added. The first find_package to run creates the
imported target and later ones leave it alone, so Ceres inherits ours. Then assert
it: if Ceres ever creates an Eigen3::Eigen of its own, the configure fails with an
explanation rather than producing a binary that is quietly ill-formed. The guard
fires only on that condition, not merely because two Eigens are installed.
After the change no translation unit sees the older headers - 0 of 227 flags files,
against 30 before - and Ceres reports the Eigen it actually compiled against. The
same nine runs that all crashed now all complete. Release output is unaffected:
eight datasets give byte-identical reflection files and identical merging
statistics either way, so nothing previously measured is invalidated.
Eigen and ZLIB stay external find_package dependencies on every platform, and
OVERRIDE_FIND_PACKAGE is not reintroduced. Where only one Eigen is installed - the
Windows and macOS case - Ceres' non-range fallback honours the same Eigen3_DIR and
the change is a no-op.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016NNnL26LAvruQ9eLUUWvrJ