Skip to content

Instantly share code, notes, and snippets.

@amir-saniyan
Last active February 1, 2024 14:17
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amir-saniyan/de99cee82fa9d8d615bb69f3f53b6004 to your computer and use it in GitHub Desktop.
Save amir-saniyan/de99cee82fa9d8d615bb69f3f53b6004 to your computer and use it in GitHub Desktop.
Pure CMake function to convert any file into C/C++ source code, implemented with only CMake commands.
####################################################################################################
# This function converts any file into C/C++ source code.
# Example:
# - input file: data.dat
# - output file: data.h
# - variable name declared in output file: DATA
# - data length: sizeof(DATA)
# embed_resource("data.dat" "data.h" "DATA")
####################################################################################################
function(embed_resource resource_file_name source_file_name variable_name)
if(EXISTS "${source_file_name}")
if("${source_file_name}" IS_NEWER_THAN "${resource_file_name}")
return()
endif()
endif()
file(READ "${resource_file_name}" hex_content HEX)
string(REPEAT "[0-9a-f]" 32 pattern)
string(REGEX REPLACE "(${pattern})" "\\1\n" content "${hex_content}")
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " content "${content}")
string(REGEX REPLACE ", $" "" content "${content}")
set(array_definition "static const unsigned char ${variable_name}[] =\n{\n${content}\n};")
set(source "// Auto generated file.\n${array_definition}\n")
file(WRITE "${source_file_name}" "${source}")
endfunction()
@StanislavMikhailenko
Copy link

StanislavMikhailenko commented Nov 10, 2020

There is an error in line 21 string does not recognize sub-command REPEAT
CMake 3.10

on CMake 3.19 its ok

@amir-saniyan
Copy link
Author

There is an error in line 21 string does not recognize sub-command REPEAT
CMake 3.10

on CMake 3.19 its ok

string(REPEAT <input string> <count> <output variable>) added in CMake 3.15.

@StanislavMikhailenko
Copy link

StanislavMikhailenko commented Nov 11, 2020

string(REPEAT "[0-9a-f]" 32 pattern)

could be replaced by

    foreach(a RANGE 31)
      string(CONCAT pattern "[0-9a-f]" pattern)
    endforeach(a RANGE 31) 

to support CMAke 3.10

@onacit
Copy link

onacit commented Oct 4, 2021

How can I call this function? Does this function have a name?

@onacit
Copy link

onacit commented Oct 4, 2021

Would please add some for attaching size?

static const unsigned char variable[] = {
};

static const size_t variable_size = N;

@onacit
Copy link

onacit commented Oct 4, 2021

I add following lines and it seems work.

    STRING(LENGTH "${hex_content}" hex_content_length)
    set(size_definition "\nstatic const size_t ${variable_name}_length = ${hex_content_length}\n;")
    file(APPEND "${source_file_name}" "${size_definition}")

which yields

// Auto generated file.
static const unsigned char variable[] =
{
    ...
};

static const size_t variable_length = N;

@amir-saniyan
Copy link
Author

You can use sizeof operator:

// Auto generated file.
static const unsigned char variable[] =
{
    ...
};

// Your code:
static const size_t variable_length = sizeof(variable);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment