#1153154 libopenimageio-dev: internalized fmt headers go stale when fmtlib changes, rdeps then fail to build

Package:
libopenimageio-dev
Source:
libopenimageio-dev
Description:
Library for reading and writing images - development
Submitter:
Sebastien Bacher
Date:
2026-11-06 10:23:02 UTC
Severity:
normal
#1153154#5
Date:
2026-11-06 10:21:44 UTC
From:
To:
Hi,

openimageio builds with OIIO_INTERNALIZE_FMT, which defaults to ON
(src/cmake/externalpackages.cmake, line 252 in v3.1.18.1):

  option (OIIO_INTERNALIZE_FMT "Copy fmt headers into
<install>/include/OpenImageIO/detail/fmt" ON)

src/include/CMakeLists.txt (from line 52) then copies the fmt headers it
finds at build time (core.h format-inl.h format.h ostream.h printf.h std.h
base.h chrono.h, the ones that exist) from the system libfmt-dev into
/usr/include/OpenImageIO/detail/fmt/. debian/rules doesn't override this.

So libopenimageio-dev ships a snapshot of whatever fmtlib was in the build
chroot, with fmt's own include guards (FMT_FORMAT_H_, FMT_CORE_H_, ...).
Nothing ties that snapshot to the installed libfmt-dev: openimageio uses fmt
header-only, its binaries don't depend on libfmt*, so it isn't part of
fmtlib
transitions (the fmtlib 11 tracker in #1147429 used
.depends ~ "libfmt10" | .depends ~ "libfmt11") and doesn't get binNMUed.

When the two get out of sync, a package that includes the system
<fmt/format.h> before an OpenImageIO header gets OpenImageIO's own
ostream.h (not guarded by the system headers it already pulled in) on top
of a different fmt, and fails to build.

We hit this in Ubuntu: openimageio 3.1.18.1+dfsg-2 was built there while
the archive still had fmtlib 10.1.1, so its detail/fmt/core.h has
FMT_VERSION 100100 (and no base.h), while Debian's build of the same
version has FMT_VERSION 110101 and base.h. After fmtlib 11.1.1+ds1-2
reached Ubuntu, blender 5.2.2+dfsg-1 fails in
intern/cycles/util/image_maketx.cpp, which includes <fmt/format.h> and
then <OpenImageIO/Imath.h>:

  In file included from /usr/include/OpenImageIO/detail/fmt.h:73,
                   from /usr/include/OpenImageIO/Imath.h:9,
                   from intern/cycles/util/image_maketx.cpp:17:
  /usr/include/OpenImageIO/detail/fmt/ostream.h:160:31: error:
'type_identity_t' was not declared in this scope; did you mean
'std::type_identity_t'?

A rebuild of openimageio against fmtlib 11 fixes it. Debian only has
matching headers today because openimageio 3.1 was uploaded (#1150216)
after fmtlib 11 was in unstable. With fmtlib 12.2.0 in experimental, the
same mismatch will happen in Debian once fmt 12 reaches unstable, unless
openimageio is rebuilt with it.

Possible ways to avoid it, roughly in order of preference:

1. Build with -DOIIO_INTERNALIZE_FMT=OFF, so the OpenImageIO headers use
   the system fmt and there is no copy to go stale. That changes what the
   installed headers include, so it may need checking with the
   reverse dependencies.
2. Keep the copy, but make libopenimageio-dev depend on the fmt it was
   built with, e.g. libfmt-dev (>= X), libfmt-dev (<< X+1~) with X filled
   in at build time. A new fmtlib then makes the mismatch visible
   (openimageio needs a rebuild) instead of breaking rdeps' builds.
3. At least make sure openimageio is part of future fmtlib transitions
   (e.g. by including libfmt-dev in the tracker for packages that embed it).

Thanks,
Sebastien Bacher