GodotCPPModule.cmake 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #[=======================================================================[.rst:
  2. GodotCPPModule.cmake
  3. ---------------------
  4. This file contains functions and tests which may be needed by consumers.
  5. * Generate Trimmed API
  6. * Generate File List
  7. * Generate Bindings
  8. If you want to use these functions in your project extend the CMAKE_MODULE_PATH
  9. by adding these two lines into your CMakeLists.txt after the inclusion
  10. godot-cpp
  11. .. highlight:: cmake
  12. list(APPEND CMAKE_MODULE_PATH "${godot-cpp_SOURCE_DIR}/cmake")
  13. include( GodotCPPModule )
  14. ]=======================================================================]
  15. find_package(Python3 3.4 REQUIRED) # pathlib should be present
  16. #[[ Generate Trimmed API
  17. The build_profile.py has a __main__ and is used as a tool
  18. Its usage is listed as:
  19. $ python build_profile.py BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]
  20. ]]
  21. function(build_profile_generate_trimmed_api BUILD_PROFILE INPUT_JSON OUTPUT_JSON)
  22. execute_process(
  23. COMMAND
  24. "${Python3_EXECUTABLE}" "${godot-cpp_SOURCE_DIR}/build_profile.py" "${BUILD_PROFILE}" "${INPUT_JSON}"
  25. "${OUTPUT_JSON}"
  26. WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
  27. )
  28. endfunction()
  29. #[[ Generate File List
  30. Use the binding_generator.py Python script to determine the list of files that
  31. will be passed to the code generator using extension_api.json.
  32. NOTE: This happens for every configure.]]
  33. function(binding_generator_get_file_list OUT_VAR_NAME API_FILEPATH OUTPUT_DIR)
  34. # This code snippet will be squashed into a single line
  35. # The two strings make this a list, in CMake lists are semicolon delimited strings.
  36. set(PYTHON_SCRIPT
  37. "from binding_generator import print_file_list"
  38. "print_file_list( api_filepath='${API_FILEPATH}',
  39. output_dir='${OUTPUT_DIR}',
  40. headers=True,
  41. sources=True)"
  42. )
  43. message(DEBUG "Python:\n${PYTHON_SCRIPT}")
  44. # Strip newlines and whitespace to make it a one-liner.
  45. string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
  46. execute_process(
  47. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  48. WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
  49. OUTPUT_VARIABLE GENERATED_FILES_LIST
  50. OUTPUT_STRIP_TRAILING_WHITESPACE
  51. )
  52. # Debug output
  53. message(DEBUG "FileList-Begin")
  54. foreach(PATH ${GENERATED_FILES_LIST})
  55. message(DEBUG ${PATH})
  56. endforeach()
  57. # Error out if the file list generator returned no files.
  58. list(LENGTH GENERATED_FILES_LIST LIST_LENGTH)
  59. if(NOT LIST_LENGTH GREATER 0)
  60. message(FATAL_ERROR "File List Generation Failed")
  61. endif()
  62. message(STATUS "There are ${LIST_LENGTH} Files to generate")
  63. set(${OUT_VAR_NAME} ${GENERATED_FILES_LIST} PARENT_SCOPE)
  64. endfunction()
  65. #[[ Generate Bindings
  66. Using the generated file list, use the binding_generator.py to generate the
  67. godot-cpp bindings. This will run at build time only if there are files
  68. missing. ]]
  69. function(
  70. binding_generator_generate_bindings
  71. API_FILE
  72. USE_TEMPLATE_GET_NODE,
  73. BITS,
  74. PRECISION,
  75. OUTPUT_DIR
  76. )
  77. # This code snippet will be squashed into a single line
  78. set(PYTHON_SCRIPT
  79. "from binding_generator import generate_bindings"
  80. "generate_bindings(
  81. api_filepath='${API_FILE}',
  82. use_template_get_node='${USE_TEMPLATE_GET_NODE}',
  83. bits='${BITS}',
  84. precision='${PRECISION}',
  85. output_dir='${OUTPUT_DIR}')"
  86. )
  87. message(DEBUG "Python:\n${PYTHON_SCRIPT}")
  88. # Strip newlines and whitespace to make it a one-liner.
  89. string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
  90. add_custom_command(
  91. OUTPUT ${GENERATED_FILES_LIST}
  92. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  93. VERBATIM
  94. WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
  95. MAIN_DEPENDENCY ${GODOTCPP_GDEXTENSION_API_FILE}
  96. DEPENDS ${godot-cpp_SOURCE_DIR}/binding_generator.py
  97. COMMENT "Generating bindings"
  98. )
  99. endfunction()
  100. #[[ Generate doc_data.cpp
  101. The documentation displayed in the Godot editor is compiled into the extension.
  102. It takes a list of XML source files, and transforms them into a cpp file that
  103. is added to the sources list.]]
  104. function(generate_doc_source OUTPUT_PATH SOURCES)
  105. # Transform SOURCES CMake LIST
  106. # quote each path with ''
  107. # join with , to transform into a python list minus the surrounding []
  108. set(PYTHON_LIST "${SOURCES}")
  109. list(TRANSFORM PYTHON_LIST REPLACE "(.*\.xml)" "'\\1'")
  110. list(JOIN PYTHON_LIST "," PYTHON_LIST)
  111. get_filename_component(OUTPUT_DIR "${OUTPUT_PATH}" DIRECTORY)
  112. file(MAKE_DIRECTORY ${OUTPUT_DIR})
  113. # Python one-liner to run our command
  114. # lists in CMake are just strings delimited by ';', so this works.
  115. set(PYTHON_SCRIPT
  116. "from doc_source_generator import generate_doc_source"
  117. "generate_doc_source( '${OUTPUT_PATH}', [${PYTHON_LIST}] )"
  118. )
  119. add_custom_command(
  120. OUTPUT "${OUTPUT_PATH}"
  121. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  122. VERBATIM
  123. WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
  124. DEPENDS
  125. DEPENDS #
  126. "${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
  127. "${SOURCES}"
  128. COMMENT "Generating: ${OUTPUT_PATH}"
  129. )
  130. endfunction()
  131. #[[ target_doc_sources
  132. A simpler interface to add xml files as doc source to a output target.
  133. TARGET: The gdexension library target
  134. SOURCES: a list of xml files to use for source generation and inclusion.
  135. This function also adds a doc_gen target to test source generation.]]
  136. function(target_doc_sources TARGET SOURCES)
  137. # set the generated file name
  138. set(DOC_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen/doc_source.cpp")
  139. # Create the file generation target, this won't be triggered unless a target
  140. # that depends on DOC_SOURCE_FILE is built
  141. generate_doc_source( "${DOC_SOURCE_FILE}" ${SOURCES} )
  142. # Add DOC_SOURCE_FILE as a dependency to TARGET
  143. target_sources(${TARGET} PRIVATE "${DOC_SOURCE_FILE}")
  144. # Create a dummy target that depends on the source so that users can
  145. # test the file generation task.
  146. if(TARGET doc_gen)
  147. else()
  148. add_custom_target(doc_gen)
  149. endif()
  150. target_sources(doc_gen PRIVATE "${DOC_SOURCE_FILE}")
  151. endfunction()