Merge pull request #1244 from dsnopek/4.1-cherrypicks-3

Cherry-picks for the godot-cpp 4.1 branch - 3rd batch
pull/1261/head
Rémi Verschelde 2023-09-20 23:48:26 +02:00 committed by GitHub
commit 4eed2d7be0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 143 additions and 47 deletions

View File

@ -83,7 +83,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
@ -168,7 +168,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
@ -192,7 +192,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
@ -216,7 +216,7 @@ jobs:
runs-on: windows-2019 runs-on: windows-2019
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
# Azure repositories are not reliable, we need to prevent Azure giving us packages. # Azure repositories are not reliable, we need to prevent Azure giving us packages.
- name: Make apt sources.list use the default Ubuntu repositories - name: Make apt sources.list use the default Ubuntu repositories

View File

@ -5,7 +5,6 @@ import platform
import sys import sys
import subprocess import subprocess
from binding_generator import scons_generate_bindings, scons_emit_files from binding_generator import scons_generate_bindings, scons_emit_files
from SCons.Errors import UserError
EnsureSConsVersion(4, 0) EnsureSConsVersion(4, 0)

View File

@ -97,9 +97,10 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
files.append(str(source_filename.as_posix())) files.append(str(source_filename.as_posix()))
for engine_class in api["classes"]: for engine_class in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings. # Generate code for the ClassDB singleton under a different name.
if engine_class["name"] == "ClassDB": if engine_class["name"] == "ClassDB":
continue engine_class["name"] = "ClassDBSingleton"
engine_class["alias_for"] = "ClassDB"
header_filename = include_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".hpp") 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") source_filename = source_gen_folder / "classes" / (camel_to_snake(engine_class["name"]) + ".cpp")
if headers: if headers:
@ -1038,21 +1039,23 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
# First create map of classes and singletons. # First create map of classes and singletons.
for class_api in api["classes"]: for class_api in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings. # Generate code for the ClassDB singleton under a different name.
if class_api["name"] == "ClassDB": if class_api["name"] == "ClassDB":
continue class_api["name"] = "ClassDBSingleton"
class_api["alias_for"] = "ClassDB"
engine_classes[class_api["name"]] = class_api["is_refcounted"] engine_classes[class_api["name"]] = class_api["is_refcounted"]
for native_struct in api["native_structures"]: for native_struct in api["native_structures"]:
engine_classes[native_struct["name"]] = False engine_classes[native_struct["name"]] = False
native_structures.append(native_struct["name"]) native_structures.append(native_struct["name"])
for singleton in api["singletons"]: for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name.
if singleton["name"] == "ClassDB":
singleton["name"] = "ClassDBSingleton"
singleton["alias_for"] = "ClassDB"
singletons.append(singleton["name"]) singletons.append(singleton["name"])
for class_api in api["classes"]: for class_api in api["classes"]:
# TODO: Properly setup this singleton since it conflicts with ClassDB in the bindings.
if class_api["name"] == "ClassDB":
continue
# Check used classes for header include. # Check used classes for header include.
used_classes = set() used_classes = set()
fully_used_classes = set() fully_used_classes = set()
@ -1142,6 +1145,12 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
else: else:
fully_used_classes.add("Wrapped") fully_used_classes.add("Wrapped")
# In order to ensure that PtrToArg specializations for native structs are
# always used, let's move any of them into 'fully_used_classes'.
for type_name in used_classes:
if is_struct_type(type_name) and not is_included_struct_type(type_name):
fully_used_classes.add(type_name)
for type_name in fully_used_classes: for type_name in fully_used_classes:
if type_name in used_classes: if type_name in used_classes:
used_classes.remove(type_name) used_classes.remove(type_name)
@ -1244,7 +1253,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
if len(fully_used_classes) > 0: if len(fully_used_classes) > 0:
result.append("") result.append("")
if class_name != "Object": if class_name != "Object" and class_name != "ClassDBSingleton":
result.append("#include <godot_cpp/core/class_db.hpp>") result.append("#include <godot_cpp/core/class_db.hpp>")
result.append("") result.append("")
result.append("#include <type_traits>") result.append("#include <type_traits>")
@ -1265,6 +1274,9 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped" inherits = class_api["inherits"] if "inherits" in class_api else "Wrapped"
result.append(f"class {class_name} : public {inherits} {{") result.append(f"class {class_name} : public {inherits} {{")
if "alias_for" in class_api:
result.append(f"\tGDEXTENSION_CLASS_ALIAS({class_name}, {class_api['alias_for']}, {inherits})")
else:
result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})") result.append(f"\tGDEXTENSION_CLASS({class_name}, {inherits})")
result.append("") result.append("")
@ -1423,6 +1435,51 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});') result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});')
result.append("") result.append("")
if class_name == "ClassDBSingleton":
result.append("#define CLASSDB_SINGLETON_FORWARD_METHODS \\")
for method in class_api["methods"]:
# ClassDBSingleton shouldn't have any static or vararg methods, but if some appear later, lets skip them.
if vararg:
continue
if "is_static" in method and method["is_static"]:
continue
method_signature = "\tstatic "
if "return_type" in method:
method_signature += f'{correct_type(method["return_type"])} '
elif "return_value" in method:
method_signature += (
correct_type(method["return_value"]["type"], method["return_value"].get("meta", None)) + " "
)
else:
method_signature += "void "
method_signature += f'{method["name"]}('
method_arguments = []
if "arguments" in method:
method_arguments = method["arguments"]
method_signature += make_function_parameters(
method_arguments, include_default=True, for_builtin=True, is_vararg=False
)
method_signature += ") { \\"
result.append(method_signature)
method_body = "\t\t"
if "return_type" in method or "return_value" in method:
method_body += "return "
method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}('
method_body += ", ".join(map(lambda x: escape_identifier(x["name"]), method_arguments))
method_body += "); \\"
result.append(method_body)
result.append("\t} \\")
result.append("\t;")
result.append("")
result.append(f"#endif // ! {header_guard}") result.append(f"#endif // ! {header_guard}")
return "\n".join(result) return "\n".join(result)
@ -2319,6 +2376,7 @@ def escape_identifier(id):
"operator": "_operator", "operator": "_operator",
"typeof": "type_of", "typeof": "type_of",
"typename": "type_name", "typename": "type_name",
"enum": "_enum",
} }
if id in cpp_keywords_map: if id in cpp_keywords_map:
return cpp_keywords_map[id] return cpp_keywords_map[id]

