Skip to content

Conversation

@HazardyKnusperkeks
Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks commented Jul 29, 2025

That way one can provide ones own implementation for assert_fail, which is moved out of the detail namespace. For binary compatibility the detail version stays to call the outer version.

@HazardyKnusperkeks
Copy link
Contributor Author

I want to use libfmt in a bare metal project, with exceptions disabled and I don't want to pull in any of the printf-familiy, so I need my own implementation. Instead of a weak symbol one could hide the implementation behind an #if (e.g. FMT_USER_PROVIDED_ASSERT_FAIL), if that's more to your liking.

@HazardyKnusperkeks
Copy link
Contributor Author

I want to use libfmt in a bare metal project, with exceptions disabled and I don't want to pull in any of the printf-familiy, so I need my own implementation. Instead of a weak symbol one could hide the implementation behind an #if (e.g. FMT_USER_PROVIDED_ASSERT_FAIL), if that's more to your liking.

Seeing the failing tests, that seems to be needed?

@HazardyKnusperkeks HazardyKnusperkeks changed the title Mark detail::assert_fail as weak symbol Add FMT_USER_PROVIDED_ASSERT_FAIL Jul 29, 2025
@vitaut
Copy link
Contributor

vitaut commented Aug 1, 2025

Thanks for the PR but I don't think we should add yet another configuration macro. You can already control this via FMT_ASSERT / FMT_THROW.

@vitaut vitaut closed this Aug 1, 2025
@HazardyKnusperkeks
Copy link
Contributor Author

I actually can not really. Because the functions I'd like to be called is not yet in scope, when fmt/format.h is included, even if using the classic assert, obviously the same for my own functions.

/opt/bin/g++ -g -O0 -Wall -Wextra -m64 -pipe -fexceptions -fvisibility=default -fPIC -DFMT_USE_NOEXCEPT '-DFMT_ASSERT(c,t)=assert(c)' -I.../libs/3rdParty/fmt/include -std=c++2b -o.../build/Desktop-Debug/Debug_Desktop_038b678e9426a45b/fmt.875c51b4/f5439ee4c1a5e132/os.cc.o -c .../libs/3rdParty/fmt/src/os.cc
.../libs/3rdParty/fmt/include/fmt/format.h: In function 'constexpr fmt::v11::detail::uint128_fallback fmt::v11::detail::operator*(const uint128_fallback&, uint32_t)':
<command-line>: error: 'assert' was not declared in this scope
.../libs/3rdParty/fmt/include/fmt/format.h:325:5: note: in expansion of macro 'FMT_ASSERT'
  325 |     FMT_ASSERT(lhs.hi_ == 0, "");
      |     ^~~~~~~~~~
In file included from .../libs/3rdParty/fmt/include/fmt/os.h:11,
                 from .../libs/3rdParty/fmt/src/os.cc:13:

But declaring it as weak, if and only if FMT_HEADER_ONLY is not defined would also work for me.

@vitaut vitaut reopened this Aug 3, 2025
@vitaut
Copy link
Contributor

vitaut commented Aug 3, 2025

Good point, let's reopen this.

@vitaut
Copy link
Contributor

vitaut commented Aug 9, 2025

Have you considered wrapping {fmt} headers such that your custom assertion function is visible at the point of use?

@HazardyKnusperkeks
Copy link
Contributor Author

I have not. But that would be hard for other libraries which also use fmt (which I don't have yet), and fmt's own source files. I did hope to land some form in the official code.

I understand your concern, and if we don't find an agreement here, I'll probably go with a fork.

Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a weak symbol is slightly better than introducing a configuration macro. Also if we are making it overridable the symbol should go from detail to the fmt (with version) namespace. For ABI compatibility we should also have detail::assert_fail that can forward to the public API version.

@HazardyKnusperkeks HazardyKnusperkeks changed the title Add FMT_USER_PROVIDED_ASSERT_FAIL Add fmt::assert_fail as a weak symbol Aug 18, 2025
Comment on lines 273 to 281
#if (FMT_GCC_VERSION || FMT_CLANG_VERSION) && !defined(FMT_HEADER_ONLY) && \
!FMT_WIN32
// Header only (which implies everything is inline) and weak symbols do not work
// together. And on Windows weak symbols seem not to work properly.
# define FMT_WEAK __attribute__((weak))
#endif
#ifndef FMT_WEAK
# define FMT_WEAK
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at all the caveats, I am now leaning towards your previous version with a configuration macro.

Also what's up with the test failures?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming-wise I suggest FMT_CUSTOM_ASSERT_FAIL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some update trouble with my Linux machine to investigate, my gut feeling is, that the assert tries to jump to an invalid address. I had something like on my Windows machine too, but thought that was because (as I've been told), that weak symbols currently do not work with binutils.

