Skip to content

Commit

Permalink
Update build script to automate asio sdk install
Browse files Browse the repository at this point in the history
  • Loading branch information
alisomay committed Oct 16, 2023
1 parent 4baa191 commit 48ff0ee
Showing 1 changed file with 45 additions and 27 deletions.
72 changes: 45 additions & 27 deletions asio-sys/build.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,45 @@
extern crate bindgen;
extern crate cc;
extern crate walkdir;
extern crate reqwest;
extern crate walkdir;
extern crate zip;

use walkdir::WalkDir;
use std::path::PathBuf;
use std::process::{Command, exit};
use reqwest::blocking::Client;
use std::env;
use std::fs;
use std::io::{Cursor, Read};
use reqwest::blocking::Client;
use std::path::PathBuf;
use std::process::{exit, Command};
use walkdir::WalkDir;
use zip::read::ZipArchive;

const CPAL_ASIO_DIR: &str = "CPAL_ASIO_DIR";
const ASIO_SDK_URL: &str = "https://www.steinberg.net/asiosdk";

const ASIO_HEADER: &str = "asio.h";
const ASIO_SYS_HEADER: &str = "asiosys.h";
const ASIO_DRIVERS_HEADER: &str = "asiodrivers.h";

fn main() {
println!("cargo:rerun-if-env-changed={}", CPAL_ASIO_DIR);

// If ASIO directory isn't set silently return early
// let cpal_asio_dir_var = match env::var(CPAL_ASIO_DIR) {
// Err(_) => return,
// Ok(var) => var,
// };

// Asio directory
// let cpal_asio_dir = PathBuf::from(cpal_asio_dir_var);
// ASIO SDK directory
let cpal_asio_dir = get_asio_dir();
println!("cargo:rerun-if-changed={}", cpal_asio_dir.display());

panic!("cpal_asio_dir: {}", cpal_asio_dir.display());

// Directory where bindings and library are created
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("bad path"));

// Check if library exists
// If it doesn't create it
let mut vc_vars_invoked = false;

// Check if library exists,
// if it doesn't create it
let mut lib_path = out_dir.clone();
lib_path.push("libasio.a");
if !lib_path.exists() {
// Set env vars from vcvarsall.bat before attempting to build
invoke_vcvars();
vc_vars_invoked = true;
create_lib(&cpal_asio_dir);
}

Expand All @@ -58,6 +55,10 @@ fn main() {
let mut binding_path = out_dir.clone();
binding_path.push("asio_bindings.rs");
if !binding_path.exists() {
// Set env vars from vcvarsall.bat before attempting to build if not already done
if !vc_vars_invoked {
invoke_vcvars();
}
create_bindings(&cpal_asio_dir);
}
}
Expand Down Expand Up @@ -218,26 +219,30 @@ fn create_bindings(cpal_asio_dir: &PathBuf) {
.expect("Couldn't write bindings!");
}


fn get_asio_dir() -> PathBuf {
// Check if CPAL_ASIO_DIR env var is set
if let Ok(path) = env::var(CPAL_ASIO_DIR) {
println!("CPAL_ASIO_DIR is set at {CPAL_ASIO_DIR}");
return PathBuf::from(path);
}

// If not set, check temp directory for ASIO SDK, maybe it is previously downloaded
let temp_dir = env::temp_dir();
let asio_dir = temp_dir.join("asio_sdk");
if asio_dir.exists() {
println!("CPAL_ASIO_DIR is set at {}", asio_dir.display());
return asio_dir;
}

// If not found, download ASIO SDK
println!("CPAL_ASIO_DIR is not set or contents are cached downloading from {ASIO_SDK_URL}");
let response = Client::new().get(ASIO_SDK_URL).send();

match response {
Ok(mut resp) => {
if resp.status().is_success() {
println!("Downloaded ASIO SDK successfully");
println!("Extracting ASIO SDK..");
// Unzip the archive
let mut archive_bytes = Vec::new();
resp.read_to_end(&mut archive_bytes).unwrap();
Expand All @@ -249,11 +254,14 @@ fn get_asio_dir() -> PathBuf {
// Move the contents of the inner directory to asio_dir
for entry in walkdir::WalkDir::new(&temp_dir).min_depth(1).max_depth(1) {
let entry = entry.unwrap();
if entry.file_type().is_dir() && entry.file_name().to_string_lossy().starts_with("asio") {
if entry.file_type().is_dir()
&& entry.file_name().to_string_lossy().starts_with("asio")
{
fs::rename(entry.path(), &asio_dir).expect("Failed to rename directory");
break;
}
}
println!("CPAL_ASIO_DIR is set at {}", asio_dir.display());
asio_dir
} else {
panic!("Failed to download ASIO SDK")
Expand All @@ -264,7 +272,8 @@ fn get_asio_dir() -> PathBuf {
}

fn invoke_vcvars() {
println!("Determining system architecture...");
println!("Invoking vcvarsall.bat..");
println!("Determining system architecture..");

// Determine the system architecture to be used as an argument to vcvarsall.bat
let arch = if cfg!(target_arch = "x86_64") {
Expand Down Expand Up @@ -292,13 +301,20 @@ fn invoke_vcvars() {
};

// Search for vcvarsall.bat using walkdir
println!("Searching for vcvarsall.bat..");
println!("Searching for vcvarsall.bat in {paths:?}");
for path in paths.iter() {
for entry in WalkDir::new(path).into_iter().filter_map(Result::ok).filter(|e| !e.file_type().is_dir()) {
for entry in WalkDir::new(path)
.into_iter()
.filter_map(Result::ok)
.filter(|e| !e.file_type().is_dir())
{
if entry.path().ends_with("vcvarsall.bat") {
println!("Found vcvarsall.bat at {}. Initializing environment...", entry.path().display());

// Invoke vcvarsall.bat
println!(
"Found vcvarsall.bat at {}. Initializing environment..",
entry.path().display()
);

// Invoke vcvarsall.bat
let output = Command::new("cmd")
.args(&["/c", entry.path().to_str().unwrap(), &arch, "&&", "set"])
.output()
Expand All @@ -309,14 +325,16 @@ fn invoke_vcvars() {
let parts: Vec<&str> = line.splitn(2, '=').collect();
if parts.len() == 2 {
env::set_var(parts[0], parts[1]);
println!("{}={}", parts[0], parts[1]);
}
}
panic!();
return;
}
}
}

eprintln!("Error: Could not find vcvarsall.bat. Please install the latest version of Visual Studio.");
eprintln!(
"Error: Could not find vcvarsall.bat. Please install the latest version of Visual Studio."
);
exit(1);
}

0 comments on commit 48ff0ee

Please sign in to comment.