# Filename: ConcatenateToCXX.cmake # # Description: When run, creates a single C++ file which includes a const char[] # containing the bytes from one or more files. # # There is a {SYMBOL_NAME}_size symbol defined as well, storing the total # number of bytes in the concatenated input files. # # A single null terminator byte is added for the benefit of programs that # simply treat the data array as a string. # # Usage: # This script is invoked via add_custom_target, like this: # cmake -D OUTPUT_FILE="out.cxx" -D SYMBOL_NAME=data -D INPUT_FILES="a.bin b.bin" -P ConcatenateToCXX.cmake # if(NOT CMAKE_SCRIPT_MODE_FILE) message(FATAL_ERROR "ConcatenateToCXX.cmake should not be included but run in script mode.") return() endif() if(NOT DEFINED OUTPUT_FILE) message(FATAL_ERROR "OUTPUT_FILE should be defined when running ConcatenateToCXX.cmake!") return() endif() if(NOT DEFINED SYMBOL_NAME) set(SYMBOL_NAME "data") endif() file(WRITE "${OUTPUT_FILE}" "/* Generated by CMake. DO NOT EDIT. */ extern const char ${SYMBOL_NAME}[]; extern const int ${SYMBOL_NAME}_size; const char ${SYMBOL_NAME}[] = {\n") set(byte_count 0) separate_arguments(INPUT_FILES) foreach(infile ${INPUT_FILES}) file(APPEND "${OUTPUT_FILE}" " /* ${infile} */\n") set(offset 0) while(1) # Read up to 1024 bytes from the input file file(READ "${infile}" data LIMIT 1024 OFFSET ${offset} HEX) math(EXPR offset "${offset} + 1024") # If 'data' is empty, we're done if(NOT data) break() endif() # Count the bytes we're adding string(LENGTH "${data}" strlen) math(EXPR byte_count "${byte_count} + (${strlen} / 2)") # Format runs of up to 32 hex chars by indenting and giving a newline string(REGEX REPLACE "(...?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?)" " \\1\n" data "${data}") # Format each byte (2 hex chars) in each line with 0x prefix and comma suffix string(REGEX REPLACE "([0-9a-fA-F][0-9a-fA-F])" " 0x\\1," data "${data}") file(APPEND "${OUTPUT_FILE}" "${data}") endwhile() endforeach(infile) file(APPEND "${OUTPUT_FILE}" " 0\n}; extern const int ${SYMBOL_NAME}_size = ${byte_count};\n")