From f411c5b2f18a715b58f97a57a04704b14f4d0670 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Wed, 11 Jun 2025 12:14:51 -0400 Subject: [PATCH] [Web] Add Web-build specific stdout header --- core/os/os.cpp | 15 ++++--- platform/web/SCsub | 1 + platform/web/detect.py | 1 + platform/web/eslint.config.cjs | 1 + platform/web/export/export_plugin.cpp | 5 +++ platform/web/godot_js.h | 3 ++ .../web/js/libs/library_godot_emscripten.js | 44 +++++++++++++++++++ platform/web/os_web.cpp | 16 +++++++ platform/web/web_main.cpp | 20 +++++++++ 9 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 platform/web/js/libs/library_godot_emscripten.js diff --git a/core/os/os.cpp b/core/os/os.cpp index 51bf30ac7eb..716126d232c 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -591,15 +591,20 @@ bool OS::has_feature(const String &p_feature) { } #endif -#ifdef THREADS_ENABLED if (p_feature == "threads") { +#ifdef THREADS_ENABLED return true; - } #else - if (p_feature == "nothreads") { - return true; - } + return false; #endif + } + if (p_feature == "nothreads") { +#ifdef THREADS_ENABLED + return false; +#else + return true; +#endif + } if (_check_internal_feature_support(p_feature)) { return true; diff --git a/platform/web/SCsub b/platform/web/SCsub index 14f52dca337..bd001fd6dc4 100644 --- a/platform/web/SCsub +++ b/platform/web/SCsub @@ -40,6 +40,7 @@ sys_env.AddJSLibraries( [ "js/libs/library_godot_audio.js", "js/libs/library_godot_display.js", + "js/libs/library_godot_emscripten.js", "js/libs/library_godot_fetch.js", "js/libs/library_godot_webmidi.js", "js/libs/library_godot_os.js", diff --git a/platform/web/detect.py b/platform/web/detect.py index a26c17d218a..aa65040a523 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -267,6 +267,7 @@ def configure(env: "SConsEnvironment"): print_warning("GDExtension support requires proxy_to_pthread=no, disabling proxy to pthread.") env["proxy_to_pthread"] = False + env.Append(CPPDEFINES=["WEB_DLINK_ENABLED"]) env.Append(CCFLAGS=["-sSIDE_MODULE=2"]) env.Append(LINKFLAGS=["-sSIDE_MODULE=2"]) env.Append(CCFLAGS=["-fvisibility=hidden"]) diff --git a/platform/web/eslint.config.cjs b/platform/web/eslint.config.cjs index d898a874760..4f51aec4cff 100644 --- a/platform/web/eslint.config.cjs +++ b/platform/web/eslint.config.cjs @@ -29,6 +29,7 @@ const emscriptenGlobals = { '_free': true, '_malloc': true, 'autoAddDeps': true, + 'addToLibrary': true, 'addOnPostRun': true, 'getValue': true, 'lengthBytesUTF8': true, diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index ad73125a2a4..4575c3b51e1 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -353,6 +353,11 @@ void EditorExportPlatformWeb::get_preset_features(const Ref } else { r_features->push_back("nothreads"); } + if (p_preset->get("variant/extensions_support").operator bool()) { + r_features->push_back("web_extensions"); + } else { + r_features->push_back("web_noextensions"); + } r_features->push_back("wasm32"); } diff --git a/platform/web/godot_js.h b/platform/web/godot_js.h index 3ab71bad6ee..4e282181d0d 100644 --- a/platform/web/godot_js.h +++ b/platform/web/godot_js.h @@ -38,6 +38,9 @@ extern "C" { #endif +// Emscripten +extern char *godot_js_emscripten_get_version(); + // Config extern void godot_js_config_locale_get(char *p_ptr, int p_ptr_max); extern void godot_js_config_canvas_id_get(char *p_ptr, int p_ptr_max); diff --git a/platform/web/js/libs/library_godot_emscripten.js b/platform/web/js/libs/library_godot_emscripten.js new file mode 100644 index 00000000000..4a686e92c30 --- /dev/null +++ b/platform/web/js/libs/library_godot_emscripten.js @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* library_godot_emscripten.js */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +const GodotEmscripten = { + $GodotEmscripten__deps: ['$GodotRuntime'], + $GodotEmscripten: {}, + + godot_js_emscripten_get_version__proxy: 'sync', + godot_js_emscripten_get_version__sig: 'p', + godot_js_emscripten_get_version: function () { + // WARNING: The caller needs to free the string pointer. + const emscriptenVersionPtr = GodotRuntime.allocString('{{{ EMSCRIPTEN_VERSION }}}'); + return emscriptenVersionPtr; + }, +}; +autoAddDeps(GodotEmscripten, '$GodotEmscripten'); +addToLibrary(GodotEmscripten); diff --git a/platform/web/os_web.cpp b/platform/web/os_web.cpp index 57d03418418..83fe201a8c2 100644 --- a/platform/web/os_web.cpp +++ b/platform/web/os_web.cpp @@ -160,6 +160,22 @@ bool OS_Web::_check_internal_feature_support(const String &p_feature) { if (p_feature == "web") { return true; } + + if (p_feature == "web_extensions") { +#ifdef WEB_DLINK_ENABLED + return true; +#else + return false; +#endif + } + if (p_feature == "web_noextensions") { +#ifdef WEB_DLINK_ENABLED + return false; +#else + return true; +#endif + } + if (godot_js_os_has_feature(p_feature.utf8().get_data())) { return true; } diff --git a/platform/web/web_main.cpp b/platform/web/web_main.cpp index 55a8c678c59..477b48f4a33 100644 --- a/platform/web/web_main.cpp +++ b/platform/web/web_main.cpp @@ -104,6 +104,24 @@ void main_loop_callback() { } } +void print_web_header() { + // Emscripten. + char *emscripten_version_char = godot_js_emscripten_get_version(); + String emscripten_version = vformat("Emscripten %s", emscripten_version_char); + memfree(emscripten_version_char); + + // Build features. + String thread_support = OS::get_singleton()->has_feature("threads") + ? "multi-threaded" + : "single-threaded"; + String extensions_support = OS::get_singleton()->has_feature("web_extensions") + ? "GDExtension support" + : "no GDExtension support"; + + Vector build_configuration = { emscripten_version, thread_support, extensions_support }; + print_line(vformat("Build configuration: %s.", String(", ").join(build_configuration))); +} + /// When calling main, it is assumed FS is setup and synced. extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) { os = new OS_Web(); @@ -128,6 +146,8 @@ extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) { return EXIT_FAILURE; } + print_web_header(); + main_started = true; // Ease up compatibility.