Coding shenanigans and other nerdy musings
01/Mar/2024
Last time I talked about the C++ and GDScript sides of exporting the C++ Threads and OpenCL implementations of toyBrot to Godot projects as GDExtensions. As I alluded, though, the “raw code” side of things is really only a piece of the whole pie. There’s an entire set of considerations and pitfalls regarding just setting your project up and getting it to build in the first place. But the last post was already way too long as it ended up to then talk about this whole other set of nonsense. So, instead, let’s NOW take the time to go over just about all of this setup and build side!
The previous post MAY give you some more context but, ultimately, it’s not really needed to understand this one. The background is this:
I’ve taken a couple of implementations of my Raymarching Fractal Generator, the one for C++ std::threads and the one for OpenCL and wrapped them in Godot Nodes as GDExtensions. I immediately noped out of SCons and used just CMake instead
Want to know why I did that and what sort of issues I ran into? You know the drill, get the beverage of your choosing and let’s nerd out for a bit!
As usual, all the code this is referring to is online and open, you can check it out on Gitlab as part of the toyBrot project. Behind the scenes, at the time this post is going live, I’m taking a chainsaw to the whole thing and doing some pretty big refactoring in that code… A Great Refactoring, of sorts, if you will. In case you, from The Future, are looking at the code and things don’t seem to match with what’s described, main branch at this point was at commit 1689b05c
Something I mentioned last time is that Godot’s official documentation only really mentions SCons as a build system. CMake is like the secret level easter egg that you only find out by looking directly at the code for the godot-cpp bindings. So why not use the actual standard official default thingamabob? In my case, one of the main reasons is that:
“SCons is an Open Source software construction tool that replaces the classic Make utility with Python scripts and integrated functionality.”
So… if you’re bringing Python into your builds, just take a breather, go outside, relax for a bit and rethink your life think about what you’re doing. This isn’t a slight against SCons specifically or its devs, which I’m sure put in a lot of work but, honestly, just stay away from Python. I’ve had enough experiences with “Oh, I’m sorry, you’re using 3.x.7, the entire build turns inside out and explodes for no reason with incomprehensible errors later on if the Python you’re using is not EXACTLY 3.x.5-2” and, as a person who’s had to wrangle some pretty nasty builds (even toyBrot is doing its own weird shenanigans with ISPC and CUDA) the very last thing I want is this brittle layer of a temperamental scripting language that will fall apart if you breathe at it wrong
As I was going through the demo, I was dreading this. I’ll use this sort of stuff if I have to (and will replace it if I have the chance) but I’m not going to beat around the bush here: “If you want to use this tool you need to be using this build system built on Python” is pretty much grounds for me to walk away and never come back unless something forces me to. It’s not an INSTANT game over but I am unable to look at it as anything other than a nightmare in maintainability just waiting to waste the time of everyone who ever has to touch whatever that thing is. That is a very VERY steep price to pay; whatever’s beyond an entry barrier like this has better change my bloody life if it wants me to consider paying that price and, as much as I love Godot… That is a sure way to keep me at arm’s length
Credit where it’s due, though, I didn’t have any problems in my build with either SCons or Python, things here just worked smoothly. “I use Arch, by the way”, whatever Python was currently in my system was what it was going to get, and it picked that up and ran with it fine. On the other hand, the case for Scons wasn’t helped by the tutorial itself saying outright “We cannot easily write by hand a Sconstruct file that SCons would use for building”. Instead they recommend you download and customise a skeleton file they provide:
#!/usr/bin/env python
import os
import sys
env = SConscript("godot-cpp/SConstruct")
# For reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags
# tweak this if you want to use different folders
# or more folders, to store your source code in.
env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp")
if env["platform"] == "macos":
library = env.SharedLibrary(
"demo/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
env["platform"], env["target"], env["platform"], env["target"]
),
source=sources,
)
else:
library = env.SharedLibrary(
"demo/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
source=sources,
)
Default(library)
And… well, It’s not that this file has a lot going on, but it’s relying on a lot of magic out of sight so I guess I can see how it IS actually a build system that’s unwieldy
CMake is a build system that, admittedly, DOES have some cursed legacy problems, those have been slowly been shoved out of sight but are still (and maybe never will) not entirely gone. It also has a syntax that can, admittedly, be weird to wrap your head around at first. But its got solid building blocks and is very easy to tweak around. Since I want to use a preexisting codebase, toyBrot, I can also just integrate this within toyBrot’s own CMake and, honestly, it’s a pretty trivial CmakeLists.txt to write, basically zero magic going on
# godot/extensions/cpp-threads/CMakeLists.txt
cmake_minimum_required(VERSION 3.9)
project(gdex-cppthreads LANGUAGES CXX)
set(${PROJECT_NAME}_ADDITIONAL_SRCS
"toybrot-cppthreads.gdextension"
)
# Just so this shows in the IDE
add_custom_target(${PROJECT_NAME}_EXTRAS SOURCES ${${PROJECT_NAME}_ADDITIONAL_SRCS})
# The actual extension. Only half the files are even new
add_library(${PROJECT_NAME} SHARED
"${CMAKE_SOURCE_DIR}/raymarched/STDTHREADS/FracGen.hpp"
"register_types.hpp"
"toybrotcppthreads.hpp"
"${TB_COMMON_SRC_DIR}/util.hpp"
"${CMAKE_SOURCE_DIR}/raymarched/STDTHREADS/FracGen.cpp"
"register_types.cpp"
"toybrotcppthreads.cpp"
"${TB_COMMON_SRC_DIR}/util.cpp" )
# Set the library filename so it matches what I've copied into the .gdextension file
set_target_properties(${PROJECT_NAME} PROPERTIES
OUTPUT_NAME ${PROJECT_NAME}.$<LOWER_CASE:$<PLATFORM_ID>>.template_$<LOWER_CASE:$<CONFIG>>.x86_64
)
# This is the crucial bit, link the bindings
target_link_libraries(${PROJECT_NAME} godot::cpp ${TB_STD_LIBS})
# This is for the output shenanigans I mentioned in the previous post
target_compile_definitions(${PROJECT_NAME} PRIVATE "TB_GDEX" "TB_NOSTDOUT")
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${TB_COMMON_SRC_DIR}
"${CMAKE_SOURCE_DIR}/raymarched/STDTHREADS/" )
include(GNUInstallDirs)
# Copy the built stuff over to the Godot project
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_SOURCE_DIR}/godot/extensions/extensions-demo/bin)
install(FILES toybrot-cppthreads.gdextension DESTINATION ${CMAKE_SOURCE_DIR}/godot/extensions/extensions-demo/bin)
So yeah, until CMake irreparably explodes in my face, I am simply not touching Scons, I’m not even really considering it as a possibility. For a minimal GDExtension project, you basically just need to set a filename that matches what’s in your .gdextension descriptor (and I’ve just straight up copied the example here for a first go) and link in the godot::cpp static library, that the binding project generates. It doesn’t really get easier than this. A final nail in the coffin in that SCons builds things in-tree and then pollutes your project with build garbage
This should be illegal and I hate it, and this should also be grounds to never touch a build system. I haven’t checked if it can be made not to do so but if that’s the case, the demo doesn’t bother to do it. Do not pollute my source tree, this is a source of easily avoidable but very intense headache in many a project
But how does one go around getting their hands on that godot::cpp library, then?
The example offers a pretty straightforward solution: Add godot-cpp to your project as a git submodule. That’s what that “folder in folder” icon means in the screenshot above. For a standalone personal project, this is a really good solution. Once the repository has been cloned, you can simply add_subdirectory(godot-cpp) in your CMakeLists and that’s basically it, you’re good to go. But there is ONE caveat you MAY want to think about
The GDExtensions bindings are pretty strictly tied to a specific Godot minor version. The intent is that the engine is backwards compatible with extensions for previous minors (as in, Godot 5.3 would work with an extension built for 5.1) but as of right now, in the real world of Godot 4.2, this is not quite the case. This means that if you want to build your extensions for, say, Godot 4.1 because that’s what you’re targeting for your overarching project, you need to clone specifically the branch/tag for 4.1 from godot-cpp
I say this is a caveat you MAY need to think about because if you’re building this for a specific project and you have a specific engine version in mind, who cares? You pull that tag and go have fun. But if the extension itself is the project, then maybe you want to be a bit more “loosey goosey” with this whole tag thing. And this is where a submodule MAY be a bit cumbersome
When you add a git submodule, your submodule points to a specific branch / tag / commit in that repository. This means that if you built your extension for Godot 4.1, put it out and then someone wanted to build it for 4.2, they would need to remember to update the submodule to the correct HEAD
Is this a REAL problem? Eh, arguable, for sure. But I didn’t like that myself. On my own workstation I just get Godot from Arch Linux repositories and I’ve never had any particular reason to want to stick to a specific version yet. I don’t want to have to keep bumping this submodule every time there’s a new version and I want to play with this. But there are alternatives, CMake can do some pretty crazy stuff, after all
CMake actually has a module that’s made specifically for building dependencies as part of your own build. Cmake’s External Project will clone/unzip/wget/cp some code you point it to and then build it with whatever params you want as part of your own build step
# Something like this would clone and build protobuf as part of your build
# You can be very specific with your options and steps
include(ExternalProject)
ExternalProject_Add( Protobuf
PREFIX ${ProtobufRoot}
GIT_REPOSITORY ${ProtobufGit}
GIT_PROGRESS 1
GIT_TAG "v${Protobuf_VERSION}"
BUILD_BYPRODUCTS ${Protobuf_GENLIBS}
BUILD_IN_SOURCE 1
SOURCE_SUBDIR cmake
CMAKE_GENERATOR ${ProtobufGen}
CMAKE_ARGS -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-D CMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/external
-D CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-D CMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-D protobuf_BUILD_TESTS=OFF
-D CMAKE_INSTALL_LIBDIR=lib
-D ${Protobuf_SYSTEMFLAGS}
-D CMAKE_OBJECT_PATH_MAX=512
-D CMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE}
STEP_TARGETS INSTALL
)
This means if you have a way for CMake to know what’s “your Godot version”, you could then make it checkout that specific tag or branch and… oh, look at that! You absolutely CAN have CMake ask your Godot Editor what version it is! Isn’t that convenient?
execute_process(COMMAND ${GODOT_EXE} --headless --version
OUTPUT_VARIABLE GODOT_VERSION)
string(REGEX MATCH "[0-9]+\.[0-9]+" GODOT_VERSION ${GODOT_VERSION})
For this project I’ve put together a “working for me but I wouldn’t call it production-ready” solution that does precisely this. Feed this into an ExternalProjectAdd call and you’ve got it going… but it DOES have one pretty annoying drawback
When you’re working on a CMake project, your flow usually goes along the lines of:
Even if you’re using an IDE that’ll handle the CMake for you such as Qt Creator, VS Code, Clion… they’ll normally follow this pattern. The first call to cmake is the “generation” or “configuration” step. They’ll do that as loading your project and setting it up. You’ll work from there. And if ALL of ExternalProject’s work happens during the BUILD phase, this means that it hasn’t cloned any of those repos at that point. That imposes some limitations to what you can do. You can’t refer to the CMake files of those projects, nor the targets they define. You also don’t have any of the headers for your dependency there, so for us, if you have an #include <godot-cpp/core/godot.hpp> there, your IDE absolutely cannot find it as you’re working
In order to overcome this issue, there is the alternative of FetchContent. FetchContent is the beefier brother of ExternalProject and allows, among others, for you to do the acquisition of the project during the configure step of CMake. And it can kind of magically include the CMakeLists in your project, if it IS a CMake project. So nonsense like this becomes an option that actually kind of works
# godot/CMakeLists.txt gets godot-cpp
# this GODOT_VERSION is the one we asked the Godot editor for earlier
FetchContent_Declare(godot-cpp
GIT_REPOSITORY https://github.com/godotengine/godot-cpp.git
GIT_TAG ${GODOT_TARGET_VERSION})
FetchContent_MakeAvailable(godot-cpp)
add_subdirectory(extensions)
##############################################
# in godot godot/extensions/cpp-threads/CMakeLists.txt
# we can just use the target as if it was in our normal build tree
target_link_libraries(${PROJECT_NAME} godot::cpp ${TB_STD_LIBS})
This would mostly solve the problems we’re concerned about…. For most projects other than godot-cpp
There is ONE annoying thing with godot-cpp in that a lot of the headers are generated during build. So you may still need to build your project once for those to be available and get picked up. Godot-cpp’s build itself is pretty intense too, so you can expect some annoyingly long build times if CMake doesn’t trust the bindings it built and invalidates those artefacts. But it IS an option that works, even with these details, I was happy enough once I implemented this and have been using it without too much issue. All them threadripper cores earning their keep
But with all this in mind, though, I’m more and more of the mind that the ideal situation would be to, optionally, just bootstrap a build of godot-cpp for your project. You can have that as an option for development and then use FetchContent or ExternalProject only if CMake can’t find a deployed version of the bindings in whatever directory you’ve told it to look. This can give you different workflows for active development and just cloning and building. When you are working on it, you can bootstrap once, get it built and then you don’t need to worry about missing headers or CMake deciding it needs to rebuild all the bindings and waste your time. But if you or someone else just wants to USE the project, you know, clone and build, CMake can do that fetch as part of the build itself and target a specific version that it either tries to auto-detect or that you pass as a parameter to CMake during config
It may feel like a bit of “giving up” having the initial bootstrap but it’s something that does have its own advantages. Ultimately this is one of those situations for which there is no perfect, clearly superior answer. And it depends on what you care about, what annoys you and how you see your project in general. In my view these are the things you should think about when making this decision: scope and familiarity. Because if you just hate FetchContent and ExternalProject, for example, or have no patience for submodules, then this question answers itself =P
I mentioned the chicken and the egg sort of issue last time. You need a Godot project to deploy to, but if your project is going to rely on the extension, then you want said extension to start doing some real work
While your projects don’t NEED to be one inside the other, there will be some overlap. In my specific case, all of these different parts are still more or less part of the same overarching “toyBrot project” so I have the Godot projects live inside the same repository, in their own directories. CMake is very well behaved and this helps. Standard practice is to build out of source so your garbage is all in one well defined place and CMake will only look at files and directories you explicitly point it to so it’s pretty safe to have one or several Godot projects living in the same repository, you can add the relevant Godot garbage folders to your main .gitignore and it’s all pretty straightforward
One thing to pay attention here is that Godot itself doesn’t look for your extensions in any predetermined place. It’ll look for any .gdextension files anywhere in its project folder and that file will tell it where to look for the actual libraries to load. So you need to make the Godot-side of the directory structure already in the C++/CMake side of your extension
I mentioned that the official example places all of this stuff in the /bin directory of your Godot project and I think that’s a silly place, SOs go in lib, duh! But DLLs DO go in bin so there is a platform standard mismatch there and you may want to give it some thought when you’re determining your own. I personally would put it on a `lib` folder or an `extensions` folder…. Maybe <orgname> would be a good option, especially if you have a handful of them. Just try and be mindful that you don’t pollute your user’s project tree too much. If you DO go crazy on the CI and have a bunch of different versions, there’s no reason you couldn’t have something like <orgname>/<platform> too for the libraries themselves. Godot will look at the .gdextension file to know where each specific one is and will copy the library itself as part of the project export process
If you’re developing both sides together, you can always just tell CMake to deploy your stuff straight into your Godot project. That is what I do with toyBrot. This does make more sense if they’re both in the same sort of general project tree but there’s no reason why you can’t have a `GDEXT_DEPLOY_ROOT` variable in your CmakeLists to point to an arbitrary project
# CMake install is super helpful
install(TARGETS ${PROJECT_NAME} DESTINATION
${CMAKE_SOURCE_DIR}/godot/extensions/extensions-demo/bin)
install(FILES toybrot-cppthreads.gdextension DESTINATION
${CMAKE_SOURCE_DIR}/godot/extensions/extensions-demo/bin)
The one final thing to keep in mind here is DEBUG vs RELEASE builds. When you’re just running your project in the Godot Editor, you may have noticed there is a (DEBUG) on the window title. The Editor by default loads a debug project and it will look for the debug libraries, as defined by your .gdextension file
When you Export your Godot project, chances are you want a Release build instead. As I mentioned in the previous post, you MAY also want some other additional files, like that OpenCL kernel source that gave me a bit of trouble. One option that you could consider then is having CMake do your Godot Export as part of its deploy. Once you have the details of your deploy set up in Godot, you COULD, as an additional install target on Release, have CMake ask Godot to deploy your project as Release and then copy over whatever other files it wants in the final directory
While I don’t expect many projects to need to do this and, instead, you probably just want to build your extension and then close your C++ IDE, it’s always worth remembering that you can call arbitrary things from CMake and you can just tell Godot to do an export without needing to go through the IDE. But… well… let’s just have a look at some of those “new options when an IDE gets involved”
And speaking of arbitrarily running Godot, one thing that can give you pause is debugging your C++ code when it’s running in your Godot project. The Godot debugger really can’t do much if things are exploding within your C++ library but most IDEs will let you attach your debugger to a random process. I actually had to do some debugging on my code, with the usual breakpoints and stepping through and whatnot. My IDE of choice for C++ is Qt Creator so I’m going to quickly show you how it’s done there but once you’re poking around I’m sure you’ll find ways to do something like this in whatever other IDE you like using
Before we get any further, I just want to take a detour to make sure no one is confused about Qt Creator itself. If you already know (and I would, then, assume love) QtC this bit should have nothing new but if you’re not, some of the next screenshots can look a bit confusing
Qt Creator is a C++ IDE made by Qt and it is primarily intended to support Qt Development. It is, though, by no means exclusive to it and it’s my favourite C++ IDE regardless of using Qt or not. This project, for example, has only about 0% Qt in its code
One of the ways Qt Creator facilitates Qt development is through their notion of “kits”, which is essentially a toolchain bundle. A kit determines the compilers you use for C and C++, you can point to a specific debugger, a specific version of CMake, provide predetermined environment variables and additional CMake flags…
It’s super handy for a lot of stuff. Notable for Qt development is targeting specific versions of Qt. Since this project doesn’t use Qt, we don’t care about that. The only thing that changes is the compiler we’re using (throughout these screenshots it’s GCC, but I can just select a CLANG kit and it’ll configure and build with that). Under the hood Qt normally has the build artefacts for each kit and build config separate too, so you don’t mix your garbage piles
Qt creator also helps you define different steps for “Building” and “Running”. You CAN use that to tweak things like environment variables and CMake configuration… Important for us here is that in the “Run” section, we have not only configuration for what we’re actually running (it adds automatic targets for all executables we’re building, which is why toyBrot’s list is so polluted) but also allows you to add “deployment steps”. Normally in these you’ll call things like “make install” to make sure you’re copying over what you need but it DOES allow you to add arbitrary commands as well and that’s what we’re about to make use of
So long story short is that for this project the kit selected is not really important, the Qt version is entirely irrelevant and I just picked a random GCC kit really. Feel free to completely disregard that left-hand side of the application and not worry about it, but I DO encourage you to fiddle with it when you have the chance
You COULD just “attach to running process” or what have you but that’s just not practical. The tricky thing in debugging a library is that you launch applications, not library, so you need to launch something other than “the product of my build” which is usually the default. If your Godot project is set up and working, though, we can absolutely launch that manually on its own. The godot application, which brings up the editor is built in a way that it can act as a general tool instead. If you run godot --help you’ll find it actually has a LOT to offer
So one thing we can do is just add “Godot please run my project” as an executable run in Qt Creator
Once that’s done, you can just select it from the options as your current executable
Better yet, you can the launch it with a debugger attached and that’ll give you the usual experience. You can inspect variables, step through code, look at threads… The one thing you don’t have in this setup is debug information for the Godot side of things so with this setup right here, you’re just debugging your extension specifically. For debugging the Godot side of your project, I don’t really know of a solution better than using the Godot Editor itself
Another thing the Godot editor can do through the command line, though, is exporting your project. So you can have Qt Creator ask it to do that as well; and remember that OpenCL file we needed to copy into the export? Why not just do it here too, then?
This does rely on your export_presets.cfg from Godot. So make sure you go through the process once in the Editor itself to set everything up. Once that’s sorted and you just need to run things, though, you can just re-export from your IDE and you can also just straight up tell it to run your exported project, in case you wanted to double check whether you didn’t forget anything, or had something broken along the way
# export_presets.cfg will get generated by the Export dialogue in the Godot Editor
[preset.0]
name="Linux/X11"
platform="Linux/X11"
runnable=true
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter=""
export_path="../../../redist/godot/extensions-demo.x86_64"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=1
binary_format/embed_pck=false
texture_format/bptc=true
texture_format/s3tc=true
texture_format/etc=false
texture_format/etc2=false
binary_format/architecture="x86_64"
ssh_remote_deploy/enabled=false
ssh_remote_deploy/host="user@host_ip"
ssh_remote_deploy/port="22"
ssh_remote_deploy/extra_args_ssh=""
ssh_remote_deploy/extra_args_scp=""
ssh_remote_deploy/run_script="#!/usr/bin/env bash
export DISPLAY=:0
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
\"{temp_dir}/{exe_name}\" {cmd_args}"
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\")
rm -rf \"{temp_dir}\""
The one thing to keep in mind here that is a hassle is Debug vs Release. As a reminder, the editor normally runs things in debug (it IS a development environment) so it’ll look for your debug libraries. When you deploy, though, you very likely want to deploy release instead. If your .gdextension file has both listed and they’re named different, you can just deploy the project twice, no problem. Your Godot project export will pick up whichever you need at the time. Most build systems (and here I’m talking about the actual underlying build systems that CMake creates configs for) only deal with one build config at a time, so you’ll be either building Debug, or Release. Even msbuild that has the same config for both will ask you to specify at build time which one you actually want. While you probably CAN massage CMake into building both always correctly (something I’m likely to try at some point, I know how I am), it may be just more efficient to just deploy twice when you need to so it’s probably not worth it worrying too much about only building one library (or set of libraries) at a time
Again, since it’s the IDE I like using, all the examples I’ve given have been specific to how you do things THERE but if you fumble around in your IDE of choice, you should be able to find similar options allowing you to run arbitrary commands to execute and deploy your targets. Sort that out and you can debug away even when godot::UtilityFunctions::print() is not enough
With all of those things in mind and having gone through the process of making those decisions and thinking of those details and pitfalls, one thing that I immediately thought about was making my own project template for GDExtensions with CMake. I could bake a lot of this boilerplatey stuff into it as well some other things I haven’t really mentioned yet
CMake can actually help you in more ways here. In my project I’ve kept the filename convention of the demo but whereas the .gdextension is hard-coded to the project, the actual library build has a bunch of switches so it gets generated with the correct name
# Generator expressions: Another super cool tool
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME
${PROJECT_NAME}.$<LOWER_CASE:$<PLATFORM_ID>>.template_$<LOWER_CASE:$<CONFIG>>.x86_64 )
find_package(<yourlib>) , you probably dealt with Cmake’s configure_file() function. That .gdextension file is a prime candidate for that Plus the stuff I either did or gestured towards with deployment and integrating with the Godot side of the project, etc… CMake is ridiculously powerful and can do some crazy stuff if you ask it just right. But then I had a surge of lucidity and instead of writing my own CMake GDExtension template, I asked myself the obvious question: “Has anyone already done a decent one?”
Turns out the answer to that question is a resounding “heck yeah, someone has”. If you’ve done your hello world and are familiar with CMake (just so you can tell what’s going on), I’d STRONGLY recommend checking out ackack’s GDExtension CMake project template
It does most of the things which I talk about here and he’s been at this for a while, so he’s got into into some deeper weeds than I’ve had the opportunity to at this point. While I haven’t used it myself, I was looking around and it has most of what I’d want to do myself, honestly, it’s great stuff
The one place where we “disagree” is that he prefers the git submodule approach but, as I mentioned a while back, it’s not like there’s not some strong reasons to like that either. Once you’re planning a more involved project, definitely worth checking this out. At the very least it’s going to give you a good idea about what to look out for once you’re fiddling about on your own
For my part, this is something that I probably won’t revisit until I’ve done that big toyBrot refactor I’ve mentioned. Until then, honestly the more I look at his stuff the more I think I don’t really have much to add other than talking about stuff and I can do that right here so, once again, just go have a look at this and once you realise for yourself how cool of a project it is, feel free to show @acakack@mastodon.gamedev.place some love (possibly through his ko-fi? Just saying….)
With this post out of the way, There’s not a lot explicitly planned for the immediate future. I want to get started on the refactoring I keep talking about and writing this post straight away was, partly, to just get this over before I start breaking stuff. This whole experience made me dangerously curious about “what if oops all C++ with Godot in general, lmao” but I don’t see a CMakeLists.txt in the actual engine repo so, lucky for me, that’s probably not going to happen any time soon
GDExtensions have their finicky details but once you get over the initial teething and become familiar with the details, the possibilities they open are pretty huge. When it comes to Godot I might do some more actually gamedev related stuff next so we’ll see how that goes
Feel free to poke me in Mastodon or something if there’s anything you’d like me to ramble about. I’m known to type lots =P
@tgr@vilelasagna.ddns.net Ad-blocker not detected
Consider installing a browser extension that blocks ads and other malicious scripts in your browser to protect your privacy and security. Learn more.