Skip to content

Commit fb11ccd

Browse files
committed
Add support for the wasm32-unknown-emscripten target
Build is working with emscripten 3.1.1, but requires setting some environment variables: EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0" EMSDK=~/.asdf/installs/emsdk/3.1.1 cargo build --target wasm32-unknown-emscripten ERROR_ON_UNDEFINED_SYMBOLS is a workaround for: warning: ___gxx_personality_v0 may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library This error appeared with emscripten 2.0.10 and has yet to be fixed in rust: rust-lang/rust#85821 (comment) EMSDK is for building skia-bindings against emscripten's platform includes. This is adapted from https://github.com/tuxmark5/rust-skia.
1 parent 4beb315 commit fb11ccd

File tree

4 files changed

+106
-23
lines changed

4 files changed

+106
-23
lines changed

README.md

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Skia Submodule Status: chrome/m97 ([upstream changes][skia-upstream], [our chang
99

1010
## Goals
1111

12-
This project provides _up to date_ safe bindings that bridge idiomatic Rust with Skia's C++ API on desktop and mobile platforms, including GPU rendering backends for [Vulkan](https://en.wikipedia.org/wiki/Vulkan_(API)), [Metal](https://en.wikipedia.org/wiki/Metal_(API)), [OpenGL](https://en.wikipedia.org/wiki/OpenGL), and [Direct3D](https://en.wikipedia.org/wiki/Direct3D).
12+
This project provides _up to date_ safe bindings that bridge idiomatic Rust with Skia's C++ API on desktop and mobile platforms, including GPU rendering backends for [Vulkan](<https://en.wikipedia.org/wiki/Vulkan_(API)>), [Metal](<https://en.wikipedia.org/wiki/Metal_(API)>), [OpenGL](https://en.wikipedia.org/wiki/OpenGL), and [Direct3D](https://en.wikipedia.org/wiki/Direct3D).
1313

1414
## Status
1515

@@ -40,31 +40,29 @@ For other platforms, more information is available at the [OpenSSL crate documen
4040

4141
### Platform Support, Build Targets, and Prebuilt Binaries
4242

43-
Because building Skia takes a lot of time and needs tools that may be missing, the skia-bindings crate's `build.rs` tries to download prebuilt binaries from [the skia-binaries repository](<https://github.com/rust-skia/skia-binaries/releases>).
43+
Because building Skia takes a lot of time and needs tools that may be missing, the skia-bindings crate's `build.rs` tries to download prebuilt binaries from [the skia-binaries repository](https://github.com/rust-skia/skia-binaries/releases).
4444

45-
| Platform | Binaries |
46-
| -------- | -------- |
47-
| Windows | `x86_64-pc-windows-msvc` |
48-
| Linux Ubuntu 16+<br />CentOS 7, 8 | `x86_64-unknown-linux-gnu` |
49-
| macOS | `x86_64-apple-darwin` |
50-
| Android | `aarch64-linux-android`<br/>`x86_64-linux-android` |
51-
| iOS | `aarch64-apple-ios`<br/>`x86_64-apple-ios` |
52-
53-
There no support for WebAssembly yet. If you'd like to help out, take a look at issue [#39](https://github.com/rust-skia/rust-skia/issues/39).
45+
| Platform | Binaries |
46+
| --------------------------------- | -------------------------------------------------- |
47+
| Windows | `x86_64-pc-windows-msvc` |
48+
| Linux Ubuntu 16+<br />CentOS 7, 8 | `x86_64-unknown-linux-gnu` |
49+
| macOS | `x86_64-apple-darwin` |
50+
| Android | `aarch64-linux-android`<br/>`x86_64-linux-android` |
51+
| iOS | `aarch64-apple-ios`<br/>`x86_64-apple-ios` |
5452

5553
### Wrappers & Codecs & Supported Features
5654

5755
The supported wrappers, Skia codecs, and additional Skia features are documented in the [skia-safe package's readme](skia-safe/README.md). Prebuilt binaries are available for most feature combinations.
5856

5957
## Building
6058

61-
If the target platform or feature configuration is not available as a prebuilt binary, skia-bindings' `build.rs` will try to build Skia and generate the Rust bindings.
59+
If the target platform or feature configuration is not available as a prebuilt binary, skia-bindings' `build.rs` will try to build Skia and generate the Rust bindings.
6260

6361
To prepare for that, **LLVM** and **Python 2** are needed:
6462

6563
**LLVM**
6664

67-
We recommend the version that comes preinstalled with your platform, or, if not available, the [latest official LLVM release](http://releases.llvm.org/download.html). To see which version of LLVM/Clang is installed on your system, use `clang --version`.
65+
We recommend the version that comes preinstalled with your platform, or, if not available, the [latest official LLVM release](http://releases.llvm.org/download.html). To see which version of LLVM/Clang is installed on your system, use `clang --version`.
6866

6967
**Python 2**
7068

@@ -88,9 +86,9 @@ The build script probes for `python --version` and `python2 --version` and uses
8886
sudo open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
8987
```
9088

91-
If not installed, the Skia build _may_ fail to build `SkJpegUtility.cpp` and the binding generation _will_ fail with `'TargetConditionals.h' file not found` . Also note that the Command Line Tools _and_ SDK headers _should_ be reinstalled after an update of XCode.
89+
If not installed, the Skia build _may_ fail to build `SkJpegUtility.cpp` and the binding generation _will_ fail with `'TargetConditionals.h' file not found` . Also note that the Command Line Tools _and_ SDK headers _should_ be reinstalled after an update of XCode.
9290

93-
- As an alternative to Apple's XCode LLVM, install LLVM via `brew install llvm` or `brew install llvm` and then set `PATH`, `CPPFLAGS`, and `LDFLAGS` like instructed.
91+
- As an alternative to Apple's XCode LLVM, install LLVM via `brew install llvm` or `brew install llvm` and then set `PATH`, `CPPFLAGS`, and `LDFLAGS` like instructed.
9492

9593
If the environment variables are not set, [bindgen](https://github.com/rust-lang/rust-bindgen) will most likely use the wrong `libclang.dylib` and cause confusing compilation errors (see #228).
9694

@@ -103,15 +101,15 @@ The build script probes for `python --version` and `python2 --version` and uses
103101
- Install the [latest LLVM](http://releases.llvm.org/download.html) distribution.
104102

105103
If the environment variable `LLVM_HOME` is not defined, the build script will look for LLVM installations located at `C:\Program Files\LLVM\`, `C:\LLVM\`, and `%USERPROFILE%\scoop\apps\llvm\current\`.
106-
104+
107105
- [MSYS2](https://www.msys2.org/):
108-
106+
109107
- Install Python2 with `pacman -S python2`.
110-
108+
111109
- Windows Shell (`Cmd.exe`):
112-
110+
113111
- Download and install Python version 2 from [python.org](https://www.python.org/downloads/release/python-2716/).
114-
112+
115113
- Install and select the MSVC toolchain:
116114
```bash
117115
rustup default stable-msvc
@@ -202,6 +200,7 @@ export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android26-clang.c
202200

203201
cargo build -vv --target aarch64-linux-android
204202
```
203+
205204
_Notes:_
206205

207206
- The `CARGO_TARGET_${TARGET}_LINKER` environment variable name [needs to be all uppercase](https://github.com/rust-lang/cargo/issues/1109#issuecomment-386850387).
@@ -212,6 +211,51 @@ _Notes:_
212211

213212
Compilation to iOS is supported on macOS targeting the iOS simulator (`--target x86_64-apple-ios`) and 64 bit ARM devices (`--target aarch64-apple-ios`). The ARM64**e** architecture is [not supported yet](https://github.com/rust-lang/rust/issues/73628).
214213

214+
### For WebAssembly
215+
216+
Install `emscripten` version 3.1.1 or superior.
217+
218+
Build with the `wasm32-unknown-emscripten` target (`wasm32-unknown-unknown` is
219+
unsupported because it is [fundamentally incompatible with linking C code](https://github.com/rustwasm/team/issues/291#issuecomment-645482430):
220+
221+
```bash
222+
export EMSDK=~/.asdf/installs/emsdk/3.1.1
223+
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0"
224+
225+
cargo build --target wasm32-unknown-emscripten
226+
```
227+
228+
The `EMSDK` environment variable must be set to the root of your `emscripten` SDK.
229+
230+
In `EMCC_CFLAGS`, `-s ERROR_ON_UNDEFINED_SYMBOLS` is a
231+
[workaround](https://github.com/rust-lang/rust/issues/85821#issuecomment-969369677) to build with
232+
`emscripten > 2.0.9`.
233+
234+
If you want to enable WebGL, you will also have to set `MAX_WEBGL_VERSION=2`:
235+
236+
```bash
237+
export EMSDK=~/.asdf/installs/emsdk/3.1.1
238+
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0 -s MAX_WEBGL_VERSION=2"
239+
240+
cargo build --target wasm32-unknown-emscripten --features gl
241+
```
242+
243+
On MacOS there is a problem with the OS version of `ar` so you will have to install the GNU version from homebrew:
244+
245+
```bash
246+
brew install binutils
247+
```
248+
249+
Then prepend `binutils` path for the build:
250+
251+
```bash
252+
export EMSDK=~/.asdf/installs/emsdk/3.1.1
253+
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0"
254+
export PATH="/opt/homebrew/opt/binutils/bin:$PATH"
255+
256+
cargo build --target wasm32-unknown-emscripten
257+
```
258+
215259
### Skia
216260

217261
For situations in which Skia does not build or needs to be configured differently, we support some customization support in `skia-bindings/build.rs`. For more details take a look at the [README of the skia-bindings package](skia-bindings/README.md).
@@ -249,7 +293,8 @@ cargo run -- [OUTPUT_DIR] --driver opengl
249293
```
250294

251295
And to show the drivers that are supported
252-
```bash
296+
297+
```bash
253298
cargo run -- --help
254299
```
255300

@@ -305,5 +350,3 @@ More details can be found at [CONTRIBUTING.md](https://github.com/rust-skia/rust
305350
## License
306351

307352
MIT
308-
309-

skia-bindings/build_support/binaries_config.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ impl BinariesConfiguration {
110110
(_, "apple", "ios", abi) => {
111111
link_libraries.extend(ios::link_libraries(abi, features));
112112
}
113+
("wasm32", "unknown", "emscripten", _) => {
114+
if features.gl {
115+
link_libraries.extend(["GL"]);
116+
}
117+
}
113118
_ => panic!("unsupported target: {:?}", cargo::target()),
114119
};
115120

skia-bindings/build_support/skia/config.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,15 @@ impl FinalBuildConfiguration {
223223
args.push(("target_cpu", quote(clang::target_arch(arch))));
224224
ios::extra_skia_cflags(arch, abi, &mut cflags);
225225
}
226+
("wasm32", "unknown", "emscripten", _) => {
227+
args.push(("cc", quote("emcc")));
228+
args.push(("cxx", quote("em++")));
229+
args.push(("skia_gl_standard", quote("webgl")));
230+
args.push(("skia_use_freetype", yes()));
231+
args.push(("skia_use_system_freetype2", no()));
232+
args.push(("skia_use_webgl", yes_if(features.gpu())));
233+
args.push(("target_cpu", quote("wasm")));
234+
}
226235
(arch, _, os, _) => {
227236
let skia_target_os = match os {
228237
"darwin" => {

skia-bindings/build_support/skia_bindgen.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,32 @@ pub fn generate_bindings(build: &FinalBuildConfiguration, output_directory: &Pat
243243
builder = builder.clang_arg(arg);
244244
}
245245
}
246+
("wasm32", "unknown", "emscripten", _) => {
247+
// visibility=default, otherwise some types may be missing:
248+
// https://github.com/rust-lang/rust-bindgen/issues/751#issuecomment-555735577
249+
builder = builder.clang_arg("-fvisibility=default");
250+
251+
let emsdk_base_dir = match std::env::var("EMSDK") {
252+
Ok(val) => val,
253+
Err(_e) => panic!("please set the EMSDK environment variable to the root of your Emscripten installation"),
254+
};
255+
256+
// Add C++ includes (otherwise build will fail with <cmath> not found)
257+
let add_sys_include = |builder: bindgen::Builder, path: &str| -> bindgen::Builder {
258+
let cflag = format!(
259+
"-isystem{}/upstream/emscripten/system/{}",
260+
emsdk_base_dir, path
261+
);
262+
builder.clang_arg(&cflag)
263+
};
264+
265+
builder = builder.clang_arg("-nobuiltininc");
266+
builder = add_sys_include(builder, "lib/libc/musl/arch/emscripten");
267+
builder = add_sys_include(builder, "lib/libc/musl/arch/generic");
268+
builder = add_sys_include(builder, "lib/libcxx/include");
269+
builder = add_sys_include(builder, "lib/libc/musl/include");
270+
builder = add_sys_include(builder, "include");
271+
}
246272
_ => {}
247273
}
248274

0 commit comments

Comments
 (0)