diff --git a/SConstruct b/SConstruct index ed352e2..a735709 100644 --- a/SConstruct +++ b/SConstruct @@ -3,6 +3,7 @@ import os import sys import subprocess +from binding_generator import scons_generate_bindings, scons_emit_files if sys.version_info < (3,): @@ -112,13 +113,7 @@ opts.Add( ) opts.Add(PathVariable("custom_api_file", "Path to a custom JSON API file", None, PathVariable.PathIsFile)) opts.Add( - EnumVariable( - "generate_bindings", - "Generate GDNative API bindings", - "auto", - allowed_values=["yes", "no", "auto", "true"], - ignorecase=2, - ) + BoolVariable("generate_bindings", "Force GDExtension API bindings generation. Auto-detected by default.", False) ) opts.Add(EnumVariable("android_arch", "Target Android architecture", "armv7", ["armv7", "arm64v8", "x86", "x86_64"])) opts.Add("macos_deployment_target", "macOS deployment target", "default") @@ -442,16 +437,8 @@ elif env["platform"] == "javascript": elif env["target"] == "release": env.Append(CCFLAGS=["-O3"]) -env.Append( - CPPPATH=[ - ".", - env["headers_dir"], - "#include", - "#gen/include", - ] -) - -# Generate bindings? +# Generate bindings +env.Append(BUILDERS={"GenerateBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)}) json_api_file = "" if "custom_api_file" in env: @@ -459,17 +446,16 @@ if "custom_api_file" in env: else: json_api_file = os.path.join(os.getcwd(), env["headers_dir"], "extension_api.json") -if env["generate_bindings"] == "auto": - # Check if generated files exist - should_generate_bindings = not os.path.isfile(os.path.join(os.getcwd(), "gen", "src", "classes", "object.cpp")) -else: - should_generate_bindings = env["generate_bindings"] in ["yes", "true"] +bindings = env.GenerateBindings( + env.Dir("."), [json_api_file, os.path.join(env["headers_dir"], "godot", "gdnative_interface.h")] +) -if should_generate_bindings: - # Actually create the bindings here - import binding_generator +# Forces bindings regeneration. +if env["generate_bindings"]: + AlwaysBuild(bindings) - binding_generator.generate_bindings(json_api_file, env["generate_template_get_node"]) +# Includes +env.Append(CPPPATH=[[env.Dir(d) for d in [env["headers_dir"], "include", os.path.join("gen", "include")]]]) # Sources to compile sources = [] @@ -477,8 +463,7 @@ add_sources(sources, "src", "cpp") add_sources(sources, "src/classes", "cpp") add_sources(sources, "src/core", "cpp") add_sources(sources, "src/variant", "cpp") -add_sources(sources, "gen/src/variant", "cpp") -add_sources(sources, "gen/src/classes", "cpp") +sources.extend([f for f in bindings if str(f).endswith(".cpp")]) env["arch_suffix"] = env["bits"] if env["platform"] == "android": @@ -500,7 +485,6 @@ if env["build_library"]: library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources) Default(library) -env.Append(CPPPATH=[env.Dir(f) for f in ["gen/include", "include", "godot-headers"]]) env.Append(LIBPATH=[env.Dir("bin")]) env.Append(LIBS=library_name) Return("env") diff --git a/binding_generator.py b/binding_generator.py index 7211261..2b18a78 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -6,9 +6,9 @@ import shutil from pathlib import Path -def print_file_list(api_filepath, output_dir, headers=False, sources=False): +def get_file_list(api_filepath, output_dir, headers=False, sources=False): api = {} - end = ";" + files = [] with open(api_filepath) as api_file: api = json.load(api_file) @@ -25,9 +25,9 @@ def print_file_list(api_filepath, output_dir, headers=False, sources=False): header_filename = include_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".hpp") source_filename = source_gen_folder / "variant" / (camel_to_snake(builtin_class["name"]) + ".cpp") if headers: - print(str(header_filename.as_posix()), end=end) + files.append(str(header_filename.as_posix())) if sources: - print(str(source_filename.as_posix()), end=end) + files.append(str(source_filename.as_posix())) for engine_class in api["classes"]: # 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): header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp") source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp") if headers: - print(str(header_filename.as_posix()), end=end) + files.append(str(header_filename.as_posix())) if sources: - print(str(source_filename.as_posix()), end=end) + files.append(str(source_filename.as_posix())) utility_functions_header_path = include_gen_folder / "variant" / "utility_functions.hpp" utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp" global_constants_header_path = include_gen_folder / "classes" / "global_constants.hpp" if headers: - print(str(utility_functions_header_path.as_posix()), end=end) - print(str(global_constants_header_path.as_posix()), end=end) + files.append(str(utility_functions_header_path.as_posix())) + files.append(str(global_constants_header_path.as_posix())) if sources: - print(str(utility_functions_source_path.as_posix()), end=end) + files.append(str(utility_functions_source_path.as_posix())) + return files + + +def print_file_list(api_filepath, output_dir, headers=False, sources=False): + end = ";" + for f in get_file_list(api_filepath, output_dir, headers, sources): + print(f, end=end) + + +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)] + env.Clean(files, target) + return [target[0]] + files, source + + +def scons_generate_bindings(target, source, env): + generate_bindings(str(source[0]), env["generate_template_get_node"], target[0].abspath) + return None def generate_bindings(api_filepath, use_template_get_node, output_dir="."):