Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow creating GDExtension plugins from inside the Godot editor #90979

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aaronfranke
Copy link
Member

@aaronfranke aaronfranke commented Apr 21, 2024

This PR implements godotengine/godot-proposals#3367 and godotengine/godot-proposals#9306 (not exactly as the proposals describe, but solves the same problem).

The status quo for GDExtension development is really unfortunate. For the most part the only easy way to get started is to copy-paste an existing GDExtension project and use it as a template. If you don't do this, you'd need to follow the documentation, which is a massive behemoth that manually explains to the user how to create each file from scratch, and it would take a user hours to follow this guide.

Really, I believe it should be as simple as making a GDScript plugin:

  • Click a button to open a wizard to make an extension.
  • Give your extension a name.
  • Select a language from the dropdown menu.
  • Click Create.

This is what this PR implements. Just go into Project Settings -> GDExtension:

Screenshot 2024-05-27 at 12 02 11 AM

Next, click Create GDExtension, type in a base name, click "Create", and then it will create and compile an extension.

Screenshot 2024-05-27 at 1 30 48 AM

The library name and path are optional. If you do not specify these, they will be determined automatically.

The dialog includes hover tooltips if you hover over the boxes, which explain what each field is and what the values you write in it should be.

The language system is designed to be completely language-agnostic. The dialogs have no clue about the existence of C++ or SCons. All of the C++ and SCons specific code is isolated in one class, and in the future we can allow editor plugins to extend this. It's not exposed as of this PR in case we want to iterate on the internal code first, but we can expose it whenever, either in this PR or in a future PR.

As mentioned by proposal godotengine/godot-proposals#3367, this sets up the build system with a build command (scons), the .gitignore files, the .gdextension file, the type registration boilerplate, and it even git clones godot-cpp. By default, it will also initiate scons to compile the extension, but this does take awhile, so you can skip this step by unchecking the "Compile now?" box.

Note that this PR does not include setting up system-level dependencies, such as installing a C++ compiler, installing Git, installing SCons, etc. This varies widely by operating system and it would be a slippery slope to try and have that. This PR is purely focused on the files that go in your project, not the system-wide dependencies. This PR does not try to detect a C++ compiler, but it will warn the user if either Git or SCons is not found on their system.

When you create a GDExtension plugin with this PR, one example node is provided called ExampleNode. Like the Blender default cube, this is expected to be replaced by users as soon as possible. However, its existence is useful to both new and experienced users, since it serves 2 functions: 1) As a reference for how to make a node type, including the code, registration, docs, icon, etc, and 2) A minimal test to check if your GDExtension plugin works (don't see it in the editor? It's not working).

Assuming you have the system-wide dependencies installed, and you leave the "Compile now?" checkbox enabled, and you wait for it to finish, the extension immediately works. No fuss, the example node is just there.

Screenshot 2024-05-27 at 1 27 30 AM

Assuming it was compiled, it will show up in a list of GDExtensions. This list will contain every loaded GDExtension, regardless of whether it was been created by the create dialog. It gets this list from GDExtensionManager, so it will not include any non-compiled or otherwise broken extensions.

Screenshot 2024-05-27 at 12 08 11 AM

If you change the code, you just need to run scons in either the extension folder or the project root. A future idea would be to detect this in projects and provide a "Build" button in the editor UI like we already do for C#, but that is technically separate from what this PR does.

The files look like this:

Screenshot 2024-04-21 at 4 25 19 AM

The SConstruct at the project root is extremely barebones, it is only one line to call into another SConstruct. It is designed to be simple enough so that more GDExtension plugins can be added to the same Godot project with no manual work. The _ensure_file_contains helper function in this PR completely handles the merging of more calls into this file. Except for deleting the first plugin's ExampleNode, you can just make 2 plugins back-to-back with no conflicts. If you want to have 20 GDExtension plugins, this PR will let you do that just fine, with one call to scons in the root folder able to compile all of them at once.

This PR provides 2 options for making a GDExtension plugin: "C++ with SCons, GDExtension only" or "C++ with SCons, GDExtension and engine module". The former creates a standalone GDExtension C++ plugin, with the only files stored in the root of the project being a .gitignore and barebones SConstruct.

The engine module option provides a few more files like SCsub and config.py, provides lots of #ifdef directives to support both GDExtensions and modules, and places most of the C++ code in the root of the folder, which is more suitable for making a Godot engine module. This way if users want to target both GDExtension and modules with one codebase, they can do this as easily as selecting it from the dropdown. This option turns the project's root folder into a module, so only one module is allowed per project.

Screenshot 2024-05-27 at 12 10 59 AM

When in this mode, you can either compile for GDExtension the same as with the "only" option, or you can copy-paste the entire Godot project into the engine modules folder, naming the folder the same as the addon folder name, and it works.

The source files are designed to handle the extension+module case, but are automatically simplified by this PR's project generator when making a non-module extension, including by looking at the #if preprocessor directives to determine which lines of code to exclude.

In the extension list, you can click the pencil button on any of these items to open a menu to edit the GDExtension.

Screenshot 2024-09-20 at 2 01 18 AM

Like the create dialog, the dialog includes hover tooltips which describe each field. However, for the Libraries and Icons fields, the hover tooltips are placed on the Label nodes instead of the Dictionary editors.


EDIT: This PR has changed a lot since first opening. For the record, here's the old PR description:

This PR implements godotengine/godot-proposals#3367 (not exactly as that proposal describes, but solves the same problem).

The status quo for GDExtension development is really unfortunate. For the most part the only easy way to get started is to copy-paste an existing GDExtension project and use it as a template. If you don't do this, you'd need to follow the documentation, which is a massive behemoth that manually explains to the user how to create each file from scratch, and it would take a user hours to follow this guide.

Really, I believe it should be as simple as making a GDScript plugin:

  • Click a button to open a wizard to make a plugin.
  • Give your plugin a name.
  • Select GDExtension from the dropdown menu (only step added compared to GDScript plugins).
  • Click Create.

This is what this PR implements. Just go into Project Settings -> Plugins, click Create New Plugin, and select GDExtension.

Screenshot 2024-04-21 at 3 55 37 AM

As mentioned by proposal godotengine/godot-proposals#3367, this sets up the build system with a build command (scons), the .gitignore files, the .gdextension file, the type registration boilerplate, and it even git clones godot-cpp. By default, it will also initiate scons to compile the extension, but this does take awhile, so you can skip this step by unchecking the "Compile now? (slow)" box.

Note that this PR does not include setting up system-level dependencies, such as installing a C++ compiler, installing Git, installing SCons, etc. This varies widely by operating system and it would be a slippery slope to try and have that. This PR is purely focused on the files that go in your project, not the system-wide dependencies. This PR does not try to detect a C++ compiler, but it will warn the user if either Git or SCons is not found on their system.

When you create a GDExtension plugin with this PR, one example node is provided called ExampleNode. Like the Blender default cube, this is expected to be replaced by users as soon as possible. However, its existence is useful to both new and experienced users, since it serves 2 functions: 1) As a reference for how to make a node type, including the code, registration, docs, icon, etc, and 2) A minimal test to check if your GDExtension plugin works (don't see it in the editor? It's not working).

Assuming you have the system-wide dependencies installed, and you leave the "Compile now?" checkbox enabled, and you wait for it to finish, the extension immediately works. No fuss, the example node is just there:

Screenshot 2024-04-21 at 4 19 38 AM

If you change the code, you just need to run scons in the root. A future idea would be to detect this in projects and provide a "Build" button in the editor UI like we already do for C#, but that is technically separate from what this PR does.

The files look like this:

Screenshot 2024-04-21 at 4 25 19 AM

