# How to Enable FMT_OS for Platform-Specific APIs and File I/O in {fmt}

> Unlock platform-specific APIs and file I/O in fmtlib by enabling FMT_OS. Learn how to set the CMake option or define the FMT_OS macro for RAII file wrappers and system error utilities.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-04

---

**Enable FMT_OS by setting the CMake option `-DFMT_OS=ON` (enabled by default) or defining the `FMT_OS` macro to `1` before including [`fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/fmt/os.h) to access RAII file wrappers and system error utilities.**

The {fmt} library provides optional operating system helpers—file I/O abstractions, formatted `system_error` exceptions, and portable system call wrappers—controlled by the **FMT_OS** feature flag. Enabling this feature compiles platform-specific code paths in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h) and links implementations from `src/os.cc`, giving you safe file handling and error reporting across POSIX and Windows systems.

## Configuring FMT_OS with CMake

The build system controls FMT_OS through a top-level CMake option.

### Default Configuration

According to the source in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (line 86), the option is declared as:

```cmake
option(FMT_OS "Include OS-specific APIs." ON)

```

By default, **FMT_OS is enabled**, meaning OS-specific APIs are compiled into the library. When you build {fmt} without customization, you automatically receive `fmt::buffered_file`, `fmt::system_error`, and related utilities.

### Explicit Enable or Disable

To explicitly enable the feature (or re-enable after a previous disable), pass the definition to CMake:

```bash
cmake -DFMT_OS=ON ..

# or

cmake -DFMT_OS=1 ..

```

To disable the OS layer entirely—for header-only deployments or embedded systems where file I/O is unavailable—use:

```bash
cmake -DFMT_OS=OFF ..

```

Disabling FMT_OS excludes `src/os.cc` from compilation and hides all OS-specific declarations from [`fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/fmt/os.h), producing a smaller binary footprint.

## Understanding the FMT_OS Macro

Beyond CMake, the feature is guarded by a C++ preprocessor macro that controls conditional compilation.

### Macro Definition

In `src/fmt.cc` (line 127), the library defines the default state:

```cpp
#ifndef FMT_OS

#  define FMT_OS 1

#endif

```

If you consume {fmt} as a header-only library without the CMake build system, define this macro yourself before including headers:

```cpp
#define FMT_OS 1
#include <fmt/os.h>

```

### Conditional Compilation

The header [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h) wraps platform-specific declarations with preprocessor guards:

```cpp
#if FMT_OS
// OS-specific declarations are compiled
#endif

```

When `FMT_OS` evaluates to a non-zero value, symbols like `fmt::buffered_file`, `fmt::file`, and `fmt::system_error` are available. When defined as `0` or undefined, these classes are omitted, but the header still includes successfully due to guard macros.

## Platform-Specific APIs Available

Enabling FMT_OS unlocks three major categories of functionality implemented in [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h).

### File I/O Wrappers

The library provides RAII-style file management classes:

- **`fmt::buffered_file`** (lines 64-100): Wraps `std::FILE*` with automatic close, EINTR retry logic, and platform-specific path handling
- **`fmt::file`**: Low-level file descriptor wrapper with portable open/close semantics

These classes ensure resources are released automatically and integrate with `fmt::print` for direct formatting to file streams.

### Error Handling Utilities

FMT_OS enables formatted exception types for system errors:

- **`fmt::system_error`** (lines 115-158): Exception class that formats `errno` or system error codes with custom messages
- **`fmt::windows_error`**: Windows-specific variant for `GetLastError()` codes
- **`fmt::report_system_error`**: Non-throwing error reporting function

The header also provides helper macros: **`FMT_POSIX(call)`**, **`FMT_SYSTEM(call)`**, and **`FMT_RETRY`**, which wrap system calls for testability and automatic retry on interrupt.

## Practical Usage Examples

The following examples compile only when FMT_OS is enabled.

### Writing to Buffered Files

