Skip to content

Commit

Permalink
Add support for the wasm32-unknown-emscripten target
Browse files Browse the repository at this point in the history
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

EMCC_CFLAGS=... 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.
  • Loading branch information
flupke committed Jan 17, 2022
1 parent 4beb315 commit e86dbf1
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 23 deletions.
63 changes: 40 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Skia Submodule Status: chrome/m97 ([upstream changes][skia-upstream], [our chang

## Goals

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).
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).

## Status

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

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

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>).
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).

| Platform | Binaries |
| -------- | -------- |
| Windows | `x86_64-pc-windows-msvc` |
| Linux Ubuntu 16+<br />CentOS 7, 8 | `x86_64-unknown-linux-gnu` |
| macOS | `x86_64-apple-darwin` |
| Android | `aarch64-linux-android`<br/>`x86_64-linux-android` |
| iOS | `aarch64-apple-ios`<br/>`x86_64-apple-ios` |

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).
| Platform | Binaries |
| --------------------------------- | -------------------------------------------------- |
| Windows | `x86_64-pc-windows-msvc` |
| Linux Ubuntu 16+<br />CentOS 7, 8 | `x86_64-unknown-linux-gnu` |
| macOS | `x86_64-apple-darwin` |
| Android | `aarch64-linux-android`<br/>`x86_64-linux-android` |
| iOS | `aarch64-apple-ios`<br/>`x86_64-apple-ios` |

### Wrappers & Codecs & Supported Features

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.

## Building

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.
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.

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

**LLVM**

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`.
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`.

**Python 2**

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

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.
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.

- 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.
- 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.

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).

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

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\`.

- [MSYS2](https://www.msys2.org/):

- Install Python2 with `pacman -S python2`.

- Windows Shell (`Cmd.exe`):

- Download and install Python version 2 from [python.org](https://www.python.org/downloads/release/python-2716/).

- Install and select the MSVC toolchain:
```bash
rustup default stable-msvc
Expand Down Expand Up @@ -202,6 +200,7 @@ export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android26-clang.c

cargo build -vv --target aarch64-linux-android
```

_Notes:_

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

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).

### For WebAssembly

Install `emscripten` version 3.1.1 or superior.

Build with the `wasm32-unknown-emscripten` target (`wasm32-unknown-unknown` is
unsupported because it is [fundamentally incompatible with linking C code](https://github.com/rustwasm/team/issues/291#issuecomment-645482430):

```bash
export EMSDK=~/.asdf/installs/emsdk/3.1.1
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0"

cargo build --target wasm32-unknown-emscripten
```

The `EMSDK` environment variable must be set to the root of your `emscripten` SDK.

`EMCC_CFLAGS` is a [workaround](https://github.com/rust-lang/rust/issues/85821#issuecomment-969369677)
to build with `emscripten > 2.0.9`.

### Skia

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).
Expand Down Expand Up @@ -249,7 +267,8 @@ cargo run -- [OUTPUT_DIR] --driver opengl
```

And to show the drivers that are supported
```bash

```bash
cargo run -- --help
```

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

MIT


5 changes: 5 additions & 0 deletions skia-bindings/build_support/binaries_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ impl BinariesConfiguration {
(_, "apple", "ios", abi) => {
link_libraries.extend(ios::link_libraries(abi, features));
}
("wasm32", "unknown", "emscripten", _) => {
if features.gl {
link_libraries.extend(["GL"]);
}
}
_ => panic!("unsupported target: {:?}", cargo::target()),
};

Expand Down
9 changes: 9 additions & 0 deletions skia-bindings/build_support/skia/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@ impl FinalBuildConfiguration {
args.push(("target_cpu", quote(clang::target_arch(arch))));
ios::extra_skia_cflags(arch, abi, &mut cflags);
}
("wasm32", "unknown", "emscripten", _) => {
args.push(("cc", quote("emcc")));
args.push(("cxx", quote("em++")));
args.push(("skia_gl_standard", quote("webgl")));
args.push(("skia_use_freetype", yes()));
args.push(("skia_use_system_freetype2", no()));
args.push(("skia_use_webgl", yes_if(features.gpu())));
args.push(("target_cpu", quote("wasm")));
}
(arch, _, os, _) => {
let skia_target_os = match os {
"darwin" => {
Expand Down
26 changes: 26 additions & 0 deletions skia-bindings/build_support/skia_bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,32 @@ pub fn generate_bindings(build: &FinalBuildConfiguration, output_directory: &Pat
builder = builder.clang_arg(arg);
}
}
("wasm32", "unknown", "emscripten", _) => {
// visibility=default, otherwise some types may be missing:
// https://github.com/rust-lang/rust-bindgen/issues/751#issuecomment-555735577
builder = builder.clang_arg("-fvisibility=default");

let emsdk_base_dir = match std::env::var("EMSDK") {
Ok(val) => val,
Err(_e) => panic!("please set the EMSDK environment variable to the root of your Emscripten installation"),
};

// Add C++ includes (otherwise build will fail with <cmath> not found)
let add_sys_include = |builder: bindgen::Builder, path: &str| -> bindgen::Builder {
let cflag = format!(
"-isystem{}/upstream/emscripten/system/{}",
emsdk_base_dir, path
);
builder.clang_arg(&cflag)
};

builder = builder.clang_arg("-nobuiltininc");
builder = add_sys_include(builder, "lib/libc/musl/arch/emscripten");
builder = add_sys_include(builder, "lib/libc/musl/arch/generic");
builder = add_sys_include(builder, "lib/libcxx/include");
builder = add_sys_include(builder, "lib/libc/musl/include");
builder = add_sys_include(builder, "include");
}
_ => {}
}

Expand Down

0 comments on commit e86dbf1

Please # to comment.