From: Stuart Henderson Subject: Re: Unbreak mongodb-4.4.29 with libcxx19 To: Rafael Sadowski Cc: The OpenBSD ports mailing-list Date: Sat, 27 Sep 2025 14:31:13 +0100 On 2025/09/27 09:08, Rafael Sadowski wrote: > Diff to unbreak mongodb44. > > For details read patch-src_third_party_fmt_dist_include_fmt_format_h > > OK? Please would you also bump REVISION for clarity (pkg_add will find it anyway because of the libc++ bump, but I think it's better that way) and remove rather than just comment-out BROKEN. Ok :) > Index: Makefile > =================================================================== > RCS file: /cvs/ports/databases/mongodb/44/Makefile,v > diff -u -p -u -p -r1.25 Makefile > --- Makefile 2 Sep 2025 12:13:35 -0000 1.25 > +++ Makefile 27 Sep 2025 07:06:13 -0000 > @@ -1,6 +1,6 @@ > PORTROACH = limitw:1,even > > -BROKEN = fails with newer libc++ > +#BROKEN = fails with newer libc++ > > V = 4.4.29 > REVISION = 5 > Index: patches/patch-src_third_party_fmt_dist_include_fmt_format_h > =================================================================== > RCS file: patches/patch-src_third_party_fmt_dist_include_fmt_format_h > diff -N patches/patch-src_third_party_fmt_dist_include_fmt_format_h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ patches/patch-src_third_party_fmt_dist_include_fmt_format_h 27 Sep 2025 07:06:13 -0000 > @@ -0,0 +1,113 @@ > +"The base template for std::char_traits has been removed in LLVM 19. If you are > +using std::char_traits with types other than char, wchar_t, char8_t, char16_t, > +char32_t or a custom character type for which you specialized std::char_traits, > +your code will stop working. The Standard does not mandate that a base template > +is provided, and such a base template is bound to be incorrect for some types, > +which could currently cause unexpected behavior while going undetected." > + > +https://releases.llvm.org/19.1.0/projects/libcxx/docs/ReleaseNotes.htm > + > +This affects fmt 6.x used by MongoDB 4.4, which uses fmt::char8_t with > +std::char_traits. > + > +Add a minimal std::char_traits impl for fmt::char8_t based on the > +libc++ reference implementation for char traits: > +https://github.com/llvm/llvm-project/blob/main/libcxx/include/__string/char_traits.h#L46 > + > +This is a minimal fix to fix mongodb44 with libcxx19 from base. > + > +Index: src/third_party/fmt/dist/include/fmt/format.h > +--- src/third_party/fmt/dist/include/fmt/format.h.orig > ++++ src/third_party/fmt/dist/include/fmt/format.h > +@@ -43,6 +43,91 @@ > + #include > + #include > + > ++#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 190000 > ++namespace std { > ++template <> > ++struct char_traits { > ++ using char_type = fmt::char8_t; > ++ using int_type = unsigned int; > ++ using off_type = streamoff; > ++ using pos_type = streampos; > ++ using state_type = mbstate_t; > ++ > ++ static constexpr void assign(char_type& c1, const char_type& c2) noexcept { > ++ c1 = c2; > ++ } > ++ > ++ static constexpr bool eq(char_type c1, char_type c2) noexcept { > ++ return c1 == c2; > ++ } > ++ > ++ static constexpr bool lt(char_type c1, char_type c2) noexcept { > ++ return c1 < c2; > ++ } > ++ > ++ static constexpr int compare(const char_type* s1, const char_type* s2, size_t n) { > ++ for (size_t i = 0; i < n; ++i) { > ++ if (lt(s1[i], s2[i])) return -1; > ++ if (lt(s2[i], s1[i])) return 1; > ++ } > ++ return 0; > ++ } > ++ > ++ static constexpr size_t length(const char_type* s) { > ++ size_t len = 0; > ++ while (!eq(s[len], char_type())) ++len; > ++ return len; > ++ } > ++ > ++ static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a) { > ++ for (size_t i = 0; i < n; ++i) { > ++ if (eq(s[i], a)) return s + i; > ++ } > ++ return nullptr; > ++ } > ++ > ++ static char_type* move(char_type* dest, const char_type* src, size_t n) { > ++ if (dest < src) { > ++ for (size_t i = 0; i < n; ++i) dest[i] = src[i]; > ++ } else if (src < dest) { > ++ for (size_t i = n; i > 0; --i) dest[i-1] = src[i-1]; > ++ } > ++ return dest; > ++ } > ++ > ++ static char_type* copy(char_type* dest, const char_type* src, size_t n) { > ++ for (size_t i = 0; i < n; ++i) dest[i] = src[i]; > ++ return dest; > ++ } > ++ > ++ static char_type* assign(char_type* s, size_t n, char_type a) { > ++ for (size_t i = 0; i < n; ++i) s[i] = a; > ++ return s; > ++ } > ++ > ++ static constexpr int_type not_eof(int_type c) noexcept { > ++ return eq_int_type(c, eof()) ? ~eof() : c; > ++ } > ++ > ++ static constexpr char_type to_char_type(int_type c) noexcept { > ++ return char_type(c); > ++ } > ++ > ++ static constexpr int_type to_int_type(char_type c) noexcept { > ++ return int_type(c); > ++ } > ++ > ++ static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { > ++ return c1 == c2; > ++ } > ++ > ++ static constexpr int_type eof() noexcept { > ++ return int_type(EOF); > ++ } > ++}; > ++} > ++#endif > ++ > + #ifdef __clang__ > + # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) > + #else >