Skip to content

Commit fa698dd

Browse files
committed
[Scons] Use builder to track bindings regeneration.
Using a scons Builder we now regenerate the bindings automatically when the Godot API json or header has changed. The option to force bindings regeneration (generate_bindings=yes) is retained.
1 parent 1ad24f1 commit fa698dd

File tree

2 files changed

+40
-38
lines changed

2 files changed

+40
-38
lines changed

SConstruct

+13-29
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import sys
55
import subprocess
6+
from binding_generator import scons_generate_bindings, scons_emit_files
67

78
if sys.version_info < (3,):
89

@@ -112,13 +113,7 @@ opts.Add(
112113
)
113114
opts.Add(PathVariable("custom_api_file", "Path to a custom JSON API file", None, PathVariable.PathIsFile))
114115
opts.Add(
115-
EnumVariable(
116-
"generate_bindings",
117-
"Generate GDNative API bindings",
118-
"auto",
119-
allowed_values=["yes", "no", "auto", "true"],
120-
ignorecase=2,
121-
)
116+
BoolVariable("generate_bindings", "Force GDExtension API bindings generation. Auto-detected by default.", False)
122117
)
123118
opts.Add(EnumVariable("android_arch", "Target Android architecture", "armv7", ["armv7", "arm64v8", "x86", "x86_64"]))
124119
opts.Add("macos_deployment_target", "macOS deployment target", "default")
@@ -442,43 +437,33 @@ elif env["platform"] == "javascript":
442437
elif env["target"] == "release":
443438
env.Append(CCFLAGS=["-O3"])
444439

445-
env.Append(
446-
CPPPATH=[
447-
".",
448-
env["headers_dir"],
449-
"#include",
450-
"#gen/include",
451-
]
452-
)
453-
454-
# Generate bindings?
440+
# Generate bindings
441+
env.Append(BUILDERS={"GenerateBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
455442
json_api_file = ""
456443

457444
if "custom_api_file" in env:
458445
json_api_file = env["custom_api_file"]
459446
else:
460447
json_api_file = os.path.join(os.getcwd(), env["headers_dir"], "extension_api.json")
461448

462-
if env["generate_bindings"] == "auto":
463-
# Check if generated files exist
464-
should_generate_bindings = not os.path.isfile(os.path.join(os.getcwd(), "gen", "src", "classes", "object.cpp"))
465-
else:
466-
should_generate_bindings = env["generate_bindings"] in ["yes", "true"]
449+
bindings = env.GenerateBindings(
450+
env.Dir("."), [json_api_file, os.path.join(env["headers_dir"], "godot", "gdnative_interface.h")]
451+
)
467452

468-
if should_generate_bindings:
469-
# Actually create the bindings here
470-
import binding_generator
453+
# Forces bindings regeneration.
454+
if env["generate_bindings"]:
455+
AlwaysBuild(bindings)
471456

472-
binding_generator.generate_bindings(json_api_file, env["generate_template_get_node"])
457+
# Includes
458+
env.Append(CPPPATH=[[env.Dir(d) for d in [env["headers_dir"], "include", os.path.join("gen", "include")]]])
473459

474460
# Sources to compile
475461
sources = []
476462
add_sources(sources, "src", "cpp")
477463
add_sources(sources, "src/classes", "cpp")
478464
add_sources(sources, "src/core", "cpp")
479465
add_sources(sources, "src/variant", "cpp")
480-
add_sources(sources, "gen/src/variant", "cpp")
481-
add_sources(sources, "gen/src/classes", "cpp")
466+
sources.extend([f for f in bindings if str(f).endswith(".cpp")])
482467

483468
env["arch_suffix"] = env["bits"]
484469
if env["platform"] == "android":
@@ -500,7 +485,6 @@ if env["build_library"]:
500485
library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources)
501486
Default(library)
502487

503-
env.Append(CPPPATH=[env.Dir(f) for f in ["gen/include", "include", "godot-headers"]])
504488
env.Append(LIBPATH=[env.Dir("bin")])
505489
env.Append(LIBS=library_name)
506490
Return("env")

binding_generator.py

+27-9
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
from pathlib import Path
77

88

9-
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
9+
def get_file_list(api_filepath, output_dir, headers=False, sources=False):
1010
api = {}
11-
end = ";"
11+
files = []
1212
with open(api_filepath) as api_file:
1313
api = json.load(api_file)
1414

@@ -25,9 +25,9 @@ def print_file_list(api_filepath, output_dir, headers=False, sources=False):
2525
header_filename = include_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".hpp")
2626
source_filename = source_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".cpp")
2727
if headers:
28-
print(str(header_filename.as_posix()), end=end)
28+
files.append(str(header_filename.as_posix()))
2929
if sources:
30-
print(str(source_filename.as_posix()), end=end)
30+
files.append(str(source_filename.as_posix()))
3131

3232
for engine_class in api["classes"]:
3333
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
@@ -36,18 +36,36 @@ def print_file_list(api_filepath, output_dir, headers=False, sources=False):
3636
header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp")
3737
source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp")
3838
if headers:
39-
print(str(header_filename.as_posix()), end=end)
39+
files.append(str(header_filename.as_posix()))
4040
if sources:
41-
print(str(source_filename.as_posix()), end=end)
41+
files.append(str(source_filename.as_posix()))
4242

4343
utility_functions_header_path = include_gen_folder / "variant" / "utility_functions.hpp"
4444
utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp"
4545
global_constants_header_path = include_gen_folder / "classes" / "global_constants.hpp"
4646
if headers:
47-
print(str(utility_functions_header_path.as_posix()), end=end)
48-
print(str(global_constants_header_path.as_posix()), end=end)
47+
files.append(str(utility_functions_header_path.as_posix()))
48+
files.append(str(global_constants_header_path.as_posix()))
4949
if sources:
50-
print(str(utility_functions_source_path.as_posix()), end=end)
50+
files.append(str(utility_functions_source_path.as_posix()))
51+
return files
52+
53+
54+
def print_file_list(api_filepath, output_dir, headers=False, sources=False):
55+
end = ";"
56+
for f in get_file_list(api_filepath, output_dir, headers, sources):
57+
print(f, end=end)
58+
59+
60+
def scons_emit_files(target, source, env):
61+
files = [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]
62+
env.Clean(files, target)
63+
return [target[0]] + files, source
64+
65+
66+
def scons_generate_bindings(target, source, env):
67+
generate_bindings(str(source[0]), env["generate_template_get_node"], target[0].abspath)
68+
return None
5169

5270

5371
def generate_bindings(api_filepath, use_template_get_node, output_dir="."):

0 commit comments

Comments
 (0)