View File

@ -132,16 +132,16 @@ protected:
return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \ return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \
} \ } \
\ \
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \ static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name)) & m_class::_property_can_revert; \ return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \
} \ } \
\ \
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) { \ static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) const { \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &)) & m_class::_property_get_revert; \ return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
} \ } \
\ \
static ::godot::String (::godot::Wrapped::*_get_to_string())() { \ static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
return (::godot::String(::godot::Wrapped::*)()) & m_class::_to_string; \ return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \ } \
\ \
template <class T, class B> \ template <class T, class B> \
@ -306,7 +306,7 @@ public:
}; };
// Don't use this for your classes, use GDCLASS() instead. // Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) \ #define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \
private: \ private: \
void operator=(const m_class &p_rval) {} \ void operator=(const m_class &p_rval) {} \
\ \
@ -338,15 +338,15 @@ protected:
return nullptr; \ return nullptr; \
} \ } \
\ \
static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) { \ static bool (Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return nullptr; \ return nullptr; \
} \ } \
\ \
static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) { \ static bool (Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, Variant &) const { \
return nullptr; \ return nullptr; \
} \ } \
\ \
static String (Wrapped::*_get_to_string())() { \ static String (Wrapped::*_get_to_string())() const { \
return nullptr; \ return nullptr; \
} \ } \
\ \
@ -354,7 +354,7 @@ public:
static void initialize_class() {} \ static void initialize_class() {} \
\ \
static ::godot::StringName &get_class_static() { \ static ::godot::StringName &get_class_static() { \
static ::godot::StringName string_name = ::godot::StringName(#m_class); \ static ::godot::StringName string_name = ::godot::StringName(#m_alias_for); \
return string_name; \ return string_name; \
} \ } \
\ \
@ -379,6 +379,9 @@ public:
_gde_binding_free_callback, \ _gde_binding_free_callback, \
_gde_binding_reference_callback, \ _gde_binding_reference_callback, \
}; \ }; \
m_class() : m_class(#m_class) {} m_class() : m_class(#m_alias_for) {}
// Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
#endif // GODOT_WRAPPED_HPP #endif // GODOT_WRAPPED_HPP

View File

@ -38,6 +38,8 @@
#include <godot_cpp/core/method_bind.hpp> #include <godot_cpp/core/method_bind.hpp>
#include <godot_cpp/core/object.hpp> #include <godot_cpp/core/object.hpp>
#include <godot_cpp/classes/class_db_singleton.hpp>
#include <list> #include <list>
#include <set> #include <set>
#include <string> #include <string>
@ -146,6 +148,8 @@ public:
static void initialize(GDExtensionInitializationLevel p_level); static void initialize(GDExtensionInitializationLevel p_level);
static void deinitialize(GDExtensionInitializationLevel p_level); static void deinitialize(GDExtensionInitializationLevel p_level);
CLASSDB_SINGLETON_FORWARD_METHODS;
}; };
#define BIND_CONSTANT(m_constant) \ #define BIND_CONSTANT(m_constant) \

