Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mscv configuration #181

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,14 @@ On Mac OS X, you may need to install manually `portaudio` and `pkg-config` (usin

You can build the tests and examples with `cargo test`, and the documentation with `cargo doc`.

# Installation on windows-msvc

On the windows-msvc, **rust-portaudio-sys** uses the Visual Studio solution file to build portaudio.
So, the following programs must be put through the system `PATH`.

- **Git**: getting the source code from repository
- **devenv**: updating the solution file in the repository of portaudio
- **MSBuild**: building PortAudio statically

It is remark that cargo does not read the user-wise path, so you must add these programs to the system path.

1 change: 1 addition & 0 deletions rust-portaudio-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ crate-type = ["rlib"]

[build-dependencies]
pkg-config = "0.3.6"
force_remove = "0.1.1"
127 changes: 108 additions & 19 deletions rust-portaudio-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,22 @@ use std::process::Command;
#[cfg(all(unix, not(target_os = "linux")))]
use unix_platform as platform;

#[cfg(not(target_os = "windows"))]
const PORTAUDIO_LIBRARY: &'static str = "libportaudio.a";
#[cfg(target_os = "windows")]
const PORTAUDIO_LIBRARY: &'static str = "portaudio.lib";

fn main() {
println!("cargo:rerun-if-changed=build.rs");

println!("cargo:rerun-if-env-changed=PORTAUDIO_ONLY_STATIC");
if env::var("PORTAUDIO_ONLY_STATIC").is_err() {
// If pkg-config finds a library on the system, we are done
if pkg_config::Config::new().atleast_version("19").find("portaudio-2.0").is_ok() {
if pkg_config::Config::new()
.atleast_version("19")
.find("portaudio-2.0")
.is_ok()
{
return;
}
}
Expand All @@ -48,7 +57,7 @@ fn build() {
let out_dir_str = env::var("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir_str);

let static_lib = out_dir.join("lib/libportaudio.a");
let static_lib = out_dir.join("lib/").join(PORTAUDIO_LIBRARY);
if let Err(_) = ::std::fs::metadata(static_lib) {
platform::download();
platform::build(out_dir);
Expand All @@ -62,7 +71,7 @@ fn build() {
fn err_to_panic<T, E: Display>(result: Result<T, E>) -> T {
match result {
Ok(x) => x,
Err(e) => panic!("{}", e)
Err(e) => panic!("{}", e),
}
}

Expand All @@ -76,14 +85,15 @@ fn run(command: &mut Command) {

#[allow(dead_code)]
mod unix_platform {
use std::process::Command;
use std::path::Path;
use std::process::Command;

use std::env;

use super::{err_to_panic, run};

pub const PORTAUDIO_URL: &'static str = "http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz";
pub const PORTAUDIO_URL: &'static str =
"http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz";
pub const PORTAUDIO_TAR: &'static str = "pa_stable_v19_20140130.tgz";
pub const PORTAUDIO_FOLDER: &'static str = "portaudio";

Expand Down Expand Up @@ -114,24 +124,28 @@ mod unix_platform {
err_to_panic(env::set_current_dir(".."));

// cleaning portaudio sources
run(Command::new("rm").arg("-rf")
run(Command::new("rm")
.arg("-rf")
.args(&[PORTAUDIO_TAR, PORTAUDIO_FOLDER]));
}

pub fn print_libs(out_dir: &Path) {
let out_str = out_dir.to_str().unwrap();
println!("cargo:rustc-flags=-L native={}/lib -l static=portaudio", out_str);
println!(
"cargo:rustc-flags=-L native={}/lib -l static=portaudio",
out_str
);
}
}

#[cfg(target_os = "linux")]
mod platform {
use pkg_config;
use std::process::Command;
use super::unix_platform;
use pkg_config;
use std::path::Path;
use std::process::Command;

use super::{run, err_to_panic};
use super::{err_to_panic, run};

pub fn download() {
run(Command::new("wget").arg(unix_platform::PORTAUDIO_URL));
Expand All @@ -145,29 +159,104 @@ mod platform {
let portaudio_pc_file = out_dir.join("lib/pkgconfig/portaudio-2.0.pc");
let portaudio_pc_file = portaudio_pc_file.to_str().unwrap();

err_to_panic(pkg_config::Config::new().statik(true).find(portaudio_pc_file));
err_to_panic(
pkg_config::Config::new()
.statik(true)
.find(portaudio_pc_file),
);
}
}

#[cfg(windows)]
mod platform {
use std::{env, fs};
use std::path::Path;
use std::process::Command;

const PORTAUDIO_DOWNLOAD_URL: &'static str = "http://www.portaudio.com";
use super::{err_to_panic, run};

const PORTAUDIO_REPOSITORY: &'static str = "https://git.assembla.com/portaudio.git";
const PORTAUDIO_STABLE_BRANCH: &'static str = "pa_stable_v190600_20161030";
const PORTAUDIO_FOLDER: &'static str = "portaudio";
const STEINBERG_URL: &'static str = "http://www.steinberg.net/sdk_downloads/";
const ASIOSDK_ZIP: &'static str = "asiosdk2.3.zip";
const ASIOSDK_EXPANDED_FOLDER: &'static str = "asiosdk2.3";
const ASIOSDK_EXPANDED_ENTITY: &'static str = "asiosdk2.3\\ASIOSDK2.3";
const ASIOSDK_SPECIFIED_LOCATION: &'static str = "portaudio\\src\\hostapi\\asio\\ASIOSDK";
const PORTAUDIO_BUILD_DIR: &'static str = "portaudio\\build\\msvc";
const PORTAUDIO_SOLUTION: &'static str = "portaudio.sln";
const PORTAUDIO_PROJECT: &'static str = "portaudio.vcxproj";
const MSBUILD_BUILD_CONFIG: &'static str =
"/p:Configuration=Release;Platform=x64;ConfigurationType=StaticLibrary";
const MSBUILD_TARGET_DIRECTORY: &'static str = "x64\\Release";

/// Gets the source of portaudio from git repository.
/// Windows users use different tar expanding tools, but Git is uniformly consistent.
fn download_portaudio() {
// If the source code from the previous build remains, delete it.
if Path::new(PORTAUDIO_FOLDER).exists() {
err_to_panic(force_remove::force_remove_dir_all(PORTAUDIO_FOLDER));
}
run(Command::new("git").args(&["clone", PORTAUDIO_REPOSITORY]));
// Checkouts the latest stable branch
err_to_panic(env::set_current_dir(PORTAUDIO_FOLDER));
run(Command::new("git").args(&["checkout", PORTAUDIO_STABLE_BRANCH]));
// Backs to the project dir
err_to_panic(env::set_current_dir(".."));
}

fn print_lib_url() {
panic!("Don't know how to build portaudio on Windows yet. Sources and build instructions available at: {}", PORTAUDIO_DOWNLOAD_URL);
/// Gets the ASIO SDK from Steinberg's web site. Places the SDK in the specified location.
fn download_asiosdk() {
// Windows' standard wget "bitsadmin" requires the full path to the installation location.
let asiosdk_url = &format!("{}{}", STEINBERG_URL, ASIOSDK_ZIP);
let path = env::current_dir().unwrap();
let zip_fullpath = &format!("{}\\{}", path.display(), ASIOSDK_ZIP);
run(Command::new("bitsadmin").args(&["/TRANSFER", "htmlget", asiosdk_url, zip_fullpath]));

// unzip
run(Command::new("powershell").args(&["expand-archive", ASIOSDK_ZIP]));

// Places the SDK in the specified location, and removes a zip and an empty directory.
err_to_panic(fs::rename(
ASIOSDK_EXPANDED_ENTITY,
ASIOSDK_SPECIFIED_LOCATION,
));
err_to_panic(fs::remove_file(ASIOSDK_ZIP));
err_to_panic(fs::remove_dir(ASIOSDK_EXPANDED_FOLDER));
}

pub fn download() {
print_lib_url();
download_portaudio();
download_asiosdk();
}

pub fn build(_: &Path) {
print_lib_url();
pub fn build(out_dir: &Path) {
// Backups the current dir
let path = env::current_dir().unwrap();

// Builds portaudio!
err_to_panic(env::set_current_dir(PORTAUDIO_BUILD_DIR));
run(Command::new("devenv").args(&[PORTAUDIO_SOLUTION, "/Upgrade"]));
run(Command::new("msbuild").args(&[PORTAUDIO_PROJECT, MSBUILD_BUILD_CONFIG]));

// Places the library to the target.
let prefix = &format!("{}\\lib", out_dir.display());
err_to_panic(fs::create_dir_all(prefix));
let current_portoudio_path =
&format!("{}\\{}", MSBUILD_TARGET_DIRECTORY, super::PORTAUDIO_LIBRARY);
let portaudio_target_path =
&format!("{}\\lib\\{}", out_dir.display(), super::PORTAUDIO_LIBRARY);
err_to_panic(fs::rename(current_portoudio_path, portaudio_target_path));

// Backs to the current dir and removes the portaudio directory.
err_to_panic(env::set_current_dir(path));
err_to_panic(force_remove::force_remove_dir_all(PORTAUDIO_FOLDER));
}

pub fn print_libs(_: &Path) {
print_lib_url();
pub fn print_libs(out_dir: &Path) {
println!(
"cargo:rustc-flags=-L native={}/lib -l static=portaudio",
out_dir.display()
);
}
}