Use `fmt::buffered_file` for automatic resource management and direct formatting:

```cpp
#include <fmt/os.h>
#include <fmt/format.h>
#include <chrono>

int main() {
    // Opens "log.txt" in append mode; destructor closes automatically
    fmt::buffered_file f("log.txt", "a");
    
    fmt::print(f, "Timestamp: {}\n", 
               fmt::format("{}", std::chrono::system_clock::now()));
    // Explicit flush optional; destructor handles cleanup
}

```

### Throwing System Errors

Report file system failures with formatted error messages:

```cpp
#include <fmt/os.h>
#include <cerrno>
#include <cstdio>

void open_or_fail(const char* name) {
    std::FILE* f = std::fopen(name, "r");
    if (!f) {
        // Throws exception combining errno and formatted message
        throw fmt::system_error(errno, "cannot open file '{}'", name);
    }
    std::fclose(f);
}

```

### Windows-Specific Error Reporting

For Windows applications, report errors without throwing exceptions:

```cpp
#ifdef _WIN32
#include <fmt/os.h>
#include <windows.h>

void create_process_or_report() {
    // ... process creation logic ...
    DWORD err = GetLastError();
    if (err != ERROR_SUCCESS) {
        fmt::report_windows_error(err, "failed to create process");
    }
}
#endif

```

## Verifying the Build

After configuring with `-DFMT_OS=ON`, compile the library and verify symbol availability:

1. Build the project with `cmake --build .` (or `make`, `ninja`)
2. Confirm `fmt::buffered_file` appears in the static/shared library using `nm` (Linux) or `dumpbin` (Windows)
3. Run the unit tests in `test/module-test.cc` and `test/os.cc` to validate file I/O and error handling on your target platform

If FMT_OS is disabled, these test files will either skip OS-specific tests or fail to compile the relevant sections.

## Summary

- **FMT_OS is a CMake option** defined in [`CMakeLists.txt`](https://github.com/fmtlib/fmt/blob/main/CMakeLists.txt) (line 86) that defaults to `ON`, enabling OS-specific APIs by default
- **The FMT_OS macro** controls conditional compilation in `src/fmt.cc` and [`include/fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/os.h); define it to `1` manually for header-only usage
- **Enabling FMT_OS provides** `fmt::buffered_file`, `fmt::file`, `fmt::system_error`, and platform-specific error reporting macros
- **Disabling FMT_OS** removes file I/O dependencies, useful for embedded or restricted environments
- **Verification** requires checking that `src/os.cc` is compiled and symbols appear in the library binary

## Frequently Asked Questions

### What happens if I include `<fmt/os.h>` with FMT_OS disabled?

The header includes guards that check `#if FMT_OS`, so the include succeeds but all OS-specific classes and functions are omitted. Any code attempting to use `fmt::buffered_file` or `fmt::system_error` will fail to compile with "identifier not found" errors.

### Can I use FMT_OS features in a header-only configuration?

Yes, but you must manually define `FMT_OS 1` before including [`fmt/os.h`](https://github.com/fmtlib/fmt/blob/main/fmt/os.h), and ensure that `src/os.cc` (or its contents) is compiled into your project. The CMake option is the recommended path, but manual definition works for custom build systems.

### Does FMT_OS affect the size of the compiled binary?

Yes. Disabling FMT_OS with `-DFMT_OS=OFF` excludes `src/os.cc` and associated platform-specific code from the library, reducing binary size. This is beneficial for embedded targets or WebAssembly builds where file system access is unavailable or restricted.

### Is FMT_OS required for basic string formatting in {fmt}?

No. Core formatting functionality in `<fmt/format.h>` operates independently of FMT_OS. You only need to enable FMT_OS when your application requires **file I/O helpers** (`fmt::buffered_file`), **system error formatting** (`fmt::system_error`), or **portable system call wrappers** (`FMT_POSIX`, `FMT_RETRY`).