Skip to content

Commit

Permalink
Add support for build profiles.
Browse files Browse the repository at this point in the history
Allow enabling or disabling specific classes (which will not be built).
  • Loading branch information
Faless committed Jan 18, 2024
1 parent 0ddef6e commit 081c693
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 7 deletions.
84 changes: 77 additions & 7 deletions binding_generator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python

import json
import os
import re
import shutil
from pathlib import Path
Expand Down Expand Up @@ -70,7 +71,15 @@ def generate_wrappers(target):
f.write(txt)


def get_file_list(api_filepath, output_dir, headers=False, sources=False):
def is_class_included(class_name, build_profile):
if "enabled_classes" in build_profile:
return class_name in build_profile["enabled_classes"]
if "disabled_classes" in build_profile:
return class_name not in build_profile["disabled_classes"]
return True


def get_file_list(api_filepath, output_dir, headers=False, sources=False, build_profile={}):
api = {}
files = []
with open(api_filepath, encoding="utf-8") as api_file:
Expand All @@ -97,6 +106,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
files.append(str(source_filename.as_posix()))

for engine_class in api["classes"]:
if not is_class_included(engine_class["name"], build_profile):
continue
# Generate code for the ClassDB singleton under a different name.
if engine_class["name"] == "ClassDB":
engine_class["name"] = "ClassDBSingleton"
Expand Down Expand Up @@ -137,12 +148,64 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
return files


def print_file_list(api_filepath, output_dir, headers=False, sources=False):
print(*get_file_list(api_filepath, output_dir, headers, sources), sep=";", end=None)
def print_file_list(api_filepath, output_dir, headers=False, sources=False, build_profile={}):
print(*get_file_list(api_filepath, output_dir, headers, sources, build_profile), sep=";", end=None)


def scons_parse_build_profile(env, api_filepath):
if not "build_profile" in env:
return {}
profile_filename = env["build_profile"]
if not os.path.isabs(profile_filename):
profile_filename = os.path.join(env.Dir("#").abspath, profile_filename)
print("Using feature build profile: " + profile_filename)

with open(profile_filename, encoding="utf-8") as profile_file:
profile = json.load(profile_file)

with open(api_filepath, encoding="utf-8") as api_file:
api = json.load(api_file)

parents = {}
childs = {}
for engine_class in api["classes"]:
parent = engine_class.get("inherits", "")
child = engine_class["name"]
parents[child] = parent
if parent == "":
continue
if parent not in childs:
childs[parent] = childs.get(parent, [])
childs[parent].append(child)

included = []
front = list(profile.get("enabled_classes", []))
while len(front):
cls = front.pop()
if cls in included:
continue
included.append(cls)
parent = parents.get(cls, "")
if parent:
front.append(parent)

excluded = []
front = list(profile.get("disabled_classes", []))
while len(front):
cls = front.pop()
if cls in excluded:
continue
excluded.append(cls)
front.concat(childs.get(cls, []))
return {
"enabled_classes": included,
"disabled_classes": excluded,
}


def scons_emit_files(target, source, env):
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]
build_profile = scons_parse_build_profile(env, str(source[0]))
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True, build_profile)]
env.Clean(target, files)
env["godot_cpp_gen_dir"] = target[0].abspath
return files, source
Expand All @@ -159,7 +222,9 @@ def scons_generate_bindings(target, source, env):
return None


def generate_bindings(api_filepath, use_template_get_node, bits="64", precision="single", output_dir="."):
def generate_bindings(
api_filepath, use_template_get_node, bits="64", precision="single", output_dir=".", build_profile={}
):
api = None

target_dir = Path(output_dir) / "gen"
Expand All @@ -177,7 +242,7 @@ def generate_bindings(api_filepath, use_template_get_node, bits="64", precision=
generate_version_header(api, target_dir)
generate_global_constant_binds(api, target_dir)
generate_builtin_bindings(api, target_dir, real_t + "_" + bits)
generate_engine_classes_bindings(api, target_dir, use_template_get_node)
generate_engine_classes_bindings(api, target_dir, use_template_get_node, build_profile)
generate_utility_functions(api, target_dir)


Expand Down Expand Up @@ -1070,7 +1135,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
return "\n".join(result)


def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
def generate_engine_classes_bindings(api, output_dir, use_template_get_node, build_profile={}):
global engine_classes
global singletons
global native_structures
Expand All @@ -1083,6 +1148,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):

# First create map of classes and singletons.
for class_api in api["classes"]:
if not is_class_included(class_api["name"], build_profile):
continue
# Generate code for the ClassDB singleton under a different name.
if class_api["name"] == "ClassDB":
class_api["name"] = "ClassDBSingleton"
Expand All @@ -1102,6 +1169,9 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
singletons.append(singleton["name"])

for class_api in api["classes"]:
if not is_class_included(class_api["name"], build_profile):
continue

# Check used classes for header include.
used_classes = set()
fully_used_classes = set()
Expand Down
20 changes: 20 additions & 0 deletions test/build_profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"enabled_classes": [
"Control",
"Viewport",
"InputEventKey",
"TileMap",
"Label",
"ClassDB",
"Texture2D",
"Material",
"StyleBox",
"SceneTree",
"Mesh",
"Window",
"FileAccess",
"DirAccess",
"Shader",
"Multimesh"
]
}
9 changes: 9 additions & 0 deletions tools/godotcpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ def options(opts, env):
)
)

opts.Add(
PathVariable(
"build_profile",
"Path to a file containing a feature build profile",
default=env.get("build_profile", None),
validator=validate_file,
)
)

# Add platform options
for pl in platforms:
tool = Tool(pl, toolpath=["tools"])
Expand Down

0 comments on commit 081c693

Please sign in to comment.