فهرست منبع

CMake: Support using build_profile.json

Add python_callouts.py to hold functions which call python utilities
- generate trimmed API
- generate file list
- generate bindings

if GODOT_BUILD_PROFILE is specified, a trimmed API file is created in the CMAKE_CURRENT_BINARY_DIR and used as the source for binding generation

Simplify Code Generation Variables
- use generator expressions
- use math for bits
- simplify if statements
Samuel Nicholas 7 ماه پیش
والد
کامیت
ae198fe860
2فایلهای تغییر یافته به همراه135 افزوده شده و 26 حذف شده
  1. 36 26
      cmake/godotcpp.cmake
  2. 99 0
      cmake/python_callouts.cmake

+ 36 - 26
cmake/godotcpp.cmake

@@ -30,6 +30,7 @@ include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux.cmake)
 include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos.cmake)
 include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web.cmake)
 include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake)
+include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/python_callouts.cmake)
 
 # Detect number of processors
 include(ProcessorCount)
@@ -109,7 +110,9 @@ function( godotcpp_options )
     #TODO threads
     #TODO compiledb
     #TODO compiledb_file
-    #TODO build_profile
+
+    set( GODOT_BUILD_PROFILE "" CACHE PATH
+            "Path to a file containing a feature build profile" )
 
     set(GODOT_USE_HOT_RELOAD "" CACHE BOOL
             "Enable the extra accounting required to support hot reload. (ON|OFF)")
@@ -193,40 +196,47 @@ function( godotcpp_generate )
         set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
     endif ()
 
-    #[[ Generate Bindings ]]
-    if(NOT DEFINED BITS)
-        set(BITS 32)
-        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-            set(BITS 64)
-        endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    #[[ Configure Binding Variables ]]
+    # Generate Binding Parameters (True|False)
+    set( USE_TEMPLATE_GET_NODE "False" )
+    if( GODOT_GENERATE_TEMPLATE_GET_NODE )
+        set( USE_TEMPLATE_GET_NODE "True" )
     endif()
 
+    # Bits (32|64)
+    math( EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8" ) # CMAKE_SIZEOF_VOID_P refers to target architecture.
+
+    # API json File
     set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
-    if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "")  # User-defined override.
+    if( GODOT_CUSTOM_API_FILE )  # User-defined override.
         set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
     endif()
 
-    # Code Generation option
-    if(GODOT_GENERATE_TEMPLATE_GET_NODE)
-        set(GENERATE_BINDING_PARAMETERS "True")
-    else()
-        set(GENERATE_BINDING_PARAMETERS "False")
+    # Build Profile
+    if( GODOT_BUILD_PROFILE )
+        message( STATUS "Using build profile to trim api file")
+        message(  "\tBUILD_PROFILE = '${GODOT_BUILD_PROFILE}'")
+        message(  "\tAPI_SOURCE = '${GODOT_GDEXTENSION_API_FILE}'")
+        build_profile_generate_trimmed_api(
+                "${GODOT_BUILD_PROFILE}"
+                "${GODOT_GDEXTENSION_API_FILE}"
+                "${CMAKE_CURRENT_BINARY_DIR}/extension_api.json" )
+        set( GODOT_GDEXTENSION_API_FILE "${CMAKE_CURRENT_BINARY_DIR}/extension_api.json" )
     endif()
 
-    execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list('${GODOT_GDEXTENSION_API_FILE}', '${CMAKE_CURRENT_BINARY_DIR}', headers=True, sources=True)"
-            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-            OUTPUT_VARIABLE GENERATED_FILES_LIST
-            OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
+    message( STATUS "GODOT_GDEXTENSION_API_FILE = '${GODOT_GDEXTENSION_API_FILE}'")
 
