Browse Source

CMake: Generate interrogate_preamble_python_native.cxx at build time

This also makes sure the file is only rebuilt if the inputs
change, saving on unnecessary rebuilds.
Sam Edwards 6 years ago
parent
commit
873c6b48d6
2 changed files with 63 additions and 14 deletions
  1. 54 0
      cmake/scripts/ConcatenateToCXX.cmake
  2. 9 14
      dtool/src/interrogate/CMakeLists.txt

+ 54 - 0
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")

+ 9 - 14
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)