Comment on lines 273 to 281
#if (FMT_GCC_VERSION || FMT_CLANG_VERSION) && !defined(FMT_HEADER_ONLY) && \
!FMT_WIN32
// Header only (which implies everything is inline) and weak symbols do not work
// together. And on Windows weak symbols seem not to work properly.
# define FMT_WEAK __attribute__((weak))
#endif
#ifndef FMT_WEAK
# define FMT_WEAK
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming-wise I suggest FMT_CUSTOM_ASSERT_FAIL.

@HazardyKnusperkeks HazardyKnusperkeks changed the title Add fmt::assert_fail as a weak symbol Add FMT_CUSTOM_ASSERT_FAIL Aug 23, 2025
Comment on lines 351 to 354
FMT_BEGIN_EXPORT
FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
const char* message);
FMT_END_EXPORT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it needs to be exported from the module. The reason why it is in the fmt namespace is that it can be replaced by users, but it's not supposed to be called directly.

@vitaut
Copy link
Contributor

vitaut commented Aug 24, 2025

Overall looks good but please address the remaining comment and rebase.

@HazardyKnusperkeks HazardyKnusperkeks force-pushed the weak-assert branch 2 times, most recently from 17d715e to 96f28a9 Compare August 24, 2025 20:58
That way one can provide ones own implementation for assert_fail, which
is moved out of the detail namespace. For binary compatibility the
detail version stays to call the outer version.
@HazardyKnusperkeks
Copy link
Contributor Author

Done, sorry for the noise.

@vitaut vitaut merged commit e181e94 into fmtlib:master Aug 25, 2025
41 checks passed
@vitaut
Copy link
Contributor

vitaut commented Aug 25, 2025

Merged, thanks!