-    add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
-            COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings('${GODOT_GDEXTENSION_API_FILE}', '${GENERATE_BINDING_PARAMETERS}', '${BITS}', '${GODOT_PRECISION}', '${CMAKE_CURRENT_BINARY_DIR}')"
-            VERBATIM
-            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-            MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
-            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
-            COMMENT "Generating bindings"
-    )
+    # generate the file list to use
+    binding_generator_get_file_list( GENERATED_FILES_LIST
+            "${GODOT_GDEXTENSION_API_FILE}"
+            "${CMAKE_CURRENT_BINARY_DIR}" )
+
+    binding_generator_generate_bindings(
+            "${GODOT_GDEXTENSION_API_FILE}"
+            "${USE_TEMPLATE_GET_NODE}"
+            "${BITS}"
+            "${GODOT_PRECISION}"
+            "${CMAKE_CURRENT_BINARY_DIR}" )
 
     ### Platform is derived from the toolchain target
     # See GeneratorExpressions PLATFORM_ID and CMAKE_SYSTEM_NAME

+ 99 - 0
cmake/python_callouts.cmake

@@ -0,0 +1,99 @@
+#[=======================================================================[.rst:
+python_callouts.cmake
+---------------------
+
+This file contains functions which which rely on calling Python
+
+* Generate Trimmed API
+* Generate File List
+* Generate Bindings
+]=======================================================================]
+
+
+#[[ Generate Trimmed API
+
+The build_profile.py has a __main__ and is used as a tool
+Its usage is listed as:
+    $ python build_profile.py BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]
+]]
+function( build_profile_generate_trimmed_api BUILD_PROFILE INPUT_JSON OUTPUT_JSON )
+    execute_process(
+            COMMAND "${Python3_EXECUTABLE}" "build_profile.py" "${BUILD_PROFILE}" "${INPUT_JSON}" "${OUTPUT_JSON}"
+            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+    )
+endfunction(  )
+
+
+#[[ Generate File List
+
+Use the binding_generator.py Python script to determine the list of files that
+will be passed to the code generator using extension_api.json.
+NOTE: This happens for every configure.]]
+function( binding_generator_get_file_list OUT_VAR_NAME API_FILEPATH OUTPUT_DIR )
+
+    # This code snippet will be squashed into a single line
+    # The two strings make this a list, in CMake lists are semicolon delimited strings.
+    set( PYTHON_SCRIPT
+"from binding_generator import print_file_list"
+"print_file_list( api_filepath='${API_FILEPATH}',
+    output_dir='${OUTPUT_DIR}',
+    headers=True,
+    sources=True)")
+    message( DEBUG "Python:\n${PYTHON_SCRIPT}" )
+
+    # Strip newlines and whitespace to make it a one-liner.
+    string( REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}" )
+
+    execute_process( COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
+            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+            OUTPUT_VARIABLE GENERATED_FILES_LIST
+            OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+
+    # Debug output
+    message( DEBUG "FileList-Begin" )
+    foreach( PATH ${GENERATED_FILES_LIST} )
+        message( DEBUG ${PATH} )
+    endforeach()
+
+    # Error out if the file list generator returned no files.
+    list( LENGTH GENERATED_FILES_LIST LIST_LENGTH )
+    if( NOT LIST_LENGTH GREATER 0 )
+        message( FATAL_ERROR "File List Generation Failed")
+    endif()
+    message( STATUS "There are ${LIST_LENGTH} Files to generate" )
+
+    set( ${OUT_VAR_NAME} ${GENERATED_FILES_LIST} PARENT_SCOPE )
+endfunction(  )
+
+
+#[[ Generate Bindings
+
+Using the generated file list, use the binding_generator.py to generate the
+godot-cpp bindings. This will run at build time only if there are files
+missing. ]]
+function( binding_generator_generate_bindings API_FILE USE_TEMPLATE_GET_NODE, BITS, PRECISION, OUTPUT_DIR )
+    # This code snippet will be squashed into a single line
+    set( PYTHON_SCRIPT
+"from binding_generator import generate_bindings"
+"generate_bindings(
+    api_filepath='${API_FILE}',
+    use_template_get_node='${USE_TEMPLATE_GET_NODE}',
+    bits='${BITS}',
+    precision='${PRECISION}',
+    output_dir='${OUTPUT_DIR}')")
+
+    message( DEBUG "Python:\n${PYTHON_SCRIPT}" )
+
+    # Strip newlines and whitespace to make it a one-liner.
+    string( REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}" )
+
+    add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
+            COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
+            VERBATIM
+            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+            MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
+            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
+            COMMENT "Generating bindings"
+    )
+endfunction(  )