diff --git a/cmake/scripts/ConcatenateToCXX.cmake b/cmake/scripts/ConcatenateToCXX.cmake new file mode 100644 index 0000000000..d8d5d1864d --- /dev/null +++ b/cmake/scripts/ConcatenateToCXX.cmake @@ -0,0 +1,54 @@ +# Filename: ConcatenateToCXX.cmake +# +# Description: When run, creates a single C++ file which includes a const char[] +# containing the bytes from one or more files. +# +# 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}[]; +const char ${SYMBOL_NAME}[] = {\n") + +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() + + # 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}" "};\n") diff --git a/dtool/src/interrogate/CMakeLists.txt b/dtool/src/interrogate/CMakeLists.txt index 639344d6d4..2ddc367aa7 100644 --- a/dtool/src/interrogate/CMakeLists.txt +++ b/dtool/src/interrogate/CMakeLists.txt @@ -64,20 +64,15 @@ target_link_libraries(interrogate p3cppParser p3dtoolconfig p3pystub PKG::OPENSSL) # Python preamble for interrogate_module -file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx - "extern const char interrogate_preamble_python_native[];\n") -file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx - "const char interrogate_preamble_python_native[] = (\n") -foreach(preamble_file ${INTERROGATE_PREAMBLE_PYTHON_NATIVE}) - file(READ ${preamble_file} preamble_content) - string(REPLACE "\\" "\\\\" preamble_content "${preamble_content}") - string(REPLACE "\"" "\\\"" preamble_content "${preamble_content}") - string(REPLACE "\n" "\\n" preamble_content "${preamble_content}") - file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx - " \"${preamble_content}\"\n") -endforeach(preamble_file) -file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx - ");\n") +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx + COMMAND ${CMAKE_COMMAND} + -D OUTPUT_FILE="${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx" + -D INPUT_FILES="${INTERROGATE_PREAMBLE_PYTHON_NATIVE}" + -D SYMBOL_NAME="interrogate_preamble_python_native" + -P ${PROJECT_SOURCE_DIR}/cmake/scripts/ConcatenateToCXX.cmake + DEPENDS ${INTERROGATE_PREAMBLE_PYTHON_NATIVE} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") add_executable(interrogate_module interrogate_module.cxx ${CMAKE_CURRENT_BINARY_DIR}/interrogate_preamble_python_native.cxx)