gabime / spdlog

Fast C++ logging library.
Other
24.59k stars 4.59k forks source link

Problem building spdlog with external fmt #3115

Open askraskr opened 5 months ago

askraskr commented 5 months ago

Just installed and test fmt library (development version) with the following instructions:

cmake -S fmt -B fmtb -DBUILD_SHARED_LIBS=TRUE -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_COMPILER=/usr/bin/g++-13
cmake --build fmtb
sudo cmake --install fmtb

It's working perfectly fine.

But I wanted my spdlog library to not use the bundled fmt, so I used SPDLOG_FMT_EXTERNAL option with the following command:

cmake -S spdlog -B spdlogb -DSPDLOG_FMT_EXTERNAL=ON -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_COMPILER=/usr/bin/g++-13 -DSPDLOG_BUILD_SHARED=ON -DSPDLOG_BUILD_PIC=ON

But when I tried to build it, I got this error.

cmake --build spdlogb
/usr/local/include/fmt/base.h: In instantiation of ‘static void fmt::v10::detail::value<Context>::format_custom_arg(void*, typename Context::parse_context_type&, Context&) [with T = my_type; Formatter = fmt::v10::formatter<my_type>; Context = fmt::v10::context; typename Context::parse_context_type = fmt::v10::basic_format_parse_context<char>]’:
/usr/local/include/fmt/base.h:1374:19:   required from ‘constexpr fmt::v10::detail::value<Context>::value(T&) [with T = my_type; Context = fmt::v10::context]’
/usr/local/include/fmt/base.h:1632:41:   required from ‘constexpr fmt::v10::detail::value<Context> fmt::v10::detail::make_arg(T&) [with bool PACKED = true; Context = fmt::v10::context; T = my_type; typename std::enable_if<PACKED, int>::type <anonymous> = 0]’
/usr/local/include/fmt/base.h:2003:74:   required from ‘constexpr fmt::v10::detail::format_arg_store<Context, NUM_ARGS, 0, DESC> fmt::v10::make_format_args(T& ...) [with Context = context; T = {my_type}; long unsigned int NUM_ARGS = 1; long unsigned int NUM_NAMED_ARGS = 0; long long unsigned int DESC = 15; typename std::enable_if<(NUM_NAMED_ARGS == 0), int>::type <anonymous> = 0]’
/home/linuxuser/spdlog/include/spdlog/logger.h:328:75:   required from ‘void spdlog::logger::log_(spdlog::source_loc, spdlog::level::level_enum, spdlog::string_view_t, Args&& ...) [with Args = {my_type}; spdlog::string_view_t = fmt::v10::basic_string_view<char>]’
/home/linuxuser/spdlog/include/spdlog/logger.h:80:13:   required from ‘void spdlog::logger::log(spdlog::source_loc, spdlog::level::level_enum, fmt::v10::format_string<T ...>, Args&& ...) [with Args = {my_type}; fmt::v10::format_string<T ...> = fmt::v10::basic_format_string<char, my_type>]’
/home/linuxuser/spdlog/include/spdlog/logger.h:85:12:   required from ‘void spdlog::logger::log(spdlog::level::level_enum, fmt::v10::format_string<T ...>, Args&& ...) [with Args = {my_type}; fmt::v10::format_string<T ...> = fmt::v10::basic_format_string<char, my_type>]’
/home/linuxuser/spdlog/include/spdlog/logger.h:140:12:   required from ‘void spdlog::logger::info(fmt::v10::format_string<T ...>, Args&& ...) [with Args = {my_type}; fmt::v10::format_string<T ...> = fmt::v10::basic_format_string<char, my_type>]’
/home/linuxuser/spdlog/include/spdlog/spdlog.h:168:31:   required from ‘void spdlog::info(fmt::v10::format_string<T ...>, Args&& ...) [with Args = {my_type}; fmt::v10::format_string<T ...> = fmt::v10::basic_format_string<char, my_type>]’
/home/linuxuser/spdlog/example/example.cpp:289:43:   required from here
/usr/local/include/fmt/base.h:1393:29: error: passing ‘const fmt::v10::formatter<my_type>’ as ‘this’ argument discards qualifiers [-fpermissive]
 1393 |     ctx.advance_to(cf.format(*static_cast<qualified_type*>(arg), ctx));
      |                    ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/linuxuser/spdlog/example/example.cpp:275:10: note:   in call to ‘fmt::v10::context::iterator fmt::v10::formatter<my_type>::format(my_type, fmt::v10::format_context&)’
  275 |     auto format(my_type my, format_context &ctx) -> decltype(ctx.out()) {
      |          ^~~~~~
gmake[2]: *** [example/CMakeFiles/example.dir/build.make:76: example/CMakeFiles/example.dir/example.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:126: example/CMakeFiles/example.dir/all] Error 2
gmake: *** [Makefile:156: all] Error 2

No matter what compiler (gcc) version or C++ standard I use, I get the same error. What is the problem?

tt4g commented 5 months ago

It may be that the definition of the fmt custom formatter refers to an older document (https://fmt.dev/8.0.0/api.html#formatting-user-defined-types). The fmt 10 documentation gives auto as the return type, but example.cpp gives decltype(ctx.out()). The two types are probably incompatible.

In fmt 10 document (https://fmt.dev/10.2.0/api.html#formatting-user-defined-types):

#include <fmt/core.h>

enum class color {red, green, blue};

template <> struct fmt::formatter<color>: formatter<string_view> {
  // parse is inherited from formatter<string_view>.

  auto format(color c, format_context& ctx) const;
};

Since it is example that is failing to build, you can work around the problem with -DSPDLOG_BUILD_EXAMPLE=OFF.

ziyao233 commented 4 months ago

starting from 11.0.0, fmt requires formatter::format to be const.

In the release note,

Started enforcing that formatter::format is const for compatibility with std::format

we should sync with this change.