How to Enable FMT_OS for Platform-Specific APIs and File I/O in {fmt}
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 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 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 (line 86), the option is declared as:
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:
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:
cmake -DFMT_OS=OFF ..
Disabling FMT_OS excludes src/os.cc from compilation and hides all OS-specific declarations from 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:
#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:
#define FMT_OS 1
#include <fmt/os.h>
Conditional Compilation
The header include/fmt/os.h wraps platform-specific declarations with preprocessor guards:
#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.
File I/O Wrappers
The library provides RAII-style file management classes:
fmt::buffered_file(lines 64-100): Wrapsstd::FILE*with automatic close, EINTR retry logic, and platform-specific path handlingfmt::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 formatserrnoor system error codes with custom messagesfmt::windows_error: Windows-specific variant forGetLastError()codesfmt::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:
#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:
#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:
#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:
- Build the project with
cmake --build .(ormake,ninja) - Confirm
fmt::buffered_fileappears in the static/shared library usingnm(Linux) ordumpbin(Windows) - Run the unit tests in
test/module-test.ccandtest/os.ccto 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(line 86) that defaults toON, enabling OS-specific APIs by default - The FMT_OS macro controls conditional compilation in
src/fmt.ccandinclude/fmt/os.h; define it to1manually 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.ccis 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, 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).
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 →