Code Generation#
The code generation module has functions for generating code in C or C++. This includes code generation to embed resources, serving as a replacement for the C23 #embed directive.
toolbelt_embed#
Embeds a resource into source code as a variable or define macro. This function is similar to the C23 #embed
directive. The #embed directive should be preferred over toolbelt_embed
if it is available.
toolbelt_embed(
<file>
<variable>
<EMBED embed_files...>
[NAMESPACE namespace]
[OUTPUT_DIR output_dir]
[TARGET target]
[VISIBILITY visibility]
[AUTO_LITERAL | CHAR_LITERAL | BYTE_ARRAY | DEFINE]
)
This function generates C or C++ code at the file
which embeds data contained within EMBED
in a variable or preprocessor macro called variable
. If multiple files are specified in cmake:EMBED,
then they are all concatenated and embedded in the same variable
.
Note
This function cannot create multiple variables in the same file.
In order to control how the variable is created the mode should be specified as either AUTO_LITERAL
,
CHAR_LITERAL
, BYTE_ARRAY
, DEFINE
. This function returns an error if more than one of
these modes if specified. The default mode is AUTO_LITERAL
.
AUTO_LITERAL
and CHAR_LITERAL
both define string literal variables with a null terminator, and a type
of constexpr auto
or const char *
respectively. BYTE_ARRAY
defines a byte array variable without
a null terminator, and a type of const uint8_t []
. DEFINE
defines a preprocessor macro.
The following table shows the generated code using these modes.
Mode |
Generate Code |
---|---|
|
embed.h#
constexpr auto variable = "This is an embedded literal.\n";
|
|
embed.h#
const char* include_const_char = "This is an embedded literal.\n";
|
|
embed.h#
constexpr auto variable = "This is an embedded literal.\n";
|
|
embed.h#
#define INCLUDE_DEFINE_CONSTANT "This is an embedded literal.\n"
|
The variable definition can be surrounded by a namespace by specifying NAMESPACE
. By default,
toolbelt_embed
places the generated file in ${CMAKE_CURRENT_BINARY_DIR}/generated
. OUTPUT_DIR
can be used
to change this location. If TARGET
is specified, then target_sources
is used to add the generated
file to the TARGET
with VISIBILITY
visibility. The default visibility is "PRIVATE"
.
This function sets the a variable called toolbelt_ret
with PARENT_SCOPE
to the value of the
OUTPUT_DIR
. This can be used with target_include_directories
to allow the source code to access the embedded
resource.
Examples#
Embed a single file#
This example embeds a single file into an auto literal and links the generated code to application
.
create_header_file(
"include_constexpr_auto.h"
"include_constexpr_auto"
EMBED "embed_one.txt"
TARGET application
)
target_include_directories(application PRIVATE ${cmake_toolbelt_ret})
This generates the following code, assuming embed_one.txt
contains "This is an embedded literal.\n"
:
// Auto-generated by toolbelt_embed.
#ifndef INCLUDE_CONSTEXPR_AUTO_H
#define INCLUDE_CONSTEXPR_AUTO_H
constexpr auto include_constexpr_auto = "This is an embedded literal.\n";
#endif // INCLUDE_CONSTEXPR_AUTO_H
Embed multiple files#
This example embeds multiple files into a char literal and links the generated code to application
.
create_header_file(
"include_const_char.h"
"include_const_char"
EMBED "embed_one.txt" "embed_two.txt"
NAMESPACE "application::detail"
TARGET application
CHAR_LITERAL
)
target_include_directories(application PRIVATE ${cmake_toolbelt_ret})
This generates the following code, assuming embed_one.txt
contains "This is an embedded literal.\\n"
and
embed_two.txt
contains "This is also an embedded literal.\\nWith multiple lines.\\n"
:
// Auto-generated by toolbelt_embed.
#ifndef APPLICATION_DETAIL_INCLUDE_CONST_CHAR_H
#define APPLICATION_DETAIL_INCLUDE_CONST_CHAR_H
namespace application::detail {
const char* include_const_char_multi = "This is an embedded literal.\n"
"This is also an embedded literal.\n"
"With multiple lines.\n";
} // namespace application::detail
#endif // APPLICATION_DETAIL_INCLUDE_CONST_CHAR_H