-
Notifications
You must be signed in to change notification settings - Fork 214
Add cpp-to-wasm test #968
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
Add cpp-to-wasm test #968
Changes from all commits
b772583
cc49894
8c276dc
2ef0e6e
6678f7a
6fbeb50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,11 +31,11 @@ all-features = true | |
skip_optional_dependencies = true | ||
# Bench feature gets tested separately and is only relevant for CI. | ||
# wearos/freertos/x86tiny are not relevant in normal environments, | ||
# and smaller_static gets tested on the FFI job anyway | ||
# smaller_static gets tested on the FFI job anyway | ||
denylist = ["bench", "wearos", "freertos", "x86tiny", "smaller_static"] | ||
|
||
[lib] | ||
crate-type = ["staticlib", "rlib", "cdylib"] | ||
crate-type = ["staticlib", "rlib"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dylib had to be removed because it doesn't work for emscripten (without what seems to be a large amount of extra effort), we're not using cdylibs anyway, and it's still possible to compile icu_capi to a cdylib, just not in the emscripten context, and unfortunately rust-lang/cargo#4881 doesn't exist. |
||
path = "src/lib.rs" | ||
|
||
[features] | ||
|
@@ -86,3 +86,20 @@ icu_provider_fs = { path = "../../provider/fs/", optional = true } | |
[target.'cfg(target_os = "none")'.dependencies] | ||
freertos-rust = { version = "0.1.2", optional = true } | ||
cortex-m = { version = "0.7.3", optional = true } | ||
|
||
# Unfortunately, --crate-type cannot be set per-target | ||
# (https://github.com/rust-lang/cargo/issues/4881) | ||
# and emscripten has link errors when compiling icu_capi due to | ||
# symbols like log_js being undefined. There is no way to ask Cargo | ||
# to only build a particular crate type for an invocation | ||
# | ||
# As a workaround, we define an example crate that just reexports icu_capi, | ||
# but is built as a cdylib. Due to how Cargo invocations work around examples, | ||
# `--features` is still passed down to `icu_capi`, but the end result is an | ||
# `icu_capi_cdylib.wasm`/`icu_capi_cdylib.so`/etc file that is for all intents | ||
# and purposes identical to the file one would get from adding "cdylib" to | ||
# `crate-type` above. | ||
[[example]] | ||
name = "icu_capi_cdylib" | ||
path = "src/crate_type_hack.rs" | ||
crate-type = ["cdylib"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// This file is part of ICU4X. For terms of use, please see the file | ||
// called LICENSE at the top level of the ICU4X source tree | ||
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). | ||
|
||
// See comment in icu_capi's Cargo.toml | ||
// | ||
// This is essentially a hack that allows icu_capi to be compiled | ||
// to arbitrary `--crate-type`s without having to add a `--crate-type` | ||
// to the list in Cargo.toml | ||
extern crate icu_capi; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,4 +22,4 @@ a.out: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.cpp | |
build: a.out | ||
|
||
test: build | ||
./a.out | ||
./a.out |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
web-version.html | ||
web-version.wasm | ||
web-version.js | ||
node-version.js | ||
node-version.wasm | ||
package-lock.json | ||
node_modules | ||
a.out |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# This file is part of ICU4X. For terms of use, please see the file | ||
# called LICENSE at the top level of the ICU4X source tree | ||
# (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). | ||
|
||
.DEFAULT_GOAL := build | ||
.PHONY: build test clean serve build-host test-host | ||
|
||
ALL_HEADERS := $(wildcard ../../include/*.hpp) $(wildcard ../../../capi/include/*.h) | ||
ALL_RUST := $(wildcard ../../../capi//src/*.rs) | ||
|
||
$(ALL_RUST): | ||
|
||
$(ALL_HEADERS): | ||
|
||
../../../../target/debug/libicu_capi.a: $(ALL_RUST) | ||
cargo build -p icu_capi | ||
|
||
a.out: ../../../../target/debug/libicu_capi.a $(ALL_HEADERS) test.cpp | ||
g++ -std=c++17 test.cpp ../../../../target/debug/libicu_capi.a -ldl -lpthread -lm -g | ||
|
||
../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a: $(ALL_RUST) | ||
RUSTFLAGS="-Cpanic=abort" cargo +nightly-2021-02-28 build --release -p icu_capi --target wasm32-unknown-emscripten -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort | ||
|
||
web-version.html: ../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a $(ALL_HEADERS) test.cpp | ||
emcc -std=c++17 test.cpp ../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a -ldl -lpthread -lm -g -o web-version.html --bind --emrun -sENVIRONMENT=web -sWASM=1 -sEXPORT_ES6=1 -sMODULARIZE=1 | ||
|
||
node-version.js: ../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a $(ALL_HEADERS) test.cpp | ||
emcc -std=c++17 test.cpp ../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a -ldl -lpthread -lm -g -o node-version.js --bind -sWASM=1 -sENVIRONMENT=node -sWASM_ASYNC_COMPILATION=0 -DNOMAIN | ||
|
||
build: web-version.html node-version.js | ||
|
||
test: node-version.js | ||
exec node ./node-test.js | ||
|
||
serve: web-version.html | ||
emrun web-version.html | ||
|
||
# These make it possible to ensure that the C++ code is up to date with the bindings | ||
# without needing to set up emsdk. This way `make test-ffi` works without emsdk. | ||
build-host: a.out | ||
|
||
test-host: build-host | ||
./a.out | ||
|
||
clean: | ||
rm -f web-version.html | ||
rm -f web-version.wasm | ||
rm -f web-version.js | ||
rm -f node-version.js | ||
rm -f node-version.wasm | ||
rm -f ../../../../target/wasm32-unknown-emscripten/release/libicu_capi.a | ||
rm -f ../../../../target/debug/libicu_capi.a | ||
rm -f a.out |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
This folder contains a test for calling ICU4X from C++ compiled to WASM (via emscripten). | ||
|
||
You need the [Emscripten SDK](https://emscripten.org/docs/getting_started/downloads.html) downloaded and sourced into your environment to run this. | ||
|
||
There are two ways to run the test. Firstly, you can call `make test`, which runs `node node-test.js` after building the appropriate WASM files. This runs a CLI test with the fixed decimal example in test.cpp. | ||
|
||
The other way is to run `make serve`, which will open a web page running test.cpp in your browser. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
wasm = require("./node-version.js"); | ||
|
||
const exitCode = wasm.runFixedDecimal(); | ||
if (exitCode !== 0) { | ||
throw new Error(`Test failed with exit code ${exitCode}`) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"type": "commonjs", | ||
"scripts": { | ||
"test": "node node-test.js" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// This file is part of ICU4X. For terms of use, please see the file | ||
// called LICENSE at the top level of the ICU4X source tree | ||
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). | ||
|
||
#ifdef __EMSCRIPTEN__ | ||
#include <emscripten/bind.h> | ||
#endif | ||
|
||
#include "../../include/ICU4XFixedDecimalFormat.hpp" | ||
|
||
#include <iostream> | ||
|
||
extern "C" void diplomat_init(); | ||
extern "C" void log_js(char* s) { | ||
std::cout<<"LOG: " <<s <<std::endl; | ||
} | ||
|
||
int runFixedDecimal() { | ||
#ifdef __EMSCRIPTEN__ | ||
diplomat_init(); | ||
#endif | ||
ICU4XLocale locale = ICU4XLocale::create("bn").value(); | ||
std::cout << "Running test for locale " << locale.tostring().ok().value() << std::endl; | ||
ICU4XDataProvider dp = ICU4XDataProvider::create_static().provider.value(); | ||
ICU4XFixedDecimalFormatOptions opts = {ICU4XFixedDecimalGroupingStrategy::Auto, ICU4XFixedDecimalSignDisplay::Auto}; | ||
ICU4XFixedDecimalFormat fdf = ICU4XFixedDecimalFormat::try_new(locale, dp, opts).fdf.value(); | ||
|
||
ICU4XFixedDecimal decimal = ICU4XFixedDecimal::create(1000007); | ||
std::string out = fdf.format(decimal).ok().value(); | ||
std::cout << "Formatted value is " << out << std::endl; | ||
if (out != "১০,০০,০০৭") { | ||
std::cout << "Output does not match expected output" << std::endl; | ||
return 1; | ||
} | ||
|
||
std::string out2; | ||
fdf.format_to_writeable(decimal, out2); | ||
std::cout << "Formatted writeable value is " << out2 << std::endl; | ||
if (out2 != "১০,০০,০০৭") { | ||
std::cout << "Output does not match expected output" << std::endl; | ||
return 1; | ||
} | ||
|
||
decimal.multiply_pow10(2); | ||
decimal.negate(); | ||
out = fdf.format(decimal).ok().value(); | ||
std::cout << "Value x100 and negated is " << out << std::endl; | ||
if (out != "-১০,০০,০০,৭০০") { | ||
std::cout << "Output does not match expected output" << std::endl; | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
#ifdef __EMSCRIPTEN__ | ||
EMSCRIPTEN_BINDINGS(testFixedDecimal) { | ||
emscripten::function("runFixedDecimal", &runFixedDecimal); | ||
} | ||
#endif | ||
|
||
#ifndef NOMAIN | ||
int main() { | ||
return runFixedDecimal(); | ||
} | ||
#endif |
Uh oh!
There was an error while loading. Please reload this page.