Skip to content

Latest commit

 

History

History
77 lines (63 loc) · 4.3 KB

File metadata and controls

77 lines (63 loc) · 4.3 KB

tools-embed

mcpp.tools.embed reads a file while the build program runs and writes a header that carries it as an array, through four entry points; the declarations a consumer names are generated by mcpp::plugins::surface.

tools-embed

Module mcpp.tools.embed; engine floor: 2026.9.5.4.

Needs and behaviour. nothing beyond mcpp: it reads a file and writes a header while the build program runs. The floor is the release whose fast path compares a declared file input, without which an edit to the data does not reach the binary

tools-embed's four entry points

entry point inputs outputs shape
file() one one header one array, one _size, included by name
files() N N headers one file() call per input; options::identifier is refused, because it names one symbol and there are several
group() N N headers + one generated interface the same N headers, handed to mcpp::plugins::surface so a consumer writes one import and names no generated file -- see What a consumer names
table() N one header one array of rows, each carrying its input's key beside its bytes; the consumer iterates or looks a row up by key

table() is for a set the consumer wants to walk rather than name member by member, where files()'s one accessor per input and group()'s one function per input are both the wrong shape. The motivating case is a shader set:

mcpp::tools::embed::table_options opt;
opt.name_space = "myapp";
opt.identifier = "shaders";
opt.row_type   = "shader_entry";
mcpp::tools::embed::table({ "shaders/Standard.vert", "shaders/Standard.frag" }, opt);

which produces, in one header, a struct and an array of it:

struct shader_entry { const char* key; const unsigned char* data; std::size_t size; };
inline constexpr shader_entry shaders[] = {
    { "Standard.vert", /* ... */, /* ... */ },
    { "Standard.frag", /* ... */, /* ... */ },
};

The row struct is generated beside the array it describes, for the reason 0.2.6 fixed for mcpp.rules.spirv's header: a generated header has to be includable on its own with nothing else. A consumer never declares the row type by hand, so it cannot declare one that has drifted from what the array actually holds.

Each row's bytes are a numeric array, never a raw string literal. A raw string literal delimits on a fixed marker ()" closes R"(...)"), and no byte sequence in an arbitrary payload is excluded strongly enough to promise it never contains that marker: shader source can carry it by accident, and a binary payload can carry it by construction. The motivating case for this entry point built its shader table by concatenating file contents into one string in a build script -- exactly this bug: a shader containing that four-character sequence truncates the string at that point, and every shader concatenated after it goes missing, with nothing but an unrelated compiler error to show for it.

A row's key is a choice, not a convention. table_options::key selects between the file name with its extension (Standard.vert, the default, because a bare stem would collide with Standard.frag), the bare stem, and the path relative to the manifest directory -- for a nested input set where two directories hold a file of the same name, which the file name alone cannot tell apart. Two inputs that derive one key are refused, naming both: the same shape mcpp.rules.spirv refuses two shaders sharing one output name, because the alternative is a table that silently keeps the last row sharing a key and drops the rest, and a build that did that would still link and run.

table_options is its own type rather than a second meaning for options's fields. options::identifier names one symbol, so files() refuses a caller who sets it for several inputs rather than silently applying it to the first. A table writes exactly one array regardless of how many inputs feed it, so there is always exactly one name to give: table_options::identifier (default embedded_table) and table_options::row_type (default embedded_file) name the array and the struct. out_dir, name_space, elem and width mean what they mean in options, element::word32's "not a multiple of 4" refusal included -- checked per input, since a table has several.