Skip to content

Commit

Permalink
Module support (#17)
Browse files Browse the repository at this point in the history
* Fix warnings

* Module agnostic defines

GODOT_MODULE define determines how Godot sources are included
All Godot sources should be included in defs.h
REGISTRATION_METHOD defines the method name used to register methods and properties
Method registration must be defined twice based on GODOT_MODULE
NS define used for godot namespace required by anonymous namespaces when compiling as addon
Define godot_error as alias of Error for module
Errors used for Godot 3.x addon are defined (enables max compatibility with module and Godot 4)
Godot library source file (addon specific) skipped if GODOT_MODULE present
StreamPeer superclass defined depending on context
StreamPeerGDNative interface defined for addon (likely to be ugliest part of module agnosticism)

* Generalize signature array creation

* Stream peer getter

* Basic module scaffolding

* Update readme

* GNU++14 compiler support

* Exclude godot library file for module
  • Loading branch information
ashtonmeuser authored Apr 22, 2023
1 parent c18b7d9 commit 1642e7d
Show file tree
Hide file tree
Showing 13 changed files with 222 additions and 100 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ addons.zip
*.so
*.dylib
*.dll
*.o
__pycache__
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,34 @@
A Godot addon allowing for loading and interacting with [WebAssembly (Wasm)](https://webassembly.org) modules from GDScript. Note that this project is still in development.

This [GDNative](https://docs.godotengine.org/en/stable/tutorials/scripting/gdnative/what_is_gdnative.html) addon uses [Wasmer](https://wasmer.io) as the WebAssembly runtime.
Godot Wasm can be used either as a [GDNative](https://docs.godotengine.org/en/stable/tutorials/scripting/gdnative/what_is_gdnative.html) addon or Godot module. It uses [Wasmer](https://wasmer.io) as the WebAssembly runtime.

## Installation

Godot Wasm supports installation via addon or module. Installing as an addon is far faster and simpler and requires merely including the asset in your Godot project while installing the module requires recompilation of the Godot engine. Note that exporting to web/HTML5 is only supported for modules (see [#15](https://github.com/ashtonmeuser/godot-wasm/issues/15)).

### Addon

Installation in a Godot project involves simply downloading and installing a zip file from Godot's UI. Recompilation of the engine is *not* required.

1. Download the Godot Wasm addon zip file from the [releases page](https://github.com/ashtonmeuser/godot-wasm/releases).
1. In Godot's Asset Library tab, click Import and select the addon zip file. Follow prompts to complete installation of the addon.

Alternatively, you can use the Asset Library tab within the Godot editor, search for "Wasm", and follow the prompts to install. Yet another alternative is downloading directly from the [asset page](https://godotengine.org/asset-library/asset/1798) and following the installation instructions above. Note that the Asset Library has an approval process that can take several days and may therefore be a version or two behind.

### Godot Module

Installation as a Godot module requires recompilation of the Godot engine. This enables exporting to web/HTML5.

1. Clone or download the [Godot engine](https://github.com/godotengine/godot) following [this guide](https://docs.godotengine.org/en/3.5/development/compiling/getting_source.html).
1. Download the project source via the [releases page](https://github.com/ashtonmeuser/godot-wasm/releases) or Code → Download ZIP on GitHub.
1. Include the entire Godot Wasm directory within the *godot/modules* directory.
1. Rename the Godot Wasm directory to *wasm*. All project files e.g. *SCsub* should now be in *godot/modules/wasm*.

Recompile the Godot engine following [this guide](https://docs.godotengine.org/en/3.5/development/compiling/index.html#toc-devel-compiling). More information on custom Godot modules can be found in [this guide](https://docs.godotengine.org/en/3.5/development/cpp/custom_modules_in_cpp.html).

To export using the customized engine, you'll also need to recompile the export templates (documented in the Engine compilation guide).

## Usage

Once installed as an addon in a Godot project, the Godot Wasm addon class can be accessed via `Wasm`.
Expand All @@ -56,7 +73,7 @@ Once installed as an addon in a Godot project, the Godot Wasm addon class can be
### Exporting Godot Project
> **Note**
> Exporting to web/HTML5 using a GDNative addon is not supported by Godot. See [godotengine/godot#12243](https://github.com/godotengine/godot/issues/12243).
> Exporting to web/HTML5 using a GDNative addon is not supported by Godot. See [godotengine/godot#12243](https://github.com/godotengine/godot/issues/12243). Install as a Godot Module to enable web/HTML5 exports.
Exporting from Godot may require the following additional steps. See the export configuration of the [example Godot project](https://github.com/ashtonmeuser/godot-wasm/tree/master/examples) for a practical illustration.
Expand Down
3 changes: 2 additions & 1 deletion SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import re
from urllib import request
import tarfile

# Initial options inheriting from CLI args
opts = Variables([], ARGUMENTS)

# Define options
Expand Down Expand Up @@ -56,7 +57,7 @@ if env['download_wasmer'] or not os.path.isdir('wasmer'):

# Check platform specifics
if env['platform'] == 'osx':
env.Append(CCFLAGS=['-arch', 'x86_64'])
env.Append(CCFLAGS=['-arch', 'x86_64', '-Wall'])
env.Append(CXXFLAGS=['-std=c++17'])
env.Append(LINKFLAGS=['-arch', 'x86_64', '-framework', 'Security'])
if env['target'] in ('debug', 'd'):
Expand Down
28 changes: 28 additions & 0 deletions SCsub
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Import env and create module-specific clone
Import('env')
module_env = env.Clone()

# Check platform specifics
if env['platform']=='linuxbsd':
module_env['LIBSUFFIX'] = '.a'
module_env.Append(CXXFLAGS=['-std=c++17'])
elif env['platform']=='osx':
module_env['LIBSUFFIX'] = '.a'
module_env.Append(CXXFLAGS=['-std=c++17'])
env.Append(LINKFLAGS=['-framework', 'Security'])
elif env['platform']=='windows':
module_env['LIBSUFFIX'] = '.lib'

# Explicit static libraries
wasmer_library = env.File('{}wasmer{}'.format(env['LIBPREFIX'], module_env.get('LIBWASMERSUFFIX', module_env['LIBSUFFIX'])))

# Linked libraries (global env) and includes (cloned env)
env.Append(LIBPATH=[env.Dir('wasmer/lib').abspath])
env.Append(LIBS=[wasmer_library])
module_env.Append(CPPPATH=['wasmer/include'])

# Defines for module agnosticism
module_env.Append(CPPDEFINES=["GODOT_MODULE"])

# Module sources
module_env.add_source_files(env.modules_sources, ['register_types.cpp', env.Glob('src/*.cpp', exclude='src/godot-library.cpp')])
5 changes: 5 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def can_build(env, platform):
return True

def configure(env):
pass
16 changes: 16 additions & 0 deletions register_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifdef GODOT_MODULE

#include "register_types.h"

#include "core/class_db.h"
#include "src/godot-wasm.h"
#include "src/stream-peer-wasm.h"

void register_wasm_types() {
ClassDB::register_class<godot::Wasm>();
ClassDB::register_class<godot::StreamPeerWasm>();
}

void unregister_wasm_types() { }

#endif
2 changes: 2 additions & 0 deletions register_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void register_wasm_types();
void unregister_wasm_types();
26 changes: 23 additions & 3 deletions src/defs.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
#ifndef GODOT_WASM_DEFS_H
#define GODOT_WASM_DEFS_H

#ifdef GODOT_MODULE // Godot includes when building module
#include "core/io/stream_peer.h"
#else // Godot addon includes
#include <Godot.hpp>
#include <StreamPeerGDNative.hpp>
#endif

namespace {
#ifdef __GNUC__
#define UNLIKELY(cond) __builtin_expect(!!(cond), 0)
#else
#define UNLIKELY(cond) cond
#endif
#define GDERROR(error) GODOT_##error
#define PRINT_ERROR(message) godot::Godot::print_error("Godot Wasm: " + godot::String(message), __func__, __FILE__, __LINE__);
#ifdef GODOT_MODULE
#define NS
#define godot_error Error
#define PRINT_ERROR(message) print_error("Godot Wasm: " + String(message))
#define REGISTRATION_METHOD _bind_methods
#else
#define NS godot
#define OK GODOT_OK
#define ERR_INVALID_DATA GODOT_ERR_INVALID_DATA
#define ERR_COMPILATION_FAILED GODOT_ERR_COMPILATION_FAILED
#define ERR_CANT_CREATE GODOT_ERR_CANT_CREATE
#define PRINT_ERROR(message) godot::Godot::print_error("Godot Wasm: " + godot::String(message), __func__, __FILE__, __LINE__)
#define GDCLASS GODOT_CLASS
#define REGISTRATION_METHOD _register_methods
#endif
#define FAIL(message, ret) do { PRINT_ERROR(message); return ret; } while (0)
#define FAIL_IF(cond, message, ret) if (UNLIKELY(cond)) FAIL(message, ret)
#define NULL_VARIANT godot::Variant()
#define NULL_VARIANT NS::Variant()
#define PAGE_SIZE 65536
}

Expand Down
4 changes: 4 additions & 0 deletions src/godot-library.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#ifndef GODOT_MODULE

#include "godot-wasm.h"
#include "stream-peer-wasm.h"

Expand All @@ -15,3 +17,5 @@ extern "C" void GDN_EXPORT wasm_nativescript_init(void *handle) {
godot::register_class<godot::Wasm>();
godot::register_class<godot::StreamPeerWasm>();
}

#endif
Loading

0 comments on commit 1642e7d

Please sign in to comment.