Skip to content

Commit 814b71d

Browse files
feat: Download WASI-SDK during build
fixes #180
1 parent b30271c commit 814b71d

File tree

1 file changed

+55
-2
lines changed

1 file changed

+55
-2
lines changed

build.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,63 @@ fn stubs_for_clippy(out_dir: &Path) -> Result<()> {
9292
Ok(())
9393
}
9494

95+
fn find_wasi_sdk(out_dir: &Path) -> Result<PathBuf> {
96+
let mut wasi_sdk =
97+
PathBuf::from(env::var_os("WASI_SDK_PATH").unwrap_or_else(|| "/opt/wasi-sdk".into()));
98+
99+
// Don't think we have to worry about a time-of-check time-of-use issue here
100+
// Previously we assumed that it existed and the build failed when attempting to use it
101+
// We'd do the same here if it was deleted after the check...
102+
if wasi_sdk.exists() || env::var("NO_DOWNLOAD_WASI_SDK").unwrap_or_default() == "1" {
103+
return Ok(wasi_sdk);
104+
}
105+
106+
// otherwise we want to download the sdk into the target directory
107+
let url = env::var("WASI_SDK_URL").or_else(|_| -> Result<String> {
108+
// Version should be just the major version number, matching
109+
// how it's given in the github release build pipeline
110+
let version = match env::var("WASI_SDK_VERSION").ok() {
111+
Some(v) => v,
112+
None => bail!("wasi-sdk not found and WASI_SDK_VERSION not set, cannot download"),
113+
};
114+
// same as the github release pipeline, allow overriding source repo
115+
let source = env::var("WASI_SDK_SOURCE").unwrap_or("WebAssembly".to_string());
116+
// Wasi-sdk currently releases for x86_64 and arm64 linux, macos, and windows
117+
let (arch, os) = match (env::consts::ARCH, env::consts::OS) {
118+
pair @ ("x86_64", "linux" | "windows" | "macos") => pair,
119+
("aarch64", os @ ("linux" | "windows" | "macos")) => ("arm64", os),
120+
_ => bail!("Unsupported platform for automatic wasi-sdk download: {} {}", env::consts::ARCH, env::consts::OS),
121+
};
122+
Ok(format!("https://github.com/{source}/wasi-sdk/releases/download/wasi-sdk-{version}/wasi-sdk-{version}.0-{arch}-{os}.tar.gz"))
123+
})?;
124+
125+
// get the filename from the url
126+
let filename = url
127+
.rsplit('/')
128+
.next()
129+
.ok_or_else(|| anyhow!("could not get filename from url: {}", url))?;
130+
// strip the .tar.gz suffix to get the directory name
131+
let dir_name = filename.strip_suffix(".tar.gz").unwrap_or(filename);
132+
133+
wasi_sdk = out_dir.join(dir_name);
134+
if wasi_sdk.exists() {
135+
// already downloaded from a previous build
136+
return Ok(wasi_sdk);
137+
}
138+
println!(
139+
"cargo:warning=wasi-sdk not found, downloading from {} into {}",
140+
url,
141+
wasi_sdk.display()
142+
);
143+
fetch_extract(&url, &out_dir)?;
144+
145+
Ok(wasi_sdk)
146+
}
147+
95148
fn package_all_the_things(out_dir: &Path) -> Result<()> {
96149
let repo_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
97150

98-
let wasi_sdk =
99-
PathBuf::from(env::var_os("WASI_SDK_PATH").unwrap_or_else(|| "/opt/wasi-sdk".into()));
151+
let wasi_sdk = find_wasi_sdk(out_dir)?;
100152

101153
maybe_make_cpython(&repo_dir, &wasi_sdk)?;
102154

@@ -261,6 +313,7 @@ fn maybe_make_cpython(repo_dir: &Path, wasi_sdk: &Path) -> Result<()> {
261313
cpython_wasi_dir.display()
262314
),
263315
)
316+
.env("WASI_SDK_PATH", wasi_sdk)
264317
.env(
265318
"LDFLAGS",
266319
format!(

0 commit comments

Comments
 (0)