4 * @brief Utility for including binary files
6 * Facilities for including binary files into the current translation unit and
7 * making use from them externally in other translation units.
12 #if defined(__AVX512BW__) || \
13 defined(__AVX512CD__) || \
14 defined(__AVX512DQ__) || \
15 defined(__AVX512ER__) || \
16 defined(__AVX512PF__) || \
17 defined(__AVX512VL__) || \
19 # define INCBIN_ALIGNMENT_INDEX 6
20 #elif defined(__AVX__) || \
22 # define INCBIN_ALIGNMENT_INDEX 5
23 #elif defined(__SSE__) || \
24 defined(__SSE2__) || \
25 defined(__SSE3__) || \
26 defined(__SSSE3__) || \
27 defined(__SSE4_1__) || \
28 defined(__SSE4_2__) || \
30 # define INCBIN_ALIGNMENT_INDEX 4
31 #elif ULONG_MAX != 0xffffffffu
32 # define INCBIN_ALIGNMENT_INDEX 3
34 # define INCBIN_ALIGNMENT_INDEX 2
37 /* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
38 #define INCBIN_ALIGN_SHIFT_0 1
39 #define INCBIN_ALIGN_SHIFT_1 2
40 #define INCBIN_ALIGN_SHIFT_2 4
41 #define INCBIN_ALIGN_SHIFT_3 8
42 #define INCBIN_ALIGN_SHIFT_4 16
43 #define INCBIN_ALIGN_SHIFT_5 32
44 #define INCBIN_ALIGN_SHIFT_6 64
46 /* Actual alignment value */
47 #define INCBIN_ALIGNMENT \
49 INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
50 INCBIN_ALIGNMENT_INDEX)
53 #define INCBIN_STR(X) \
55 #define INCBIN_STRINGIZE(X) \
58 #define INCBIN_CAT(X, Y) \
60 #define INCBIN_CONCATENATE(X, Y) \
62 /* Deferred macro expansion */
63 #define INCBIN_EVAL(X) \
65 #define INCBIN_INVOKE(N, ...) \
66 INCBIN_EVAL(N(__VA_ARGS__))
68 /* Green Hills uses a different directive for including binary data */
71 # define INCBIN_MACRO ".file"
72 /* Or consider the ".myrawdata" entry in the ld file */
74 # define INCBIN_MACRO "\tINCBIN"
77 # define INCBIN_MACRO ".incbin"
81 # define INCBIN_ALIGN \
82 __attribute__((aligned(INCBIN_ALIGNMENT)))
84 # define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
87 #if defined(__arm__) || /* GNU C and RealView */ \
88 defined(__arm) || /* Diab */ \
89 defined(_ARM) /* ImageCraft */
94 /* Utilize .balign where supported */
95 # define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
96 # define INCBIN_ALIGN_BYTE ".balign 1\n"
97 #elif defined(INCBIN_ARM)
99 * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
100 * the shift count. This is the value passed to `.align'
102 # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
103 # define INCBIN_ALIGN_BYTE ".align 0\n"
105 /* We assume other inline assembler's treat `.align' as `.balign' */
106 # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
107 # define INCBIN_ALIGN_BYTE ".align 1\n"
110 /* INCBIN_CONST is used by incbin.c generated files */
111 #if defined(__cplusplus)
112 # define INCBIN_EXTERNAL extern "C"
113 # define INCBIN_CONST extern const
115 # define INCBIN_EXTERNAL extern
116 # define INCBIN_CONST const
120 * @brief Optionally override the linker section into which data is emitted.
122 * @warning If you use this facility, you'll have to deal with platform-specific linker output
123 * section naming on your own
125 * Overriding the default linker output section, e.g for esp8266/Arduino:
127 * #define INCBIN_OUTPUT_SECTION ".irom.text"
128 * #include "incbin.h"
129 * INCBIN(Foo, "foo.txt");
130 * // Data is emitted into program memory that never gets copied to RAM
133 #if !defined(INCBIN_OUTPUT_SECTION)
134 # if defined(__APPLE__)
135 # define INCBIN_OUTPUT_SECTION ".const_data"
137 # define INCBIN_OUTPUT_SECTION ".rodata"
141 #if defined(__APPLE__)
142 /* The directives are different for Apple branded compilers */
143 # define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
144 # define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
145 # define INCBIN_INT ".long "
146 # define INCBIN_MANGLE "_"
147 # define INCBIN_BYTE ".byte "
148 # define INCBIN_TYPE(...)
150 # define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
151 # define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
152 # if defined(__ghs__)
153 # define INCBIN_INT ".word "
155 # define INCBIN_INT ".int "
157 # if defined(__USER_LABEL_PREFIX__)
158 # define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
160 # define INCBIN_MANGLE ""
162 # if defined(INCBIN_ARM)
163 /* On arm assemblers, `@' is used as a line comment token */
164 # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
165 # elif defined(__MINGW32__) || defined(__MINGW64__)
166 /* Mingw doesn't support this directive either */
167 # define INCBIN_TYPE(NAME)
169 /* It's safe to use `@' on other architectures */
170 # define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
172 # define INCBIN_BYTE ".byte "
175 /* List of style types used for symbol names */
176 #define INCBIN_STYLE_CAMEL 0
177 #define INCBIN_STYLE_SNAKE 1
180 * @brief Specify the prefix to use for symbol names.
182 * By default this is `g', producing symbols of the form:
184 * #include "incbin.h"
185 * INCBIN(Foo, "foo.txt");
187 * // Now you have the following symbols:
188 * // const unsigned char gFooData[];
189 * // const unsigned char *const gFooEnd;
190 * // const unsigned int gFooSize;
193 * If however you specify a prefix before including: e.g:
195 * #define INCBIN_PREFIX incbin
196 * #include "incbin.h"
197 * INCBIN(Foo, "foo.txt");
199 * // Now you have the following symbols instead:
200 * // const unsigned char incbinFooData[];
201 * // const unsigned char *const incbinFooEnd;
202 * // const unsigned int incbinFooSize;
205 #if !defined(INCBIN_PREFIX)
206 # define INCBIN_PREFIX g
210 * @brief Specify the style used for symbol names.
212 * Possible options are
213 * - INCBIN_STYLE_CAMEL "CamelCase"
214 * - INCBIN_STYLE_SNAKE "snake_case"
216 * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
218 * #include "incbin.h"
219 * INCBIN(Foo, "foo.txt");
221 * // Now you have the following symbols:
222 * // const unsigned char <prefix>FooData[];
223 * // const unsigned char *const <prefix>FooEnd;
224 * // const unsigned int <prefix>FooSize;
227 * If however you specify a style before including: e.g:
229 * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
230 * #include "incbin.h"
231 * INCBIN(foo, "foo.txt");
233 * // Now you have the following symbols:
234 * // const unsigned char <prefix>foo_data[];
235 * // const unsigned char *const <prefix>foo_end;
236 * // const unsigned int <prefix>foo_size;
239 #if !defined(INCBIN_STYLE)
240 # define INCBIN_STYLE INCBIN_STYLE_CAMEL
243 /* Style lookup tables */
244 #define INCBIN_STYLE_0_DATA Data
245 #define INCBIN_STYLE_0_END End
246 #define INCBIN_STYLE_0_SIZE Size
247 #define INCBIN_STYLE_1_DATA _data
248 #define INCBIN_STYLE_1_END _end
249 #define INCBIN_STYLE_1_SIZE _size
251 /* Style lookup: returning identifier */
252 #define INCBIN_STYLE_IDENT(TYPE) \
253 INCBIN_CONCATENATE( \
255 INCBIN_CONCATENATE( \
256 INCBIN_EVAL(INCBIN_STYLE), \
257 INCBIN_CONCATENATE(_, TYPE)))
259 /* Style lookup: returning string literal */
260 #define INCBIN_STYLE_STRING(TYPE) \
262 INCBIN_STYLE_IDENT(TYPE)) \
264 /* Generate the global labels by indirectly invoking the macro with our style
265 * type and concatenating the name against them. */
266 #define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
269 INCBIN_CONCATENATE( \
272 INCBIN_STYLE_IDENT, \
276 INCBIN_CONCATENATE( \
279 INCBIN_STYLE_IDENT, \
283 * @brief Externally reference binary data included in another translation unit.
285 * Produces three external symbols that reference the binary data included in
286 * another translation unit.
288 * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
289 * "Data", as well as "End" and "Size" after. An example is provided below.
291 * @param NAME The name given for the binary data
294 * INCBIN_EXTERN(Foo);
296 * // Now you have the following symbols:
297 * // extern const unsigned char <prefix>FooData[];
298 * // extern const unsigned char *const <prefix>FooEnd;
299 * // extern const unsigned int <prefix>FooSize;
302 #define INCBIN_EXTERN(NAME) \
303 INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
304 INCBIN_CONCATENATE( \
305 INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
306 INCBIN_STYLE_IDENT(DATA))[]; \
307 INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
308 INCBIN_CONCATENATE( \
309 INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
310 INCBIN_STYLE_IDENT(END)); \
311 INCBIN_EXTERNAL const unsigned int \
312 INCBIN_CONCATENATE( \
313 INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
314 INCBIN_STYLE_IDENT(SIZE))
317 * @brief Include a binary file into the current translation unit.
319 * Includes a binary file into the current translation unit, producing three symbols
320 * for objects that encode the data and size respectively.
322 * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
323 * "Data", as well as "End" and "Size" after. An example is provided below.
325 * @param NAME The name to associate with this binary data (as an identifier.)
326 * @param FILENAME The file to include (as a string literal.)
329 * INCBIN(Icon, "icon.png");
331 * // Now you have the following symbols:
332 * // const unsigned char <prefix>IconData[];
333 * // const unsigned char *const <prefix>IconEnd;
334 * // const unsigned int <prefix>IconSize;
337 * @warning This must be used in global scope
338 * @warning The identifiers may be different if INCBIN_STYLE is not default
340 * To externally reference the data included by this in another translation unit
341 * please @see INCBIN_EXTERN.
344 #define INCBIN(NAME, FILENAME) \
347 #define INCBIN(NAME, FILENAME) \
348 __asm__(INCBIN_SECTION \
349 INCBIN_GLOBAL_LABELS(NAME, DATA) \
351 INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
352 INCBIN_MACRO " \"" FILENAME "\"\n" \
353 INCBIN_GLOBAL_LABELS(NAME, END) \
355 INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
357 INCBIN_GLOBAL_LABELS(NAME, SIZE) \
359 INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
360 INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
361 INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \