mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Build WASI libc using Zig, instead of using a checked-in binary
This commit is contained in:
parent
de7fbc3fb9
commit
dd1d49db75
7 changed files with 102 additions and 10 deletions
|
@ -55,6 +55,7 @@ exclude = [
|
||||||
"compiler/test_mono_macros",
|
"compiler/test_mono_macros",
|
||||||
# `cargo build` would cause roc_std to be built with default features which errors on windows
|
# `cargo build` would cause roc_std to be built with default features which errors on windows
|
||||||
"roc_std",
|
"roc_std",
|
||||||
|
"wasi-libc-sys",
|
||||||
]
|
]
|
||||||
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
||||||
# see www/build.sh for more.
|
# see www/build.sh for more.
|
||||||
|
|
|
@ -72,16 +72,12 @@ fn find_zig_str_path() -> PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_wasi_libc_path() -> PathBuf {
|
fn find_wasi_libc_path() -> PathBuf {
|
||||||
let wasi_libc_path = PathBuf::from("compiler/builtins/bitcode/wasi-libc.a");
|
// Environment variable defined in wasi-libc-sys/build.rs
|
||||||
|
if let Ok(wasi_libc_path) = std::env::var("WASI_LIBC_SYS_PATH") {
|
||||||
if std::path::Path::exists(&wasi_libc_path) {
|
let wasi_libc_pathbuf = PathBuf::from(&wasi_libc_path);
|
||||||
return wasi_libc_path;
|
if std::path::Path::exists(&wasi_libc_pathbuf) {
|
||||||
}
|
return wasi_libc_pathbuf;
|
||||||
|
}
|
||||||
// when running the tests, we start in the /cli directory
|
|
||||||
let wasi_libc_path = PathBuf::from("../compiler/builtins/bitcode/wasi-libc.a");
|
|
||||||
if std::path::Path::exists(&wasi_libc_path) {
|
|
||||||
return wasi_libc_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("cannot find `wasi-libc.a`")
|
panic!("cannot find `wasi-libc.a`")
|
||||||
|
|
Binary file not shown.
8
wasi-libc-sys/Cargo.toml
Normal file
8
wasi-libc-sys/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
authors = ["The Roc Contributors"]
|
||||||
|
description = "Rust wrapper for a WebAssembly test platform built on libc"
|
||||||
|
edition = "2018"
|
||||||
|
license = "UPL-1.0"
|
||||||
|
name = "wasi_libc_sys"
|
||||||
|
repository = "https://github.com/rtfeldman/roc"
|
||||||
|
version = "0.1.0"
|
70
wasi-libc-sys/build.rs
Normal file
70
wasi-libc-sys/build.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
// Environment variable that can be used from other build scripts
|
||||||
|
const WASI_LIBC_SYS_PATH: &str = "WASI_LIBC_SYS_PATH";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=src/dummy.c");
|
||||||
|
|
||||||
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
|
let zig_cache_dir = format!("{}/zig-cache", 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),
|
||||||
|
];
|
||||||
|
|
||||||
|
let zig = zig_executable();
|
||||||
|
|
||||||
|
// println!("{} {}", zig, args.join(" "));
|
||||||
|
|
||||||
|
run_command(Path::new("."), &zig, args);
|
||||||
|
let zig_libc_path = run_command(Path::new("."), "find", [&zig_cache_dir, "-name", "libc.a"]);
|
||||||
|
|
||||||
|
// Copy libc out of Zig's cache, to where Cargo expects it
|
||||||
|
fs::copy(&zig_libc_path, &out_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zig_executable() -> String {
|
||||||
|
match std::env::var("ROC_ZIG") {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(_) => "zig".into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command<S, I, P: AsRef<Path>>(path: P, command_str: &str, args: I) -> String
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = S>,
|
||||||
|
S: AsRef<OsStr>,
|
||||||
|
{
|
||||||
|
let output_result = Command::new(OsStr::new(&command_str))
|
||||||
|
.current_dir(path)
|
||||||
|
.args(args)
|
||||||
|
.output();
|
||||||
|
match output_result {
|
||||||
|
Ok(output) => match output.status.success() {
|
||||||
|
true => std::str::from_utf8(&output.stdout).unwrap().to_string(),
|
||||||
|
false => {
|
||||||
|
let error_str = match std::str::from_utf8(&output.stderr) {
|
||||||
|
Ok(stderr) => stderr.to_string(),
|
||||||
|
Err(_) => format!("Failed to run \"{}\"", command_str),
|
||||||
|
};
|
||||||
|
panic!("{} failed: {}", command_str, error_str);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(reason) => panic!("{} failed: {}", command_str, reason),
|
||||||
|
}
|
||||||
|
}
|
6
wasi-libc-sys/src/dummy.c
Normal file
6
wasi-libc-sys/src/dummy.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf("I am a dummy C program. I only exist to help the build script to find libc.a and copy it");
|
||||||
|
}
|
11
wasi-libc-sys/src/lib.rs
Normal file
11
wasi-libc-sys/src/lib.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
use core::ffi::c_void;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
extern "C" {
|
||||||
|
pub fn malloc(size: usize) -> *mut c_void;
|
||||||
|
pub fn free(p: *mut c_void);
|
||||||
|
pub fn realloc(p: *mut c_void, size: 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;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue