diff --git a/.travis.yml b/.travis.yml index 879b5945a..894919421 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,20 +15,31 @@ addons: - libelf-dev - libdw-dev - binutils-dev + - libiberty-dev - cmake + - musl + - musl-dev + - musl-tools sources: - kalakris-cmake before_script: - - cargo install --force cargo-travis + - cargo install cargo-travis || true - export PATH=$HOME/.cargo/bin:$PATH - rustup component add rustfmt-preview + - rustup target add x86_64-unknown-linux-musl script: - cargo fmt --version - cargo fmt -- --check - cargo build - cargo test + - cargo build --no-default-features + - cargo test --no-default-features + - cargo build --target x86_64-unknown-linux-musl + - cargo test --target x86_64-unknown-linux-musl + - cargo build --target x86_64-unknown-linux-musl --no-default-features + - cargo test --target x86_64-unknown-linux-musl --no-default-features after_success: - cargo coveralls diff --git a/Cargo.toml b/Cargo.toml index 98a7cbd0f..0a6a1671f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,9 @@ documentation = "https://docs.rs/rust-htslib" [dependencies] libc = "0.2" +libz-sys = "1.0" +bzip2-sys = { version = "0.1.6", git = "https://github.com/alexcrichton/bzip2-rs.git", optional = true } +lzma-sys = { version = "0.1.10", optional = true } itertools = "0.6" quick-error = "1.2" newtype_derive = "0.1" @@ -28,8 +31,8 @@ bio-types = ">=0.1.1" [features] default = ["bzip2", "lzma"] -bzip2 = [] -lzma = [] +bzip2 = ["bzip2-sys"] +lzma = ["lzma-sys"] [dev-dependencies] tempdir = "0.3" @@ -40,3 +43,4 @@ pretty_assertions = "0.5.1" [build-dependencies] fs-utils = "1.0" bindgen = "0.36" +cc = "1.0" diff --git a/build.rs b/build.rs index 8fe14aab5..09f60e974 100644 --- a/build.rs +++ b/build.rs @@ -4,11 +4,13 @@ // except according to those terms. extern crate bindgen; +extern crate cc; extern crate fs_utils; use fs_utils::copy::copy_directory; use std::env; +use std::fs; use std::path::PathBuf; use std::process::Command; @@ -31,6 +33,13 @@ fn sed_htslib_makefile(out: &PathBuf, patterns: &Vec<&str>, feature: &str) { fn main() { let out = PathBuf::from(env::var("OUT_DIR").unwrap()); + let mut cfg = cc::Build::new(); + cfg.warnings(false).static_flag(true).pic(true); + + if let Ok(z_inc) = env::var("DEP_Z_INCLUDE") { + cfg.include(z_inc); + } + if !out.join("htslib").exists() { copy_directory("htslib", &out).unwrap(); } @@ -39,17 +48,28 @@ fn main() { if !use_bzip2 { let bzip2_patterns = vec!["s/ -lbz2//", "/#define HAVE_LIBBZ2/d"]; sed_htslib_makefile(&out, &bzip2_patterns, "bzip2"); + } else if let Ok(inc) = env::var("DEP_BZIP2_ROOT") + .map(PathBuf::from) + .map(|path| path.join("include")) + { + cfg.include(inc); } let use_lzma = env::var("CARGO_FEATURE_LZMA").is_ok(); if !use_lzma { let lzma_patterns = vec!["s/ -llzma//", "/#define HAVE_LIBLZMA/d"]; sed_htslib_makefile(&out, &lzma_patterns, "lzma"); + } else if let Ok(inc) = env::var("DEP_LZMA_INCLUDE").map(PathBuf::from) { + cfg.include(inc); } + let tool = cfg.get_compiler(); + let (cc_path, cflags_env) = (tool.path(), tool.cflags_env()); + let cc_cflags = cflags_env.to_string_lossy().replace("-O0", ""); if Command::new("make") .current_dir(out.join("htslib")) - .arg("CFLAGS=-g -Wall -O2 -fPIC") + .arg(format!("CC={}", cc_path.display())) + .arg(format!("CFLAGS={}", cc_cflags)) .arg("lib-static") .arg("-B") .status() @@ -59,47 +79,27 @@ fn main() { panic!("failed to build htslib"); } - let bindings = bindgen::Builder::default() + cfg.file("wrapper.c").compile("wrapper"); + + bindgen::Builder::default() .header("wrapper.h") .generate_comments(false) .blacklist_type("max_align_t") .generate() - .expect("Unable to generate bindings."); - bindings + .expect("Unable to generate bindings.") .write_to_file(out.join("bindings.rs")) .expect("Could not write bindings."); - // we additionally build and link to the wrapper in order to enable redefinition of inline - // functions - if Command::new("gcc") - .arg("-static") - .arg("-fPIC") - .arg("-c") - .arg("wrapper.c") - .arg("-o") - .arg(out.join("wrapper.o")) - .status() - .unwrap() - .success() != true - { - panic!("failed to build wrapper.o"); - } - if Command::new("ar") - .current_dir(&out) - .arg("rcs") - .arg("libwrapper.a") - .arg("wrapper.o") - .status() - .unwrap() - .success() != true - { - panic!("failed to build wrapper.a"); + let include = out.join("include"); + fs::create_dir_all(&include).unwrap(); + if include.join("htslib").exists() { + fs::remove_dir_all(include.join("htslib")).expect("remove exist include dir"); } + copy_directory(out.join("htslib").join("htslib"), &include).unwrap(); + fs::copy(out.join("htslib").join("libhts.a"), out.join("libhts.a")).unwrap(); - println!( - "cargo:rustc-flags=-L {out}/htslib -L {out} -l static=hts -l static=wrapper -l z {lzma} {bzip2}", - out = out.to_str().unwrap(), - lzma = if use_lzma { "-l lzma" } else { "" }, - bzip2 = if use_bzip2 { "-l bz2" } else { "" }, - ); + println!("cargo:root={}", out.display()); + println!("cargo:include={}", include.display()); + println!("cargo:libdir={}", out.display()); + println!("cargo:rustc-link-lib=static=hts"); } diff --git a/src/lib.rs b/src/lib.rs index 40ca92e4e..3477431db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,6 +99,13 @@ extern crate serde_json; extern crate bio_types; +extern crate libz_sys; + +#[cfg(feature = "bzip2")] +extern crate bzip2_sys; +#[cfg(feature = "lzma")] +extern crate lzma_sys; + pub mod bam; pub mod bcf; pub mod htslib;