Skip to content

FMT_STRING consteval error with Apple clang 21 (Xcode 26.4) #4740

Closed

Description

@turban

Compiling the fmt pod via CocoaPods on Xcode 26.4 (Apple clang 21.0.0, clang-2100.0.123.102) fails with:

error: call to consteval function 'fmt::basic_format_string<char, ...>::basic_format_string<FMT_COMPILE_STRING, 0>' is not a constant expression

Errors appear in fmt/include/fmt/format-inl.h at lines 59, 60, 1387, 1391, and 1394 — all call sites of FMT_STRING(...).

Environment

  • Xcode 26.4, build version 17E192
  • Apple clang 21.0.0 (clang-2100.0.123.102)
  • fmt version: bundled with @maplibre/maplibre-react-native via CocoaPods

Root cause

base.h sets FMT_USE_CONSTEVAL 1 for Apple clang ≥ 14 (__apple_build_version__ >= 14000029L), enabling the consteval constructor in basic_format_string. Apple clang 21 is stricter about requiring consteval call sites to themselves be constant expressions, so the FMT_STRING(...) usages in format-inl.h — which are not constant expressions — are rejected.

Workaround

Patch base.h to treat all Apple clang versions the same as < 14 (i.e. FMT_USE_CONSTEVAL 0):

-#elif defined(__apple_build_version__) && __apple_build_version__ < 14000029L
+#elif defined(__apple_build_version__)
 #  define FMT_USE_CONSTEVAL 0  // consteval is broken in Apple clang

Prior art

PR #4703 proposed a fix for this (adding a new threshold for clang 21+) but was closed without merging and without explanation. This issue is a request to reconsider that fix or apply an alternative.

Note: passing -DFMT_CONSTEVAL= or -DFMT_USE_CONSTEVAL=0 via compiler flags does not work, because base.h unconditionally redefines both macros through its own #if/#elif chain, overwriting any -D flag.

Activity

  1. vitaut commented on Apr 10, 2026

    @vitaut
    Contributor

    As commented on #4703 I wasn't able to repro the issue which is why it was closed, so you'll need to provide repro details. In particular do you get the error when compiling your code or {fmt} and what is the build configuration?

  2. vitaut commented on Apr 10, 2026

    @vitaut
    Contributor

    Note: passing -DFMT_CONSTEVAL= or -DFMT_USE_CONSTEVAL=0 via compiler flags does not work, because base.h unconditionally redefines both macros through its own #if/#elif chain, overwriting any -D flag.

    This is incorrect. User-provided FMT_USE_CONSTEVAL is checked first and takes precedence over any auto-detection:

    fmt/include/fmt/base.h

    Lines 117 to 118 in 9396f77

    #ifdef FMT_USE_CONSTEVAL
    // Use the provided definition.

    The root cause is also not quite correct because FMT_STRING("...") is a constant expression.

  3. vitaut commented on Apr 10, 2026

    @vitaut
    Contributor

    It is possible that the issue is specific to the older version of {fmt}. Does it reproduce on main?

  4. turban commented on Apr 10, 2026

    @turban
    Author

    Thanks for the clarification. After investigating further:

    The fmt version in question is 11.0.2, bundled via React Native's RCT-Folly CocoaPod (which pins fmt = 11.0.2). In that version, FMT_USE_CONSTEVAL is not guarded by #ifdef, so user-provided values via -D flags are overwritten by the detection chain — which is why the preprocessor flag approach didn't work for us. The #ifdef guard was added in 12.1.0, per the 12.1.0 release notes.

    So the fix already exists in fmt 12.1.0 — the issue is that React Native hasn't upgraded yet. This is being tracked in:

    Apologies for the incorrect root cause analysis in the original report. Feel free to close this issue — the fix is in fmt and the ball is in React Native's court.

  5. vitaut commented on Apr 10, 2026

    @vitaut
    Contributor

    No worries, I'm glad this is fixed already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions