Skip to content

Commit 8814ac5

Browse files
enetherudsnopek
andcommitted
CMake: Support for XML documentation
Add new function generate_doc_source to python_callouts.cmake Update Test extension to use generate_doc_source function and include generated file in the build. Cleanup: Fix godotcpp.py imports after rebase Pre-Commit hook sorted python imports in doc_source_generator.py - replace ${CMAKE_CURRENT_SOURCE_DIR} with ${godot-cpp_SOURCE_DIR} when referencing current working directory and script locations when invoking python scripts. Co-authored-by: David Snopek <dsnopek@gmail.com>
1 parent 94a1f4f commit 8814ac5

File tree

4 files changed

+104
-52
lines changed

4 files changed

+104
-52
lines changed

cmake/python_callouts.cmake

+33-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ Its usage is listed as:
1818
]]
1919
function( build_profile_generate_trimmed_api BUILD_PROFILE INPUT_JSON OUTPUT_JSON )
2020
execute_process(
21-
COMMAND "${Python3_EXECUTABLE}" "build_profile.py" "${BUILD_PROFILE}" "${INPUT_JSON}" "${OUTPUT_JSON}"
22-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
21+
COMMAND "${Python3_EXECUTABLE}"
22+
"${godot-cpp_SOURCE_DIR}/build_profile.py"
23+
"${BUILD_PROFILE}"
24+
"${INPUT_JSON}"
25+
"${OUTPUT_JSON}"
26+
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
2327
)
2428
endfunction( )
2529

@@ -45,7 +49,7 @@ function( binding_generator_get_file_list OUT_VAR_NAME API_FILEPATH OUTPUT_DIR )
4549
string( REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}" )
4650

4751
execute_process( COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
48-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
52+
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
4953
OUTPUT_VARIABLE GENERATED_FILES_LIST
5054
OUTPUT_STRIP_TRAILING_WHITESPACE
5155
)
@@ -91,9 +95,33 @@ function( binding_generator_generate_bindings API_FILE USE_TEMPLATE_GET_NODE, BI
9195
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
9296
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
9397
VERBATIM
94-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
98+
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
9599
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
96-
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
100+
DEPENDS ${godot-cpp_SOURCE_DIR}/binding_generator.py
97101
COMMENT "Generating bindings"
98102
)
99103
endfunction( )
104+
105+
#[[ Generate doc_data.cpp
106+
The documentation displayed in the Godot editor is compiled into the extension.
107+
It takes a list of XML source files, and transforms them into a cpp file that
108+
is added to the sources list.]]
109+
function( generate_doc_source OUTPUT_PATH XML_SOURCES )
110+
# Transform the CMake list into the content of a python list
111+
# quote and join to form the interior of a python array
112+
list( TRANSFORM XML_SOURCES REPLACE "(.*\.xml)" "'\\1'" )
113+
list( JOIN XML_SOURCES "," XML_SOURCES )
114+
115+
# Python one-liner to run our command
116+
# lists in CMake are just strings delimited by ';', so this works.
117+
set( PYTHON_SCRIPT "from doc_source_generator import generate_doc_source"
118+
"generate_doc_source( '${OUTPUT_PATH}', [${XML_SOURCES}] )" )
119+
120+
add_custom_command( OUTPUT "${OUTPUT_PATH}"
121+
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
122+
VERBATIM
123+
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
124+
DEPENDS "${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
125+
COMMENT "Generating Doc Data"
126+
)
127+
endfunction()

doc_source_generator.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env python
2+
3+
import glob
4+
import os
5+
import zlib
6+
7+
8+
def generate_doc_source(dst, source):
9+
g = open(dst, "w", encoding="utf-8")
10+
buf = ""
11+
docbegin = ""
12+
docend = ""
13+
for src in source:
14+
src_path = str(src)
15+
if not src_path.endswith(".xml"):
16+
continue
17+
with open(src_path, "r", encoding="utf-8") as f:
18+
content = f.read()
19+
buf += content
20+
21+
buf = (docbegin + buf + docend).encode("utf-8")
22+
decomp_size = len(buf)
23+
24+
# Use maximum zlib compression level to further reduce file size
25+
# (at the cost of initial build times).
26+
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
27+
28+
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
29+
g.write("\n")
30+
g.write("#include <godot_cpp/godot.hpp>\n")
31+
g.write("\n")
32+
33+
g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n')
34+
g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
35+
g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
36+
g.write("static const unsigned char _doc_data_compressed[] = {\n")
37+
for i in range(len(buf)):
38+
g.write("\t" + str(buf[i]) + ",\n")
39+
g.write("};\n")
40+
g.write("\n")
41+
42+
g.write(
43+
"static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n"
44+
)
45+
g.write("\n")
46+
47+
g.close()
48+
49+
50+
def scons_generate_doc_source(target, source, env):
51+
generate_doc_source(str(target[0]), source)
52+
53+
54+
def generate_doc_source_from_directory(target, directory):
55+
generate_doc_source(target, glob.glob(os.path.join(directory, "*.xml")))

