mirror of
https://github.com/gabime/spdlog.git
synced 2024-11-15 08:25:43 +08:00
Support compile-time format string checking with std::format (#2544)
* Support compile-time format string checking with std::format * Fix pre-VS 17.5 compilation * Fix compilation without wchar_t support * What am I doing * Bring back fmt optimization * Move to_string_view to common.h * Fix SPDLOG_CONSTEXPR_FUNC emitting duplicate symbol errors when building in C++11 * Also add inline on VS 2013 * Appender doesn't work on wide strings
This commit is contained in:
parent
c5a09ebc49
commit
4f80077339
@ -83,7 +83,7 @@ option(SPDLOG_BUILD_WARNINGS "Enable compiler warnings" OFF)
|
|||||||
|
|
||||||
# install options
|
# install options
|
||||||
option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
|
option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
|
||||||
option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library. No compile-time format string checking." OFF)
|
option(SPDLOG_USE_STD_FORMAT "Use std::format instead of fmt library." OFF)
|
||||||
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
|
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
|
||||||
option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF)
|
option(SPDLOG_FMT_EXTERNAL_HO "Use external fmt header-only library instead of bundled" OFF)
|
||||||
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
|
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
|
||||||
|
@ -92,7 +92,7 @@ environment:
|
|||||||
WCHAR_FILES: 'OFF'
|
WCHAR_FILES: 'OFF'
|
||||||
BUILD_EXAMPLE: 'OFF'
|
BUILD_EXAMPLE: 'OFF'
|
||||||
USE_STD_FORMAT: 'ON'
|
USE_STD_FORMAT: 'ON'
|
||||||
CXX_STANDARD: 23 # std::format is only available with /std:c++latest at the moment.
|
CXX_STANDARD: 20
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
- GENERATOR: '"Visual Studio 17 2022" -A x64'
|
- GENERATOR: '"Visual Studio 17 2022" -A x64'
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
@ -102,7 +102,7 @@ environment:
|
|||||||
WCHAR_FILES: 'ON'
|
WCHAR_FILES: 'ON'
|
||||||
BUILD_EXAMPLE: 'OFF'
|
BUILD_EXAMPLE: 'OFF'
|
||||||
USE_STD_FORMAT: 'ON'
|
USE_STD_FORMAT: 'ON'
|
||||||
CXX_STANDARD: 23 # std::format is only available with /std:c++latest at the moment.
|
CXX_STANDARD: 20
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: >-
|
- cmd: >-
|
||||||
|
@ -17,7 +17,12 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#ifdef SPDLOG_USE_STD_FORMAT
|
#ifdef SPDLOG_USE_STD_FORMAT
|
||||||
# include <string_view>
|
# include <version>
|
||||||
|
# if __cpp_lib_format >= 202207L
|
||||||
|
# include <format>
|
||||||
|
# else
|
||||||
|
# include <string_view>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPDLOG_COMPILED_LIB
|
#ifdef SPDLOG_COMPILED_LIB
|
||||||
@ -59,14 +64,14 @@
|
|||||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||||
# define SPDLOG_NOEXCEPT _NOEXCEPT
|
# define SPDLOG_NOEXCEPT _NOEXCEPT
|
||||||
# define SPDLOG_CONSTEXPR
|
# define SPDLOG_CONSTEXPR
|
||||||
# define SPDLOG_CONSTEXPR_FUNC
|
# define SPDLOG_CONSTEXPR_FUNC inline
|
||||||
#else
|
#else
|
||||||
# define SPDLOG_NOEXCEPT noexcept
|
# define SPDLOG_NOEXCEPT noexcept
|
||||||
# define SPDLOG_CONSTEXPR constexpr
|
# define SPDLOG_CONSTEXPR constexpr
|
||||||
# if __cplusplus >= 201402L
|
# if __cplusplus >= 201402L
|
||||||
# define SPDLOG_CONSTEXPR_FUNC constexpr
|
# define SPDLOG_CONSTEXPR_FUNC constexpr
|
||||||
# else
|
# else
|
||||||
# define SPDLOG_CONSTEXPR_FUNC
|
# define SPDLOG_CONSTEXPR_FUNC inline
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -134,7 +139,11 @@ using string_view_t = std::string_view;
|
|||||||
using memory_buf_t = std::string;
|
using memory_buf_t = std::string;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
# if __cpp_lib_format >= 202207L
|
||||||
|
using format_string_t = std::format_string<Args...>;
|
||||||
|
# else
|
||||||
using format_string_t = std::string_view;
|
using format_string_t = std::string_view;
|
||||||
|
# endif
|
||||||
|
|
||||||
template<class T, class Char = char>
|
template<class T, class Char = char>
|
||||||
struct is_convertible_to_basic_format_string : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::value>
|
struct is_convertible_to_basic_format_string : std::integral_constant<bool, std::is_convertible<T, std::basic_string_view<Char>>::value>
|
||||||
@ -145,7 +154,11 @@ using wstring_view_t = std::wstring_view;
|
|||||||
using wmemory_buf_t = std::wstring;
|
using wmemory_buf_t = std::wstring;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
# if __cpp_lib_format >= 202207L
|
||||||
|
using wformat_string_t = std::wformat_string<Args...>;
|
||||||
|
# else
|
||||||
using wformat_string_t = std::wstring_view;
|
using wformat_string_t = std::wstring_view;
|
||||||
|
# endif
|
||||||
# endif
|
# endif
|
||||||
# define SPDLOG_BUF_TO_STRING(x) x
|
# define SPDLOG_BUF_TO_STRING(x) x
|
||||||
#else // use fmt lib instead of std::format
|
#else // use fmt lib instead of std::format
|
||||||
@ -323,6 +336,44 @@ struct file_event_handlers
|
|||||||
|
|
||||||
namespace details {
|
namespace details {
|
||||||
|
|
||||||
|
// to_string_view
|
||||||
|
|
||||||
|
SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
return spdlog::string_view_t{buf.data(), buf.size()};
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
|
||||||
|
SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
return spdlog::wstring_view_t{buf.data(), buf.size()};
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPDLOG_USE_STD_FORMAT
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
inline fmt::basic_string_view<T> to_string_view(fmt::basic_format_string<T, Args...> fmt)
|
||||||
|
{
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
#elif __cpp_lib_format >= 202207L
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
SPDLOG_CONSTEXPR_FUNC std::basic_string_view<T> to_string_view(std::basic_format_string<T, Args...> fmt) SPDLOG_NOEXCEPT
|
||||||
|
{
|
||||||
|
return fmt.get();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// make_unique support for pre c++14
|
// make_unique support for pre c++14
|
||||||
|
|
||||||
#if __cplusplus >= 201402L // C++14 and beyond
|
#if __cplusplus >= 201402L // C++14 and beyond
|
||||||
|
@ -18,11 +18,6 @@ namespace spdlog {
|
|||||||
namespace details {
|
namespace details {
|
||||||
namespace fmt_helper {
|
namespace fmt_helper {
|
||||||
|
|
||||||
inline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEXCEPT
|
|
||||||
{
|
|
||||||
return spdlog::string_view_t{buf.data(), buf.size()};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
|
inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
|
||||||
{
|
{
|
||||||
auto *buf_ptr = view.data();
|
auto *buf_ptr = view.data();
|
||||||
|
@ -87,7 +87,7 @@ public:
|
|||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)
|
void log(source_loc loc, level::level_enum lvl, format_string_t<Args...> fmt, Args &&... args)
|
||||||
{
|
{
|
||||||
log_(loc, lvl, fmt, std::forward<Args>(args)...);
|
log_(loc, lvl, details::to_string_view(fmt), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
@ -180,7 +180,7 @@ public:
|
|||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log(source_loc loc, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)
|
void log(source_loc loc, level::level_enum lvl, wformat_string_t<Args...> fmt, Args &&... args)
|
||||||
{
|
{
|
||||||
log_(loc, lvl, fmt, std::forward<Args>(args)...);
|
log_(loc, lvl, details::to_string_view(fmt), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
@ -394,12 +394,8 @@ protected:
|
|||||||
{
|
{
|
||||||
// format to wmemory_buffer and convert to utf8
|
// format to wmemory_buffer and convert to utf8
|
||||||
wmemory_buf_t wbuf;
|
wmemory_buf_t wbuf;
|
||||||
# ifdef SPDLOG_USE_STD_FORMAT
|
|
||||||
fmt_lib::vformat_to(
|
fmt_lib::vformat_to(
|
||||||
std::back_inserter(wbuf), fmt, fmt_lib::make_format_args<fmt_lib::wformat_context>(std::forward<Args>(args)...));
|
std::back_inserter(wbuf), fmt, fmt_lib::make_format_args<fmt_lib::wformat_context>(std::forward<Args>(args)...));
|
||||||
# else
|
|
||||||
fmt::vformat_to(std::back_inserter(wbuf), fmt, fmt::make_format_args<fmt::wformat_context>(std::forward<Args>(args)...));
|
|
||||||
# endif
|
|
||||||
|
|
||||||
memory_buf_t buf;
|
memory_buf_t buf;
|
||||||
details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf);
|
details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf);
|
||||||
@ -408,27 +404,6 @@ protected:
|
|||||||
}
|
}
|
||||||
SPDLOG_LOGGER_CATCH(loc)
|
SPDLOG_LOGGER_CATCH(loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// T can be statically converted to wstring_view, and no formatting needed.
|
|
||||||
template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::wstring_view_t>::value, int>::type = 0>
|
|
||||||
void log_(source_loc loc, level::level_enum lvl, const T &msg)
|
|
||||||
{
|
|
||||||
bool log_enabled = should_log(lvl);
|
|
||||||
bool traceback_enabled = tracer_.enabled();
|
|
||||||
if (!log_enabled && !traceback_enabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SPDLOG_TRY
|
|
||||||
{
|
|
||||||
memory_buf_t buf;
|
|
||||||
details::os::wstr_to_utf8buf(msg, buf);
|
|
||||||
details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()));
|
|
||||||
log_it_(log_msg, log_enabled, traceback_enabled);
|
|
||||||
}
|
|
||||||
SPDLOG_LOGGER_CATCH(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
|
||||||
|
|
||||||
// log the given message (if the given log level is high enough),
|
// log the given message (if the given log level is high enough),
|
||||||
|
@ -82,8 +82,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Uncomment to use C++20 std::format instead of fmt. This removes compile
|
// Uncomment to use C++20 std::format instead of fmt.
|
||||||
// time checking of format strings, but doesn't depend on the fmt library.
|
|
||||||
//
|
//
|
||||||
// #define SPDLOG_USE_STD_FORMAT
|
// #define SPDLOG_USE_STD_FORMAT
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
using spdlog::memory_buf_t;
|
using spdlog::memory_buf_t;
|
||||||
using spdlog::details::fmt_helper::to_string_view;
|
using spdlog::details::to_string_view;
|
||||||
|
|
||||||
void test_pad2(int n, const char *expected)
|
void test_pad2(int n, const char *expected)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "test_sink.h"
|
#include "test_sink.h"
|
||||||
|
|
||||||
using spdlog::memory_buf_t;
|
using spdlog::memory_buf_t;
|
||||||
using spdlog::details::fmt_helper::to_string_view;
|
using spdlog::details::to_string_view;
|
||||||
|
|
||||||
// log to str and return it
|
// log to str and return it
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
Loading…
Reference in New Issue
Block a user