View File

@ -168,6 +168,7 @@ MAKE_PTRARG_BY_REFERENCE(Variant);
template <class T> template <class T>
struct PtrToArg<T *> { struct PtrToArg<T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static T *convert(const void *p_ptr) { _FORCE_INLINE_ static T *convert(const void *p_ptr) {
return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))); return reinterpret_cast<T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
} }
@ -179,6 +180,7 @@ struct PtrToArg<T *> {
template <class T> template <class T>
struct PtrToArg<const T *> { struct PtrToArg<const T *> {
static_assert(std::is_base_of<Object, T>::value, "Cannot encode non-Object value as an Object");
_FORCE_INLINE_ static const T *convert(const void *p_ptr) { _FORCE_INLINE_ static const T *convert(const void *p_ptr) {
return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr)))); return reinterpret_cast<const T *>(godot::internal::get_object_instance_binding(*reinterpret_cast<GDExtensionObjectPtr *>(const_cast<void *>(p_ptr))));
} }

View File

@ -34,6 +34,7 @@
#include <godot_cpp/classes/wrapped.hpp> #include <godot_cpp/classes/wrapped.hpp>
#include <godot_cpp/core/class_db.hpp> #include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/memory.hpp> #include <godot_cpp/core/memory.hpp>
#include <godot_cpp/core/version.hpp>
#include <godot_cpp/variant/variant.hpp> #include <godot_cpp/variant/variant.hpp>
#include <godot_cpp/core/error_macros.hpp> #include <godot_cpp/core/error_macros.hpp>
@ -192,9 +193,15 @@ GDExtensionBinding::Callback GDExtensionBinding::init_callback = nullptr;
GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr; GDExtensionBinding::Callback GDExtensionBinding::terminate_callback = nullptr;
GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE; GDExtensionInitializationLevel GDExtensionBinding::minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
#define ERR_PRINT_EARLY(m_msg) \
internal::gdextension_interface_print_error(m_msg, FUNCTION_STR, __FILE__, __LINE__, false)
#define LOAD_PROC_ADDRESS(m_name, m_type) \ #define LOAD_PROC_ADDRESS(m_name, m_type) \
internal::gdextension_interface_##m_name = (m_type)p_get_proc_address(#m_name); \ internal::gdextension_interface_##m_name = (m_type)p_get_proc_address(#m_name); \
ERR_FAIL_NULL_V_MSG(internal::gdextension_interface_##m_name, false, "Unable to load GDExtension interface function " #m_name "()") if (!internal::gdextension_interface_##m_name) { \
ERR_PRINT_EARLY("Unable to load GDExtension interface function " #m_name "()"); \
return false; \
}
// Partial definition of the legacy interface so we can detect it and show an error. // Partial definition of the legacy interface so we can detect it and show an error.
typedef struct { typedef struct {
@ -217,14 +224,15 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
if (raw_interface[0] == 4 && raw_interface[1] == 0) { if (raw_interface[0] == 4 && raw_interface[1] == 0) {
// Use the legacy interface only to give a nice error. // Use the legacy interface only to give a nice error.
LegacyGDExtensionInterface *legacy_interface = (LegacyGDExtensionInterface *)p_get_proc_address; LegacyGDExtensionInterface *legacy_interface = (LegacyGDExtensionInterface *)p_get_proc_address;
internal::gdextension_interface_print_error_with_message = (GDExtensionInterfacePrintErrorWithMessage)legacy_interface->print_error_with_message; internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)legacy_interface->print_error;
ERR_FAIL_V_MSG(false, "Cannot load a GDExtension built for Godot 4.1+ in Godot 4.0."); ERR_PRINT_EARLY("Cannot load a GDExtension built for Godot 4.1+ in Godot 4.0.");
return false;
} }
// Load the "print_error_with_message" function first (needed by the ERR_FAIL_NULL_V_MSG() macro). // Load the "print_error" function first (needed by the ERR_PRINT_EARLY() macro).
internal::gdextension_interface_print_error_with_message = (GDExtensionInterfacePrintErrorWithMessage)p_get_proc_address("print_error_with_message"); internal::gdextension_interface_print_error = (GDExtensionInterfacePrintError)p_get_proc_address("print_error");
if (!internal::gdextension_interface_print_error_with_message) { if (!internal::gdextension_interface_print_error) {
printf("ERROR: Unable to load GDExtension interface function print_error_with_message().\n"); printf("ERROR: Unable to load GDExtension interface function print_error().\n");
return false; return false;
} }
@ -233,10 +241,33 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
internal::token = p_library; internal::token = p_library;
LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion); LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion);
internal::gdextension_interface_get_godot_version(&internal::godot_version);
// Check that godot-cpp was compiled using an extension_api.json older or at the
// same version as the Godot that is loading it.
bool compatible;
if (internal::godot_version.major != GODOT_VERSION_MAJOR) {
compatible = internal::godot_version.major > GODOT_VERSION_MAJOR;
} else if (internal::godot_version.minor != GODOT_VERSION_MINOR) {
compatible = internal::godot_version.minor > GODOT_VERSION_MINOR;
} else {
compatible = internal::godot_version.patch >= GODOT_VERSION_PATCH;
}
if (!compatible) {
// We need to use snprintf() here because vformat() uses Variant, and we haven't loaded
// the GDExtension interface far enough to use Variants yet.
char msg[128];
snprintf(msg, 128, "Cannot load a GDExtension built for Godot %d.%d.%d using an older version of Godot (%d.%d.%d).",
GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH,
internal::godot_version.major, internal::godot_version.minor, internal::godot_version.patch);
ERR_PRINT_EARLY(msg);
return false;
}
LOAD_PROC_ADDRESS(mem_alloc, GDExtensionInterfaceMemAlloc); LOAD_PROC_ADDRESS(mem_alloc, GDExtensionInterfaceMemAlloc);
LOAD_PROC_ADDRESS(mem_realloc, GDExtensionInterfaceMemRealloc); LOAD_PROC_ADDRESS(mem_realloc, GDExtensionInterfaceMemRealloc);
LOAD_PROC_ADDRESS(mem_free, GDExtensionInterfaceMemFree); LOAD_PROC_ADDRESS(mem_free, GDExtensionInterfaceMemFree);
LOAD_PROC_ADDRESS(print_error, GDExtensionInterfacePrintError); LOAD_PROC_ADDRESS(print_error_with_message, GDExtensionInterfacePrintErrorWithMessage);
LOAD_PROC_ADDRESS(print_warning, GDExtensionInterfacePrintWarning); LOAD_PROC_ADDRESS(print_warning, GDExtensionInterfacePrintWarning);
LOAD_PROC_ADDRESS(print_warning_with_message, GDExtensionInterfacePrintWarningWithMessage); LOAD_PROC_ADDRESS(print_warning_with_message, GDExtensionInterfacePrintWarningWithMessage);
LOAD_PROC_ADDRESS(print_script_error, GDExtensionInterfacePrintScriptError); LOAD_PROC_ADDRESS(print_script_error, GDExtensionInterfacePrintScriptError);
@ -368,9 +399,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin); LOAD_PROC_ADDRESS(editor_add_plugin, GDExtensionInterfaceEditorAddPlugin);
LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin); LOAD_PROC_ADDRESS(editor_remove_plugin, GDExtensionInterfaceEditorRemovePlugin);
// Load the Godot version.
internal::gdextension_interface_get_godot_version(&internal::godot_version);
r_initialization->initialize = initialize_level; r_initialization->initialize = initialize_level;
r_initialization->deinitialize = deinitialize_level; r_initialization->deinitialize = deinitialize_level;
r_initialization->minimum_initialization_level = minimum_initialization_level; r_initialization->minimum_initialization_level = minimum_initialization_level;
@ -384,6 +412,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
} }
#undef LOAD_PROC_ADDRESS #undef LOAD_PROC_ADDRESS
#undef ERR_PRINT_EARLY
void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) { void GDExtensionBinding::initialize_level(void *userdata, GDExtensionInitializationLevel p_level) {
ClassDB::current_level = p_level; ClassDB::current_level = p_level;

View File

@ -12,7 +12,7 @@ config_version=5
config/name="GDExtension Test Project" config/name="GDExtension Test Project"
run/main_scene="res://main.tscn" run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.1")
config/icon="res://icon.png" config/icon="res://icon.png"
[native_extensions] [native_extensions]

View File

@ -29,7 +29,7 @@ def generate(env):
if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"): if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"):
print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.") print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.")
Exit() env.Exit(1)
if sys.platform == "win32" or sys.platform == "msys": if sys.platform == "win32" or sys.platform == "msys":
my_spawn.configure(env) my_spawn.configure(env)

