1# 2# Convert a file (text or binary) into an assembler source file suitable 3# for gcc. Designed to replicate 'objcopy' with more predictable 4# naming, and supports appending a null byte for embedding text as 5# a string. 6# 7# Designed to be run as a script with "cmake -P" 8# 9# Set variables DATA_FILE, SOURCE_FILE, FILE_TYPE when running this. 10# 11# If FILE_TYPE is set to TEXT, a null byte is appended to DATA_FILE's contents 12# before SOURCE_FILE is created. 13# 14# If FILE_TYPE is unset (or any other value), DATA_FILE is copied 15# verbatim into SOURCE_FILE. 16# 17# 18if(NOT DATA_FILE) 19 message(FATAL_ERROR "DATA_FILE for converting must be specified") 20endif() 21 22if(NOT SOURCE_FILE) 23 message(FATAL_ERROR "SOURCE_FILE destination must be specified") 24endif() 25 26file(READ "${DATA_FILE}" data HEX) 27 28string(LENGTH "${data}" data_len) 29math(EXPR data_len "${data_len} / 2") # 2 hex bytes per byte 30 31if(FILE_TYPE STREQUAL "TEXT") 32 set(data "${data}00") # null-byte termination 33endif() 34 35## Convert string of raw hex bytes to lines of hex bytes as gcc .byte expressions 36string(REGEX REPLACE "................................" ".byte \\0\n" data "${data}") # 16 bytes per line 37string(REGEX REPLACE "[^\n]+$" ".byte \\0\n" data "${data}") # last line 38string(REGEX REPLACE "[0-9a-f][0-9a-f]" "0x\\0, " data "${data}") # hex formatted C bytes 39string(REGEX REPLACE ", \n" "\n" data "${data}") # trim the last comma 40 41# Use source file name as variable name unless VARIABLE_BASENAME is set 42if(NOT VARIABLE_BASENAME) 43 get_filename_component(varname "${DATA_FILE}" NAME) 44else() 45 set(varname "${VARIABLE_BASENAME}") 46endif() 47 48function(append str) 49 file(APPEND "${SOURCE_FILE}" "${str}") 50endfunction() 51 52function(append_line str) 53 append("${str}\n") 54endfunction() 55 56function(make_and_append_identifier str) 57 string(MAKE_C_IDENTIFIER "${str}" symbol) 58 append_line("\n.global ${symbol}") 59 append("${symbol}:") 60 if(${ARGC} GREATER 1) # optional comment 61 append(" /* ${ARGV1} */") 62 endif() 63 append("\n") 64endfunction() 65 66file(WRITE "${SOURCE_FILE}" "/*") 67append_line(" * Data converted from ${DATA_FILE}") 68if(FILE_TYPE STREQUAL "TEXT") 69 append_line(" * (null byte appended)") 70endif() 71append_line(" */") 72 73append_line(".data") 74append_line(".section .rodata.embedded") 75make_and_append_identifier("${varname}") 76make_and_append_identifier("_binary_${varname}_start" "for objcopy compatibility") 77append("${data}") 78make_and_append_identifier("_binary_${varname}_end" "for objcopy compatibility") 79 80append_line("") 81if(FILE_TYPE STREQUAL "TEXT") 82 make_and_append_identifier("${varname}_length" "not including null byte") 83else() 84 make_and_append_identifier("${varname}_length") 85endif() 86append_line(".word ${data_len}") 87