GodotCPPModule.cmake 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. INTERFACE_FILE
  73. USE_TEMPLATE_GET_NODE
  74. BITS
  75. PRECISION
  76. OUTPUT_DIR
  77. )
  78. # This code snippet will be squashed into a single line
  79. set(PYTHON_SCRIPT
  80. "from binding_generator import generate_bindings"
  81. "generate_bindings(
  82. api_filepath='${API_FILE}',
  83. interface_filepath='${INTERFACE_FILE}',
  84. use_template_get_node='${USE_TEMPLATE_GET_NODE}',
  85. bits='${BITS}',
  86. precision='${PRECISION}',
  87. output_dir='${OUTPUT_DIR}')"
  88. )
  89. message(DEBUG "Python:\n${PYTHON_SCRIPT}")
  90. # Strip newlines and whitespace to make it a one-liner.
  91. string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
  92. add_custom_command(
  93. OUTPUT ${GENERATED_FILES_LIST}
  94. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  95. VERBATIM
  96. WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
  97. MAIN_DEPENDENCY ${GODOTCPP_GDEXTENSION_API_FILE}
  98. DEPENDS ${godot-cpp_SOURCE_DIR}/binding_generator.py
  99. COMMENT "Generating bindings"
  100. )
  101. add_custom_target(generate_bindings DEPENDS ${GENERATED_FILES_LIST})
  102. set_target_properties(generate_bindings PROPERTIES FOLDER "godot-cpp")
  103. endfunction()
  104. #[[ Generate doc_data.cpp
  105. The documentation displayed in the Godot editor is compiled into the extension.
  106. It takes a list of XML source files, and transforms them into a cpp file that
  107. is added to the sources list.]]
  108. function(generate_doc_source OUTPUT_PATH SOURCES)
  109. # Transform SOURCES CMake LIST
  110. # quote each path with ''
  111. # join with , to transform into a python list minus the surrounding []
  112. set(PYTHON_LIST "${SOURCES}")
  113. list(TRANSFORM PYTHON_LIST REPLACE "(.*\.xml)" "'\\1'")
  114. list(JOIN PYTHON_LIST "," PYTHON_LIST)
  115. get_filename_component(OUTPUT_DIR "${OUTPUT_PATH}" DIRECTORY)
  116. file(MAKE_DIRECTORY ${OUTPUT_DIR})
  117. # Python one-liner to run our command
  118. # lists in CMake are just strings delimited by ';', so this works.
  119. set(PYTHON_SCRIPT
  120. "from doc_source_generator import generate_doc_source"
  121. "generate_doc_source( '${OUTPUT_PATH}', [${PYTHON_LIST}] )"
  122. )
  123. add_custom_command(
  124. OUTPUT "${OUTPUT_PATH}"
  125. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  126. VERBATIM
  127. WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
  128. DEPENDS #
  129. "${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
  130. "${SOURCES}"
  131. COMMENT "Generating: ${OUTPUT_PATH}"
  132. )
  133. add_custom_target(generate_doc_source DEPENDS "${OUTPUT_PATH}")
  134. set_target_properties(generate_doc_source PROPERTIES FOLDER "godot-cpp")
  135. endfunction()
  136. #[[ target_doc_sources
  137. A simpler interface to add xml files as doc source to a output target.
  138. TARGET: The gdexension library target
  139. SOURCES: a list of xml files to use for source generation and inclusion.]]
  140. function(target_doc_sources TARGET SOURCES)
  141. # set the generated file name
  142. set(DOC_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen/doc_source.cpp")
  143. # Create the file generation target, this won't be triggered unless a target
  144. # that depends on DOC_SOURCE_FILE is built
  145. generate_doc_source( "${DOC_SOURCE_FILE}" ${SOURCES} )
  146. # Add DOC_SOURCE_FILE as a dependency to TARGET
  147. target_sources(${TARGET} PRIVATE "${DOC_SOURCE_FILE}")
  148. # Without adding this dependency to the doc_source_generator, XCode will complain.
  149. add_dependencies(${TARGET} generate_doc_source)
  150. endfunction()