Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem building spdlog with external fmt #3115

Open
askraskr opened this issue Jun 20, 2024 · 2 comments
Open

Problem building spdlog with external fmt #3115

askraskr opened this issue Jun 20, 2024 · 2 comments

Comments

@askraskr
Copy link

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
Copy link
Contributor

tt4g commented Jun 20, 2024

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
Copy link
Contributor

ziyao233 commented Jul 8, 2024

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.

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

No branches or pull requests

3 participants