From 7088668a2ed6f0153a6ee36d9bac951309761f14 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 12 Jun 2026 13:26:23 +0900 Subject: [PATCH] Add option to use compiled fmt library Introduce OIIO_USE_COMPILED_FMT CMake option to allow linking against a compiled fmt (fmt::fmt) instead of the header-only variant. Update externalpackages.cmake to expose the option, select the appropriate fmt target and include dir, and pass the value into generated headers via oiioversion.h. Adjust Config.cmake.in to avoid forcing find_dependency(fmt) when header-only behavior is overridden. Modify detail/fmt.h to skip defining FMT_HEADER_ONLY when compiled fmt is used, and update libutil CMakeLists and ustring.cpp to link/use the compiled fmt target and use fmt::runtime for dynamic format strings. Signed-off-by: Vlad --- src/cmake/Config.cmake.in | 2 +- src/cmake/externalpackages.cmake | 12 +++++++++++- src/include/OpenImageIO/detail/fmt.h | 12 +++++++++--- src/include/OpenImageIO/oiioversion.h.in | 1 + src/libutil/CMakeLists.txt | 6 +++++- src/libutil/ustring.cpp | 2 +- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/cmake/Config.cmake.in b/src/cmake/Config.cmake.in index 2620994b38..080a499968 100644 --- a/src/cmake/Config.cmake.in +++ b/src/cmake/Config.cmake.in @@ -12,7 +12,7 @@ if (NOT @OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH@ AND NOT OPENIMAGEIO_CONFIG_DO_NOT HINTS @Imath_DIR@) endif () -if (NOT @fmt_LOCAL_BUILD@ AND NOT @OIIO_INTERNALIZE_FMT@) +if (NOT @fmt_LOCAL_BUILD@ AND (NOT @OIIO_INTERNALIZE_FMT@ OR @OIIO_USE_COMPILED_FMT@)) find_dependency(fmt) endif () diff --git a/src/cmake/externalpackages.cmake b/src/cmake/externalpackages.cmake index 2f670f77e9..8739565fcb 100644 --- a/src/cmake/externalpackages.cmake +++ b/src/cmake/externalpackages.cmake @@ -243,11 +243,21 @@ checked_find_package (Robinmap REQUIRED # fmtlib set_option (OIIO_INTERNALIZE_FMT "Copy fmt headers into /include/OpenImageIO/detail/fmt" ON) +set_option (OIIO_USE_COMPILED_FMT "Link against compiled fmt::fmt instead of header-only fmt" OFF) +if (OIIO_USE_COMPILED_FMT) + set (OIIO_USE_COMPILED_FMT_VALUE 1) +else () + set (OIIO_USE_COMPILED_FMT_VALUE 0) +endif () checked_find_package (fmt REQUIRED VERSION_MIN 9.0 BUILD_LOCAL missing ) -get_target_property(FMT_INCLUDE_DIR fmt::fmt-header-only INTERFACE_INCLUDE_DIRECTORIES) +if (OIIO_USE_COMPILED_FMT) + get_target_property(FMT_INCLUDE_DIR fmt::fmt INTERFACE_INCLUDE_DIRECTORIES) +else () + get_target_property(FMT_INCLUDE_DIR fmt::fmt-header-only INTERFACE_INCLUDE_DIRECTORIES) +endif () ########################################################################### diff --git a/src/include/OpenImageIO/detail/fmt.h b/src/include/OpenImageIO/detail/fmt.h index 111b0d5b8e..0973b74a7c 100644 --- a/src/include/OpenImageIO/detail/fmt.h +++ b/src/include/OpenImageIO/detail/fmt.h @@ -9,9 +9,15 @@ #include #include -// We want the header-only implementation of fmt -#ifndef FMT_HEADER_ONLY -# define FMT_HEADER_ONLY +// By default OIIO uses the header-only implementation of fmt. Builds that opt +// into compiled external fmt must use the same mode in OIIO and consumers. +#ifndef OIIO_USE_COMPILED_FMT +# define OIIO_USE_COMPILED_FMT 0 +#endif +#if !OIIO_USE_COMPILED_FMT +# ifndef FMT_HEADER_ONLY +# define FMT_HEADER_ONLY +# endif #endif #if OIIO_VERSION_LESS(3, 1, 2) diff --git a/src/include/OpenImageIO/oiioversion.h.in b/src/include/OpenImageIO/oiioversion.h.in index 374a5fa00c..2cff593900 100644 --- a/src/include/OpenImageIO/oiioversion.h.in +++ b/src/include/OpenImageIO/oiioversion.h.in @@ -47,6 +47,7 @@ #define OIIO_VERSION_PATCH @PROJECT_VERSION_PATCH@ #define OIIO_VERSION_TWEAK @PROJECT_VERSION_TWEAK@ #define OIIO_VERSION_RELEASE_TYPE @PROJECT_VERSION_RELEASE_TYPE@ +#define OIIO_USE_COMPILED_FMT @OIIO_USE_COMPILED_FMT_VALUE@ // Preprocessor utility: stringize #define OIIO_STRINGIZE_HELPER(a) #a diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt index e7c6447c75..877e5b7b6f 100644 --- a/src/libutil/CMakeLists.txt +++ b/src/libutil/CMakeLists.txt @@ -83,7 +83,11 @@ function (setup_oiio_util_library targetname) if (OIIO_INTERNALIZE_FMT OR fmt_LOCAL_BUILD) add_dependencies(${targetname} fmt_internal_target) - else () + endif () + if (OIIO_USE_COMPILED_FMT) + target_link_libraries (${targetname} + PUBLIC fmt::fmt) + elseif (NOT OIIO_INTERNALIZE_FMT AND NOT fmt_LOCAL_BUILD) target_link_libraries (${targetname} PUBLIC fmt::fmt-header-only) endif () diff --git a/src/libutil/ustring.cpp b/src/libutil/ustring.cpp index ec255bf1dc..346a28ddaa 100644 --- a/src/libutil/ustring.cpp +++ b/src/libutil/ustring.cpp @@ -595,7 +595,7 @@ ustring::make_unique(string_view strref) std::string s = Strutil::escape_chars(strref); print(stderr, "IDEMPOTENT RE-HASH! |{}|\n", s); for (auto c : s) - print(stderr, c > 0 ? "{:c}" : "\\{:03o}", + print(stderr, fmt::runtime(c > 0 ? "{:c}" : "\\{:03o}"), static_cast(c)); print(stderr, "\n"); # endif