#!/bin/sh # This script, and various infrastructure, is a hack to work around the lack of # stable support in Rust to generate a weak symbol. # # The basic problem here is that the Rust `wit-bindgen` crate wants to export # the `cabi_realloc` symbol from the final binary. This library, however, # is not stable which means that we're publishing new versions of `wit-bindgen` # over its development. This means that if `wit-bindgen`-the-crate were to # export a `#[no_mangle]` symbol of `cabi_realloc` then it wouldn't work to # have two versions of `wit-bindgen` in the same project. This can arise # relatively quickly, however, so this is something we want to solve. # # The general idea of the solution here is to ensure that the `cabi_realloc` # symbol itself is declared as a weak symbol. A weakly-defined symbol means # that if the linker sees multiple copies it can discard all but one. This is # the semantics we want where some `wit-bindgen` needs to define `cabi_realloc` # but it doesn't matter much which one. # # Stable Rust can't define weak symbols as of the time of this writing. C, # however, can. Unfortunately users of this crate do not always have a C # compiler on-hand for wasm, nor do we want to require one. That's where all # these hacks come into play. With that intro, the purpose of this script is to: # # * Generate a `cabi_realloc.rs` file with a "mangled" Rust symbol that's # unique per-major-version of the crate. # * Generate a `cabi_realloc.c` file that defines a weak `cabi_realloc` symbol # that calls the above Rust symbol # * Compile `cabi_realloc.c` into an object and place it into an archive and # check that archive into this repo. # # This all leads up to the point where we're distributing binary artifacts with # this crate. These artifacts are verified in CI to ensure what this script # generates. # # Overall this is intended to provide `cabi_realloc` as a weak symbol, # everything works on stable Rust, and users don't need a C compiler when they # use this crate. set -ex version=$(./ci/print-current-version.sh | sed 's/\./_/g') sym=cabi_realloc_wit_bindgen_$version cat >./crates/guest-rust/rt/src/cabi_realloc.rs <<-EOF // This file is generated by $0 #[no_mangle] pub unsafe extern "C" fn $sym( old_ptr: *mut u8, old_len: usize, align: usize, new_len: usize, ) -> *mut u8 { crate::cabi_realloc(old_ptr, old_len, align, new_len) } EOF cat >./crates/guest-rust/rt/src/cabi_realloc.c <<-EOF // This file is generated by $0 #include extern void *$sym(void *ptr, size_t old_size, size_t align, size_t new_size); __attribute__((__weak__, __export_name__("cabi_realloc"))) void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { return $sym(ptr, old_size, align, new_size); } EOF rm -f crates/guest-rust/rt/src/cabi_realloc.o $WASI_SDK_PATH/bin/clang crates/guest-rust/rt/src/cabi_realloc.c \ -O -c -o crates/guest-rust/rt/src/cabi_realloc.o # Remove the `producers` section. This appears to differ whether the host for # clang is either macOS or Linux. Not needed here anyway, so discard it to help # either host produce the same object. wasm-tools strip -d producers ./crates/guest-rust/rt/src/cabi_realloc.o \ -o ./crates/guest-rust/rt/src/cabi_realloc.o rm -f crates/guest-rust/rt/src/libwit_bindgen_cabi_realloc.a $WASI_SDK_PATH/bin/llvm-ar crus crates/guest-rust/rt/src/libwit_bindgen_cabi_realloc.a \ crates/guest-rust/rt/src/cabi_realloc.o