mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Provide a way for non-wasm Rust code to find the WASI libc
This commit is contained in:
parent
dd1d49db75
commit
5fffea969a
6 changed files with 51 additions and 31 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -3428,6 +3428,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"wasi_libc_sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4893,6 +4894,10 @@ version = "0.10.2+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi_libc_sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.79"
|
version = "0.2.79"
|
||||||
|
|
|
@ -31,6 +31,7 @@ libloading = "0.7.1"
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
inkwell = { path = "../../vendor/inkwell", optional = true }
|
inkwell = { path = "../../vendor/inkwell", optional = true }
|
||||||
target-lexicon = "0.12.3"
|
target-lexicon = "0.12.3"
|
||||||
|
wasi_libc_sys = { path = "../../wasi-libc-sys", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
serde_json = "1.0.69"
|
serde_json = "1.0.69"
|
||||||
|
@ -40,7 +41,7 @@ target-arm = []
|
||||||
target-aarch64 = ["roc_gen_dev/target-aarch64"]
|
target-aarch64 = ["roc_gen_dev/target-aarch64"]
|
||||||
target-x86 = []
|
target-x86 = []
|
||||||
target-x86_64 = ["roc_gen_dev/target-x86_64"]
|
target-x86_64 = ["roc_gen_dev/target-x86_64"]
|
||||||
target-wasm32 = ["roc_gen_wasm"]
|
target-wasm32 = ["roc_gen_wasm", "wasi_libc_sys"]
|
||||||
|
|
||||||
# This is a separate feature because when we generate docs on Netlify,
|
# This is a separate feature because when we generate docs on Netlify,
|
||||||
# it doesn't have LLVM installed. (Also, it doesn't need to do code gen.)
|
# it doesn't have LLVM installed. (Also, it doesn't need to do code gen.)
|
||||||
|
|
|
@ -72,12 +72,12 @@ fn find_zig_str_path() -> PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_wasi_libc_path() -> PathBuf {
|
fn find_wasi_libc_path() -> PathBuf {
|
||||||
|
use wasi_libc_sys::WASI_LIBC_PATH;
|
||||||
|
|
||||||
// Environment variable defined in wasi-libc-sys/build.rs
|
// Environment variable defined in wasi-libc-sys/build.rs
|
||||||
if let Ok(wasi_libc_path) = std::env::var("WASI_LIBC_SYS_PATH") {
|
let wasi_libc_pathbuf = PathBuf::from(WASI_LIBC_PATH);
|
||||||
let wasi_libc_pathbuf = PathBuf::from(&wasi_libc_path);
|
if std::path::Path::exists(&wasi_libc_pathbuf) {
|
||||||
if std::path::Path::exists(&wasi_libc_pathbuf) {
|
return wasi_libc_pathbuf;
|
||||||
return wasi_libc_pathbuf;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("cannot find `wasi-libc.a`")
|
panic!("cannot find `wasi-libc.a`")
|
||||||
|
|
1
wasi-libc-sys/.gitignore
vendored
Normal file
1
wasi-libc-sys/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
src/generated.rs
|
|
@ -1,8 +1,8 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
// Environment variable that can be used from other build scripts
|
use std::process::Command;
|
||||||
const WASI_LIBC_SYS_PATH: &str = "WASI_LIBC_SYS_PATH";
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
@ -11,31 +11,36 @@ fn main() {
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
let zig_cache_dir = format!("{}/zig-cache", out_dir);
|
let zig_cache_dir = format!("{}/zig-cache", out_dir);
|
||||||
let out_file = format!("{}/wasi-libc.a", out_dir);
|
let out_file = format!("{}/wasi-libc.a", out_dir);
|
||||||
println!("cargo:rustc-env={}={}", WASI_LIBC_SYS_PATH, &out_file);
|
|
||||||
|
|
||||||
// Compile a dummy C program with Zig, putting libc into our own private cache directory
|
|
||||||
let args = [
|
|
||||||
"build-exe",
|
|
||||||
"-target",
|
|
||||||
"wasm32-wasi",
|
|
||||||
"-lc",
|
|
||||||
"-O",
|
|
||||||
"ReleaseSmall",
|
|
||||||
"--global-cache-dir",
|
|
||||||
&zig_cache_dir,
|
|
||||||
"src/dummy.c",
|
|
||||||
&format!("-femit-bin={}/dummy.wasm", out_dir),
|
|
||||||
];
|
|
||||||
|
|
||||||
|
// Compile a dummy C program with Zig, with our own private cache directory
|
||||||
let zig = zig_executable();
|
let zig = zig_executable();
|
||||||
|
run_command(
|
||||||
|
Path::new("."),
|
||||||
|
&zig,
|
||||||
|
[
|
||||||
|
"build-exe",
|
||||||
|
"-target",
|
||||||
|
"wasm32-wasi",
|
||||||
|
"-lc",
|
||||||
|
"-O",
|
||||||
|
"ReleaseSmall",
|
||||||
|
"--global-cache-dir",
|
||||||
|
&zig_cache_dir,
|
||||||
|
"src/dummy.c",
|
||||||
|
&format!("-femit-bin={}/dummy.wasm", out_dir),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
// println!("{} {}", zig, args.join(" "));
|
// Find the libc.a file that Zig wrote (as a side-effect of compiling the dummy program)
|
||||||
|
let find_cmd_output = run_command(Path::new("."), "find", [&zig_cache_dir, "-name", "libc.a"]);
|
||||||
|
let zig_libc_path = find_cmd_output.trim(); // get rid of a newline
|
||||||
|
|
||||||
run_command(Path::new("."), &zig, args);
|
// Copy libc to where Cargo expects it
|
||||||
let zig_libc_path = run_command(Path::new("."), "find", [&zig_cache_dir, "-name", "libc.a"]);
|
fs::copy(&zig_libc_path, &out_file).unwrap();
|
||||||
|
|
||||||
// Copy libc out of Zig's cache, to where Cargo expects it
|
// Generate some Rust code to indicate where the file is
|
||||||
fs::copy(&zig_libc_path, &out_file);
|
let generated_rust = format!("pub const WASI_LIBC_PATH: &str = \"{}\";\n", out_file);
|
||||||
|
fs::write("src/generated.rs", generated_rust).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zig_executable() -> String {
|
fn zig_executable() -> String {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use core::ffi::c_void;
|
|
||||||
|
|
||||||
// Rust's libc crate doesn't support Wasm, so we provide an implementation from Zig
|
// Rust's libc crate doesn't support Wasm, so we provide an implementation from Zig
|
||||||
// We define Rust signatures here as we need them, rather than trying to cover all of libc
|
// We define Rust signatures here as we need them, rather than trying to cover all of libc
|
||||||
|
#[cfg(target_family = "wasm")]
|
||||||
|
use core::ffi::c_void;
|
||||||
|
#[cfg(target_family = "wasm")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn malloc(size: usize) -> *mut c_void;
|
pub fn malloc(size: usize) -> *mut c_void;
|
||||||
pub fn free(p: *mut c_void);
|
pub fn free(p: *mut c_void);
|
||||||
|
@ -9,3 +10,10 @@ extern "C" {
|
||||||
pub fn memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void;
|
pub fn memcpy(dst: *mut c_void, src: *mut c_void, n: usize) -> *mut c_void;
|
||||||
pub fn memset(dst: *mut c_void, ch: i32, n: usize) -> *mut c_void;
|
pub fn memset(dst: *mut c_void, ch: i32, n: usize) -> *mut c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a non-Wasm target is using this crate, we assume it is a build script that wants to emit Wasm
|
||||||
|
// Tell it where to find the Wasm .a file
|
||||||
|
#[cfg(not(target_family = "wasm"))]
|
||||||
|
mod generated;
|
||||||
|
#[cfg(not(target_family = "wasm"))]
|
||||||
|
pub use generated::WASI_LIBC_PATH;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue