Skip to content

Make libgodot_project buildable on Windows. #6

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ git clone --recursive https://github.com/migeran/libgodot_project

cd libgodot_project

# Build for the host platform (Mac and Linux)
# Build for Mac and Linux
./build_libgodot.sh

# Or build for Windows
build_libgodot.bat

# Build for iOS (Mac only)
./build_libgodot.sh --target ios
```
Expand All @@ -48,6 +51,7 @@ The C++ sample shows how Godot can be controlled by a host process, by displayin

After libgodot is compiled successfully, run the following commands to test the C++ sample:

On Linux and MacOS:
```
cd samples/cpp_sample
mkdir build
Expand All @@ -56,6 +60,16 @@ cd build
./sample
```

On Windows:
```
cd samples/cpp_sample
mkdir build
cmake -S . -B build -G Ninja
cd build
ninja
sample.exe
```

### SwiftUI Sample

To test the SwiftUI sample, just open the ios_sample project in XCode 15.1+, build it and run on any iOS device. (iOS Simulator is not supported due to Godot limitations.)
Expand Down Expand Up @@ -96,7 +110,7 @@ This class is made accessible over the GDExtension API. This class can be used t
To actually create a Godot instance a new symbol is added to the GDExtension API:

```cpp
GDExtensionObjectPtr gdextension_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func);
GDExtensionObjectPtr libgodot_create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func, void *p_platform_data);
```

This function can be used to create a new Godot instance and return a GodotInstance object reference to control it. Both samples show how easy it is to bind this function and then use the generated GDExtension API bindings with the returned GodotInstance object.
Expand Down
2 changes: 1 addition & 1 deletion SwiftGodot
Submodule SwiftGodot updated 42 files
+40 −0 .github/ISSUE_TEMPLATE/bug_report.md
+20 −0 .github/ISSUE_TEMPLATE/feature_request.md
+6 −6 .github/workflows/swift.yml
+3 −1 .gitignore
+2 −4 Generator/Generator/BuiltinGen.swift
+24 −1 Generator/Generator/ClassGen.swift
+10 −0 Generator/Generator/DocModel.swift
+3 −3 Generator/Generator/Enums.swift
+2 −4 Generator/Generator/MethodGen.swift
+1 −1 Generator/Generator/StringOperations.swift
+2 −1 Generator/Generator/TypeHelpers.swift
+8 −1 Plugins/CodeGeneratorPlugin/plugin.swift
+2 −1 README.md
+4,119 −902 Sources/ExtensionApi/extension_api.json
+57 −34 Sources/GDExtension/include/gdextension_interface.h
+69 −0 Sources/GDExtension/include/libgodot.h
+5 −0 Sources/SwiftGodot/Core/GArray.swift
+3 −3 Sources/SwiftGodot/Core/ObjectCollection.swift
+35 −12 Sources/SwiftGodot/Core/Packed.swift
+2 −2 Sources/SwiftGodot/Core/VariantCollection.swift
+4 −0 Sources/SwiftGodot/Core/VariantRepresentable.swift
+24 −8 Sources/SwiftGodot/EntryPoint.swift
+23 −4 Sources/SwiftGodot/Extensions/NodeExtensions.swift
+0 −4 Sources/SwiftGodot/GodotInterface.swift
+35 −1 Sources/SwiftGodot/MacroDefs.swift
+34 −9 Sources/SwiftGodot/SwiftGodot.docc/BindingNodes.md
+8 −10 Sources/SwiftGodot/SwiftGodot.docc/CustomTypes.md
+2 −1 Sources/SwiftGodot/SwiftGodot.docc/Differences.md
+20 −0 Sources/SwiftGodot/SwiftGodot.docc/Exports.md
+19 −4 Sources/SwiftGodot/SwiftGodot.docc/Variants.md
+12 −8 Sources/SwiftGodot/SwiftGodot.docc/WorkingInVsCode.md
+17 −20 Sources/SwiftGodotMacroLibrary/InitSwiftExtensionMacro.swift
+1 −1 Sources/SwiftGodotMacroLibrary/MacroCallable.swift
+30 −6 Sources/SwiftGodotMacroLibrary/MacroExport.swift
+39 −6 Sources/SwiftGodotMacroLibrary/MacroGodot.swift
+4 −0 Sources/SwiftGodotMacroLibrary/MacroSharedApi.swift
+1 −8 Sources/SwiftGodotMacroLibrary/PickerNameProviderMacro.swift
+134 −40 Tests/SwiftGodotMacrosTests/InitSwiftExtensionMacroTests.swift
+111 −0 Tests/SwiftGodotMacrosTests/MacroGodotExportEnumTests.swift
+18 −18 Tests/SwiftGodotMacrosTests/MacroGodotTests.swift
+25 −23 Tests/SwiftGodotMacrosTests/PickerNameProviderMacroTests.swift
+5 −3 scripts/make-libgodot.framework
2 changes: 1 addition & 1 deletion SwiftGodotKit
18 changes: 18 additions & 0 deletions build_libgodot.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
set BASE_DIR=%~dp0

cd %BASE_DIR%
mkdir build

cd godot

call scons platform=windows arch=x86_64 verbose=yes msvc=yes dev_build=yes debug_symbols=yes
call scons platform=windows target=template_debug arch=x86_64 verbose=yes msvc=yes library_type=shared_library dev_build=yes debug_symbols=yes

copy /y bin\godot.windows.template_debug.dev.x86_64.dll ..\build\libgodot.dll

start /wait bin\godot.windows.editor.dev.x86_64.exe --dump-extension-api
copy /y extension_api.json ..\build\extension_api.json
copy /y ..\build\extension_api.json ..\godot-cpp\gdextension
copy /y core\extension\gdextension_interface.h ..\godot-cpp\gdextension

cd ..
41 changes: 28 additions & 13 deletions build_libgodot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ lib_suffix="so"
host_debug=1
debug=1
force_host_rebuild=0
force_regenerate=0
update_api=0

case "$host_system" in
Linux)
Expand Down Expand Up @@ -51,18 +51,25 @@ do
--host-debug)
host_debug=1
;;
--regenerate)
force_regenerate=1
--host-release)
host_debug=0
;;
--update-api)
update_api=1
force_host_rebuild=1
;;
--debug)
debug=1
;;
--release)
debug=0
;;
--target)
shift
target_platform="${1:-}"
;;
*)
echo "Usage: $0 [--host-debug] [--host-rebuild] [--debug] [--regenerate] --target <target platform>"
echo "Usage: $0 [--host-debug] [--host-rebuild] [--host-debug] [--host-release] [--debug] [--release] [--update-api] [--target <target platform>]"
exit 1
;;
esac
Expand All @@ -72,7 +79,7 @@ done
if [ "$target_platform" = "ios" ]
then
target_arch="arm64"
target="template_debug"
target="template_release"
lib_suffix="a"
fi

Expand All @@ -97,6 +104,10 @@ if [ $debug -eq 1 ]
then
target_build_options="$target_build_options dev_build=yes"
target_godot_suffix="$target_godot_suffix.dev"
if [ "$target_platform" = "ios" ]
then
target="template_debug"
fi
fi

target_godot_suffix="$target_godot_suffix.$target_arch"
Expand All @@ -113,22 +124,26 @@ fi

mkdir -p $BUILD_DIR

if [ ! -f $BUILD_DIR/extension_api.json ] || [ $force_regenerate -eq 1 ]
if [ $update_api -eq 1 ]
then
cd $BUILD_DIR
$host_godot --dump-extension-api
cp -v $BUILD_DIR/extension_api.json $GODOT_CPP_DIR/gdextension/
cp -v $GODOT_DIR/core/extension/gdextension_interface.h $GODOT_CPP_DIR/gdextension/
cp -v $GODOT_DIR/core/extension/libgodot.h $GODOT_CPP_DIR/gdextension/
cp -v $BUILD_DIR/extension_api.json $SWIFT_GODOT_DIR/Sources/ExtensionApi/
cp -v $GODOT_DIR/core/extension/gdextension_interface.h $SWIFT_GODOT_DIR/Sources/GDExtension/include/
cp -v $GODOT_DIR/core/extension/libgodot.h $SWIFT_GODOT_DIR/Sources/GDExtension/include/

echo "Successfully updated the GDExtension API."
exit 0
fi

cd $GODOT_DIR
scons p=$target_platform target=$target $target_build_options library_type=shared_library
cp -v $target_godot $BUILD_DIR/libgodot.$lib_suffix

cp -v $BUILD_DIR/extension_api.json $GODOT_CPP_DIR/gdextension/
cp -v $GODOT_DIR/core/extension/gdextension_interface.h $GODOT_CPP_DIR/gdextension/

if [ "$target_platform" = "ios" ]
then
$SWIFT_GODOT_DIR/scripts/make-libgodot.framework $GODOT_DIR $BUILD_DIR
cp -v $BUILD_DIR/extension_api.json $SWIFT_GODOT_DIR/Sources/ExtensionApi/
cp -v $GODOT_DIR/core/extension/gdextension_interface.h $SWIFT_GODOT_DIR/Sources/GDExtension/include/
fi
$SWIFT_GODOT_DIR/scripts/make-libgodot.framework $GODOT_DIR $BUILD_DIR $target
fi
2 changes: 1 addition & 1 deletion godot
Submodule godot updated 4083 files
2 changes: 1 addition & 1 deletion godot-cpp
Submodule godot-cpp updated 105 files
6 changes: 5 additions & 1 deletion samples/cpp_sample/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ target_include_directories(${PROJECT_NAME} SYSTEM
${GODOT_CPP_DIR}/gen/include
${GODOT_CPP_DIR}/gdextension
)
target_link_libraries(${PROJECT_NAME} dl godot-cpp Threads::Threads)
if (WIN32)
target_link_libraries(${PROJECT_NAME} godot-cpp Threads::Threads)
else()
target_link_libraries(${PROJECT_NAME} dl godot-cpp Threads::Threads)
endif (WIN32)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${LIBGODOT_BUILD_DIR}/libgodot${CMAKE_SHARED_LIBRARY_SUFFIX}
Expand Down
70 changes: 61 additions & 9 deletions samples/cpp_sample/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#include <stdlib.h>
#include <stdio.h>
#if defined(__APPLE__) || defined(__unix__)
#include <dlfcn.h>
#elif defined(_WIN32)
#include <windows.h>
#endif
#include <string>
#include <vector>

#include <gdextension_interface.h>
#include <libgodot.h>

#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>
Expand All @@ -13,8 +17,10 @@

#ifdef __APPLE__
#define LIBGODOT_LIBRARY_NAME "libgodot.dylib"
#else
#elif defined(__unix__)
#define LIBGODOT_LIBRARY_NAME "./libgodot.so"
#elif defined(_WIN32)
#define LIBGODOT_LIBRARY_NAME "libgodot.dll"
#endif

extern "C" {
Expand Down Expand Up @@ -47,44 +53,90 @@ GDExtensionBool GDE_EXPORT gdextension_default_init(GDExtensionInterfaceGetProcA
class LibGodot {
public:
LibGodot(std::string p_path = LIBGODOT_LIBRARY_NAME) {
#if defined(__APPLE__) || defined(__unix__)
handle = dlopen(p_path.c_str(), RTLD_LAZY);
if (handle == nullptr) {
fprintf(stderr, "Error opening libgodot: %s\n", dlerror());
return;
}
*(void**)(&func_gdextension_create_godot_instance) = dlsym(handle, "gdextension_create_godot_instance");
if (func_gdextension_create_godot_instance == nullptr) {
*(void**)(&func_libgodot_create_godot_instance) = dlsym(handle, "libgodot_create_godot_instance");
if (func_libgodot_create_godot_instance == nullptr) {
fprintf(stderr, "Error acquiring function: %s\n", dlerror());
dlclose(handle);
handle == nullptr;
return;
}
*(void**)(&func_libgodot_destroy_godot_instance) = dlsym(handle, "libgodot_destroy_godot_instance");
if (func_libgodot_destroy_godot_instance == nullptr) {
fprintf(stderr, "Error acquiring function: %s\n", dlerror());
dlclose(handle);
handle == nullptr;
return;
}
#elif defined(_WIN32)
LPCSTR libgodot_library_name = reinterpret_cast<LPCSTR>(LIBGODOT_LIBRARY_NAME);
handle = LoadLibrary(libgodot_library_name);
if (handle == NULL) {
fprintf(stderr, "Error opening libgodot: %lu\n", GetLastError());
return;
}
func_libgodot_create_godot_instance = (GDExtensionObjectPtr (*)(int, char *[], GDExtensionInitializationFunction, void *))GetProcAddress(handle, "libgodot_create_godot_instance");
if (func_libgodot_create_godot_instance == NULL) {
fprintf(stderr, "Error acquiring function: %lu\n", GetLastError());
FreeLibrary(handle);
return;
}
#endif
}

~LibGodot() {
if (is_open()) {
#if defined(__APPLE__) || defined(__unix__)
dlclose(handle);
#elif defined(_WIN32)
FreeLibrary(handle);
#endif
}
}

bool is_open() {
return handle != nullptr && func_gdextension_create_godot_instance != nullptr;
#if defined(__APPLE__) || defined(__unix__)
return handle != nullptr && func_libgodot_create_godot_instance != nullptr;
#elif defined(_WIN32)
return handle != NULL && func_libgodot_create_godot_instance != NULL;
#endif
}

godot::GodotInstance *create_godot_instance(int p_argc, char *p_argv[], GDExtensionInitializationFunction p_init_func = gdextension_default_init) {
if (!is_open()) {
return nullptr;
}
GDExtensionObjectPtr instance = func_gdextension_create_godot_instance(p_argc, p_argv, p_init_func);
#if defined(__APPLE__) || defined(__unix__)
GDExtensionObjectPtr instance = func_libgodot_create_godot_instance(p_argc, p_argv, p_init_func, nullptr);
#elif defined(_WIN32)
GDExtensionObjectPtr instance = func_libgodot_create_godot_instance(p_argc, p_argv, p_init_func, handle);
#endif
if (instance == nullptr) {
return nullptr;
}
return reinterpret_cast<godot::GodotInstance *>(godot::internal::get_object_instance_binding(instance));
}

void destroy_godot_instance(godot::GodotInstance* instance) {
GDExtensionObjectPtr obj = godot::internal::gdextension_interface_object_get_instance_from_id(instance->get_instance_id());
func_libgodot_destroy_godot_instance(obj);
}

private:
#if defined(__APPLE__) || defined(__unix__)
void *handle = nullptr;
GDExtensionObjectPtr (*func_gdextension_create_godot_instance)(int, char *[], GDExtensionInitializationFunction) = nullptr;
GDExtensionObjectPtr (*func_libgodot_create_godot_instance)(int, char *[], GDExtensionInitializationFunction, void *) = nullptr;
void (*func_libgodot_destroy_godot_instance)(GDExtensionObjectPtr) = nullptr;
#elif defined(_WIN32)
HINSTANCE handle = NULL;
GDExtensionObjectPtr (*func_libgodot_create_godot_instance)(int, char *[], GDExtensionInitializationFunction, void *) = NULL;
void (*func_libgodot_destroy_godot_instance)(GDExtensionObjectPtr) = NULL;
#endif
};

int main(int argc, char **argv) {
Expand All @@ -95,7 +147,7 @@ int main(int argc, char **argv) {
if (argc > 0) {
program = std::string(argv[0]);
}
std::vector<std::string> args = { program, "--path", "../../project/" };
std::vector<std::string> args = { program, "--path", "../../project/", "--rendering-method", "gl_compatibility", "--rendering-driver", "opengl3" };

std::vector<char*> argvs;
for (const auto& arg : args) {
Expand All @@ -111,7 +163,7 @@ int main(int argc, char **argv) {

instance->start();
while (!instance->iteration()) {}
instance->shutdown();
libgodot.destroy_godot_instance(instance);

return EXIT_SUCCESS;
}
8 changes: 6 additions & 2 deletions samples/ios_sample/iosTest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
4009A2932BC608480066C885 /* SwiftGodotKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4009A2922BC608480066C885 /* SwiftGodotKit */; };
4041CDDD2C16837600400A0A /* game.pck in Resources */ = {isa = PBXBuildFile; fileRef = 4041CDDC2C16837600400A0A /* game.pck */; };
63091EA02BA0B27300576D34 /* main.pck in Resources */ = {isa = PBXBuildFile; fileRef = 63091E9F2BA0B27300576D34 /* main.pck */; };
633CF6A02B9EFEE1000461C9 /* iosTestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633CF69F2B9EFEE1000461C9 /* iosTestApp.swift */; };
633CF6A22B9EFEE1000461C9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633CF6A12B9EFEE1000461C9 /* ContentView.swift */; };
Expand Down Expand Up @@ -38,6 +39,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
4041CDDC2C16837600400A0A /* game.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = game.pck; sourceTree = "<group>"; };
63091E9F2BA0B27300576D34 /* main.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = main.pck; sourceTree = "<group>"; };
633CF69C2B9EFEE1000461C9 /* iosTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
633CF69F2B9EFEE1000461C9 /* iosTestApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosTestApp.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -106,6 +108,7 @@
633CF69E2B9EFEE1000461C9 /* iosTest */ = {
isa = PBXGroup;
children = (
4041CDDC2C16837600400A0A /* game.pck */,
63091E9F2BA0B27300576D34 /* main.pck */,
633CF69F2B9EFEE1000461C9 /* iosTestApp.swift */,
633CF6A12B9EFEE1000461C9 /* ContentView.swift */,
Expand Down Expand Up @@ -263,6 +266,7 @@
files = (
63091EA02BA0B27300576D34 /* main.pck in Resources */,
633CF6A72B9EFEE3000461C9 /* Preview Assets.xcassets in Resources */,
4041CDDD2C16837600400A0A /* game.pck in Resources */,
633CF6A42B9EFEE3000461C9 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -454,7 +458,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"iosTest/Preview Content\"";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = CVQ7CHHHZY;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "";
Expand Down Expand Up @@ -489,7 +493,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"iosTest/Preview Content\"";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = CVQ7CHHHZY;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "";
Expand Down
Loading