test/CMakeLists.txt

+14-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@ Integration Testing
33
-------------------
44
55
The Test target used to validate changes in the GitHub CI.
6-
76
]=======================================================================]
87

98
message( STATUS "Testing Integration targets are enabled.")
109

10+
# Generate Doc Data
11+
file( GLOB_RECURSE DOC_XML
12+
LIST_DIRECTORIES NO
13+
CONFIGURE_DEPENDS
14+
"${CMAKE_CURRENT_SOURCE_DIR}/doc_classes/*.xml" )
15+
16+
set( DOC_DATA_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/src/gen/doc_data.gen.cpp" )
17+
generate_doc_source( "${DOC_DATA_SOURCE}" "${DOC_XML}" )
18+
1119
foreach( TARGET_ALIAS template_debug template_release editor )
1220
set( TARGET_NAME "godot-cpp.test.${TARGET_ALIAS}" )
1321
set( LINK_TARGET "godot-cpp::${TARGET_ALIAS}" )
@@ -23,6 +31,11 @@ foreach( TARGET_ALIAS template_debug template_release editor )
2331
src/tests.h
2432
)
2533

34+
# conditionally add doc data to compile output
35+
if( TARGET_ALIAS MATCHES "editor|template_debug" )
36+
target_sources( ${TARGET_NAME} PRIVATE "${DOC_DATA_SOURCE}" )
37+
endif( )
38+
2639
target_link_libraries( ${TARGET_NAME} PRIVATE ${LINK_TARGET} )
2740

2841
### Get useful properties of the library

tools/godotcpp.py

+2-46
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from binding_generator import _generate_bindings, _get_file_list, get_file_list
1414
from build_profile import generate_trimmed_api
15+
from doc_source_generator import scons_generate_doc_source
1516

1617

1718
def add_sources(sources, dir, extension):
@@ -377,51 +378,6 @@ def options(opts, env):
377378
tool.options(opts)
378379

379380

380-
def make_doc_source(target, source, env):
381-
import zlib
382-
383-
dst = str(target[0])
384-
g = open(dst, "w", encoding="utf-8")
385-
buf = ""
386-
docbegin = ""
387-
docend = ""
388-
for src in source:
389-
src_path = str(src)
390-
if not src_path.endswith(".xml"):
391-
continue
392-
with open(src_path, "r", encoding="utf-8") as f:
393-
content = f.read()
394-
buf += content
395-
396-
buf = (docbegin + buf + docend).encode("utf-8")
397-
decomp_size = len(buf)
398-
399-
# Use maximum zlib compression level to further reduce file size
400-
# (at the cost of initial build times).
401-
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
402-
403-
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
404-
g.write("\n")
405-
g.write("#include <godot_cpp/godot.hpp>\n")
406-
g.write("\n")
407-
408-
g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n')
409-
g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
410-
g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
411-
g.write("static const unsigned char _doc_data_compressed[] = {\n")
412-
for i in range(len(buf)):
413-
g.write("\t" + str(buf[i]) + ",\n")
414-
g.write("};\n")
415-
g.write("\n")
416-
417-
g.write(
418-
"static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n"
419-
)
420-
g.write("\n")
421-
422-
g.close()
423-
424-
425381
def generate(env):
426382
# Default num_jobs to local cpu count if not user specified.
427383
# SCons has a peculiarity where user-specified options won't be overridden
@@ -554,7 +510,7 @@ def generate(env):
554510
env.Append(
555511
BUILDERS={
556512
"GodotCPPBindings": Builder(action=Action(scons_generate_bindings, "$GENCOMSTR"), emitter=scons_emit_files),
557-
"GodotCPPDocData": Builder(action=make_doc_source),
513+
"GodotCPPDocData": Builder(action=scons_generate_doc_source),
558514
}
559515
)
560516
env.AddMethod(_godot_cpp, "GodotCPP")

0 commit comments

Comments
 (0)