The SConstruct at the root is extremely barebones, it is only one line to call into another SConstruct. It is designed to be simple enough so that more GDExtension plugins can be added to the same Godot project with no manual work. The _ensure_file_contains helper function in this PR completely handles the merging of more calls into this file. Except for deleting the first plugin's ExampleNode, you can pretty much just make 2 plugins back-to-back with no conflicts. If you want to have 20 GDExtension plugins, this PR will let you do that just fine, with one call to scons in the root folder able to compile all of them at once.

This PR provides 2 options for making a GDExtension plugin: "GDExtension C++ only" or "GDExtension C++ and engine module". The former creates a standalone GDExtension C++ plugin, with the only files stored in the root of the project being a .gitignore and barebones SConstruct.

The engine module option provides a few more files like SCsub and config.py, provides lots of #ifdef directives to support both GDExtensions and modules, and places most of the C++ code in the root of the folder, which is more suitable for making a Godot engine module. This way if users want to target both GDExtension and modules with one codebase, they can do this as easily as selecting it from the dropdown. This option turns the project's root folder into a module, so only one module is allowed per project:

Screenshot 2024-04-21 at 4 28 47 AM

When in this mode, you can either compile for GDExtension the same as with the "only" option, or you can copy-paste the entire Godot project into the engine modules folder, naming the folder the same as the base name (the first name you entered in the Create GDExtension dialog), and it works.

The source files are designed to handle the extension+module case, but are automatically simplified by this PR's project generator when making a non-module extension, including by looking at the #if preprocessor directives to determine which lines of code to exclude.

TODO list before undrafting this PR:

@Riteo
Copy link
Contributor

Riteo commented Apr 21, 2024

Wow, this looks great! I wonder, does this also resolve godotengine/godot-proposals#9306 ? It looks like the same problem IMO.

@Naros
Copy link
Contributor

Naros commented Apr 21, 2024

This looks great, but I also definitely think its worthwhile to consider support for other build systems beyond scons. There has been a tremendous amount of work put into the cmake build in godot-cpp, and I think its at least worthwhile for supporting that build system if someone picks "GDExtension C++ only".

@Lazy-Rabbit-2001
Copy link

Lazy-Rabbit-2001 commented Apr 22, 2024

This looks wonderful as I've been annoying with handling the preparation of making GDExtension manually for days.
However, I think there could be an option to decide if godot-cpp is global or not, as some devs may use the same godot-cpp to avoid repeated compilations on this folder because of their parallel development on multiple GDExtensions.
For example, according to current status of pr, a dev may produce two GDExtensions like this:

addons

exm_a

src

godot_cpp

exm_b

src

godot_cpp

See? There are two godot_cpp-s in seperate projects, but the dev may hope to use only one for these two GDExtensions, like this:

addons

_bin

godot_cpp

exm_a

src

...

exm_b

src

...

As the direct placement of folder godot_cpp may bring ambiguity and vagueness to devs, it's better to place it in a single common folder named _bin or something else clear that resonates with the devs.

@aaronfranke
Copy link
Member Author

@Naros The big question I have is what would this feature look like? Should cmake be included as one of the supported options out of the box? Should it be plugable? If so how? I guess plugins should add more options to the dropdown menu, so we would have "GDExtension C++ only (scons)" and "GDExtension C++ only (cmake)"? Or is it worth refactoring this menu to have a more generalized "GDExtension" option and a second dropdown for "C++ SCons", "C++ CMake", etc?

@Lazy-Rabbit-2001 I agree, but there are some technical challenges when trying to make the plugins share godot-cpp. When I try to do this, and both call into the same SConstruct, it is unable to compile from the top-level SConstruct:

scons: warning: Two different environments were specified for target gen/src/variant/utility_functions.cpp,
        but they appear to have the same action: scons_generate_bindings(target, source, env)
File "/Users/aaronfranke/workspace/projects/gdextension-test/addons/godot-cpp/tools/godotcpp.py", line 463, in _godot_cpp

