diff --git a/core/SCsub b/core/SCsub index a252a07404e..1982705abc7 100644 --- a/core/SCsub +++ b/core/SCsub @@ -1,14 +1,14 @@ #!/usr/bin/env python from misc.utility.scons_hints import * -Import("env") - import os import core_builders import methods +Import("env") + env.core_sources = [] # Add required thirdparty code. @@ -161,96 +161,34 @@ env.core_sources += thirdparty_obj # Godot source files - env.add_source_files(env.core_sources, "*.cpp") - # Generate disabled classes -def disabled_class_builder(target, source, env): - with methods.generated_wrapper(str(target[0])) as file: - for c in source[0].read(): - if cs := c.strip(): - file.write(f"#define ClassDB_Disable_{cs} 1\n") - - -env.CommandNoCache("disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(disabled_class_builder)) - +env.CommandNoCache( + "disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(core_builders.disabled_class_builder) +) # Generate version info -def version_info_builder(target, source, env): - with methods.generated_wrapper(str(target[0])) as file: - file.write( - """\ -#define GODOT_VERSION_SHORT_NAME "{short_name}" -#define GODOT_VERSION_NAME "{name}" -#define GODOT_VERSION_MAJOR {major} -#define GODOT_VERSION_MINOR {minor} -#define GODOT_VERSION_PATCH {patch} -#define GODOT_VERSION_STATUS "{status}" -#define GODOT_VERSION_BUILD "{build}" -#define GODOT_VERSION_MODULE_CONFIG "{module_config}" -#define GODOT_VERSION_WEBSITE "{website}" -#define GODOT_VERSION_DOCS_BRANCH "{docs_branch}" -#define GODOT_VERSION_DOCS_URL "https://docs.godotengine.org/en/" GODOT_VERSION_DOCS_BRANCH -""".format(**source[0].read()) - ) - - env.CommandNoCache( "version_generated.gen.h", env.Value(methods.get_version_info(env.module_version_string)), - env.Run(version_info_builder), + env.Run(core_builders.version_info_builder), ) - # Generate version hash -def version_hash_builder(target, source, env): - with methods.generated_wrapper(str(target[0])) as file: - file.write( - """\ -#include "core/version.h" - -const char *const GODOT_VERSION_HASH = "{git_hash}"; -const uint64_t GODOT_VERSION_TIMESTAMP = {git_timestamp}; -""".format(**source[0].read()) - ) - - -gen_hash = env.CommandNoCache("version_hash.gen.cpp", env.Value(methods.get_git_info()), env.Run(version_hash_builder)) +gen_hash = env.CommandNoCache( + "version_hash.gen.cpp", env.Value(methods.get_git_info()), env.Run(core_builders.version_hash_builder) +) env.add_source_files(env.core_sources, gen_hash) - # Generate AES256 script encryption key -def encryption_key_builder(target, source, env): - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -#include "core/config/project_settings.h" - -uint8_t script_encryption_key[32] = {{ - {source[0]} -}};""" - ) - - -gdkey = os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY", "0" * 64) -ec_valid = len(gdkey) == 64 -if ec_valid: - try: - gdkey = ", ".join([str(int(f"{a}{b}", 16)) for a, b in zip(gdkey[0::2], gdkey[1::2])]) - except Exception: - ec_valid = False -if not ec_valid: - methods.print_error( - f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{gdkey}".\n' - "Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment " - "or make sure that it contains exactly 64 hexadecimal characters." - ) - Exit(255) -gen_encrypt = env.CommandNoCache("script_encryption_key.gen.cpp", env.Value(gdkey), env.Run(encryption_key_builder)) +gen_encrypt = env.CommandNoCache( + "script_encryption_key.gen.cpp", + env.Value(os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY")), + env.Run(core_builders.encryption_key_builder), +) env.add_source_files(env.core_sources, gen_encrypt) - # Certificates env.CommandNoCache( "#core/io/certs_compressed.gen.h", diff --git a/core/core_builders.py b/core/core_builders.py index 5eaac237a62..7d440556288 100644 --- a/core/core_builders.py +++ b/core/core_builders.py @@ -6,6 +6,71 @@ from io import TextIOWrapper import methods +# Generate disabled classes +def disabled_class_builder(target, source, env): + with methods.generated_wrapper(str(target[0])) as file: + for c in source[0].read(): + if cs := c.strip(): + file.write(f"#define ClassDB_Disable_{cs} 1\n") + + +# Generate version info +def version_info_builder(target, source, env): + with methods.generated_wrapper(str(target[0])) as file: + file.write( + """\ +#define GODOT_VERSION_SHORT_NAME "{short_name}" +#define GODOT_VERSION_NAME "{name}" +#define GODOT_VERSION_MAJOR {major} +#define GODOT_VERSION_MINOR {minor} +#define GODOT_VERSION_PATCH {patch} +#define GODOT_VERSION_STATUS "{status}" +#define GODOT_VERSION_BUILD "{build}" +#define GODOT_VERSION_MODULE_CONFIG "{module_config}" +#define GODOT_VERSION_WEBSITE "{website}" +#define GODOT_VERSION_DOCS_BRANCH "{docs_branch}" +#define GODOT_VERSION_DOCS_URL "https://docs.godotengine.org/en/" GODOT_VERSION_DOCS_BRANCH +""".format(**source[0].read()) + ) + + +def version_hash_builder(target, source, env): + with methods.generated_wrapper(str(target[0])) as file: + file.write( + """\ +#include "core/version.h" + +const char *const GODOT_VERSION_HASH = "{git_hash}"; +const uint64_t GODOT_VERSION_TIMESTAMP = {git_timestamp}; +""".format(**source[0].read()) + ) + + +def encryption_key_builder(target, source, env): + src = source[0].read() or "0" * 64 + try: + buffer = bytes.fromhex(src) + if len(buffer) != 32: + raise ValueError + except ValueError: + methods.print_error( + f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{src}".\n' + "Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment " + "or make sure that it contains exactly 64 hexadecimal characters." + ) + raise + + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +#include "core/config/project_settings.h" + +uint8_t script_encryption_key[32] = {{ + {methods.format_buffer(buffer, 1)} +}};""" + ) + + def make_certs_header(target, source, env): buffer = methods.get_buffer(str(source[0])) decomp_size = len(buffer) @@ -13,8 +78,8 @@ def make_certs_header(target, source, env): with methods.generated_wrapper(str(target[0])) as file: # System certs path. Editor will use them if defined. (for package maintainers) - file.write('#define _SYSTEM_CERTS_PATH "{}"\n'.format(env["system_certs_path"])) - if env["builtin_certs"]: + file.write(f'#define _SYSTEM_CERTS_PATH "{source[2]}"\n') + if source[1].read(): # Defined here and not in env so changing it does not trigger a full rebuild. file.write(f"""\ #define BUILTIN_CERTS_ENABLED diff --git a/editor/SCsub b/editor/SCsub index bcd6492d831..d17be6f5382 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -1,64 +1,25 @@ #!/usr/bin/env python from misc.utility.scons_hints import * -Import("env") - -env.editor_sources = [] - import os import editor_builders -import methods +Import("env") + +env.editor_sources = [] if env.editor_build: # Generate doc data paths - def doc_data_class_path_builder(target, source, env): - paths = dict(sorted(source[0].read().items())) - data = "\n".join([f'\t{{"{key}", "{value}"}},' for key, value in paths.items()]) - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -struct _DocDataClassPath {{ - const char *name; - const char *path; -}}; - -inline constexpr int _doc_data_class_path_count = {len(paths)}; -inline constexpr _DocDataClassPath _doc_data_class_paths[{len(env.doc_class_path) + 1}] = {{ -{data} - {{nullptr, nullptr}}, -}}; -""" - ) - - env.CommandNoCache("doc_data_class_path.gen.h", env.Value(env.doc_class_path), env.Run(doc_data_class_path_builder)) + env.CommandNoCache( + "doc_data_class_path.gen.h", env.Value(env.doc_class_path), env.Run(editor_builders.doc_data_class_path_builder) + ) # Register exporters - def register_exporters_builder(target, source, env): - platforms = source[0].read() - exp_inc = "\n".join([f'#include "platform/{p}/export/export.h"' for p in platforms]) - exp_reg = "\n".join([f"\tregister_{p}_exporter();" for p in platforms]) - exp_type = "\n".join([f"\tregister_{p}_exporter_types();" for p in platforms]) - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -#include "register_exporters.h" - -{exp_inc} - -void register_exporters() {{ -{exp_reg} -}} - -void register_exporter_types() {{ -{exp_type} -}} -""" - ) - gen_exporters = env.CommandNoCache( - "register_exporters.gen.cpp", env.Value(env.platform_exporters), env.Run(register_exporters_builder) + "register_exporters.gen.cpp", + env.Value(env.platform_exporters), + env.Run(editor_builders.register_exporters_builder), ) for e in env.platform_exporters: # Add all .cpp files in export folder diff --git a/editor/editor_builders.py b/editor/editor_builders.py index 50bcd7632f1..7916130472a 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -9,6 +9,49 @@ import uuid import methods +def doc_data_class_path_builder(target, source, env): + paths = dict(sorted(source[0].read().items())) + data = "\n".join([f'\t{{"{key}", "{value}"}},' for key, value in paths.items()]) + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +struct _DocDataClassPath {{ + const char *name; + const char *path; +}}; + +inline constexpr int _doc_data_class_path_count = {len(paths)}; +inline constexpr _DocDataClassPath _doc_data_class_paths[{len(paths) + 1}] = {{ + {data} + {{nullptr, nullptr}}, +}}; +""" + ) + + +def register_exporters_builder(target, source, env): + platforms = source[0].read() + exp_inc = "\n".join([f'#include "platform/{p}/export/export.h"' for p in platforms]) + exp_reg = "\n\t".join([f"register_{p}_exporter();" for p in platforms]) + exp_type = "\n\t".join([f"register_{p}_exporter_types();" for p in platforms]) + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +#include "register_exporters.h" + +{exp_inc} + +void register_exporters() {{ + {exp_reg} +}} + +void register_exporter_types() {{ + {exp_type} +}} +""" + ) + + def make_doc_header(target, source, env): buffer = b"".join([methods.get_buffer(src) for src in map(str, source)]) decomp_size = len(buffer) diff --git a/modules/SCsub b/modules/SCsub index c2400fbed8f..f4a7fe0b9cf 100644 --- a/modules/SCsub +++ b/modules/SCsub @@ -3,7 +3,7 @@ from misc.utility.scons_hints import * import os -import methods +import modules_builders Import("env") @@ -16,63 +16,15 @@ Export("env_modules") # Header with MODULE_*_ENABLED defines. -def modules_enabled_builder(target, source, env): - modules = sorted(source[0].read()) - with methods.generated_wrapper(str(target[0])) as file: - for module in modules: - file.write(f"#define MODULE_{module.upper()}_ENABLED\n") - - modules_enabled = env.CommandNoCache( - "modules_enabled.gen.h", env.Value(env.module_list), env.Run(modules_enabled_builder) + "modules_enabled.gen.h", env.Value(env.module_list), env.Run(modules_builders.modules_enabled_builder) ) -def register_module_types_builder(target, source, env): - modules = source[0].read() - mod_inc = "\n".join([f'#include "{value}/register_types.h"' for value in modules.values()]) - mod_init = "\n".join( - [ - f"""\ -#ifdef MODULE_{key.upper()}_ENABLED - initialize_{key}_module(p_level); -#endif""" - for key in modules.keys() - ] - ) - mod_uninit = "\n".join( - [ - f"""\ -#ifdef MODULE_{key.upper()}_ENABLED - uninitialize_{key}_module(p_level); -#endif""" - for key in modules.keys() - ] - ) - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -#include "register_module_types.h" - -#include "modules/modules_enabled.gen.h" - -{mod_inc} - -void initialize_modules(ModuleInitializationLevel p_level) {{ -{mod_init} -}} - -void uninitialize_modules(ModuleInitializationLevel p_level) {{ -{mod_uninit} -}} -""" - ) - - register_module_types = env.CommandNoCache( "register_module_types.gen.cpp", [env.Value(env.modules_detected), modules_enabled], - env.Run(register_module_types_builder), + env.Run(modules_builders.register_module_types_builder), ) @@ -99,14 +51,7 @@ for name, path in env.module_list.items(): # Generate header to be included in `tests/test_main.cpp` to run module-specific tests. if env["tests"]: - - def modules_tests_builder(target, source, env): - headers = sorted([os.path.relpath(src.path, methods.base_folder).replace("\\", "/") for src in source]) - with methods.generated_wrapper(str(target[0])) as file: - for header in headers: - file.write(f'#include "{header}"\n') - - env.CommandNoCache("modules_tests.gen.h", test_headers, env.Run(modules_tests_builder)) + env.CommandNoCache("modules_tests.gen.h", test_headers, env.Run(modules_builders.modules_tests_builder)) # libmodules.a with only register_module_types. # Must be last so that all libmodule_.a libraries are on the right side diff --git a/modules/modules_builders.py b/modules/modules_builders.py new file mode 100644 index 00000000000..318f0c6de93 --- /dev/null +++ b/modules/modules_builders.py @@ -0,0 +1,60 @@ +"""Functions used to generate source files during build time""" + +import os + +import methods + + +def modules_enabled_builder(target, source, env): + modules = sorted(source[0].read()) + with methods.generated_wrapper(str(target[0])) as file: + for module in modules: + file.write(f"#define MODULE_{module.upper()}_ENABLED\n") + + +def register_module_types_builder(target, source, env): + modules = source[0].read() + mod_inc = "\n".join([f'#include "{value}/register_types.h"' for value in modules.values()]) + mod_init = "\n".join( + [ + f"""\ +#ifdef MODULE_{key.upper()}_ENABLED + initialize_{key}_module(p_level); +#endif""" + for key in modules.keys() + ] + ) + mod_uninit = "\n".join( + [ + f"""\ +#ifdef MODULE_{key.upper()}_ENABLED + uninitialize_{key}_module(p_level); +#endif""" + for key in modules.keys() + ] + ) + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +#include "register_module_types.h" + +#include "modules/modules_enabled.gen.h" + +{mod_inc} + +void initialize_modules(ModuleInitializationLevel p_level) {{ +{mod_init} +}} + +void uninitialize_modules(ModuleInitializationLevel p_level) {{ +{mod_uninit} +}} +""" + ) + + +def modules_tests_builder(target, source, env): + headers = sorted([os.path.relpath(src.path, methods.base_folder).replace("\\", "/") for src in source]) + with methods.generated_wrapper(str(target[0])) as file: + for header in headers: + file.write(f'#include "{header}"\n') diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 71e1c614141..71c10f42d4b 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -1,32 +1,13 @@ #!/usr/bin/env python from misc.utility.scons_hints import * -import methods +import text_server_adv_builders Import("env") Import("env_modules") env_text_server_adv = env_modules.Clone() - -def make_icu_data(target, source, env): - buffer = methods.get_buffer(str(source[0])) - with methods.generated_wrapper(str(target[0])) as file: - file.write(f"""\ -/* (C) 2016 and later: Unicode, Inc. and others. */ -/* License & terms of use: https://www.unicode.org/copyright.html */ - -#include -#include -#include - -extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = {len(buffer)}; -extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {{ - {methods.format_buffer(buffer, 1)} -}}; -""") - - # Thirdparty source files thirdparty_obj = [] @@ -512,7 +493,9 @@ if env["builtin_icu4c"]: if env.editor_build: icudata = env_icu.CommandNoCache( - "#thirdparty/icu4c/icudata.gen.h", "#thirdparty/icu4c/icudt_godot.dat", env.Run(make_icu_data) + "#thirdparty/icu4c/icudata.gen.h", + "#thirdparty/icu4c/icudt_godot.dat", + env.Run(text_server_adv_builders.make_icu_data), ) env_text_server_adv.Prepend(CPPEXTPATH=["#thirdparty/icu4c/"]) env_icu.Depends(lib, icudata) diff --git a/modules/text_server_adv/text_server_adv_builders.py b/modules/text_server_adv/text_server_adv_builders.py new file mode 100644 index 00000000000..3040becbea8 --- /dev/null +++ b/modules/text_server_adv/text_server_adv_builders.py @@ -0,0 +1,21 @@ +"""Functions used to generate source files during build time""" + +import methods + + +def make_icu_data(target, source, env): + buffer = methods.get_buffer(str(source[0])) + with methods.generated_wrapper(str(target[0])) as file: + file.write(f"""\ +/* (C) 2016 and later: Unicode, Inc. and others. */ +/* License & terms of use: https://www.unicode.org/copyright.html */ + +#include +#include +#include + +extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = {len(buffer)}; +extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {{ + {methods.format_buffer(buffer, 1)} +}}; +""") diff --git a/platform/SCsub b/platform/SCsub index d4f35a2c298..82c56f443d2 100644 --- a/platform/SCsub +++ b/platform/SCsub @@ -2,9 +2,8 @@ from misc.utility.scons_hints import * from glob import glob -from pathlib import Path -import methods +import platform_builders Import("env") @@ -12,51 +11,16 @@ env.platform_sources = [] # Generate export icons -def export_icon_builder(target, source, env): - src_path = Path(str(source[0])) - src_name = src_path.stem - platform = src_path.parent.parent.stem - with open(str(source[0]), "r") as file: - svg = file.read() - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -inline constexpr const char *_{platform}_{src_name}_svg = {methods.to_raw_cstring(svg)}; -""" - ) - - for platform in env.platform_exporters: for path in glob(f"{platform}/export/*.svg"): - env.CommandNoCache(path.replace(".svg", "_svg.gen.h"), path, env.Run(export_icon_builder)) + env.CommandNoCache(path.replace(".svg", "_svg.gen.h"), path, env.Run(platform_builders.export_icon_builder)) # Register platform-exclusive APIs -def register_platform_apis_builder(target, source, env): - platforms = source[0].read() - api_inc = "\n".join([f'#include "{p}/api/api.h"' for p in platforms]) - api_reg = "\n".join([f"\tregister_{p}_api();" for p in platforms]) - api_unreg = "\n".join([f"\tunregister_{p}_api();" for p in platforms]) - with methods.generated_wrapper(str(target[0])) as file: - file.write( - f"""\ -#include "register_platform_apis.h" - -{api_inc} - -void register_platform_apis() {{ -{api_reg} -}} - -void unregister_platform_apis() {{ -{api_unreg} -}} -""" - ) - - register_platform_apis = env.CommandNoCache( - "register_platform_apis.gen.cpp", env.Value(env.platform_apis), env.Run(register_platform_apis_builder) + "register_platform_apis.gen.cpp", + env.Value(env.platform_apis), + env.Run(platform_builders.register_platform_apis_builder), ) env.add_source_files(env.platform_sources, register_platform_apis) for platform in env.platform_apis: diff --git a/platform/android/SCsub b/platform/android/SCsub index 14a64845839..5eccdd19295 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -2,9 +2,10 @@ from misc.utility.scons_hints import * import platform -import subprocess import sys +import platform_android_builders + from methods import print_warning Import("env") @@ -101,33 +102,9 @@ if lib_arch_dir != "" and host_subpath != "": stl_lib_path = f"{env['ANDROID_NDK_ROOT']}/toolchains/llvm/prebuilt/{host_subpath}/sysroot/usr/lib/{triple_target_dir}/libc++_shared.so" env_android.CommandNoCache(out_dir + "/libc++_shared.so", stl_lib_path, Copy("$TARGET", "$SOURCE")) - def generate_android_binaries(target, source, env): - gradle_process = [] - - if sys.platform.startswith("win"): - gradle_process = [ - "cmd", - "/c", - "gradlew.bat", - ] - else: - gradle_process = ["./gradlew"] - - if env["target"] == "editor": - gradle_process += ["generateGodotEditor", "generateGodotHorizonOSEditor", "generateGodotPicoOSEditor"] - else: - gradle_process += ["generateGodotTemplates"] - gradle_process += ["--quiet"] - - if env["gradle_do_not_strip"]: - gradle_process += ["-PdoNotStrip=true"] - - subprocess.run( - gradle_process, - cwd="platform/android/java", - ) - if env["generate_android_binaries"]: env_android.AlwaysBuild( - env_android.CommandNoCache("generate_android_binaries", lib, env.Run(generate_android_binaries)) + env_android.CommandNoCache( + "generate_android_binaries", lib, env.Run(platform_android_builders.generate_android_binaries) + ) ) diff --git a/platform/android/platform_android_builders.py b/platform/android/platform_android_builders.py new file mode 100644 index 00000000000..f5b1386d968 --- /dev/null +++ b/platform/android/platform_android_builders.py @@ -0,0 +1,31 @@ +"""Functions used to generate source files during build time""" + +import subprocess +import sys + + +def generate_android_binaries(target, source, env): + gradle_process = [] + + if sys.platform.startswith("win"): + gradle_process = [ + "cmd", + "/c", + "gradlew.bat", + ] + else: + gradle_process = ["./gradlew"] + + if env["target"] == "editor": + gradle_process += ["generateGodotEditor", "generateGodotHorizonOSEditor", "generateGodotPicoOSEditor"] + else: + gradle_process += ["generateGodotTemplates"] + gradle_process += ["--quiet"] + + if env["gradle_do_not_strip"]: + gradle_process += ["-PdoNotStrip=true"] + + subprocess.run( + gradle_process, + cwd="platform/android/java", + ) diff --git a/platform/ios/SCsub b/platform/ios/SCsub index bb89b1dc431..ae21d90f9cb 100644 --- a/platform/ios/SCsub +++ b/platform/ios/SCsub @@ -1,64 +1,10 @@ #!/usr/bin/env python from misc.utility.scons_hints import * +import platform_ios_builders + Import("env") -import os -import shutil - -from platform_methods import detect_mvk, lipo - - -def generate_bundle(target, source, env): - bin_dir = Dir("#bin").abspath - - # Template bundle. - app_prefix = "godot." + env["platform"] - rel_prefix = "libgodot." + env["platform"] + "." + "template_release" - dbg_prefix = "libgodot." + env["platform"] + "." + "template_debug" - if env.dev_build: - app_prefix += ".dev" - rel_prefix += ".dev" - dbg_prefix += ".dev" - if env["precision"] == "double": - app_prefix += ".double" - rel_prefix += ".double" - dbg_prefix += ".double" - - # Lipo template libraries. - rel_target_bin = lipo(bin_dir + "/" + rel_prefix, env.extra_suffix + ".a") - dbg_target_bin = lipo(bin_dir + "/" + dbg_prefix, env.extra_suffix + ".a") - rel_target_bin_sim = lipo(bin_dir + "/" + rel_prefix, ".simulator" + env.extra_suffix + ".a") - dbg_target_bin_sim = lipo(bin_dir + "/" + dbg_prefix, ".simulator" + env.extra_suffix + ".a") - - # Assemble Xcode project bundle. - app_dir = Dir("#bin/ios_xcode").abspath - templ = Dir("#misc/dist/ios_xcode").abspath - if os.path.exists(app_dir): - shutil.rmtree(app_dir) - shutil.copytree(templ, app_dir) - if rel_target_bin != "": - shutil.copy(rel_target_bin, app_dir + "/libgodot.ios.release.xcframework/ios-arm64/libgodot.a") - if dbg_target_bin != "": - shutil.copy(dbg_target_bin, app_dir + "/libgodot.ios.debug.xcframework/ios-arm64/libgodot.a") - if rel_target_bin_sim != "": - shutil.copy( - rel_target_bin_sim, app_dir + "/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/libgodot.a" - ) - if dbg_target_bin_sim != "": - shutil.copy( - dbg_target_bin_sim, app_dir + "/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a" - ) - mvk_path = detect_mvk(env, "ios-arm64") - if mvk_path != "": - shutil.copytree(mvk_path, app_dir + "/MoltenVK.xcframework") - - # ZIP Xcode project bundle. - zip_dir = Dir("#bin/" + (app_prefix + env.extra_suffix).replace(".", "_")).abspath - shutil.make_archive(zip_dir, "zip", root_dir=app_dir) - shutil.rmtree(app_dir) - - ios_lib = [ "godot_ios.mm", "os_ios.mm", @@ -86,20 +32,11 @@ ios_lib = env_ios.add_library("ios", ios_lib) env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) -def combine_libs(target=None, source=None, env=None): - lib_path = target[0].srcnode().abspath - if "osxcross" in env: - libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}libtool" - else: - libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/libtool" - env.Execute( - libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) - ) - - combine_command = env_ios.CommandNoCache( - "#bin/libgodot" + env_ios["LIBSUFFIX"], [ios_lib] + env_ios["LIBS"], env.Run(combine_libs) + "#bin/libgodot" + env_ios["LIBSUFFIX"], [ios_lib] + env_ios["LIBS"], env.Run(platform_ios_builders.combine_libs) ) if env["generate_bundle"]: - env.AlwaysBuild(env.CommandNoCache("generate_bundle", combine_command, env.Run(generate_bundle))) + env.AlwaysBuild( + env.CommandNoCache("generate_bundle", combine_command, env.Run(platform_ios_builders.generate_bundle)) + ) diff --git a/platform/ios/platform_ios_builders.py b/platform/ios/platform_ios_builders.py new file mode 100644 index 00000000000..3e5b0df8a3c --- /dev/null +++ b/platform/ios/platform_ios_builders.py @@ -0,0 +1,67 @@ +"""Functions used to generate source files during build time""" + +import os +import shutil + +from platform_methods import detect_mvk, lipo + + +def combine_libs(target, source, env): + lib_path = target[0].srcnode().abspath + if "osxcross" in env: + libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}libtool" + else: + libtool = "$IOS_TOOLCHAIN_PATH/usr/bin/libtool" + env.Execute( + libtool + ' -static -o "' + lib_path + '" ' + " ".join([('"' + lib.srcnode().abspath + '"') for lib in source]) + ) + + +def generate_bundle(target, source, env): + bin_dir = env.Dir("#bin").abspath + + # Template bundle. + app_prefix = "godot." + env["platform"] + rel_prefix = "libgodot." + env["platform"] + "." + "template_release" + dbg_prefix = "libgodot." + env["platform"] + "." + "template_debug" + if env.dev_build: + app_prefix += ".dev" + rel_prefix += ".dev" + dbg_prefix += ".dev" + if env["precision"] == "double": + app_prefix += ".double" + rel_prefix += ".double" + dbg_prefix += ".double" + + # Lipo template libraries. + rel_target_bin = lipo(bin_dir + "/" + rel_prefix, env.extra_suffix + ".a") + dbg_target_bin = lipo(bin_dir + "/" + dbg_prefix, env.extra_suffix + ".a") + rel_target_bin_sim = lipo(bin_dir + "/" + rel_prefix, ".simulator" + env.extra_suffix + ".a") + dbg_target_bin_sim = lipo(bin_dir + "/" + dbg_prefix, ".simulator" + env.extra_suffix + ".a") + + # Assemble Xcode project bundle. + app_dir = env.Dir("#bin/ios_xcode").abspath + templ = env.Dir("#misc/dist/ios_xcode").abspath + if os.path.exists(app_dir): + shutil.rmtree(app_dir) + shutil.copytree(templ, app_dir) + if rel_target_bin != "": + shutil.copy(rel_target_bin, app_dir + "/libgodot.ios.release.xcframework/ios-arm64/libgodot.a") + if dbg_target_bin != "": + shutil.copy(dbg_target_bin, app_dir + "/libgodot.ios.debug.xcframework/ios-arm64/libgodot.a") + if rel_target_bin_sim != "": + shutil.copy( + rel_target_bin_sim, app_dir + "/libgodot.ios.release.xcframework/ios-arm64_x86_64-simulator/libgodot.a" + ) + if dbg_target_bin_sim != "": + shutil.copy( + dbg_target_bin_sim, app_dir + "/libgodot.ios.debug.xcframework/ios-arm64_x86_64-simulator/libgodot.a" + ) + mvk_path = detect_mvk(env, "ios-arm64") + if mvk_path != "": + shutil.copytree(mvk_path, app_dir + "/MoltenVK.xcframework") + + # ZIP Xcode project bundle. + zip_dir = env.Dir("#bin/" + (app_prefix + env.extra_suffix).replace(".", "_")).abspath + shutil.make_archive(zip_dir, "zip", root_dir=app_dir) + shutil.rmtree(app_dir) diff --git a/platform/macos/SCsub b/platform/macos/SCsub index a71455cc539..e3ad3146e79 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -1,117 +1,9 @@ #!/usr/bin/env python from misc.utility.scons_hints import * -Import("env") - -import os -import shutil -import subprocess - import platform_macos_builders -from platform_methods import get_build_version, lipo - - -def generate_bundle(target, source, env): - bin_dir = Dir("#bin").abspath - - if env.editor_build: - # Editor bundle. - prefix = "godot." + env["platform"] + "." + env["target"] - if env.dev_build: - prefix += ".dev" - if env["precision"] == "double": - prefix += ".double" - - # Lipo editor executable. - target_bin = lipo(bin_dir + "/" + prefix, env.extra_suffix + env.module_version_string) - - # Assemble .app bundle and update version info. - app_dir = Dir( - "#bin/" + (prefix + env.extra_suffix + env.module_version_string).replace(".", "_") + ".app" - ).abspath - templ = Dir("#misc/dist/macos_tools.app").abspath - if os.path.exists(app_dir): - shutil.rmtree(app_dir) - - # Create the .app bundle directory itself from scratch so that the creation - # date is accurate, but copy the rest of the template over. - os.mkdir(app_dir) - shutil.copytree( - os.path.join(templ, "Contents"), - os.path.join(app_dir, "Contents"), - ignore=shutil.ignore_patterns("Info.plist"), - ) - - if not os.path.isdir(app_dir + "/Contents/MacOS"): - os.mkdir(app_dir + "/Contents/MacOS") - if target_bin != "": - shutil.copy(target_bin, app_dir + "/Contents/MacOS/Godot") - if "mono" in env.module_version_string: - shutil.copytree(Dir("#bin/GodotSharp").abspath, app_dir + "/Contents/Resources/GodotSharp") - version = get_build_version(False) - short_version = get_build_version(True) - with open(Dir("#misc/dist/macos").abspath + "/editor_info_plist.template", "rt", encoding="utf-8") as fin: - with open(app_dir + "/Contents/Info.plist", "wt", encoding="utf-8", newline="\n") as fout: - for line in fin: - line = line.replace("$version", version) - line = line.replace("$short_version", short_version) - fout.write(line) - - # Sign .app bundle. - if env["bundle_sign_identity"] != "": - sign_command = [ - "codesign", - "-s", - env["bundle_sign_identity"], - "--deep", - "--force", - "--options=runtime", - "--entitlements", - ] - if env.dev_build: - sign_command += [Dir("#misc/dist/macos").abspath + "/editor_debug.entitlements"] - else: - sign_command += [Dir("#misc/dist/macos").abspath + "/editor.entitlements"] - sign_command += [app_dir] - subprocess.run(sign_command) - - else: - # Template bundle. - app_prefix = "godot." + env["platform"] - rel_prefix = "godot." + env["platform"] + "." + "template_release" - dbg_prefix = "godot." + env["platform"] + "." + "template_debug" - if env.dev_build: - app_prefix += ".dev" - rel_prefix += ".dev" - dbg_prefix += ".dev" - if env["precision"] == "double": - app_prefix += ".double" - rel_prefix += ".double" - dbg_prefix += ".double" - - # Lipo template executables. - rel_target_bin = lipo(bin_dir + "/" + rel_prefix, env.extra_suffix + env.module_version_string) - dbg_target_bin = lipo(bin_dir + "/" + dbg_prefix, env.extra_suffix + env.module_version_string) - - # Assemble .app bundle. - app_dir = Dir("#bin/macos_template.app").abspath - templ = Dir("#misc/dist/macos_template.app").abspath - if os.path.exists(app_dir): - shutil.rmtree(app_dir) - shutil.copytree(templ, app_dir) - if not os.path.isdir(app_dir + "/Contents/MacOS"): - os.mkdir(app_dir + "/Contents/MacOS") - if rel_target_bin != "": - shutil.copy(rel_target_bin, app_dir + "/Contents/MacOS/godot_macos_release.universal") - if dbg_target_bin != "": - shutil.copy(dbg_target_bin, app_dir + "/Contents/MacOS/godot_macos_debug.universal") - - # ZIP .app bundle. - zip_dir = Dir("#bin/" + (app_prefix + env.extra_suffix + env.module_version_string).replace(".", "_")).abspath - shutil.make_archive(zip_dir, "zip", root_dir=bin_dir, base_dir="macos_template.app") - shutil.rmtree(app_dir) - +Import("env") files = [ "os_macos.mm", @@ -144,4 +36,4 @@ if env["debug_symbols"] and env["separate_debug_symbols"]: env.AddPostAction(prog, env.Run(platform_macos_builders.make_debug_macos)) if env["generate_bundle"]: - env.AlwaysBuild(env.CommandNoCache("generate_bundle", prog, env.Run(generate_bundle))) + env.AlwaysBuild(env.CommandNoCache("generate_bundle", prog, env.Run(platform_macos_builders.generate_bundle))) diff --git a/platform/macos/platform_macos_builders.py b/platform/macos/platform_macos_builders.py index eabe5aae2f2..0446285081a 100644 --- a/platform/macos/platform_macos_builders.py +++ b/platform/macos/platform_macos_builders.py @@ -1,6 +1,113 @@ """Functions used to generate source files during build time""" import os +import shutil +import subprocess + +from platform_methods import get_build_version, lipo + + +def generate_bundle(target, source, env): + bin_dir = env.Dir("#bin").abspath + + if env.editor_build: + # Editor bundle. + prefix = "godot." + env["platform"] + "." + env["target"] + if env.dev_build: + prefix += ".dev" + if env["precision"] == "double": + prefix += ".double" + + # Lipo editor executable. + target_bin = lipo(bin_dir + "/" + prefix, env.extra_suffix + env.module_version_string) + + # Assemble .app bundle and update version info. + app_dir = env.Dir( + "#bin/" + (prefix + env.extra_suffix + env.module_version_string).replace(".", "_") + ".app" + ).abspath + templ = env.Dir("#misc/dist/macos_tools.app").abspath + if os.path.exists(app_dir): + shutil.rmtree(app_dir) + + # Create the .app bundle directory itself from scratch so that the creation + # date is accurate, but copy the rest of the template over. + os.mkdir(app_dir) + shutil.copytree( + os.path.join(templ, "Contents"), + os.path.join(app_dir, "Contents"), + ignore=shutil.ignore_patterns("Info.plist"), + ) + + if not os.path.isdir(app_dir + "/Contents/MacOS"): + os.mkdir(app_dir + "/Contents/MacOS") + if target_bin != "": + shutil.copy(target_bin, app_dir + "/Contents/MacOS/Godot") + if "mono" in env.module_version_string: + shutil.copytree(env.Dir("#bin/GodotSharp").abspath, app_dir + "/Contents/Resources/GodotSharp") + version = get_build_version(False) + short_version = get_build_version(True) + with open(env.Dir("#misc/dist/macos").abspath + "/editor_info_plist.template", "rt", encoding="utf-8") as fin: + with open(app_dir + "/Contents/Info.plist", "wt", encoding="utf-8", newline="\n") as fout: + for line in fin: + line = line.replace("$version", version) + line = line.replace("$short_version", short_version) + fout.write(line) + + # Sign .app bundle. + if env["bundle_sign_identity"] != "": + sign_command = [ + "codesign", + "-s", + env["bundle_sign_identity"], + "--deep", + "--force", + "--options=runtime", + "--entitlements", + ] + if env.dev_build: + sign_command += [env.Dir("#misc/dist/macos").abspath + "/editor_debug.entitlements"] + else: + sign_command += [env.Dir("#misc/dist/macos").abspath + "/editor.entitlements"] + sign_command += [app_dir] + subprocess.run(sign_command) + + else: + # Template bundle. + app_prefix = "godot." + env["platform"] + rel_prefix = "godot." + env["platform"] + "." + "template_release" + dbg_prefix = "godot." + env["platform"] + "." + "template_debug" + if env.dev_build: + app_prefix += ".dev" + rel_prefix += ".dev" + dbg_prefix += ".dev" + if env["precision"] == "double": + app_prefix += ".double" + rel_prefix += ".double" + dbg_prefix += ".double" + + # Lipo template executables. + rel_target_bin = lipo(bin_dir + "/" + rel_prefix, env.extra_suffix + env.module_version_string) + dbg_target_bin = lipo(bin_dir + "/" + dbg_prefix, env.extra_suffix + env.module_version_string) + + # Assemble .app bundle. + app_dir = env.Dir("#bin/macos_template.app").abspath + templ = env.Dir("#misc/dist/macos_template.app").abspath + if os.path.exists(app_dir): + shutil.rmtree(app_dir) + shutil.copytree(templ, app_dir) + if not os.path.isdir(app_dir + "/Contents/MacOS"): + os.mkdir(app_dir + "/Contents/MacOS") + if rel_target_bin != "": + shutil.copy(rel_target_bin, app_dir + "/Contents/MacOS/godot_macos_release.universal") + if dbg_target_bin != "": + shutil.copy(dbg_target_bin, app_dir + "/Contents/MacOS/godot_macos_debug.universal") + + # ZIP .app bundle. + zip_dir = env.Dir( + "#bin/" + (app_prefix + env.extra_suffix + env.module_version_string).replace(".", "_") + ).abspath + shutil.make_archive(zip_dir, "zip", root_dir=bin_dir, base_dir="macos_template.app") + shutil.rmtree(app_dir) def make_debug_macos(target, source, env): diff --git a/platform/platform_builders.py b/platform/platform_builders.py new file mode 100644 index 00000000000..76a7ad0fe61 --- /dev/null +++ b/platform/platform_builders.py @@ -0,0 +1,44 @@ +"""Functions used to generate source files during build time""" + +from pathlib import Path + +import methods + + +def export_icon_builder(target, source, env): + src_path = Path(str(source[0])) + src_name = src_path.stem + platform = src_path.parent.parent.stem + + with open(str(source[0]), "r") as file: + svg = file.read() + + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +inline constexpr const char *_{platform}_{src_name}_svg = {methods.to_raw_cstring(svg)}; +""" + ) + + +def register_platform_apis_builder(target, source, env): + platforms = source[0].read() + api_inc = "\n".join([f'#include "{p}/api/api.h"' for p in platforms]) + api_reg = "\n\t".join([f"register_{p}_api();" for p in platforms]) + api_unreg = "\n\t".join([f"unregister_{p}_api();" for p in platforms]) + with methods.generated_wrapper(str(target[0])) as file: + file.write( + f"""\ +#include "register_platform_apis.h" + +{api_inc} + +void register_platform_apis() {{ + {api_reg} +}} + +void unregister_platform_apis() {{ + {api_unreg} +}} +""" + )