This is an appendix item for Unicode Input Terminal.
With gcc, the linker can can happily create an object file from arbitrary input files. This is useful for embedding images, fonts, etc into firmware. Full CMake code at the end, but the important parts are:
# Create object file
arm-none-eabi-ld --relocatable --format binary --output logo.o unicode-logo.png
If you run nm logo.o
, you can see the symbols that are available:
00000445 D _binary_unicode_logo_png_end
00000445 A _binary_unicode_logo_png_size
00000000 D _binary_unicode_logo_png_start
These can be added to your build (gcc ... main.c logo.o
, etc), but some boilerplate
is needed to make them ergonomic. This code makes the symbols accessible as pointers:
Header: embeds.hh
#pragma once
namespace assets {
extern const uint8_t* unicode_logo_png;
extern const uint8_t* unicode_logo_png_end;
}
Source: embeds.cpp
#include "embeds.hh"
// Note these aren't pointers: they're fixed size arrays with an address defined by the linker
extern "C" {
extern const uint8_t _binary_assets_unicode_logo_png_start[];
extern const uint8_t _binary_assets_unicode_logo_png_end[];
}
// Pointers that to the memory above (whereever it ends up at link time)
namespace assets {
const uint8_t* unicode_logo_png = _binary_assets_unicode_logo_png_start;
const uint8_t* unicode_logo_png_end = _binary_assets_unicode_logo_png_end;
}
#
# Support embedding resources in the binary (GCC-specific)
# Based on https://stackoverflow.com/a/56006001/1470907
#
set(RC_DEPENDS "")
function(add_resource target input)
string(MAKE_C_IDENTIFIER ${input} input_identifier)
set(output "${CMAKE_CURRENT_BINARY_DIR}/${input_identifier}.o")
target_link_libraries(${target} ${output})
add_custom_command(
OUTPUT ${output}
COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} --relocatable --format binary --output ${output}
${input}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${input}
)
set(RC_DEPENDS ${RC_DEPENDS} ${output} PARENT_SCOPE)
endfunction()
Using this looks like:
add_resource(my_firmware "assets/unicode-logo.png")