Skip to content

Add HTML5 export guide #71

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

Merged
merged 3 commits into from
Sep 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- [Android](./exporting/android.md)
- [(TODO) iOS](./exporting/ios.md)
- [Mac OS X](./exporting/macosx.md)
- [HTML5](./exporting/html5.md)
- [Advanced Guides](./advanced-guides.md)
- [Using custom Godot versions](./advanced-guides/custom-godot.md)
- [Migrating from godot-rust 0.8](advanced-guides/migrating-0-8.md)
Expand Down
92 changes: 92 additions & 0 deletions src/exporting/html5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# HTML5

Exporting to HTML5 works just like exporting to other platforms, however there are some things that can make the process a bit tricky and require extra attention.

## General considerations
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this export process doesn't have a trivial set up, I think this section can be called "Tooling Requirements", "Setup Requirements" or something like that. This would make it more obvious to users that there are very specific requirements for this export process.


The Godot HTML5 export templates are built with [Emscripten](https://emscripten.org/), so you need to build your code for the `wasm32-unknown-emscripten` target, `wasm32-unknown-unknown` will not work. Furthermore, you need to use a version of emscripten that is compatible with both your version of Rust and the version of emscripten used to build the export template.
In practice, this means you might have to [build the HTML5 export template yourself](https://docs.godotengine.org/en/stable/development/compiling/compiling_for_web.html) and/or use a specific version of Rust. You can check which versions you are using like this:

```bash
emcc -v
rustc --version --verbose
```

Also note that `wasm32-unknown-emscripten` is a 32-bit target, which can cause problems with crates incorrectly assuming that `usize` is 64 bits wide.

## Godot 3.4.4

**Disclaimer**: _Currently, the following steps are only tested and confirmed to work on Linux._
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth making this disclaimer into it's own section where we can include all of the additional version requirements. In the future, more folks may be able to test this and confirm working versions so having a section could be useful for new users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I expect this whole section to become outdated very rapidly. What I said under "General Considerations" (matching emscripten versions) is fairly general, but building Godot will probably not be necessary with 3.6, and rust compiler flags could change any second now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair point. I think keeping a normal disclaimer is probably enough in that case.


Godot 3.4.4's export template is built with a very old Emscripten version that doesn't play nice with Rust. We will have to build it ourselves with a more recent version.
We also need to build the `std` crate ourselves, so we will have to use a nightly Rust build.

Confirmed working versions are:
* rustc 1.63.0-nightly (dc80ca78b 2022-06-21)
* Emscripten 3.1.15-git (4100960b42619b28f19baf4254d5db2097234b32)


### Getting Emscripten
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor nitpick, "Installing and configuring Emscripten" might be a more appropriate section title.


We will be using Emscripten tip-of-tree:

```bash
# Get the emsdk repo
git clone https://github.com/emscripten-core/emsdk.git

# Enter that directory
cd emsdk

# Download and install the tip-of-tree SDK tools.
./emsdk install tot

# Make the "tot" SDK "active" for the current user. (writes .emscripten file)
./emsdk activate tot

# Activate PATH and other environment variables in the current terminal
source ./emsdk_env.sh
```

### Building Godot
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this require building Godot from source? or only the export template? If the latter, can we change the title to "Building Godot export template"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As far as I can tell an export template is just a pre-built version of Godot, so these are the same thing. We are compiling the engine from source to wasm.

Copy link
Member

Choose a reason for hiding this comment

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

Since you built Godot from source, did you use gdnative with the custom-godot Cargo feature?


Build the Godot Export template according to the [instructions](https://docs.godotengine.org/en/stable/development/compiling/compiling_for_web.html):

```bash
source "/path/to/emsdk-portable/emsdk_env.sh"
scons platform=javascript tools=no gdnative_enabled=yes target=release
mv bin/godot.javascript.opt.gdnative.zip bin/webassembly_gdnative_release.zip
```

Set the newly built export template as a custom template in Godot and be sure to set the export type as GDNative. When exporting, uncheck "Export With Debug".
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm assuming that the export template requires installing from a file as per: https://docs.godotengine.org/en/stable/tutorials/export/exporting_basics.html#export-templates

Is that correct? If so, can I ask for you to add the above link for completeness?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is what I'm referring to:
image

We could link that image?

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good to me!


### Building your Rust code

In your project's `config.toml`, add the following:
Copy link
Member

Choose a reason for hiding this comment

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

This refers to the godot-rust crate which is compiled as a cdylib? If yes, maybe quickly mention that to resolve ambiguities 🙂


```toml
[target.wasm32-unknown-emscripten]
rustflags = [
"-Clink-arg=-sSIDE_MODULE=2", # build a side module that Godot can load
"-Crelocation-model=pic", # needed to prevent linker errors
Copy link

Choose a reason for hiding this comment

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

This is not needed on nightly Rust:
rust-lang/rust#98149

"-Cpanic=abort", # panic unwinding is currently broken without -sWASM_BIGINT, see below
Copy link

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the guide to reflect the current state of affairs.

I initially had some problems where I still needed -Zbuild-std (to fix missing __cxa_is_pointer_type) and -Zlink-native-libraries=no (to fix wasm-ld: error: unable to find library -lc, but after cargo clean it works without those flags so maybe rust was incorrectly reusing some old build artifact? @hoodmane can you confirm that these flags shouldn't be needed?

Copy link

@hoodmane hoodmane Jul 4, 2022

Choose a reason for hiding this comment

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

Currently Pyodide is using:

export RUSTFLAGS= \
	-C link-arg=-sSIDE_MODULE=2 \
	-C link-arg=-sWASM_BIGINT \
	-Z link-native-libraries=no

https://github.com/pyodide/pyodide/blob/main/Makefile.envs#L159

The problem that -Zlink-native-libraries=no fixes is not resolved either on the Rust side or on the Emscripten side. But if it works without it...

#"-Clink-arg=-sWASM_BIGINT", # alternative to panic=abort, requires building godot with -sWASM_BIGINT also
]
```

Build like this:

```bash
source "/path/to/emsdk-portable/emsdk_env.sh"
export C_INCLUDE_PATH=$EMSDK/upstream/emscripten/cache/sysroot/include

cargo +nightly build --target=wasm32-unknown-emscripten --release -Zbuild-std=core,std,alloc,panic_abort
```

### Further reading

In the future, some/all of this will probably not be needed, for more info see:
* [Tracking issue for godot-rust wasm support](https://github.com/godot-rust/godot-rust/issues/647)
* [Rust PR that obsoletes -Clink-arg=-sSIDE_MODULE=2](https://github.com/rust-lang/rust/pull/98358)
* [Rust PR that obsoletes -Crelocation-model=pic and -Zbuild-std](https://github.com/rust-lang/rust/pull/98149)
* [Godot PR that updates Emscripten version](https://github.com/godotengine/godot/pull/61989)
* [Godot PR that would obsolete -Cpanic=abort in favor of -sWASM_BIGINT](https://github.com/godotengine/godot/pull/62397)