scons: *** Two environments with different actions were specified for the same target: src/godot.macos.template_debug.universal.o

I would need some help from the build system gurus to make this work.

@dsnopek
Copy link
Contributor

dsnopek commented Apr 23, 2024

Thanks for taking this on! It looks really cool :-)

I did a quick test of the PR, and the "Compile on" checkbox didn't seem to work for me. It detected scons and git, but it encountered an error when trying to run it:

scons: Reading SConscript files ...
Auto-detected 32 CPU cores available for build parallelism. Using 31 cores by default. You can override it with the -j argument.
Building for architecture x86_64 on platform linux
KeyError: 'arch_suffix':
  File "/home/dsnopek/Sync/Projects/games/gdext-creation-test/SConstruct", line 4:
    SConscript("addons/zap/SConstruct")
  File "/usr/lib/python3/dist-packages/SCons/Script/SConscript.py", line 661:
    return method(*args, **kw)
  File "/usr/lib/python3/dist-packages/SCons/Script/SConscript.py", line 598:
    return _SConscript(self.fs, *files, **subst_kw)
  File "/usr/lib/python3/dist-packages/SCons/Script/SConscript.py", line 287:
    exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  File "/home/dsnopek/Sync/Projects/games/gdext-creation-test/addons/zap/SConstruct", line 35:
    env["arch_suffix"],
  File "/usr/lib/python3/dist-packages/SCons/Environment.py", line 405:
    return self._dict[key]

If I change the SConstruct to remove the env["arch_suffix"] part, then it builds fine when running scons manually. After that, the ExampleNode class appears and I can add it to my scene!

It looks like this creates a plugin.cfg file, which leads to an entry on the "Plugins" tab in "Project Settings". However, GDExtensions aren't plugins in this sense, and enabling/disabling the created plugin there will actually have no effect. We do plan to eventually add the ability to enable/disable GDExtensions in "Project Settings", but work hasn't started on that yet.

However, GDExtensions are quite different from plugins in many ways. It may make sense for GDExtensions to have their own tab distinct from "Plugins"? And, if so, then the UI here should probably be disentangled from the "Create New Plugin" form and process.

Anyway, this is a great start!

@Naros
Copy link
Contributor

Naros commented Apr 23, 2024

The big question I have is what would this feature look like? Should cmake be included as one of the supported options out of the box? Should it be plugable? If so how? I guess plugins should add more options to the dropdown menu, so we would have "GDExtension C++ only (scons)" and "GDExtension C++ only (cmake)"? Or is it worth refactoring this menu to have a more generalized "GDExtension" option and a second dropdown for "C++ SCons", "C++ CMake", etc?

So first, I think David is right, we should completely separate GDExtension from GDScript plug-ins here, 💯 . An independent UI has several benefits:

  • Avoids confusing GDScript plug-in creators with C++ / GDExtension noise.
  • Allows creating a screen tailored for GDExtension and its toolings.

On the GDExtension create dialog, I could imagine this being a bit similar to Project Settings with a tree on the left, and a panel on the right where we display context-specific options based on the choice on the left. The left panel tree might look like this:

- General 
- Build, Execution, and Deployment
  - Toolchains
    - Custom compiler
  - CMake
  - Meson
  - Scons
  - ...
- Plugins
  - ... 

The General tab allows you to define basic data about the extension, its name, a custom entry point name, the base path for where the compiled binaries should be copied, i.e. res:\\addons\<addon-name>\bin being the default. Additionally, this is where the user can define the minimum compatibility, hot-reload, etc.

Under the Build tab, we'd have sections for each supported build system that would be output for the user. These tabs could include specific options that can be customized for that specific build system. For example, here's what I could imagine being the case for CMAKE:

image

The Plugins section is really some future scope I would say, but could be where the build files get customized, additional classes added, or some other customizations are done that can be tailored to an organization's needs.