View File

@ -3,6 +3,7 @@ import os, sys, platform
from SCons.Variables import EnumVariable, PathVariable, BoolVariable from SCons.Variables import EnumVariable, PathVariable, BoolVariable
from SCons.Tool import Tool from SCons.Tool import Tool
from SCons.Builder import Builder from SCons.Builder import Builder
from SCons.Errors import UserError
from binding_generator import scons_generate_bindings, scons_emit_files from binding_generator import scons_generate_bindings, scons_emit_files
@ -226,7 +227,7 @@ def generate(env):
env["arch"] = "x86_32" env["arch"] = "x86_32"
else: else:
print("Unsupported CPU architecture: " + host_machine) print("Unsupported CPU architecture: " + host_machine)
Exit() env.Exit(1)
print("Building for architecture " + env["arch"] + " on platform " + env["platform"]) print("Building for architecture " + env["arch"] + " on platform " + env["platform"])
@ -284,8 +285,8 @@ def _godot_cpp(env):
) )
# Forces bindings regeneration. # Forces bindings regeneration.
if env["generate_bindings"]: if env["generate_bindings"]:
AlwaysBuild(bindings) env.AlwaysBuild(bindings)
NoCache(bindings) env.NoCache(bindings)
# Sources to compile # Sources to compile
sources = [] sources = []

View File

@ -8,7 +8,7 @@ def exists(env):
def generate(env): def generate(env):
if env["arch"] not in ("wasm32"): if env["arch"] not in ("wasm32"):
print("Only wasm32 supported on web. Exiting.") print("Only wasm32 supported on web. Exiting.")
Exit() env.Exit(1)
if "EM_CONFIG" in os.environ: if "EM_CONFIG" in os.environ:
env["ENV"] = os.environ env["ENV"] = os.environ

View File

@ -20,7 +20,7 @@ def exists(env):
def generate(env): def generate(env):
if env["arch"] not in ("universal", "arm64", "x86_64"): if env["arch"] not in ("universal", "arm64", "x86_64"):
print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.") print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.")
Exit() env.Exit(1)
if sys.platform == "darwin": if sys.platform == "darwin":
# Use clang on macOS by default # Use clang on macOS by default