mtremer pushed a commit to ipfire/ipfire-2.x that referenced this pull request Nov 6, 2025
- Update from version 11.2.0 to 12.1.0
- Update of rootfile
- so-bump so mpd requires shipping
- Changelog
    12.1.0
	- Optimized `buffer::append`, resulting in up to ~16% improvement on spdlog
	  benchmarks (fmtlib/fmt#4541). Thanks @fyrsta7.
	- Worked around an ABI incompatibility in `std::locale_ref` between clang and
	  gcc (fmtlib/fmt#4573).
	- Made `std::variant` and `std::expected` formatters work with `format_as`
	  (fmtlib/fmt#4574,
	  fmtlib/fmt#4575). Thanks @phprus.
	- Made `fmt::join<string_view>` work with C++ modules
	  (fmtlib/fmt#4379,
	  fmtlib/fmt#4577). Thanks @Arghnews.
	- Exported `fmt::is_compiled_string` and `operator""_cf` from the module
	  (fmtlib/fmt#4544). Thanks @CrackedMatter.
	- Fixed a compatibility issue with C++ modules in clang
	  (fmtlib/fmt#4548). Thanks @tsarn.
	- Added support for cv-qualified types to the `std::optional` formatter
	  (fmtlib/fmt#4561,
	  fmtlib/fmt#4562). Thanks @OleksandrKvl.
	- Added demangling support (used in exception and `std::type_info` formatters)
	  for libc++ and clang-cl
	  (fmtlib/fmt#4542,
	  fmtlib/fmt#4560,
	  fmtlib/fmt#4568,
	  fmtlib/fmt#4571).
	  Thanks @FatihBAKIR and @rohitsutreja.
	- Switched to global `malloc`/`free` to enable allocator customization
	  (fmtlib/fmt#4569,
	  fmtlib/fmt#4570). Thanks @rohitsutreja.
	- Made the `FMT_USE_CONSTEVAL` macro configurable by users
	  (fmtlib/fmt#4546). Thanks @SnapperTT.
	- Fixed compilation with locales disabled in the header-only mode
	  (fmtlib/fmt#4550).
	- Fixed compilation with clang 21 and `-std=c++20`
	  (fmtlib/fmt#4552).
	- Fixed a dynamic linking issue with clang-cl
	  (fmtlib/fmt#4576,
	  fmtlib/fmt#4584). Thanks @FatihBAKIR.
	- Fixed a warning suppression leakage on gcc
	  (fmtlib/fmt#4588). Thanks @ZedThree.
	- Made more internal color APIs `constexpr`
	  (fmtlib/fmt#4581). Thanks @ishani.
	- Fixed compatibility with clang as a host compiler for NVCC
	  (fmtlib/fmt#4564). Thanks @valgur.
	- Fixed various warnings and lint issues
	  (fmtlib/fmt#4565,
	  fmtlib/fmt#4572,
	  fmtlib/fmt#4557).
	  Thanks @LiangHuDream and @teruyamato0731.
	- Improved documentation
	  (fmtlib/fmt#4549,
	  fmtlib/fmt#4551,
	  fmtlib/fmt#4566,
	  fmtlib/fmt#4567,
	  fmtlib/fmt#4578,).
	  Thanks @teruyamato0731, @petersteneteg and @zimmerman-dev.
    12.0.0
	- Optimized the default floating point formatting
	  (fmtlib/fmt#3675,
	  fmtlib/fmt#4516). In particular, formatting a
	  `double` with format string compilation into a stack allocated buffer is
	  more than 60% faster in version 12.0 compared to 11.2 according to
	  [dtoa-benchmark](https://github.com/fmtlib/dtoa-benchmark):
	  ```
	  Function  Time (ns)  Speedup
	  fmt11        34.471    1.00x
	  fmt12        21.000    1.64x
	  ```
	  <img width="766" height="609" src="https://github.com/user-attachments/assets/d7d768ad-7543-468c-b0bb-449abf73b31b" />
	- Added `constexpr` support to `fmt::format`. For example:
	  ```c++
	  #include <fmt/compile.h>
	  using namespace fmt::literals;
	  std::string s = fmt::format(""_cf, 42);
	  ```
	  now works at compile time provided that `std::string` supports `constexpr`
	  (fmtlib/fmt#3403,
	  fmtlib/fmt#4456). Thanks @msvetkin.
	- Added `FMT_STATIC_FORMAT` that allows formatting into a string of the exact
	  required size at compile time.
	  For example:
	  ```c++
	  #include <fmt/compile.h>
	  constexpr auto s = FMT_STATIC_FORMAT("{}", 42);
	  ```
	  compiles to just
	  ```s
	  __ZL1s:
	        .asciiz "42"
	  ```
	  It can be accessed as a C string with `s.c_str()` or as a string view with
	  `s.str()`.
	- Improved C++20 module support
	  (fmtlib/fmt#4451,
	  fmtlib/fmt#4459,
	  fmtlib/fmt#4476,
	  fmtlib/fmt#4488,
	  fmtlib/fmt#4491,
	  fmtlib/fmt#4495).
	  Thanks @arBmind, @tkhyn, @Mishura4, @anonymouspc and @autoantwort.
	- Switched to using estimated display width in precision. For example:
	  ```c++
	  fmt::print("|{:.4}|\n|1234|\n", "🐱🐱🐱");
	  ```
	  prints
	  ![](https://github.com/user-attachments/assets/6c4446b3-13eb-43b9-b74a-b4543540ad6a)
	  because `🐱` has an estimated width of 2
	  (fmtlib/fmt#4272,
	  fmtlib/fmt#4443,
	  fmtlib/fmt#4475).
	  Thanks @nikhilreddydev and @localspook.
	- Fix interaction between debug presentation, precision, and width for strings
	  (fmtlib/fmt#4478). Thanks @localspook.
	- Implemented allocator propagation on `basic_memory_buffer` move
	  (fmtlib/fmt#4487,
	  fmtlib/fmt#4490). Thanks @toprakmurat.
	- Fixed an ambiguity between `std::reference_wrapper<T>` and `format_as`
	  formatters (fmtlib/fmt#4424,
	  fmtlib/fmt#4434). Thanks @jeremy-rifkin.
	- Removed the following deprecated APIs:
	  - `has_formatter`: use `is_formattable` instead,
	  - `basic_format_args::parse_context_type`,
	    `basic_format_args::formatter_type` and similar aliases in context types,
	  - wide stream overload of `fmt::printf`,
	  - wide stream overloads of `fmt::print` that take text styles,
	  - `is_*char` traits,
	  - `fmt::localtime`.
	- Deprecated wide overloads of `fmt::fprintf` and `fmt::sprintf`.
	- Improved diagnostics for the incorrect usage of `fmt::ptr`
	  (fmtlib/fmt#4453). Thanks @TobiSchluter.
	- Made handling of ANSI escape sequences more efficient
	  (fmtlib/fmt#4511,
	  fmtlib/fmt#4528).
	  Thanks @localspook and @Anas-Hamdane.
	- Fixed a buffer overflow on all emphasis flags set
	  (fmtlib/fmt#4498). Thanks @dominicpoeschko.
	- Fixed an integer overflow for precision close to the max `int` value.
	- Fixed compatibility with WASI (fmtlib/fmt#4496,
	  fmtlib/fmt#4497). Thanks @whitequark.
	- Fixed `back_insert_iterator` detection, preventing a fallback on slower path
	  that handles arbitrary iterators (fmtlib/fmt#4454).
	- Fixed handling of invalid glibc `FILE` buffers
	  (fmtlib/fmt#4469).
	- Added `wchar_t` support to the `std::byte` formatter
	  (fmtlib/fmt#4479,
	  fmtlib/fmt#4480). Thanks @phprus.
	- Changed component prefix from `fmt-` to `fmt_` for compatibility with
	  NSIS/CPack on Windows, e.g. `fmt-doc` changed to `fmt_doc`
	  (fmtlib/fmt#4441,
	  fmtlib/fmt#4442). Thanks @n-stein.
	- Added the `FMT_CUSTOM_ASSERT_FAIL` macro to simplify providing a custom
	  `fmt::assert_fail` implementation (fmtlib/fmt#4505).
	  Thanks @HazardyKnusperkeks.
	- Switched to `FMT_THROW` on reporting format errors so that it can be
	  overriden by users when exceptions are disabled
	  (fmtlib/fmt#4521). Thanks @HazardyKnusperkeks.
	- Improved master project detection and disabled install targets when using
	  {fmt} as a subproject by default (fmtlib/fmt#4536).
	  Thanks @crueter.
	- Made various code improvements
	  (fmtlib/fmt#4445,
	  fmtlib/fmt#4448,
	  fmtlib/fmt#4473,
	  fmtlib/fmt#4522).
	  Thanks @localspook, @tchaikov and @way4sahil.
	- Added Conan instructions to the docs
	  (fmtlib/fmt#4537). Thanks @uilianries.
	- Removed Bazel files to avoid issues with downstream packaging
	  (fmtlib/fmt#4530). Thanks @mering.
	- Added more entries for generated files to `.gitignore`
	  (fmtlib/fmt#4355,
	  fmtlib/fmt#4512).
	  Thanks @dinomight and @localspook.
	- Fixed various warnings and compilation issues
	  (fmtlib/fmt#4447,
	  fmtlib/fmt#4470,
	  fmtlib/fmt#4474,
	  fmtlib/fmt#4477,
	  fmtlib/fmt#4471,
	  fmtlib/fmt#4483,
	  fmtlib/fmt#4515,
	  fmtlib/fmt#4533,
	  fmtlib/fmt#4534).
	  Thanks @dodomorandi, @localspook, @remyjette, @Tomek-Stolarczyk, @Mishura4,
	  @mattiasljungstrom and @FatihBAKIR.

Signed-off-by: Adolf Belka <[email protected]>
Signed-off-by: Michael Tremer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants