Skip to content

Commit b1ada38

Browse files
committed
ruby-rbs-sys: support wasm32-wasip1
1 parent 716ca05 commit b1ada38

2 files changed

Lines changed: 85 additions & 6 deletions

File tree

‎.github/workflows/rust.yml‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,41 @@ jobs:
184184
run: |
185185
cd rust
186186
cargo clippy
187+
188+
wasm:
189+
name: cargo:wasm
190+
runs-on: ubuntu-latest
191+
env:
192+
# Keep these versions in sync with .github/workflows/wasm.yml.
193+
WASI_SDK_VERSION: "33"
194+
WASI_SDK_RELEASE: "33.0"
195+
steps:
196+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
197+
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
198+
- name: Set up Ruby
199+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
200+
with:
201+
ruby-version: ruby
202+
bundler: none
203+
- name: Update rubygems & bundler
204+
run: gem update --system
205+
- name: Install gems
206+
run: |
207+
bundle config set --local without libs:profilers
208+
bundle install --jobs 4 --retry 3
209+
- name: Set up vendored RBS source
210+
run: bundle exec rake rust:rbs:sync
211+
- name: Install Rust target
212+
run: |
213+
rustup update --no-self-update stable
214+
rustup default stable
215+
rustup target add wasm32-wasip1
216+
- name: Install the WASI SDK
217+
run: |
218+
url="https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_RELEASE}-x86_64-linux.tar.gz"
219+
mkdir -p "$RUNNER_TEMP/wasi-sdk"
220+
curl -sSL "$url" | tar xz --strip-components=1 -C "$RUNNER_TEMP/wasi-sdk"
221+
echo "WASI_SDK_PATH=$RUNNER_TEMP/wasi-sdk" >> "$GITHUB_ENV"
222+
- name: Build Rust crates for wasm
223+
working-directory: rust
224+
run: cargo build --locked --target wasm32-wasip1 -p ruby-rbs-sys -p ruby-rbs

‎rust/ruby-rbs-sys/build.rs‎

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,47 @@ fn main() -> Result<(), Box<dyn Error>> {
1111
let include = vendor_rbs.join("include");
1212
let c_src = vendor_rbs.join("src");
1313

14-
build(&include, &c_src)?;
14+
let target = env::var("TARGET").unwrap_or_default();
15+
let is_wasi = target.contains("wasm32") && target.contains("wasi");
1516

16-
let bindings = generate_bindings(&include)?;
17+
build(&include, &c_src, is_wasi)?;
18+
19+
let bindings = generate_bindings(&include, is_wasi)?;
1720
write_bindings(&bindings)?;
1821

1922
Ok(())
2023
}
2124

22-
fn build(include_dir: &Path, src_dir: &Path) -> Result<(), Box<dyn Error>> {
25+
fn build(include_dir: &Path, src_dir: &Path, is_wasi: bool) -> Result<(), Box<dyn Error>> {
2326
let mut build = cc::Build::new();
2427

2528
build.include(include_dir);
2629

2730
// Suppress unused parameter warnings from C code
2831
build.flag_if_supported("-Wno-unused-parameter");
2932

33+
if is_wasi {
34+
// Compile the C parser with the WASI SDK so that its headers and
35+
// runtime support match the target platform.
36+
println!("cargo:rerun-if-env-changed=WASI_SDK_PATH");
37+
38+
let wasi_sdk = PathBuf::from(
39+
env::var("WASI_SDK_PATH").expect("WASI_SDK_PATH must be set for wasm builds"),
40+
);
41+
build.compiler(wasi_sdk.join("bin").join("clang"));
42+
43+
let sysroot = wasi_sdk.join("share").join("wasi-sysroot");
44+
build.flag(format!("--sysroot={}", sysroot.display()));
45+
build.include(sysroot.join("include"));
46+
47+
println!(
48+
"cargo:rustc-link-search=native={}",
49+
sysroot.join("lib/wasm32-wasi").display()
50+
);
51+
build.define("_WASI_EMULATED_MMAN", "1");
52+
println!("cargo:rustc-link-lib=wasi-emulated-mman");
53+
}
54+
3055
build.files(source_files(src_dir)?);
3156
build.try_compile("rbs")?;
3257

@@ -64,8 +89,11 @@ fn source_files<P: AsRef<Path>>(root_dir: P) -> Result<Vec<String>, Box<dyn Erro
6489
Ok(files)
6590
}
6691

67-
fn generate_bindings(include_path: &Path) -> Result<bindgen::Bindings, Box<dyn Error>> {
68-
let bindings = bindgen::Builder::default()
92+
fn generate_bindings(
93+
include_path: &Path,
94+
is_wasi: bool,
95+
) -> Result<bindgen::Bindings, Box<dyn Error>> {
96+
let mut builder = bindgen::Builder::default()
6997
.header("wrapper.h")
7098
.clang_arg(format!("-I{}", include_path.display()))
7199
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
@@ -172,7 +200,20 @@ fn generate_bindings(include_path: &Path) -> Result<bindgen::Bindings, Box<dyn E
172200
// Constant pool functions
173201
.allowlist_function("rbs_constant_pool_free")
174202
.allowlist_function("rbs_constant_pool_id_to_constant")
175-
.allowlist_function("rbs_constant_pool_init")
203+
.allowlist_function("rbs_constant_pool_init");
204+
205+
if is_wasi {
206+
// wasm-target bindgen output depends on the libclang implementation
207+
// and may drop declarations or make structs opaque. Generate the
208+
// ABI declarations with the host target instead; rustc will compile
209+
// them for the actual target. Host layout tests are not valid here.
210+
let host = env::var("HOST").expect("HOST is not set");
211+
builder = builder
212+
.clang_arg(format!("--target={host}"))
213+
.layout_tests(false);
214+
}
215+
216+
let bindings = builder
176217
.generate()
177218
.map_err(|_| "Unable to generate rbs bindings")?;
178219

0 commit comments

Comments
 (0)