microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
include
microfmt
detail
compat.hpp
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2
//
3
// SPDX-License-Identifier: BSD-2-Clause
4
5
#pragma once
6
16
#include "../microfmt_config.hpp"
17
18
#include <reloco/detail/compat.hpp>
19
20
#if RELOCO_CXX20 && RELOCO_HAS_INCLUDE(<source_location>)
21
#include <source_location>
22
#endif
23
24
#if RELOCO_CXX20 && defined(__cpp_lib_source_location) && (__cpp_lib_source_location >= 201907L)
25
#define MICROFMT_HAS_STD_SOURCE_LOCATION 1
26
#else
27
#define MICROFMT_HAS_STD_SOURCE_LOCATION 0
28
#endif
29
30
#if RELOCO_CXX23 && RELOCO_HAS_INCLUDE(<expected>)
31
#include <expected>
32
#endif
33
34
#if RELOCO_CXX23 && defined(__cpp_lib_expected) && (__cpp_lib_expected >= 202202L)
35
#define MICROFMT_HAS_STD_EXPECTED 1
36
#else
37
#define MICROFMT_HAS_STD_EXPECTED 0
38
#endif
39
40
#if defined(MICROFMT_ENABLE_BOOST_SOURCE_LOCATION)
41
// clang-format off
42
#if RELOCO_HAS_INCLUDE(<boost/assert/source_location.hpp>)
43
#include <boost/assert/source_location.hpp>
44
// clang-format on
45
#define MICROFMT_HAS_BOOST_SOURCE_LOCATION 1
46
#else
47
#error "MICROFMT_ENABLE_BOOST_SOURCE_LOCATION requires <boost/assert/source_location.hpp>"
48
#endif
49
#else
50
#define MICROFMT_HAS_BOOST_SOURCE_LOCATION 0
51
#endif
52
53
#if MICROFMT_HAS_STD_SOURCE_LOCATION || MICROFMT_HAS_BOOST_SOURCE_LOCATION
54
#define MICROFMT_HAS_SOURCE_LOCATION 1
55
#else
56
#define MICROFMT_HAS_SOURCE_LOCATION 0
57
#endif
58
59
#if defined(MICROFMT_ENABLE_BOOST_UUID) || defined(BOOST_UUID_UUID_HPP) || defined(BOOST_UUID_HPP)
60
#if !defined(BOOST_UUID_UUID_HPP) && !defined(BOOST_UUID_HPP)
61
// clang-format off
62
#if RELOCO_HAS_INCLUDE(<boost/uuid/uuid.hpp>)
63
#include <boost/uuid/uuid.hpp>
64
// clang-format on
65
#else
66
#error "MICROFMT_ENABLE_BOOST_UUID requires <boost/uuid/uuid.hpp>"
67
#endif
68
#endif
69
#define MICROFMT_HAS_BOOST_UUID 1
70
#else
71
#define MICROFMT_HAS_BOOST_UUID 0
72
#endif
73
74
#if defined(__unix__) || defined(__APPLE__) || defined(__posix)
75
#define MICROFMT_HAS_POSIX_FD 1
76
#else
77
#define MICROFMT_HAS_POSIX_FD 0
78
#endif
79
80
#if defined(__ANDROID__)
81
#define MICROFMT_HAS_ANDROID_LOG 1
82
#else
83
#define MICROFMT_HAS_ANDROID_LOG 0
84
#endif
85
86
// ============================================================================
87
// Shared-library build/consume support (MICROFMT_SHARED)
88
// ============================================================================
89
//
90
// microfmt is header-only by default: even the "heavy", non-templated
91
// definitions factored out into a `*.ipp` file (see e.g. `microfmt.ipp`,
92
// included from `microfmt.hpp`) are plain `inline` and live directly in the
93
// header, so -- like every other microfmt entity -- each independently
94
// compiled translation unit gets its own copy of them, and the linker only
95
// merges duplicate copies within a single link step, never across separate
96
// shared-object boundaries. For an application built as one executable
97
// plus several plugin `.so`'s that each `#include` microfmt, this means
98
// every plugin pays for its own copy of the same handful of routines (see
99
// `tools/codesize/testbed/README.md` for measured numbers).
100
//
101
// Define MICROFMT_SHARED (to any value, before including any microfmt
102
// header, e.g. via `detail/porting/microfmt_user_config.hpp` or a
103
// compiler `-D` flag applied consistently to every translation unit in the
104
// program) to switch every `*.ipp`-hosted definition to a plain
105
// declaration instead: ordinary consumers then link against one shared
106
// definition rather than each instantiating their own copy.
107
//
108
// Exactly one translation unit in the whole program -- the one building
109
// the actual shared library that is meant to host these definitions --
110
// must additionally define MICROFMT_SHARED_BUILD (to any value) before
111
// including any microfmt header. That TU alone re-imports the `*.ipp`
112
// bodies as exported, out-of-line definitions; every other TU (which
113
// defines MICROFMT_SHARED but not MICROFMT_SHARED_BUILD) only sees
114
// declarations and must be linked against that library.
115
//
116
// `MICROFMT_API` decorates every entity affected by this split:
117
// - MICROFMT_SHARED not defined (default):
118
// `MICROFMT_API` -> `inline`; current, unchanged header-only behavior.
119
// - MICROFMT_SHARED defined, MICROFMT_SHARED_BUILD not defined (consume):
120
// `MICROFMT_API` -> plain declaration, no body
121
// (+ `__declspec(dllimport)` on MSVC).
122
// - MICROFMT_SHARED and MICROFMT_SHARED_BUILD both defined (build):
123
// `MICROFMT_API` -> exported, out-of-line definition
124
// (`__declspec(dllexport)` on MSVC, default visibility elsewhere).
125
//
126
// `MICROFMT_SHARED_PROVIDE_DEFINITIONS` is 1 exactly when the current TU
127
// should pull in `*.ipp` bodies at all (default header-only mode, or the
128
// MICROFMT_SHARED_BUILD library-build TU) and 0 when it should only see
129
// declarations (ordinary MICROFMT_SHARED consumer).
130
//
131
// This is opt-in and off by default: a plain header-only build (the
132
// overwhelming common case, and every existing consumer) is entirely
133
// unaffected.
134
#if !defined(MICROFMT_SHARED)
135
#define MICROFMT_API inline
136
#define MICROFMT_SHARED_PROVIDE_DEFINITIONS 1
137
#elif defined(MICROFMT_SHARED_BUILD)
138
#if defined(_MSC_VER)
139
#define MICROFMT_API __declspec(dllexport)
140
#elif RELOCO_HAS_ATTRIBUTE(visibility)
141
#define MICROFMT_API __attribute__((visibility("default")))
142
#else
143
#define MICROFMT_API
144
#endif
145
#define MICROFMT_SHARED_PROVIDE_DEFINITIONS 1
146
#else
147
#if defined(_MSC_VER)
148
#define MICROFMT_API __declspec(dllimport)
149
#else
150
#define MICROFMT_API
151
#endif
152
#define MICROFMT_SHARED_PROVIDE_DEFINITIONS 0
153
#endif
154
155
// MICROFMT_API_CONSTEXPR is MICROFMT_API for an entity that is `constexpr`
156
// in the default header-only build (where MICROFMT_API is plain `inline`,
157
// so adding `constexpr` costs nothing and preserves compile-time
158
// callability exactly as before) but must drop `constexpr` under
159
// MICROFMT_SHARED: a `constexpr` function is implicitly `inline`, which
160
// would force every MICROFMT_SHARED_BUILD-declared-only consumer to still
161
// carry a definition, defeating the whole build/consume split.
162
#if !defined(MICROFMT_SHARED)
163
#define MICROFMT_API_CONSTEXPR constexpr MICROFMT_API
164
#else
165
#define MICROFMT_API_CONSTEXPR MICROFMT_API
166
#endif
167
168
// MICROFMT_API_CLASS decorates a whole class/struct (as opposed to
169
// MICROFMT_API, which decorates individual members/free functions) so its
170
// vtable and any members implicitly emitted per-TU (typeinfo, defaulted
171
// special members, ...) are deduplicated across a MICROFMT_SHARED_BUILD
172
// library's shared-object boundary, exactly like MICROFMT_API does for
173
// out-of-line function definitions.
174
//
175
// A plain `class`/`struct` head cannot be decorated `inline` (unlike a
176
// function or variable), so MICROFMT_API_CLASS -- unlike MICROFMT_API --
177
// expands to nothing in the default header-only build: there is no
178
// separate shared object to deduplicate against, and every member stays
179
// implicitly inline the same way it already does today.
180
#if !defined(MICROFMT_SHARED)
181
#define MICROFMT_API_CLASS
182
#elif defined(MICROFMT_SHARED_BUILD)
183
#if defined(_MSC_VER)
184
#define MICROFMT_API_CLASS __declspec(dllexport)
185
#elif RELOCO_HAS_ATTRIBUTE(visibility)
186
#define MICROFMT_API_CLASS __attribute__((visibility("default")))
187
#else
188
#define MICROFMT_API_CLASS
189
#endif
190
#else
191
#if defined(_MSC_VER)
192
#define MICROFMT_API_CLASS __declspec(dllimport)
193
#else
194
#define MICROFMT_API_CLASS
195
#endif
196
#endif
197
198
// dlog availability cannot be reliably inferred from a compiler-predefined
199
// macro (unlike MICROFMT_HAS_ANDROID_LOG's __ANDROID__ check); headers
200
// assume the real Tizen SDK is available unless the includer opts out via
201
// MICROFMT_COMPILE_WITHOUT_TIZEN_DLOG (see CMakeLists.txt).
202
#if defined(MICROFMT_COMPILE_WITHOUT_TIZEN_DLOG)
203
#define MICROFMT_HAS_DLOG 0
204
#else
205
#define MICROFMT_HAS_DLOG 1
206
#endif
Generated by
1.9.8