And circling back to Limbo's idea of a shared godot-cpp, this got me thinking about whether the C++ code should really reside in the project folder itself or would it make sense to reside in something like user://, with top-level paths like:

  • user://godot-cpp (shared godot-cpp)
  • user://gdextension/<extension-name>

I'm just not sure I like the idea of embedding the C++ code into the Godot project, but I'm not 100% sold either way. But now I do question if some of these settings belong configurable in the Project Settings and not in the "Create Extension" dialog 🤔

@HeadClot
Copy link

HeadClot commented May 20, 2024

Bit of a question about this Draft PR will this trigger a compile after the GDExtention is created or do will we have to do that manually?

@aaronfranke
Copy link
Member Author

aaronfranke commented May 20, 2024

@HeadClot It attempts a compile for you, but this may fail if Git, SCons, or a C++ compiler/linker/etc are missing.

@HeadClot
Copy link

@HeadClot It attempts a compile for you, but this may fail if Git, SCons, or a C++ compiler/linker/etc are missing.

Got it thank you for the info :)

@dsnopek
Copy link
Contributor

dsnopek commented May 23, 2024

Decide how we want this to work for non-C++ languages (currently the code is not designed to be plugable).

I think it probably makes sense to make this pluggable via an editor plugin, similar to the EditorExtensionSourceCodePlugin proposed in godotengine/godot-proposals#9806 (or even just being additional methods on that same plugin - keeping everything related to managing GDExtension source together makes sense).

Also, it could make sense to include the C++ support in a godotcpp module? That way, we can disable the module on certain platforms (for example, web) or folks could make custom builds of Godot that don't include this additional integration with C++ (if, for example, they wanted an editor build that focused on a different GDExtension language).

@aaronfranke aaronfranke force-pushed the create-gdextension branch 4 times, most recently from 3199f9a to 6d83772 Compare May 27, 2024 09:21
@aaronfranke aaronfranke marked this pull request as ready for review May 27, 2024 09:31
@aaronfranke aaronfranke requested review from a team as code owners May 27, 2024 09:31
@aaronfranke
Copy link
Member Author

aaronfranke commented May 27, 2024

I overhauled the entire UI frontend of this PR. Instead of using the same dialog as GDScript plugins, now there is an entirely separate tab with 2 dialogs for creating and editing GDExtensions.

I have updated the OP, please read that for a summary of how the workflow looks like. In addition to what's in the OP, here is a short description of what the classes are:

  • ProjectSettingsGDExtension: Lists GDExtensions as a tab in Project Settings. Allows opening the dialogs.
  • GDExtensionCreateDialog: Dialog for creating new GDExtensions. Uses classes that extend GDExtensionCreatorBase to do the heavy lifting. Which one the dialog uses depends on which is selected in the dropdown.
  • GDExtensionConfigDialog: Dialog for configuring/editing GDExtensions.
  • GDExtensionCreatorBase: Base class for GDExtension creator classes, the classes which are able to take in a few parameters and generate a GDExtension for some language. In the future when we expose the ability for users to add custom classes for new languages or build systems, they would extend this class.
  • CppSconsGDExtensionCreator: Extends GDExtensionCreatorBase, used for generating C++ with SCons extensions. This is the only class that knows about C++ and SCons, the other classes are language-agnostic.

If I change the SConstruct to remove the env["arch_suffix"] part, then it builds fine when running scons manually.

This should be fixed now. It will now add arch_suffix if it's missing.

It looks like this creates a plugin.cfg file, which leads to an entry on the "Plugins" tab in "Project Settings".

This is gone now.

And circling back to Limbo's idea of a shared godot-cpp, this got me thinking about whether the C++ code should really reside in the project folder itself or would it make sense to reside in

The create dialog now allows specifying any path. You can use res://gdextension/my_extension if you want, or even use a top-level folder using res://my_extension.

@KoBeWi
Copy link
Member

KoBeWi commented Jun 4, 2024

