GodotCPPModule.cmake 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. add_custom_target(generate_bindings DEPENDS ${GENERATED_FILES_LIST})
  100. set_target_properties(generate_bindings PROPERTIES FOLDER "godot-cpp")
  101. endfunction()
  102. #[[ Generate doc_data.cpp
  103. The documentation displayed in the Godot editor is compiled into the extension.
  104. It takes a list of XML source files, and transforms them into a cpp file that
  105. is added to the sources list.]]
  106. function(generate_doc_source OUTPUT_PATH SOURCES)
  107. # Transform SOURCES CMake LIST
  108. # quote each path with ''
  109. # join with , to transform into a python list minus the surrounding []
  110. set(PYTHON_LIST "${SOURCES}")
  111. list(TRANSFORM PYTHON_LIST REPLACE "(.*\.xml)" "'\\1'")
  112. list(JOIN PYTHON_LIST "," PYTHON_LIST)
  113. get_filename_component(OUTPUT_DIR "${OUTPUT_PATH}" DIRECTORY)
  114. file(MAKE_DIRECTORY ${OUTPUT_DIR})
  115. # Python one-liner to run our command
  116. # lists in CMake are just strings delimited by ';', so this works.
  117. set(PYTHON_SCRIPT
  118. "from doc_source_generator import generate_doc_source"
  119. "generate_doc_source( '${OUTPUT_PATH}', [${PYTHON_LIST}] )"
  120. )
  121. add_custom_command(
  122. OUTPUT "${OUTPUT_PATH}"
  123. COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
  124. VERBATIM
  125. WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
  126. DEPENDS #
  127. "${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
  128. "${SOURCES}"
  129. COMMENT "Generating: ${OUTPUT_PATH}"
  130. )
  131. add_custom_target(generate_doc_source DEPENDS "${OUTPUT_PATH}")
  132. set_target_properties(generate_doc_source PROPERTIES FOLDER "godot-cpp")
  133. endfunction()
  134. #[[ target_doc_sources
  135. A simpler interface to add xml files as doc source to a output target.
  136. TARGET: The gdexension library target
  137. SOURCES: a list of xml files to use for source generation and inclusion.]]
  138. function(target_doc_sources TARGET SOURCES)
  139. # set the generated file name
  140. set(DOC_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen/doc_source.cpp")
  141. # Create the file generation target, this won't be triggered unless a target
  142. # that depends on DOC_SOURCE_FILE is built
  143. generate_doc_source( "${DOC_SOURCE_FILE}" ${SOURCES} )
  144. # Add DOC_SOURCE_FILE as a dependency to TARGET
  145. target_sources(${TARGET} PRIVATE "${DOC_SOURCE_FILE}")
  146. # Without adding this dependency to the doc_source_generator, XCode will complain.
  147. add_dependencies(${TARGET} generate_doc_source)
  148. endfunction()