Skip to content

Commit d74cf74

Browse files
committed
Add support for build profiles.
Allow enabling or disabling specific classes (which will not be built).
1 parent 0ddef6e commit d74cf74

File tree

3 files changed

+105
-7
lines changed

3 files changed

+105
-7
lines changed

binding_generator.py

+76-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python
22

33
import json
4+
import os
45
import re
56
import shutil
67
from pathlib import Path
@@ -70,7 +71,15 @@ def generate_wrappers(target):
7071
f.write(txt)
7172

7273

73-
def get_file_list(api_filepath, output_dir, headers=False, sources=False):
74+
def is_class_included(class_name, build_profile):
75+
if "enabled_classes" in build_profile:
76+
return class_name in build_profile["enabled_classes"]
77+
if "disabled_classes" in build_profile:
78+
return class_name not in build_profile["disabled_classes"]
79+
return True
80+
81+
82+
def get_file_list(api_filepath, output_dir, headers=False, sources=False, build_profile={}):
7483
api = {}
7584
files = []
7685
with open(api_filepath, encoding="utf-8") as api_file:
@@ -97,6 +106,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
97106
files.append(str(source_filename.as_posix()))
98107

99108
for engine_class in api["classes"]:
109+
if not is_class_included(engine_class["name"], build_profile):
110+
continue
100111
# Generate code for the ClassDB singleton under a different name.
101112
if engine_class["name"] == "ClassDB":
102113
engine_class["name"] = "ClassDBSingleton"
@@ -137,12 +148,65 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
137148
return files
138149

139150

140-
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
141-
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
151+
def print_file_list(api_filepath, output_dir, headers=False, sources=False, build_profile={}):
152+
print(*get_file_list(api_filepath, output_dir, headers, sources, build_profile), sep=";", end=None)
153+
154+
155+
def scons_parse_build_profile(env, api_filepath):
156+
if not "build_profile" in env:
157+
return {}
158+
profile_filename = env["build_profile"]
159+
if not os.path.isabs(profile_filename):
160+
profile_filename = os.path.join(env.Dir("#").abspath, profile_filename)
161+
print("Using feature build profile: " + profile_filename)
162+
163+
with open(profile_filename, encoding="utf-8") as profile_file:
164+
profile = json.load(profile_file)
165+
166+
with open(api_filepath, encoding="utf-8") as api_file:
167+
api = json.load(api_file)
168+
169+
170+
parents = {}
171+
childs = {}
172+
for engine_class in api["classes"]:
173+
parent = engine_class.get("inherits", "")
174+
child = engine_class["name"]
175+
parents[child] = parent
176+
if parent == "":
177+
continue
178+
if parent not in childs:
179+
childs[parent] = childs.get(parent, [])
180+
childs[parent].append(child)
181+
182+
included = []
183+
front = list(profile.get("enabled_classes", []))
184+
while len(front):
185+
cls = front.pop()
186+
if cls in included:
187+
continue
188+
included.append(cls)
189+
parent = parents.get(cls, "")
190+
if parent:
191+
front.append(parent)
192+
193+
excluded = []
194+
front = list(profile.get("disabled_classes", []))
195+
while len(front):
196+
cls = front.pop()
197+
if cls in excluded:
198+
continue
199+
excluded.append(cls)
200+
front.concat(childs.get(cls, []))
201+
return {
202+
"enabled_classes": included,
203+
"disabled_classes": excluded,
204+
}
142205

143206

144207
def scons_emit_files(target, source, env):
145-
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]
208+
build_profile = scons_parse_build_profile(env, str(source[0]))
209+
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True, build_profile)]
146210
env.Clean(target, files)
147211
env["godot_cpp_gen_dir"] = target[0].abspath
148212
return files, source
@@ -159,7 +223,7 @@ def scons_generate_bindings(target, source, env):
159223
return None
160224

161225

162-
def generate_bindings(api_filepath, use_template_get_node, bits="64", precision="single", output_dir="."):
226+
def generate_bindings(api_filepath, use_template_get_node, bits="64", precision="single", output_dir=".", build_profile={}):
163227
api = None
164228

165229
target_dir = Path(output_dir) / "gen"
@@ -177,7 +241,7 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
177241
generate_version_header(api, target_dir)
178242
generate_global_constant_binds(api, target_dir)
179243
generate_builtin_bindings(api, target_dir, real_t + "_" + bits)
180-
generate_engine_classes_bindings(api, target_dir, use_template_get_node)
244+
generate_engine_classes_bindings(api, target_dir, use_template_get_node, build_profile)
181245
generate_utility_functions(api, target_dir)
182246

183247

@@ -1070,7 +1134,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
10701134
return "\n".join(result)
10711135

10721136

1073-
def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
1137+
def generate_engine_classes_bindings(api, output_dir, use_template_get_node, build_profile={}):
10741138
global engine_classes
10751139
global singletons
10761140
global native_structures
@@ -1083,6 +1147,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
10831147

10841148
# First create map of classes and singletons.
10851149
for class_api in api["classes"]:
1150+
if not is_class_included(class_api["name"], build_profile):
1151+
continue
10861152
# Generate code for the ClassDB singleton under a different name.
10871153
if class_api["name"] == "ClassDB":
10881154
class_api["name"] = "ClassDBSingleton"
@@ -1102,6 +1168,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
11021168
singletons.append(singleton["name"])
11031169

11041170
for class_api in api["classes"]:
1171+
if not is_class_included(class_api["name"], build_profile):
1172+
continue
1173+
11051174
# Check used classes for header include.
11061175
used_classes = set()
11071176
fully_used_classes = set()

test/build_profile.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"enabled_classes": [
3+
"Control",
4+
"Viewport",
5+
"InputEventKey",
6+
"TileMap",
7+
"Label",
8+
"ClassDB",
9+
"Texture2D",
10+
"Material",
11+
"StyleBox",
12+
"SceneTree",
13+
"Mesh",
14+
"Window",
15+
"FileAccess",
16+
"DirAccess",
17+
"Shader",
18+
"Multimesh"
19+
]
20+
}

tools/godotcpp.py

+9
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ def options(opts, env):
198198
)
199199
)
200200

201+
opts.Add(
202+
PathVariable(
203+
"build_profile",
204+
"Path to a file containing a feature build profile",
205+
default=env.get("build_profile", None),
206+
validator=validate_file,
207+
)
208+
)
209+
201210
# Add platform options
202211
for pl in platforms:
203212
tool = Tool(pl, toolpath=["tools"])

0 commit comments

Comments
 (0)