diff --git a/.github/workflows/cherrypick.yml b/.github/workflows/cherrypick.yml index cb3b0fca665..50d7e270e01 100644 --- a/.github/workflows/cherrypick.yml +++ b/.github/workflows/cherrypick.yml @@ -10,7 +10,7 @@ on: env: # TODO: Add a way to handle multiple potential cherrypick targets. - TARGET_BRANCH: '4.3' + TARGET_BRANCH: '4.5' USERNAME: 'Godot Organization' EMAIL: 'noreply@godotengine.org' diff --git a/.github/workflows/sync_class_ref.yml b/.github/workflows/sync_class_ref.yml index e864e74e2e6..10530828fee 100644 --- a/.github/workflows/sync_class_ref.yml +++ b/.github/workflows/sync_class_ref.yml @@ -2,12 +2,6 @@ name: Sync Class Reference on: workflow_dispatch: - # Scheduled updates only run on the default/master branch. - # Other branches need to be run manually (usually after a new release for that branch). - schedule: - # Run it at (European) night time every Saturday. - # The offset is there to try and avoid high load times. - - cron: '15 3 * * 6' # Make sure jobs cannot overlap. concurrency: @@ -23,7 +17,7 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 10 env: - engine_rev: 'master' + engine_rev: '4.5' permissions: contents: write pull-requests: write diff --git a/_extensions/gdscript.py b/_extensions/gdscript.py index f7c1e214c45..1dac79fd0e7 100644 --- a/_extensions/gdscript.py +++ b/_extensions/gdscript.py @@ -9,46 +9,39 @@ :license: MIT. modified by Daniel J. Ramirez based on the original python.py pygment + further expanded and consolidated with the godot-docs lexer by Zackery R. Smith and Ste. """ -import re - -from pygments.lexer import ( - RegexLexer, - include, - bygroups, - default, - words, - combined, -) +from pygments.lexer import RegexLexer, include, bygroups, words, combined from pygments.token import ( - Text, - Comment, - Operator, Keyword, + Literal, Name, + Comment, String, Number, - Punctuation, + Operator, Whitespace, + Punctuation, ) __all__ = ["GDScriptLexer"] -line_re = re.compile(".*?\n") - class GDScriptLexer(RegexLexer): """ - For `GDScript source code `_. + For GDScript source code. """ name = "GDScript" + url = "https://www.godotengine.org" aliases = ["gdscript", "gd"] filenames = ["*.gd"] mimetypes = ["text/x-gdscript", "application/x-gdscript"] - def innerstring_rules(ttype): + # taken from pygments/gdscript.py + @staticmethod + def inner_string_rules(ttype): return [ # the old style '%s' % (...) string formatting ( @@ -56,7 +49,7 @@ def innerstring_rules(ttype): "[hlL]?[E-GXc-giorsux%]", String.Interpol, ), - # backslashes, quotes and formatting signs must be parsed one at a time + # backslashes, quotes, and formatting signs must be parsed one at a time (r'[^\\\'"%\n]+', ttype), (r'[\'"\\]', ttype), # unhandled string formatting sign @@ -65,78 +58,19 @@ def innerstring_rules(ttype): ] tokens = { - "root": [ - (r"\n", Whitespace), - ( - r'^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")', - bygroups(Whitespace, String.Affix, String.Doc), - ), - ( - r"^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')", - bygroups(Whitespace, String.Affix, String.Doc), - ), - (r"[^\S\n]+", Whitespace), + "whitespace": [(r"\s+", Whitespace)], + "comment": [ + (r"##.*$", Comment.Doc), + (r"#(?:end)?region.*$", Comment.Region), (r"#.*$", Comment.Single), - (r"[]{}:(),;[]", Punctuation), - (r"(\\)(\n)", Whitespace), - (r"\\", Text), - # modules/gdscript/gdscript.cpp - GDScriptLanguage::get_reserved_words() - # Operators. - (r"(and|as|in|is|not|or)\b", Operator.Word), - ( - r"!=|==|<<|>>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||[-~+/*%=<>&^.!|$]", - Operator, - ), - include("keywords"), - include("control_flow_keywords"), - (r"(func)((?:\s|\\\s)+)", bygroups(Keyword, Whitespace), "funcname"), - (r"(class)((?:\s|\\\s)+)", bygroups(Keyword, Whitespace), "classname"), - include("builtins"), - include("decorators"), - ( - '([rR]|[uUbB][rR]|[rR][uUbB])(""")', - bygroups(String.Affix, String.Double), - "tdqs", - ), - ( - "([rR]|[uUbB][rR]|[rR][uUbB])(''')", - bygroups(String.Affix, String.Single), - "tsqs", - ), - ( - '([rR]|[uUbB][rR]|[rR][uUbB])(")', - bygroups(String.Affix, String.Double), - "dqs", - ), - ( - "([rR]|[uUbB][rR]|[rR][uUbB])(')", - bygroups(String.Affix, String.Single), - "sqs", - ), - ( - '([uUbB]?)(""")', - bygroups(String.Affix, String.Double), - combined("stringescape", "tdqs"), - ), - ( - "([uUbB]?)(''')", - bygroups(String.Affix, String.Single), - combined("stringescape", "tsqs"), - ), - ( - '([uUbB]?)(")', - bygroups(String.Affix, String.Double), - combined("stringescape", "dqs"), - ), - ( - "([uUbB]?)(')", - bygroups(String.Affix, String.Single), - combined("stringescape", "sqs"), - ), - include("name"), - include("numbers"), ], - "keywords": [ + "punctuation": [ + (r"[]{}(),:;[]", Punctuation), + (r":\n", Punctuation), + (r"\\", Punctuation), + ], + # NOTE: from github.com/godotengine/godot-docs + "keyword": [ ( words( ( @@ -148,27 +82,26 @@ def innerstring_rules(ttype): "enum", "extends", "func", - "namespace", # Reserved for potential future use. + "namespace", # Reserved for potential future use. "signal", "static", - "trait", # Reserved for potential future use. + "trait", # Reserved for potential future use. "var", # Other keywords. "await", "breakpoint", "self", "super", - "yield", # Reserved for potential future use. + "yield", # Reserved for potential future use. # Not really keywords, but used in property syntax. - "set", - "get", + # also colored like functions, not keywords + #"set", + #"get", ), suffix=r"\b", ), Keyword, ), - ], - "control_flow_keywords": [ ( words( ( @@ -185,6 +118,7 @@ def innerstring_rules(ttype): "return", "when", "while", + "yield", ), suffix=r"\b", ), @@ -193,7 +127,16 @@ def innerstring_rules(ttype): Keyword.ControlFlow, ), ], - "builtins": [ + "builtin": [ + ( + words( + ("true", "false", "PI", "TAU", "NAN", "INF", "null"), + prefix=r"(?>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||[-~+/*%=<>&^.!|$]", + Operator, ), - (r"(-)?(\d|(?<=\d)_)+[eE][+-]?(\d|(?<=\d)_)+j?", Number.Float), - (r"(-)?0[xX]([a-fA-F0-9]|(?<=[a-fA-F0-9])_)+", Number.Hex), + (r"(in|is|and|as|or|not)\b", Operator.Word), + ], + "number": [ + (r"([\d_]+\.[\d_]*|[\d_]*\.[\d_]+)([eE][+-]?[\d_]+)?", Number.Float), + (r"[\d_]+[eE][+-]?[\d_]+", Number.Float), + (r"0[xX][a-fA-F\d_]+", Number.Hex), (r"(-)?0[bB]([01]|(?<=[01])_)+", Number.Bin), - (r"(-)?(\d|(?<=\d)_)+j?", Number.Integer), + (r"[\d_]+", Number.Integer), + ], + "name": [(r"[a-zA-Z_]\w*", Name)], + "typehint": [ + (r"[a-zA-Z_]\w*", Name.Class, "#pop"), ], - "name": [(r"@?[a-zA-Z_]\w*", Name)], - "funcname": [(r"[a-zA-Z_]\w*", Name.Function, "#pop"), default("#pop")], - "classname": [(r"[a-zA-Z_]\w*", Name.Class, "#pop")], - "stringescape": [ + "string_escape": [ ( r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|' - r"U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})", + r"U[a-fA-F0-9]{6}|x[a-fA-F0-9]{2}|[0-7]{1,3})", String.Escape, ) ], - "strings-single": innerstring_rules(String.Single), - "strings-double": innerstring_rules(String.Double), - "dqs": [ + "string_single": inner_string_rules(String.Single), + "string_double": inner_string_rules(String.Double), + "string_other": inner_string_rules(String.Other), + "string_stringname": inner_string_rules(String.StringName), + "string_nodepath": inner_string_rules(String.NodePath), + "double_quotes": [ (r'"', String.Double, "#pop"), (r'\\\\|\\"|\\\n', String.Escape), # included here for raw strings - include("strings-double"), + include("string_double"), ], - "sqs": [ + "single_quotes": [ (r"'", String.Single, "#pop"), (r"\\\\|\\'|\\\n", String.Escape), # included here for raw strings - include("strings-single"), + include("string_single"), ], - "tdqs": [ + "triple_double_quotes": [ (r'"""', String.Double, "#pop"), - include("strings-double"), - (r"\n", Whitespace), + include("string_double"), + include("whitespace"), ], - "tsqs": [ + "triple_single_quotes": [ (r"'''", String.Single, "#pop"), - include("strings-single"), - (r"\n", Whitespace), + include("string_single"), + include("whitespace"), + ], + "node_reference": [ + (r'[\$%]"', String.Other, include("node_reference_double")), + (r"[\$%]'", String.Other, include("node_reference_single")), + (r"[\$%][A-Za-z_][\w/]*/?", String.Other), + ], + "node_reference_double": [ + (r'"', String.Other, "#pop"), + include("string_other"), + ], + "node_reference_single": [ + (r"'", String.Other, "#pop"), + include("string_other"), + ], + "stringname": [ + (r'[&]"', String.StringName, include("stringname_double")), + (r"[&]'", String.StringName, include("stringname_single")), + ], + "stringname_double": [ + (r'"', String.StringName, "#pop"), + include("string_stringname"), + ], + "stringname_single": [ + (r"'", String.StringName, "#pop"), + include("string_stringname"), + ], + "nodepath": [ + (r'[\^]"', String.NodePath, include("nodepath_double")), + (r"[\^]'", String.NodePath, include("nodepath_single")), + ], + "nodepath_double": [ + (r'"', String.NodePath, "#pop"), + include("string_nodepath"), + ], + "nodepath_single": [ + (r"'", String.NodePath, "#pop"), + include("string_nodepath"), + ], + "function_name": [(r"[a-zA-Z_]\w*", Name.Function.Declaration, "#pop")], + "enum_name": [(r"[a-zA-Z_]\w*", Name, "#pop")], + "function": [ + (r"\b([a-zA-Z_]\w*)\s*(?=\()", Name.Function), + ( + # colored like functions, even without braces + words(("set", "get",), suffix=r"\b", ), + Name.Function, + ), + ], + + ####################################################################### + # LEXER ENTRY POINT + ####################################################################### + "root": [ + include("whitespace"), + include("comment"), + include("punctuation"), + include("builtin"), + # strings + include("stringname"), + include("nodepath"), + include("node_reference"), + ( + '(r)(""")', + bygroups(String.Affix, String.Double), + "triple_double_quotes", + ), + ( + "(r)(''')", + bygroups(String.Affix, String.Single), + "triple_single_quotes", + ), + ( + '(r)(")', + bygroups(String.Affix, String.Double), + "double_quotes", + ), + ( + "(r)(')", + bygroups(String.Affix, String.Single), + "single_quotes", + ), + ( + '(r?)(""")', + bygroups(String.Affix, String.Double), + combined("string_escape", "triple_double_quotes"), + ), + ( + "(r?)(''')", + bygroups(String.Affix, String.Single), + combined("string_escape", "triple_single_quotes"), + ), + ( + '(r?)(")', + bygroups(String.Affix, String.Double), + combined("string_escape", "double_quotes"), + ), + ( + "(r?)(')", + bygroups(String.Affix, String.Single), + combined("string_escape", "single_quotes"), + ), + # consider Name after a . as instance/members variables + (r"(?`. +- The editor can + :ref:`detect features used in a project and create a compilation profile `, + which can be used to create smaller export template binaries + with unneeded features disabled. - Support for :ref:`C++ modules ` statically linked into the engine binary. + + - Most built-in modules can be disabled at compile-time to reduce binary size + in custom builds. See :ref:`doc_optimizing_for_size` for details. + - Engine and editor written in C++17. - Can be :ref:`compiled ` using GCC, diff --git a/conf.py b/conf.py index f42ecace1c8..bd4671c4cb8 100644 --- a/conf.py +++ b/conf.py @@ -68,7 +68,7 @@ # Version info for the project, acts as replacement for |version| and |release| # The short X.Y version -version = os.getenv("READTHEDOCS_VERSION", "latest") +version = os.getenv("READTHEDOCS_VERSION", "4.5") # The full version, including alpha/beta/rc tags release = version @@ -161,7 +161,7 @@ "display_github": not is_i18n, # Integrate GitHub "github_user": "godotengine", # Username "github_repo": "godot-docs", # Repo name - "github_version": "master", # Version + "github_version": "master", # Version for Edit on GitHub - keep `master` for 4.x branches "conf_py_path": "/", # Path in the checkout to the docs root "godot_docs_title": supported_languages[language], "godot_docs_basepath": "https://docs.godotengine.org/", @@ -171,7 +171,7 @@ "godot_title_prefix": "" if on_rtd else "(DEV) ", # Set this to `True` when in the `latest` branch to clearly indicate to the reader # that they are not reading the `stable` documentation. - "godot_is_latest": True, + "godot_is_latest": False, "godot_version": "4.5", # Enables a banner that displays the up-to-date status of each article. "godot_show_article_status": True, diff --git a/engine_details/architecture/custom_modules_in_cpp.rst b/engine_details/architecture/custom_modules_in_cpp.rst index 6b7b625bdd6..1bc01f9c582 100644 --- a/engine_details/architecture/custom_modules_in_cpp.rst +++ b/engine_details/architecture/custom_modules_in_cpp.rst @@ -13,7 +13,7 @@ split for use and reuse in different modules. Modules are located in the ``modules/`` subdirectory of the build system. By default, dozens of modules are enabled, such as GDScript (which, yes, -is not part of the base engine), the Mono runtime, a regular expressions +is not part of the base engine), GridMap support, a regular expressions module, and others. As many new modules as desired can be created and combined. The SCons build system will take care of it transparently. @@ -31,6 +31,16 @@ instead. Adding C++ modules can be useful in the following scenarios: - Porting an existing game to Godot. - Write a whole, new game in C++ because you can't live without C++. + +.. note:: + + While it is possible to use modules for custom game logic, + :ref:`GDExtension ` is generally more suited as it doesn't + require recompiling the engine after every code change. + + C++ modules are mainly needed when GDExtension doesn't suffice and deeper engine + integration is required. + Creating a new module --------------------- @@ -378,119 +388,6 @@ We now need to add this method to ``register_types`` header and source files: // Nothing to do here in this example. } -Improving the build system for development ------------------------------------------- - -.. warning:: - - This shared library support is not designed to support distributing a module - to other users without recompiling the engine. For that purpose, use - a GDExtension instead. - -So far, we defined a clean SCsub that allows us to add the sources -of our new module as part of the Godot binary. - -This static approach is fine when we want to build a release version of our -game, given we want all the modules in a single binary. - -However, the trade-off is that every single change requires a full recompilation of the -game. Even though SCons is able to detect and recompile only the file that was -changed, finding such files and eventually linking the final binary takes a long time. - -The solution to avoid such a cost is to build our own module as a shared -library that will be dynamically loaded when starting our game's binary. - -.. code-block:: python - :caption: godot/modules/summator/SCsub - - Import('env') - - sources = [ - "register_types.cpp", - "summator.cpp" - ] - - # First, create a custom env for the shared library. - module_env = env.Clone() - - # Position-independent code is required for a shared library. - module_env.Append(CCFLAGS=['-fPIC']) - - # Don't inject Godot's dependencies into our shared library. - module_env['LIBS'] = [] - - # Define the shared library. By default, it would be built in the module's - # folder, however it's better to output it into `bin` next to the - # Godot binary. - shared_lib = module_env.SharedLibrary(target='#bin/summator', source=sources) - - # Finally, notify the main build environment it now has our shared library - # as a new dependency. - - # LIBPATH and LIBS need to be set on the real "env" (not the clone) - # to link the specified libraries to the Godot executable. - - env.Append(LIBPATH=['#bin']) - - # SCons wants the name of the library with it custom suffixes - # (e.g. ".linuxbsd.tools.64") but without the final ".so". - shared_lib_shim = shared_lib[0].name.rsplit('.', 1)[0] - env.Append(LIBS=[shared_lib_shim]) - -Once compiled, we should end up with a ``bin`` directory containing both the -``godot*`` binary and our ``libsummator*.so``. However given the .so is not in -a standard directory (like ``/usr/lib``), we have to help our binary find it -during runtime with the ``LD_LIBRARY_PATH`` environment variable: - -.. code-block:: shell - - export LD_LIBRARY_PATH="$PWD/bin/" - ./bin/godot* - -.. note:: - You have to ``export`` the environment variable. Otherwise, - you won't be able to run your project from the editor. - -On top of that, it would be nice to be able to select whether to compile our -module as shared library (for development) or as a part of the Godot binary -(for release). To do that we can define a custom flag to be passed to SCons -using the ``ARGUMENT`` command: - -.. code-block:: python - :caption: godot/modules/summator/SCsub - - Import('env') - - sources = [ - "register_types.cpp", - "summator.cpp" - ] - - module_env = env.Clone() - module_env.Append(CCFLAGS=['-O2']) - - if ARGUMENTS.get('summator_shared', 'no') == 'yes': - # Shared lib compilation - module_env.Append(CCFLAGS=['-fPIC']) - module_env['LIBS'] = [] - shared_lib = module_env.SharedLibrary(target='#bin/summator', source=sources) - shared_lib_shim = shared_lib[0].name.rsplit('.', 1)[0] - env.Append(LIBS=[shared_lib_shim]) - env.Append(LIBPATH=['#bin']) - else: - # Static compilation - module_env.add_source_files(env.modules_sources, sources) - -Now by default ``scons`` command will build our module as part of Godot's binary -and as a shared library when passing ``summator_shared=yes``. - -Finally, you can even speed up the build further by explicitly specifying your -shared module as target in the SCons command: - -.. code-block:: shell - - scons summator_shared=yes platform=linuxbsd bin/libsummator.linuxbsd.tools.64.so - Writing custom documentation ---------------------------- diff --git a/engine_details/development/compiling/compiling_for_windows.rst b/engine_details/development/compiling/compiling_for_windows.rst index 5f84cfcfd4a..cd1745e9621 100644 --- a/engine_details/development/compiling/compiling_for_windows.rst +++ b/engine_details/development/compiling/compiling_for_windows.rst @@ -354,6 +354,14 @@ and able to build Godot using Visual Studio's **Build** button. .. seealso:: See :ref:`doc_configuring_an_ide_vs` for further details. +Troubleshooting +~~~~~~~~~~~~~~~ + +If you get a compilation failure when using MSVC, make sure to apply the +latest updates. You can do so by starting the Visual Studio IDE and using +:button:`Continue without code`, then :menu:`Help > Check for Updates` in the +menu bar at the top. Install all updates, then try compiling again. + Cross-compiling for Windows from other operating systems -------------------------------------------------------- diff --git a/engine_details/development/compiling/getting_source.rst b/engine_details/development/compiling/getting_source.rst index ea49d29fa9e..55312234cb3 100644 --- a/engine_details/development/compiling/getting_source.rst +++ b/engine_details/development/compiling/getting_source.rst @@ -44,11 +44,11 @@ after the ``--branch`` (or just ``-b``) argument: :: - # Clone the continuously maintained stable branch (`4.4` as of writing). - git clone https://github.com/godotengine/godot.git -b 4.4 + # Clone the continuously maintained stable branch (`4.5` as of writing). + git clone https://github.com/godotengine/godot.git -b 4.5 - # Clone the `4.4-stable` tag. This is a fixed revision that will never change. - git clone https://github.com/godotengine/godot.git -b 4.4-stable + # Clone the `4.5-stable` tag. This is a fixed revision that will never change. + git clone https://github.com/godotengine/godot.git -b 4.5-stable # After cloning, optionally go to a specific commit. # This can be used to access the source code at a specific point in time, diff --git a/engine_details/development/compiling/optimizing_for_size.rst b/engine_details/development/compiling/optimizing_for_size.rst index bb0ac935c77..768ebc370ef 100644 --- a/engine_details/development/compiling/optimizing_for_size.rst +++ b/engine_details/development/compiling/optimizing_for_size.rst @@ -93,6 +93,29 @@ Godot 4.5 introduced the ``size_extra`` option, which can further reduce size. scons target=template_release optimize=size_extra +Detecting used features from the current project and disabling unused features +------------------------------------------------------------------------------ + +- **Space savings:** Moderate to high depending on project +- **Difficulty:** Easy to medium depending on project +- **Performed in official builds:** No + +Godot features an :ref:`doc_engine_compilation_configuration_editor` tool that can detect +the features used in the current project and create a build profile. Once saved, +this build profile can then be passed to SCons when compiling custom export templates: + +:: + + scons target=template_release build_profile=/path/to/profile.gdbuild + +Note that for certain projects, the feature detection may be too aggressive and disable +features that are actually needed at runtime. This can occur if certain features are used +in a way that their usage cannot be detected statically (such as a script being procedurally +created and run at runtime). + +More specific features can be disabled by following the sections below, but remember +that many of them are automatically detected by the engine compilation configuration detector. + Disabling advanced text server ------------------------------ diff --git a/index.rst b/index.rst index b02193ff2f5..ed2436f1876 100644 --- a/index.rst +++ b/index.rst @@ -1,7 +1,7 @@ :allow_comments: False -Godot Docs – *master* branch -============================ +Godot Docs – *4.5* branch +========================= .. only:: not i18n diff --git a/tutorials/editor/img/engine_compilation_configuration_editor_detect.webp b/tutorials/editor/img/engine_compilation_configuration_editor_detect.webp new file mode 100644 index 00000000000..6ced779da87 Binary files /dev/null and b/tutorials/editor/img/engine_compilation_configuration_editor_detect.webp differ diff --git a/tutorials/editor/img/engine_compilation_configuration_editor_detected.webp b/tutorials/editor/img/engine_compilation_configuration_editor_detected.webp new file mode 100644 index 00000000000..72427bf1680 Binary files /dev/null and b/tutorials/editor/img/engine_compilation_configuration_editor_detected.webp differ diff --git a/tutorials/editor/index.rst b/tutorials/editor/index.rst index 572eb6aa80d..66b364173bc 100644 --- a/tutorials/editor/index.rst +++ b/tutorials/editor/index.rst @@ -81,6 +81,7 @@ like Visual Studio Code or Emacs. command_line_tutorial external_editor + using_engine_compilation_configuration_editor Managing editor features ------------------------ diff --git a/tutorials/editor/using_engine_compilation_configuration_editor.rst b/tutorials/editor/using_engine_compilation_configuration_editor.rst new file mode 100644 index 00000000000..aea286140e9 --- /dev/null +++ b/tutorials/editor/using_engine_compilation_configuration_editor.rst @@ -0,0 +1,107 @@ +.. _doc_engine_compilation_configuration_editor: + +Using the engine compilation configuration editor +================================================= + +Godot comes with a large set of built-in features. While this is convenient, +this also means its binary size is larger than it could be, especially +for projects that only use a small portion of its feature set. + +To help reduce binary size, it is possible to compile custom export templates +with certain features disabled. This is described in detail in :ref:`doc_optimizing_for_size`. +However, determining which features need to be disabled can be a tedious task. +The engine compilation configuration editor aims to address this +by providing an interface to view and manage these features easily, +while also being able to detect the features currently being used in the project. + +The :menu:`Project > Tools > Engine Compilation Configuration Editor` +allows you to create and manage build profiles for your Godot project. + +From now on, you have two possibilities: + +- View the list and manually uncheck features that you don't need. +- Use the :button:`Detect from Project` button to automatically detect features + currently used in the project and disable unused features. Note that this will + override the existing list of features, so if you have manually unchecked some + items, their state will be reset based on whether the project actually + uses the feature. + +.. figure:: img/engine_compilation_configuration_editor_detect.webp + :align: center + :alt: Opening the Engine Compilation Configuration Editor + + Opening the Engine Compilation Configuration Editor + +Once you click :button:`Detect from Project`, the project detection step will run. +This can take from a few seconds up to several minutes depending on the project size. +Once detection is complete, you'll see an updated list of features with some features disabled: + +.. figure:: img/engine_compilation_configuration_editor_detected.webp + :align: center + :alt: Updated features list after using feature detection (example from the 3D platformer demo) + + Updated features list after using feature detection (example from the 3D platformer demo) + +.. warning:: + + Unchecking features in this dialog will not reduce binary size directly on export. + Since it is only possible to actually remove features from the binary at compile-time, + you still need to compile custom export templates with the build profile specified + to actually benefit from the engine compilation configuration editor. + +You can now save the build profile by clicking **Save As** at the top. +The build profile can be saved in any location, but it's a good idea to +save it somewhere in your project folder and add it to version control to be able +to go back to it later when needed. This also allows using version control +to track changes to the build profile. + +The build profile is a JSON file (and ``.gdbuild`` extension) that looks like this +after detection in the above example: + +:: + + { + "disabled_build_options": { + "disable_navigation_3d": true, + "disable_xr": true, + "module_godot_physics_3d_enabled": false, + "module_msdfgen_enabled": false, + "module_openxr_enabled": false + }, + "disabled_classes": [ + "AESContext", + ... + "ZIPReader" + ], + "type": "build_profile" + } + +This file can be passed as a SCons option when :ref:`compiling ` +export templates: + +:: + + scons target=template_release build_profile=/path/to/profile.gdbuild + +The buildsystem will use this to disable unused classes and reduce binary size as a result. + +Limitations +----------- + +The :button:`Detect from Project` functionality relies on reading the project's scenes and scripts. +It will not be able to detect used features in the following scenarios: + +- Features that are used in GDScripts that are procedurally created then run at runtime. +- Features that are used in :ref:`expressions `. +- Features that are used in :ref:`GDExtensions `, unless the language binding + allows for defining used classes and the extension makes use of the functionality. + See `GH-104129 `__ for details. +- Features that are used in :ref:`external PCKs loaded at runtime `. +- Certain edge cases may exist. If unsure, please + `open an issue on GitHub `__ + with a minimal reproduction project attached. + +.. seealso:: + + You can achieve further size reductions by passing other options that reduce binary size. + See :ref:`doc_optimizing_for_size` for more information. diff --git a/tutorials/io/data_paths.rst b/tutorials/io/data_paths.rst index 3e69484d188..7f0de3db569 100644 --- a/tutorials/io/data_paths.rst +++ b/tutorials/io/data_paths.rst @@ -114,44 +114,9 @@ through the :ref:`JavaScriptBridge ` singleton.) File logging ------------ -By default, Godot writes log files in ``user://logs/godot.log`` on desktop -platforms. You can change this location by modifying the -``debug/file_logging/log_path`` project setting. Logs are rotated to keep older -files available for inspection. Each session creates a new log file, with the -old file renamed to contain the date at which it was rotated. Up to 5 log files -are kept by default, which can be adjusted using the -``debug/file_logging/max_log_files`` project setting. - -File logging can also be disabled completely using the -``debug/file_logging/enable_file_logging`` project setting. - -When the project crashes, crash logs are written to the same file as the log -file. The crash log will only contain a usable backtrace if the binary that was -run contains debugging symbols, or if it can find a debug symbols file that -matches the binary. Official binaries don't provide debugging symbols, so this -requires a custom build to work. See -:ref:`Debugging symbols `. -for guidance on compiling binaries with debugging symbols enabled. +.. seealso:: -.. note:: - - Log files for :ref:`print` - statements are updated when standard output is *flushed* by the engine. - Standard output is flushed on every print in debug builds only. In projects that - are exported in release mode, standard output is only flushed when the project exits - or crashes to improve performance, especially if the project is often printing - text to standard output. - - On the other hand, the standard error stream - (used by :ref:`printerr`, - :ref:`push_error` and - :ref:`push_warning`) is always - flushed on every print, even in projects exported in release mode. - - For some use cases like dedicated servers, it can be preferred to have release - builds always flush stdout on print, so that logging services like journald can - collect logs while the process is running. This can be done by enabling - ``application/run/flush_stdout_on_print`` in the Project Settings. + Documentation on file logging has been moved to :ref:`doc_logging`. Converting paths to absolute paths or "local" paths --------------------------------------------------- diff --git a/tutorials/migrating/img/gltf_naming_version.webp b/tutorials/migrating/img/gltf_naming_version.webp new file mode 100644 index 00000000000..4c4216909ef Binary files /dev/null and b/tutorials/migrating/img/gltf_naming_version.webp differ diff --git a/tutorials/migrating/upgrading_to_godot_4.5.rst b/tutorials/migrating/upgrading_to_godot_4.5.rst index 6cbbf8351d2..871d6e6467b 100644 --- a/tutorials/migrating/upgrading_to_godot_4.5.rst +++ b/tutorials/migrating/upgrading_to_godot_4.5.rst @@ -190,6 +190,17 @@ Behavior changes In 4.5 some behavior changes have been introduced, which might require you to adjust your project. +3D Model Import +~~~~~~~~~~~~~~~ + +A fix has been made to the 3D model importers to correctly handle non-joint nodes within a skeleton hierarchy (`GH-104184`_). +To preserve compatibility, the default behavior is to import existing files with the same behavior as before (`GH-107352`_). +New ``.gltf``, ``.glb``, ``.blend``, and ``.fbx`` files (without a corresponding ``.import`` file) +will be imported with the new behavior. However, for existing files, if you want to use the +new behavior, you must change the "Naming Version" option at the bottom of the Import dock: + +.. image:: img/gltf_naming_version.webp + Core ~~~~ @@ -240,6 +251,7 @@ Text .. _GH-103869: https://github.com/godotengine/godot/pull/103869 .. _GH-103941: https://github.com/godotengine/godot/pull/103941 .. _GH-104087: https://github.com/godotengine/godot/pull/104087 +.. _GH-104184: https://github.com/godotengine/godot/pull/104184 .. _GH-104269: https://github.com/godotengine/godot/pull/104269 .. _GH-104872: https://github.com/godotengine/godot/pull/104872 .. _GH-104890: https://github.com/godotengine/godot/pull/104890 @@ -251,6 +263,7 @@ Text .. _GH-106300: https://github.com/godotengine/godot/pull/106300 .. _GH-106848: https://github.com/godotengine/godot/pull/106848 .. _GH-107347: https://github.com/godotengine/godot/pull/107347 +.. _GH-107352: https://github.com/godotengine/godot/pull/107352 .. _GH-107618: https://github.com/godotengine/godot/pull/107618 .. _GH-108041: https://github.com/godotengine/godot/pull/108041 .. _GH-108825: https://github.com/godotengine/godot/pull/108825 diff --git a/tutorials/scripting/debug/debugger_panel.rst b/tutorials/scripting/debug/debugger_panel.rst index b8754848814..c20a04e606b 100644 --- a/tutorials/scripting/debug/debugger_panel.rst +++ b/tutorials/scripting/debug/debugger_panel.rst @@ -120,6 +120,8 @@ and how that effects performance. A detailed explanation of how to use the profiler can be found in the dedicated :ref:`doc_the_profiler` page. +.. _doc_debugger_panel_visual_profiler: + Visual Profiler --------------- diff --git a/tutorials/scripting/debug/output_panel.rst b/tutorials/scripting/debug/output_panel.rst index 1c00e389e3b..80c38c9e3e1 100644 --- a/tutorials/scripting/debug/output_panel.rst +++ b/tutorials/scripting/debug/output_panel.rst @@ -47,6 +47,8 @@ is controlled by the **Run > Output > Always Clear Output on Play** editor setti Additionally, you can manually clear messages by clicking the "cleaning brush" icon in the top-right corner of the Output panel. +.. _doc_output_panel_printing_messages: + Printing messages ----------------- @@ -54,6 +56,8 @@ Several methods are available to print messages: - :ref:`print() `: Prints a message. This method accepts multiple arguments which are concatenated together upon printing. + This method has variants that separate arguments with tabs and spaces respectively: + :ref:`printt() ` and :ref:`prints() `. - :ref:`print_rich() `: Same as ``print()``, but BBCode can be used to format the text that is printed (see below). - :ref:`push_error() `: Prints an error message. @@ -63,9 +67,37 @@ Several methods are available to print messages: When a warning is printed in a running project, it's displayed in the **Debugger > Errors** tab instead. +For more complex use cases, these can be used: + +- :ref:`print_verbose() `: Same as ``print()``, + but only prints when verbose mode is enabled in the Project Settings + or the project is run with the ``--verbose`` command line argument. +- :ref:`printerr() `: Same as ``print()``, + but prints to the standard error stream instead of the standard output string. + ``push_error()`` should be preferred in most cases. +- :ref:`printraw() `: Same as ``print()``, + but prints without a blank line at the end. This is the only method + that does **not** print to the editor Output panel. + It prints to the standard output stream *only*, which means it's still included + in file logging. +- :ref:`print_stack() `: Print a stack trace + from the current location. Only supported when running from the editor, + or when the project is exported in debug mode. +- :ref:`print_tree() `: Prints the scene tree + relative to the current node. Useful for debugging node structures created at runtime. +- :ref:`print_tree_pretty() `: Same as + ``print_tree()``, but with Unicode characters for a more tree-like appearance. This relies on + `box-drawing characters `__, + so it may not render correctly with all fonts. + To get more advanced formatting capabilities, consider using :ref:`doc_gdscript_printf` along with the above printing functions. +.. seealso:: + + The engine's logging facilities are covered in the :ref:`logging ` + documentation. + .. _doc_output_panel_printing_rich_text: Printing rich text @@ -85,9 +117,5 @@ same colors as they would in the project. .. note:: - ANSI escape code support varies across terminal emulators. On Windows, only - Windows 10 and later can display ANSI escape codes in its default terminal - application. - - The exact colors displayed in terminal output also depend on the terminal - theme chosen by the user. + ANSI escape code support varies across terminal emulators. The exact colors + displayed in terminal output also depend on the terminal theme chosen by the user. diff --git a/tutorials/scripting/index.rst b/tutorials/scripting/index.rst index dfaf28cc7af..46c2ff946c1 100644 --- a/tutorials/scripting/index.rst +++ b/tutorials/scripting/index.rst @@ -57,3 +57,4 @@ below will help you make the most of Godot. singletons_autoload scene_tree scene_unique_nodes + logging diff --git a/tutorials/scripting/logging.rst b/tutorials/scripting/logging.rst new file mode 100644 index 00000000000..ee6a1ecd3e6 --- /dev/null +++ b/tutorials/scripting/logging.rst @@ -0,0 +1,270 @@ +.. _doc_logging: + +Logging +======= + +Godot comes with several ways to organize and collect log messages. + +Printing messages +----------------- + +.. seealso:: + + See :ref:`doc_output_panel_printing_messages` for instructions on printing + messages. The printed output is generally identical to the logged output. + + When running a project from the editor, the editor will display logged text + in the :ref:`doc_output_panel`. + +Project settings +---------------- + +There are several project settings to control logging behavior in Godot: + +- **Application > Run > Disable stdout:** Disables logging to standard output entirely. + This also affects what custom loggers receive. This can be controlled at runtime + by setting :ref:`Engine.print_to_stdout `. +- **Application > Run > Disable stderr:** Disables logging to standard error entirely. + This also affects what custom loggers receive. This can be controlled at runtime + by setting :ref:`Engine.print_error_messages `. +- **Debug > Settings > stdout > Verbose stdout:** Enables verbose logging to standard output. + Prints from :ref:`print_verbose() ` are only + visible if verbose mode is enabled. +- **Debug > Settings > stdout > Print FPS:** Prints the frames per second every second, + as well as the V-Sync status on startup (as it can effectively cap the maximum framerate). +- **Debug > Settings > stdout > Print GPU Profile:** Prints a report of GPU utilization + every second, using the same data source as the :ref:`doc_debugger_panel_visual_profiler`. + +Some of these project settings can also be overridden using +:ref:`command line arguments ` such as ``--quiet``, +``--verbose``, and ``--print-fps``. + +The engine's own file logging is also configurable, as described in the section below. + +Built-in file logging +--------------------- + +By default, Godot writes log files in ``user://logs/godot.log`` on desktop +platforms. You can change this location by modifying the +``debug/file_logging/log_path`` project setting. Logs are rotated to keep older +files available for inspection. Each session creates a new log file, with the +old file renamed to contain the date at which it was rotated. Up to 5 log files +are kept by default, which can be adjusted using the +``debug/file_logging/max_log_files`` project setting. + +File logging can also be disabled completely using the +``debug/file_logging/enable_file_logging`` project setting. + +When the project crashes, crash logs are written to the same file as the log +file. The crash log will only contain a usable backtrace if the binary that was +run contains debugging symbols, or if it can find a debug symbols file that +matches the binary. Official binaries don't provide debugging symbols, so this +requires a custom build to work. See +:ref:`Debugging symbols ` +for guidance on compiling binaries with debugging symbols enabled. + +.. note:: + + Log files for :ref:`print() ` + statements are updated when standard output is *flushed* by the engine. + Standard output is flushed on every print in debug builds only. In projects that + are exported in release mode, standard output is only flushed when the project exits + or crashes to improve performance, especially if the project is often printing + text to standard output. + + On the other hand, the standard error stream + (used by :ref:`printerr() `, + :ref:`push_error() `, and + :ref:`push_warning() `) is always + flushed on every print, even in projects exported in release mode. + + For some use cases like dedicated servers, it can be preferred to have release + builds always flush stdout on print, so that logging services like journald can + collect logs while the process is running. This can be done by enabling + ``application/run/flush_stdout_on_print`` in the Project Settings. + +Script backtraces +----------------- + +Since Godot 4.5, when GDScript code encounters an error, it will log a backtrace that points +to the origin of the error, while also containing the call stack leading to it. This behavior +is always enabled when running in the editor, or when the project is exported in debug mode. + +In projects exported in release mode, backtraces are disabled by default for performance reasons. +You can enable them by checking **Debug > Settings > GDScript > Always Track Call Stacks** in +the Project Settings. If you use a custom logging system that reports exceptions to a remote +service, it's recommended to enable this to make reported errors more actionable. + +Crash backtraces +---------------- + +.. warning:: + + Crash backtraces are only useful if they were recorded in a build that + contains :ref:`debugging symbols `. + Official Godot binaries do not contain debugging symbols, so you must compile a + custom editor or export template binary to get useful crash backtraces. + +When the project crashes, a crash backtrace is printed to the standard error stream. This is what +it can look like in a build with debug symbols: + +.. code-block:: none + + ================================================================ + handle_crash: Program crashed with signal 4 + Engine version: Godot Engine v4.5.beta.custom_build (6c9aa4c7d3b9b91cd50714c40eeb234874df7075) + Dumping the backtrace. Please include this when reporting the bug to the project developer. + [1] /lib64/libc.so.6(+0x1a070) [0x7f6e5e277070] (??:0) + [2] godot() [0x4da3358] (/path/to/godot/core/core_bind.cpp:336 (discriminator 2)) + [3] godot() [0xdf5f2f] (/path/to/godot/modules/gdscript/gdscript.h:591) + [4] godot() [0xbffd46] (/path/to/godot/modules/gdscript/gdscript.cpp:2065 (discriminator 1)) + [5] godot() [0x30f2ea4] (/path/to/godot/core/variant/variant.h:870) + [6] godot() [0x550d4e1] (/path/to/godot/core/object/object.cpp:933) + [7] godot() [0x30d996a] (/path/to/godot/scene/main/node.cpp:318 (discriminator 1)) + [8] godot() [0x3131a7f] (/path/to/godot/core/templates/hash_map.h:465) + [9] godot() [0x424589] (/path/to/godot/platform/linuxbsd/os_linuxbsd.cpp:970) + [10] /lib64/libc.so.6(+0x3575) [0x7f6e5e260575] (??:0) + [11] /lib64/libc.so.6(__libc_start_main+0x88) [0x7f6e5e260628] (??:0) + [12] godot() [0x464df5] (??:?) + -- END OF C++ BACKTRACE -- + ================================================================ + GDScript backtrace (most recent call first): + [0] _ready (res://test.gd:5) + -- END OF GDSCRIPT BACKTRACE -- + ================================================================ + +On the other hand, without debug symbols, it will look like this instead: + +.. code-block:: none + + ================================================================ + handle_crash: Program crashed with signal 4 + Engine version: Godot Engine v4.5.beta.custom_build (6c9aa4c7d3b9b91cd50714c40eeb234874df7075) + Dumping the backtrace. Please include this when reporting the bug to the project developer. + [1] /lib64/libc.so.6(+0x1a070) [0x7fdfaf666070] (??:0) + [2] godot() [0x4da3358] (??:0) + [3] godot() [0xdf5f2f] (??:0) + [4] godot() [0xbffd46] (??:0) + [5] godot() [0x30f2ea4] (??:0) + [6] godot() [0x550d4e1] (??:0) + [7] godot() [0x30d996a] (??:0) + [8] godot() [0x3131a7f] (??:0) + [9] godot() [0x424589] (??:0) + [10] /lib64/libc.so.6(+0x3575) [0x7fdfaf64f575] (??:0) + [11] /lib64/libc.so.6(__libc_start_main+0x88) [0x7fdfaf64f628] (??:0) + [12] godot() [0x464df5] (??:0) + -- END OF C++ BACKTRACE -- + ================================================================ + GDScript backtrace (most recent call first): + [0] _ready (res://test.gd:5) + -- END OF GDSCRIPT BACKTRACE -- + ================================================================ + +This backtrace is also logged to the file for the current session, but it is **not** +visible in the editor Output panel. Since the engine's scripting system is not running +anymore when the engine is crashing, it is not possible to access it from scripting in +the same session. However, you can still read the crash backtrace on the next session +by loading log files and searching for the crash backtrace string +(``Program crashed with signal``) using :ref:`class_FileAccess`. This allows you to access +the backtrace information even after a crash, as long as the user restarts the project +and file logging is enabled: + +.. code-block:: gdscript + + # This script can be made an autoload, so that it runs when the project starts. + extends Node + + func _ready() -> void: + var log_dir: String = String(ProjectSettings.get_setting("debug/file_logging/log_path")).get_base_dir() + # Get the last log file by alphabetical order. + # Since the timestamp is featured in the file name, it should always be the most recent + # log file that was rotated. The non-timestamped log file is for the current session, + # so we don't want to read that one. + var last_log_file: String = log_dir.path_join(DirAccess.get_files_at(log_dir)[-1]) + var last_long_contents: String = FileAccess.get_file_as_string(last_log_file) + + var crash_begin_idx: int = last_long_contents.find("Program crashed with signal") + if crash_begin_idx != -1: + print("The previous session has crashed with the following backtrace:\n") + print(last_long_contents.substr(crash_begin_idx)) + +You can customize the message that appears at the top of the backtrace using the +**Debug > Settings > Crash Handler > Message** project setting. This can be used +to point to a URL or email address that users can report issues to. + +Creating custom loggers +----------------------- + +Since Godot 4.5, it is possible to create custom loggers. This custom logging can +be used for many purposes: + +- Show an in-game console with the same messages as printed by the engine, + without requiring other scripts to be modified. +- Report printed errors from the player's machine to a remote server. + This can make it easier for developers to fix bugs when the game is already released, + or during playtesting. +- Integrate a dedicated server export with monitoring platforms. + +A custom logger can be registered by creating a class that inherits from :ref:`class_logger`, +then passing an instance of this class to :ref:`OS.add_logger `, +in a script's :ref:`_init() ` method. A good place to do this +is an :ref:`autoload `. + +The class must define two methods: :ref:`_log_message() ` +and :ref:`_log_error() `. + +Here is a minimal working example of a custom logger, with the script added as an autoload: + +.. code-block:: gdscript + + extends Node + + class CustomLogger extends Logger: + # Note that this method is not called for messages that use + # `push_error()` and `push_warning()`, even though these are printed to stderr. + func _log_message(message: String, error: bool) -> void: + # Do something with `message`. + # `error` is `true` for messages printed to the standard error stream (stderr) with `print_error()`. + pass + + func _log_error( + function: String, + file: String, + line: int, + code: String, + rationale: String, + editor_notify: bool, + error_type: int, + script_backtraces: Array[ScriptBacktrace] + ) -> void: + # Do something with the error. The error text is in `rationale`. + # See the Logger class reference for details on other parameters. + pass + + # Use `_init()` to initialize the logger as early as possible, which ensures that messages + # printed early are taken into account. However, even when using `_init()`, the engine's own + # initialization messages are not accessible. + func _init() -> void: + OS.add_logger(CustomLogger.new()) + +Note that to avoid infinite recursion, you cannot effectively use +:ref:`print() ` and its related methods in +``_log_message()``. You also can't effectively use +:ref:`push_error() ` +or :ref:`push_warning() ` in +``_log_error()``. Attempting to do so will print a message to the same stream +as the original message. This message is not available in the custom logger, +which is what prevents infinite recursion from occurring: + +.. code-block:: none + + While attempting to print a message, another message was printed: + ... + + While attempting to print an error, another error was printed: + ... + +.. seealso:: + + You can find an example of an in-game console built with a custom logger in the + `Custom Logging demo project `__.