diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6ae61eb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "soxr"] + path = soxr + url = https://github.com/chirlu/soxr diff --git a/Cargo.toml b/Cargo.toml index 80120f4..14f4fb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,9 @@ edition = "2018" [build-dependencies] pkg-config = "0.3" +cmake = "0.1" + +[features] +default = ["static", "dynamic"] +static = [] +dynamic = [] diff --git a/build.rs b/build.rs index b9144ca..7048c4c 100644 --- a/build.rs +++ b/build.rs @@ -1,19 +1,102 @@ +use std::{env, fmt::Display, path::Path}; + extern crate pkg_config; +/// Based on the OS or target environment we are building for, +/// this function will return an expected default library linking method. +/// +/// If we build for Windows, MacOS, or Linux with musl, we will link statically. +/// However, if you build for Linux without musl, we will link dynamically. +/// +/// **Info**: +/// This is a helper-function and may not be called if +/// if the `static`-feature is enabled, the environment variable +/// `LIBSOXR_STATIC` or `SOXR_STATIC` is set. +fn default_library_linking() -> bool { + #[cfg(any(windows, target_os = "macos", target_env = "musl"))] + { + true + } + #[cfg(any(target_os = "freebsd", all(unix, target_env = "gnu")))] + { + false + } +} + +fn is_static_build() -> bool { + if cfg!(feature = "static") && cfg!(feature = "dynamic") { + if env::var("LIBSOXR_STATIC").is_ok() || env::var("SOXR_STATIC").is_ok() { + true + } else { + default_library_linking() + } + } else if cfg!(feature = "static") + || env::var("LIBSOXR_STATIC").is_ok() + || env::var("SOXR_STATIC").is_ok() + { + println!("cargo:info=Static feature or environment variable found."); + + true + } else if cfg!(feature = "dynamic") { + println!("cargo:info=Dynamic feature enabled."); + + false + } else { + println!("cargo:info=No feature or environment variable found, linking by default."); + + default_library_linking() + } +} + +/// Outputs the library-file's prefix as word usable for actual arguments on +/// commands or paths. +const fn rustc_linking_word(is_static_link: bool) -> &'static str { + if is_static_link { + "static" + } else { + "dylib" + } +} + +fn build_soxr(is_static: bool) { + let soxr_path = Path::new("soxr"); + + println!( + "cargo:info=Soxr source path used: {:?}.", + soxr_path + .canonicalize() + .expect("Could not canonicalise to absolute path") + ); + + println!("cargo:info=Building Soxr via CMake."); + let soxr_build_dir = cmake::Config::new("soxr") + .profile("Release") + .define("WITH_CR32S", "OFF") + .define("BUILD_SHARED_LIBS", if is_static { "OFF" } else { "ON" }) + .define("WITH_OPENMP", "OFF") + .build(); + link_soxr(is_static, soxr_build_dir.display()) +} + +fn link_soxr(is_static: bool, soxr_build_dir: impl Display) { + let is_static_text = rustc_linking_word(is_static); + + println!( + "cargo:info=Linking Soxr as {} lib: {}", + is_static_text, soxr_build_dir + ); + println!("cargo:rustc-link-lib={}=soxr", is_static_text); + println!("cargo:rustc-link-search=native={}/lib", soxr_build_dir); +} + fn main() { if std::env::var("DOCS_RS").is_err() { // do not probe for libsoxr when compiling at docs.rs - if let Err(e) = pkg_config::probe_library("soxr") { - match e { - pkg_config::Error::Failure { .. } => panic! ( - "Pkg-config failed - usually this is because libsoxr development headers are not installed.\n\n\ - For Mac users using brew: brew install libsoxr\n\n\ - For Debian/Ubuntu users:\n# apt-get install libsoxr0-dev\n\n\ - pkg_config details:\n{}", - e - ), - _ => panic!("{}", e) - } + if let Err(_e) = pkg_config::Config::new() + .statik(is_static_build()) + .probe("soxr") + { + build_soxr(is_static_build()); } } } diff --git a/soxr b/soxr new file mode 160000 index 0000000..945b592 --- /dev/null +++ b/soxr @@ -0,0 +1 @@ +Subproject commit 945b592b70470e29f917f4de89b4281fbbd540c0 diff --git a/src/lib.rs b/src/lib.rs index a224d13..a3dd99a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ //! # libsoxr-sys -//! This crate is generated from [libsoxr](https://sourceforge.net/projects/soxr/) +//! This crate is generated from [libsoxr](https://sourceforge.net/projects/soxr/) //! using [bindgen](https://github.com/rust-lang/rust-bindgen). //! -//! The documentation for this library can be found in the original C header +//! The documentation for this library can be found in the original C header //! file [`soxr.h`](https://sourceforge.net/p/soxr/code/ci/master/tree/src/soxr.h) of libsoxr. #![allow(non_camel_case_types)]