EDIT:
The solution might be adding a new tab called Addons, which would have sub-tabs Plugins and GDExtension (similar to how Localization has sub-tabs.

  • When creating extension and typing a name, there is a noticeable delay between each letter (at least in debug build), likely caused by field updating. There could be some debouncing applied here.
godot.windows.editor.dev.x86_64_WmCRfH6YBH.mp4

EDIT:
The dialog also checks for git and scons, which might be another thing slowing it down. This should be cached, e.g. when opening the dialog.

  • While performing initial compilation the editor is completely unresponsive. The compilation should run in an independent process, to not stall the editor. You could display indeterminate progress bar, or if you are ambitious, you can show compilation progress and output in real time, using the new execute_with_pipe() method.

  • After compiling finishes, the new GDExtension does not appear in the list until you click the window. Seems like editor ends unfocused somehow and clicking it refreshes the list or something. (might need further testing)

  • The layout for editing extension is awkward.
    image
    You could add some text to the checkbox (e.g. On or Enabled) and align it to the right.

Despite these minor problems, the extension is created correctly and is usable out-of-the-box, which is very nice.

@aaronfranke
Copy link
Member Author

Especially the module option, which can create unnecessary files in your project by accident

Good point. I updated the PR to add a warning:

Screenshot 2024-06-05 at 3 19 41 AM

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally (rebased on top of master), it works as expected.

Some feedback:

  • SCons' stdout appears in the terminal but not in the editor Output panel. With the new process management classes, would it be possible to display it in the editor Output panel? Add colored header output #92209 will take care of the ANSI escape codes from the colored prints.

  • Should the Library Name field use the is_valid_identifier() method to check for validity? Its tooltip says it must be a valid identifier on its own, unlike Base Name. I believe most programming languages are aligned on GDScript's requirements for identifiers, so enforcing this probably makes sense. Note that is_valid_identifier() allows non-ASCII characters, so another method must be used as well to check whether only ASCII characters were entered (if this is required).

  • Adding multiple extensions in the same project with this dialog will result in errors:

    • Attempt to register extension class 'ExampleNode', which appears to be already registered.

    • Attempt to register extension method 'hello' for unexisting class 'ExampleNode'.`

To avoid this, I suggest using the plugin path as a suffix to the the node name created by the extension numeric suffix (e.g. ExampleNodeExtensionDemo for an add-on in the extension_demo folder).

  • The example extension code should probably print something in its constructor (or NOTIFICATION_READY), so you see it having an effect right away when it's added to the scene tree. Also, its hello() method should either print text directly (and return void), or be renamed to something like get_greeting_text() as it currently doesn't print and returns a String instead.

  • The line "Both Git and SCons were found." should also tell you that you need a C++17-compatible compiler (GCC, Clang or MSVC). The "or MSVC" part should only be displayed on Windows. Something like this:

    • Both Git and SCons were found. You will also need a C++17-compatible compiler such as (GCC or Clang|GCC, Clang or MSVC).

  • When using the C++ as GDExtension or engine module option, the last line of the creation dialog should be yellow, as it's a warning:

image

  • The form considers it valid to use non-digit characters in the compatibility minimum/maximum version fields. Also, using a minimum version (4.4) greater than the current editor version (4.3) is currently not prevented. This leads to an error if you confirm the dialog.

image

  • We should figure out how to handle this in the Flatpak, as there won't be a C++ compiler, Git or SCons available for it to run. I suppose the Flatpak will need a patch to run these tools using flatpak-spawn from the host system.

  • On the Android and web editors, this functionality should be disabled as there's no way the user can run a C++ compiler toolchain on those (due to sandboxing restrictions).

Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested but the code looks good to me

@aaronfranke
Copy link
Member Author

aaronfranke commented Jun 25, 2024

Note that is_valid_identifier() allows non-ASCII characters, so another method must be used as well to check whether only ASCII characters were entered (if this is required).

This is intentional. There is no reason to prevent users from naming their extension with non-ASCII characters. If some languages support it, the dialog shouldn't prevent it. If a language doesn't support a character in an identifier, the users should just not use that character (it's easy enough to just delete and recreate the addon in the unlikely event that happens)

To avoid this, I suggest using the plugin path as a suffix to the the node name

This makes sense, but I really want to avoid misleading users into thinking that putting the plugin name in the class names is necessary, or mislead them into thinking it's a good practice. I updated the PR to use numeric discriminators instead (ExampleNode, ExampleNode2, ExampleNode3, etc).

The example extension code should probably print something in its constructor (or NOTIFICATION_READY), so you see it having an effect right away when it's added to the scene tree.

Just to clarify, the node should do this, not the extension?

The form considers it valid to use non-digit characters in the compatibility minimum/maximum version fields.

I think the dialog should not prevent this. GDExtension currently accepts strings such as 4.3.abc fine, but it just does nothing (treats it as equal to 4.3 and/or 4.3.0). It may be useful to allow this, especially for third-parties, such as if a GDExtension depends on a custom engine fork. I could see 4.3.mirror being potentially useful for example.

We should figure out how to handle this in the Flatpak, as there won't be a C++ compiler, Git or SCons available for it to run. I suppose the Flatpak will need a patch to run these tools using flatpak-spawn from the host system.

On the Android and web editors, this functionality should be disabled as there's no way the user can run a C++ compiler toolchain on those (due to sandboxing restrictions).

Should there be an editor-wide define for if we're on a platform that can compile or not? I'd rather not hard-code something like #if defined(ANDROID_ENABLED) || defined(WEB_ENABLED) || defined(FLATPAK_ENABLED)...

Actually, is there a reason to disable creating GDExtensions on those platforms? Or do we just need to disable the compile checkbox? You already can't continue with the checkbox enabled if Git or SCons can't be found. While it may not be useful, I don't see any specific reason why we need to disable creating an uncompiled GDExtension.

Copy link
Contributor

@dsnopek dsnopek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is looking really awesome! This provides a great base to build even more functionality on top of.

I tested it a bunch locally, and reviewed the code in the "cpp_scons" template in detail, but only really skimmed the editor code. All looks good to me :-)

@akien-mga
Copy link
Member

For the record, the functionality looks good overall, and I tested it and it works fine.

But I'm a bit concerned about the complexity added by the cpp_scons code, on a few aspects I still need to look into some more to make a proper judgement (hence why I haven't merged this yet):

  • Support for custom modules seems to add some complexity which I'm not sure is warranted for this feature. Being able to compile a code as both an extension and a C++ module is a cool feature but a very niche one and not one I think we should provide complex scaffolding for. This can be left to a template repo.
  • Overall, I'm not sure whether we should hardcode a lot of the SCons setup for godot-cpp extensions here, instead of just using Git to clone https://github.com/godotengine/godot-cpp-template/ or a new one if it's not minimal enough. The SCons setup for godot-cpp changes frequently and hardcoding bits of it here doesn't seem too appealing to me.

CC @Faless

@aaronfranke
Copy link
Member Author

@Calinou: On the Android and web editors, this functionality should be disabled as there's no way the user can run a C++ compiler toolchain on those (due to sandboxing restrictions).

This user was able to use C++ on Android using Termux, Clang, and a custom Android NDK: https://www.reddit.com/r/godot/comments/1g50mlq/c_vs_gdscript_performance_with_large_for_loops/ls88qcn/

@Ughuuu
Copy link
Contributor

Ughuuu commented Oct 20, 2024

For supporting both addons and modules, I propose godotengine/godot-cpp#1415 (if it gets merged). With this you can use just godot_compat includes and support both. This way you can have a checkbox if you want to just have addon, or both addon and module (or just module, though not sure if that would be a good thing to offer).

However I believe too that this should support just GDExtension and not modules. Also, would be nice if this would offer option to create more than just C++ projects (eg. godot-rust, etc.)

@heavymetalmixer
Copy link

Following this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.