# How spdlog Handles Unicode and Wide Character Support on Windows

> Discover how spdlog handles Unicode and wide character support on Windows. Learn about its compile-time features that convert std::wstring to UTF-8 for seamless logging.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: internals
- Published: 2026-07-17

---

**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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/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`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h) (lines 92–96):

```cpp
// 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`](https://github.com/gabime/spdlog/blob/main/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:

```bash
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:

```cpp
spdlog::info("Message with Unicode: {}", u8"αβγ");

```

### Logging Wide Strings on Windows

With `SPDLOG_WCHAR_SUPPORT` enabled, you can pass wide string literals directly:

```cpp
#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:

```cpp
#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::wstring` and UTF-8 using helper functions in [`include/spdlog/details/os.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/os.h), ensuring the formatting engine remains UTF-8-centric while supporting Windows Unicode requirements.
- File operations use `_wfopen_s` and `DeleteFileW` when wide-character filenames are enabled, while console sinks use `WriteConsoleW` for 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.