ConcatenateToCXX.cmake 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Filename: ConcatenateToCXX.cmake
  2. #
  3. # Description: When run, creates a single C++ file which includes a const char[]
  4. # containing the bytes from one or more files.
  5. #
  6. # There is a {SYMBOL_NAME}_size symbol defined as well, storing the total
  7. # number of bytes in the concatenated input files.
  8. #
  9. # A single null terminator byte is added for the benefit of programs that
  10. # simply treat the data array as a string.
  11. #
  12. # Usage:
  13. # This script is invoked via add_custom_target, like this:
  14. # cmake -D OUTPUT_FILE="out.cxx" -D SYMBOL_NAME=data -D INPUT_FILES="a.bin b.bin" -P ConcatenateToCXX.cmake
  15. #
  16. if(NOT CMAKE_SCRIPT_MODE_FILE)
  17. message(FATAL_ERROR "ConcatenateToCXX.cmake should not be included but run in script mode.")
  18. return()
  19. endif()
  20. if(NOT DEFINED OUTPUT_FILE)
  21. message(FATAL_ERROR "OUTPUT_FILE should be defined when running ConcatenateToCXX.cmake!")
  22. return()
  23. endif()
  24. if(NOT DEFINED SYMBOL_NAME)
  25. set(SYMBOL_NAME "data")
  26. endif()
  27. file(WRITE "${OUTPUT_FILE}" "/* Generated by CMake. DO NOT EDIT. */
  28. extern const char ${SYMBOL_NAME}[];
  29. extern const int ${SYMBOL_NAME}_size;
  30. const char ${SYMBOL_NAME}[] = {\n")
  31. set(byte_count 0)
  32. separate_arguments(INPUT_FILES)
  33. foreach(infile ${INPUT_FILES})
  34. file(APPEND "${OUTPUT_FILE}" " /* ${infile} */\n")
  35. set(offset 0)
  36. while(1)
  37. # Read up to 1024 bytes from the input file
  38. file(READ "${infile}" data LIMIT 1024 OFFSET ${offset} HEX)
  39. math(EXPR offset "${offset} + 1024")
  40. # If 'data' is empty, we're done
  41. if(NOT data)
  42. break()
  43. endif()
  44. # Count the bytes we're adding
  45. string(LENGTH "${data}" strlen)
  46. math(EXPR byte_count "${byte_count} + (${strlen} / 2)")
  47. # Format runs of up to 32 hex chars by indenting and giving a newline
  48. string(REGEX REPLACE
  49. "(...?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?.?)" " \\1\n"
  50. data "${data}")
  51. # Format each byte (2 hex chars) in each line with 0x prefix and comma suffix
  52. string(REGEX REPLACE "([0-9a-fA-F][0-9a-fA-F])" " 0x\\1," data "${data}")
  53. file(APPEND "${OUTPUT_FILE}" "${data}")
  54. endwhile()
  55. endforeach(infile)
  56. file(APPEND "${OUTPUT_FILE}" " 0\n};
  57. extern const int ${SYMBOL_NAME}_size = ${byte_count};\n")