1use anyhow::Context;
2use std::fs::File;
3use std::io::BufWriter;
4use std::path::Path;
5use std::{fs, io};
6
7pub fn download_lib_if_needed(
8 lib_dir: impl AsRef<Path>,
9 lib_version: &str,
10) -> anyhow::Result<String> {
11 if lib_dir.as_ref().is_file() {
12 anyhow::bail!("lib_dir is not a directory");
13 }
14
15 #[cfg(target_os = "macos")]
16 let ext = "dylib";
17 #[cfg(target_os = "linux")]
18 let ext = "so";
19
20 let lib_file = lib_dir
21 .as_ref()
22 .join(format!("libmemtrace_{}.{ext}", lib_version));
23
24 if lib_file.exists() {
25 return Ok(lib_file.to_str().unwrap().to_string());
26 }
27
28 println!("Loading libmemtrace version {}", lib_version);
29
30 fs::create_dir_all(lib_dir).context("failed to create dirs")?;
31
32 let mut response = reqwest::blocking::get(format!(
33 "https://github.com/blkmlk/memtrace-lib/releases/download/{}/libmemtrace_lib.{ext}",
34 lib_version
35 ))
36 .with_context(|| format!("failed to download libmemtrace_lib.{ext}"))?;
37
38 if !response.status().is_success() {
39 anyhow::bail!(
40 "failed to download libmemtrace_lib.{ext}. status: {}",
41 response.status()
42 );
43 }
44
45 let mut out_file =
46 BufWriter::new(File::create(&lib_file).context("failed to create output file")?);
47
48 io::copy(&mut response, &mut out_file).context("failed to write output file")?;
49
50 println!(
51 "Successfully loaded libmemtrace_lib.{ext} version {}",
52 lib_version
53 );
54
55 Ok(lib_file.to_str().unwrap().to_string())
56}
57