@@ -292,37 +292,19 @@ def parse_build_profile(profile_filepath, api):
292292 children [parent ] = children .get (parent , [])
293293 children [parent ].append (child )
294294
295- # Parse methods dependencies
296- deps = {}
297- reverse_deps = {}
298- for name , engine_class in api_dict .items ():
299- ref_cls = set ()
300- for method in engine_class .get ("methods" , []):
301- rtype = method .get ("return_value" , {}).get ("type" , "" )
302- args = [a ["type" ] for a in method .get ("arguments" , [])]
303- if rtype in api_dict :
304- ref_cls .add (rtype )
305- elif is_enum (rtype ) and get_enum_class (rtype ) in api_dict :
306- ref_cls .add (get_enum_class (rtype ))
307- for arg in args :
308- if arg in api_dict :
309- ref_cls .add (arg )
310- elif is_enum (arg ) and get_enum_class (arg ) in api_dict :
311- ref_cls .add (get_enum_class (arg ))
312- deps [engine_class ["name" ]] = set (filter (lambda x : x != name , ref_cls ))
313- for acls in ref_cls :
314- if acls == name :
315- continue
316- reverse_deps [acls ] = reverse_deps .get (acls , set ())
317- reverse_deps [acls ].add (name )
318-
319295 included = []
320296 front = list (profile .get ("enabled_classes" , []))
321297 if front :
322298 # These must always be included
323299 front .append ("WorkerThreadPool" )
324300 front .append ("ClassDB" )
325301 front .append ("ClassDBSingleton" )
302+ # In src/classes/low_level.cpp
303+ front .append ("FileAccess" )
304+ front .append ("Image" )
305+ front .append ("XMLParser" )
306+ # In include/godot_cpp/templates/thread_work_pool.hpp
307+ front .append ("Semaphore" )
326308 while front :
327309 cls = front .pop ()
328310 if cls in included :
@@ -331,10 +313,6 @@ def parse_build_profile(profile_filepath, api):
331313 parent = parents .get (cls , "" )
332314 if parent :
333315 front .append (parent )
334- for rcls in deps .get (cls , set ()):
335- if rcls in included or rcls in front :
336- continue
337- front .append (rcls )
338316
339317 excluded = []
340318 front = list (profile .get ("disabled_classes" , []))
@@ -344,10 +322,6 @@ def parse_build_profile(profile_filepath, api):
344322 continue
345323 excluded .append (cls )
346324 front += children .get (cls , [])
347- for rcls in reverse_deps .get (cls , set ()):
348- if rcls in excluded or rcls in front :
349- continue
350- front .append (rcls )
351325
352326 if included and excluded :
353327 print (
@@ -372,24 +346,33 @@ def scons_emit_files(target, source, env):
372346
373347
374348def scons_generate_bindings (target , source , env ):
349+ profile_filepath = env .get ("build_profile" , "" )
350+ if profile_filepath and not Path (profile_filepath ).is_absolute ():
351+ profile_filepath = str ((Path (env .Dir ("#" ).abspath ) / profile_filepath ).as_posix ())
352+
375353 generate_bindings (
376354 str (source [0 ]),
377355 env ["generate_template_get_node" ],
378356 "32" if "32" in env ["arch" ] else "64" ,
379357 env ["precision" ],
380358 env ["godot_cpp_gen_dir" ],
359+ profile_filepath ,
381360 )
382361 return None
383362
384363
385- def generate_bindings (api_filepath , use_template_get_node , bits = "64" , precision = "single" , output_dir = "." ):
364+ def generate_bindings (
365+ api_filepath , use_template_get_node , bits = "64" , precision = "single" , output_dir = "." , profile_filepath = ""
366+ ):
386367 api = None
387368
388369 target_dir = Path (output_dir ) / "gen"
389370
390371 with open (api_filepath , encoding = "utf-8" ) as api_file :
391372 api = json .load (api_file )
392373
374+ build_profile = parse_build_profile (profile_filepath , api )
375+
393376 shutil .rmtree (target_dir , ignore_errors = True )
394377 target_dir .mkdir (parents = True )
395378
@@ -400,7 +383,7 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
400383 generate_version_header (api , target_dir )
401384 generate_global_constant_binds (api , target_dir )
402385 generate_builtin_bindings (api , target_dir , real_t + "_" + bits )
403- generate_engine_classes_bindings (api , target_dir , use_template_get_node )
386+ generate_engine_classes_bindings (api , target_dir , use_template_get_node , build_profile )
404387 generate_utility_functions (api , target_dir )
405388
406389
@@ -1378,7 +1361,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
13781361 return "\n " .join (result )
13791362
13801363
1381- def generate_engine_classes_bindings (api , output_dir , use_template_get_node ):
1364+ def generate_engine_classes_bindings (api , output_dir , use_template_get_node , build_profile ):
13821365 global engine_classes
13831366 global singletons
13841367 global native_structures
@@ -1421,6 +1404,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
14211404
14221405 if "methods" in class_api :
14231406 for method in class_api ["methods" ]:
1407+ if not is_method_included (method , build_profile ):
1408+ continue
14241409 if "arguments" in method :
14251410 for argument in method ["arguments" ]:
14261411 type_name = argument ["type" ]
@@ -1566,14 +1551,21 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
15661551 fully_used_classes = list (fully_used_classes )
15671552 fully_used_classes .sort ()
15681553
1554+ if not is_class_included (class_api ["name" ], build_profile ):
1555+ continue
1556+
15691557 with header_filename .open ("w+" , encoding = "utf-8" ) as header_file :
15701558 header_file .write (
1571- generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node )
1559+ generate_engine_class_header (
1560+ class_api , used_classes , fully_used_classes , use_template_get_node , build_profile
1561+ )
15721562 )
15731563
15741564 with source_filename .open ("w+" , encoding = "utf-8" ) as source_file :
15751565 source_file .write (
1576- generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node )
1566+ generate_engine_class_source (
1567+ class_api , used_classes , fully_used_classes , use_template_get_node , build_profile
1568+ )
15771569 )
15781570
15791571 for native_struct in api ["native_structures" ]:
@@ -1635,7 +1627,7 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
16351627 header_file .write ("\n " .join (result ))
16361628
16371629
1638- def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node ):
1630+ def generate_engine_class_header (class_api , used_classes , fully_used_classes , use_template_get_node , build_profile ):
16391631 global singletons
16401632 result = []
16411633
@@ -1735,6 +1727,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
17351727
17361728 if "methods" in class_api :
17371729 for method in class_api ["methods" ]:
1730+ if not is_method_included (method , build_profile ):
1731+ continue
17381732 if method ["is_virtual" ]:
17391733 # Will be done later.
17401734 continue
@@ -1759,6 +1753,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
17591753
17601754 # Virtuals now.
17611755 for method in class_api ["methods" ]:
1756+ if not is_method_included (method , build_profile ):
1757+ continue
17621758 if not method ["is_virtual" ]:
17631759 continue
17641760
@@ -1779,6 +1775,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
17791775 result .append (f"\t \t { inherits } ::register_virtuals<T, B>();" )
17801776 if "methods" in class_api :
17811777 for method in class_api ["methods" ]:
1778+ if not is_method_included (method , build_profile ):
1779+ continue
17821780 if not method ["is_virtual" ]:
17831781 continue
17841782 method_name = escape_identifier (method ["name" ])
@@ -1870,6 +1868,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
18701868 result .append ("\t \\ " )
18711869
18721870 for method in class_api ["methods" ]:
1871+ if not is_method_included (method , build_profile ):
1872+ continue
18731873 # ClassDBSingleton shouldn't have any static methods, but if some appear later, lets skip them.
18741874 if "is_static" in method and method ["is_static" ]:
18751875 continue
@@ -1944,7 +1944,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
19441944 return "\n " .join (result )
19451945
19461946
1947- def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node ):
1947+ def generate_engine_class_source (class_api , used_classes , fully_used_classes , use_template_get_node , build_profile ):
19481948 global singletons
19491949 result = []
19501950
@@ -2012,6 +2012,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
20122012
20132013 if "methods" in class_api :
20142014 for method in class_api ["methods" ]:
2015+ if not is_method_included (method , build_profile ):
2016+ continue
20152017 if method ["is_virtual" ]:
20162018 # Will be done later
20172019 continue
@@ -2106,6 +2108,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
21062108
21072109 # Virtuals now.
21082110 for method in class_api ["methods" ]:
2111+ if not is_method_included (method , build_profile ):
2112+ continue
21092113 if not method ["is_virtual" ]:
21102114 continue
21112115
@@ -2780,6 +2784,44 @@ def is_class_included(class_name, build_profile):
27802784 return True
27812785
27822786
2787+ def is_method_included (method , build_profile ):
2788+ """
2789+ Check if an engine class should be included.
2790+ This removes classes according to a build profile of enabled or disabled classes.
2791+ """
2792+ global engine_classes
2793+ included = build_profile .get ("enabled_classes" , [])
2794+ excluded = build_profile .get ("disabled_classes" , [])
2795+ ref_cls = set ()
2796+ rtype = get_base_type (method .get ("return_value" , {}).get ("type" , "" ))
2797+ args = [get_base_type (a ["type" ]) for a in method .get ("arguments" , [])]
2798+ if rtype in engine_classes :
2799+ ref_cls .add (rtype )
2800+ elif is_enum (rtype ) and get_enum_class (rtype ) in engine_classes :
2801+ ref_cls .add (get_enum_class (rtype ))
2802+ for arg in args :
2803+ if arg in engine_classes :
2804+ ref_cls .add (arg )
2805+ elif is_enum (arg ) and get_enum_class (arg ) in engine_classes :
2806+ ref_cls .add (get_enum_class (arg ))
2807+ for acls in ref_cls :
2808+ if len (included ) > 0 and acls not in included :
2809+ return False
2810+ elif len (excluded ) > 0 and acls in excluded :
2811+ return False
2812+ return True
2813+
2814+
2815+ def get_base_type (type_name ):
2816+ if type_name .startswith ("const " ):
2817+ type_name = type_name [6 :]
2818+ if type_name .endswith ("*" ):
2819+ type_name = type_name [:- 1 ]
2820+ if type_name .startswith ("typedarray::" ):
2821+ type_name = type_name .replace ("typedarray::" , "" )
2822+ return type_name
2823+
2824+
27832825def is_included (type_name , current_type ):
27842826 """
27852827 Check if a builtin type should be included.
0 commit comments