How spdlog Handles Unicode and Wide Character Support on Windows
spdlog implements Unicode and wide character support on Windows through optional compile-time features that internally convert std::wstring to UTF-8 while exposing wide-string APIs for filenames, messages, and console output.
The gabime/spdlog library uses UTF-8 narrow strings as its internal encoding standard across all platforms, including Windows. When applications need to interface with Windows-specific Unicode APIs or handle wide-character file paths, spdlog provides targeted CMake options to enable spdlog Unicode and wide character support on Windows without sacrificing its high-performance, header-only architecture.
Compile-Time Configuration Options
On Windows, spdlog offers three independent CMake options to enable wide-character functionality. These are defined in CMakeLists.txt (lines 118–124) and default to OFF to maintain POSIX compatibility.
Wide-Character API (SPDLOG_WCHAR_SUPPORT)
When you enable -DSPDLOG_WCHAR_SUPPORT=ON, spdlog exposes logger overloads that accept std::wstring and std::wstring_view. The public API in include/spdlog/spdlog.h (lines 201–215) contains conditional blocks that add these overloads, which immediately convert wide strings to UTF-8 before passing them to the fmt formatting engine.
Wide-Character Filenames (SPDLOG_WCHAR_FILENAMES)
Enabling -DSPDLOG_WCHAR_FILENAMES=ON forces all file-related operations to use the Windows wide-API. In include/spdlog/sinks/daily_file_sink.h (lines 51–55), you'll find guards that route calls like fopen_s to _wfopen_s, remove to DeleteFileW, and rename to the corresponding wide variants. This allows log files to be created with Unicode names such as L"日志文件.txt".
Wide-Character Console Output (SPDLOG_WCHAR_CONSOLE)
The -DSPDLOG_WCHAR_CONSOLE=ON option modifies console sinks to use WriteConsoleW instead of standard printf or WriteFile. The implementation in include/spdlog/sinks/msvc_sink.h (lines 9–45) detects when the terminal is attached and preserves Unicode characters by writing directly through the Windows console API.
Internal Conversion Mechanisms
When any wide-character feature is enabled, spdlog declares two conversion helpers in include/spdlog/details/os.h (lines 92–96):
// convert wide → UTF‑8
SPDLOG_API void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
// convert UTF‑8 → wide
SPDLOG_API void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target);
These functions are implemented in os-inl.h and are used throughout the library to maintain the UTF-8-centric formatting pipeline. When SPDLOG_WCHAR_TO_UTF8_SUPPORT or SPDLOG_WCHAR_FILENAMES is defined and _WIN32 is detected, the library converts wide inputs to UTF-8 buffers before processing, then converts back to wide only when interacting with Windows APIs.
Enabling Unicode Support in Your Build
To activate spdlog Unicode and wide character support on Windows, configure your CMake build with the following options:
cmake -DSPDLOG_WCHAR_SUPPORT=ON \
-DSPDLOG_WCHAR_FILENAMES=ON \
-DSPDLOG_WCHAR_CONSOLE=ON \
..
These flags propagate to the source as SPDLOG_WCHAR_TO_UTF8_SUPPORT and SPDLOG_UTF8_TO_WCHAR_CONSOLE, enabling the conditional compilation blocks that wrap Windows-specific Unicode APIs.
Practical Usage Examples
Logging UTF-8 Strings (Default Behavior)
Without any special flags, spdlog expects UTF-8 narrow strings and behaves identically to POSIX platforms:
spdlog::info("Message with Unicode: {}", u8"αβγ");
Logging Wide Strings on Windows
With SPDLOG_WCHAR_SUPPORT enabled, you can pass wide string literals directly:
#include <spdlog/spdlog.h>
#include <spdlog/logger.h>
int main()
{
auto logger = spdlog::stdout_color_mt("console");
// Wide-character overload enabled via SPDLOG_WCHAR_SUPPORT
logger->info(L"Unicode example: {}", L"例子");
// Wide-character file name requires SPDLOG_WCHAR_FILENAMES
auto file_logger = spdlog::basic_logger_mt("file", L"日志文件.txt");
file_logger->info(L"写入文件的消息");
}
Using Windows Console Sinks
For direct console output via the Windows API, use the MSVC sink with SPDLOG_WCHAR_CONSOLE enabled:
#include <spdlog/sinks/msvc_sink.h>
int main()
{
auto win_console = std::make_shared<spdlog::sinks::msvc_sink_mt>();
auto logger = std::make_shared<spdlog::logger>("wc", win_console);
spdlog::register_logger(logger);
logger->info(L"直接写入 Windows 控制台:ΩλΨ");
}
Summary
- By default, spdlog on Windows operates with UTF-8 narrow strings using standard CRT file APIs, matching POSIX behavior.
- Compile-time flags (
SPDLOG_WCHAR_SUPPORT,SPDLOG_WCHAR_FILENAMES,SPDLOG_WCHAR_CONSOLE) enable wide-character APIs, Unicode file paths, and Windows console output respectively. - The library converts between
std::wstringand UTF-8 using helper functions ininclude/spdlog/details/os.h, ensuring the formatting engine remains UTF-8-centric while supporting Windows Unicode requirements. - File operations use
_wfopen_sandDeleteFileWwhen wide-character filenames are enabled, while console sinks useWriteConsoleWfor proper Unicode display.
Frequently Asked Questions
Does spdlog support std::wstring on Windows by default?
No, wide-string support is not enabled by default. You must compile spdlog with -DSPDLOG_WCHAR_SUPPORT=ON to expose logger overloads that accept std::wstring. Without this flag, the library accepts only UTF-8 narrow strings on all platforms.
How do I create log files with Unicode characters in the filename?
Enable -DSPDLOG_WCHAR_FILENAMES=ON during CMake configuration. This activates SPDLOG_WCHAR_FILENAMES in the source code, which routes file operations through Windows wide-APIs like _wfopen_s, allowing you to pass std::wstring paths to sinks like basic_logger_mt.
What is the difference between SPDLOG_WCHAR_SUPPORT and SPDLOG_WCHAR_CONSOLE?
SPDLOG_WCHAR_SUPPORT adds wide-string overloads to the logger API (converting input to UTF-8 for formatting), while SPDLOG_WCHAR_CONSOLE specifically affects output sinks. The latter ensures that console sinks use WriteConsoleW to preserve Unicode characters in the terminal, whereas the former handles input message encoding.
Does enabling wide character support impact logging performance?
There is a minimal performance overhead because spdlog converts wide strings to UTF-8 using wstr_to_utf8buf before formatting. However, the conversion happens only at the API boundary, and the high-performance fmt formatting engine still operates on UTF-8 data. The impact is negligible for most applications but measurable in extreme high-throughput scenarios.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →