Skip to content

Conda #12

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

Open
wants to merge 8 commits 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
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@ jobs:
- name: Build and test all crates
run: cargo test -vv

conda-download:
name: Conda forge ${{ matrix.os }}
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
include:
- {os: ubuntu, rust: stable}
- {os: windows, rust: stable-msvc}
- {os: windows, rust: stable-gnu}
- {os: macos, rust: stable}
steps:
- name: Checkout repository
uses: actions/checkout@v2
with: {submodules: false}
- name: Install Rust (${{ matrix.rust }})
uses: actions-rs/toolchain@v1
with: {toolchain: '${{ matrix.rust }}', profile: minimal, override: true}
- name: Run tests
run: cargo test --features hdf5-sys/conda --workspace --exclude hdf5-derive,hdf5-src

msrv:
name: Minimal Supported Rust Version
runs-on: ubuntu-18.04
Expand Down Expand Up @@ -264,6 +285,7 @@ jobs:
run: sudo apt-get update && sudo apt install wine64 mingw-w64
- name: Build and test
run: env CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER=wine64 cargo test --features hdf5-sys/static --target x86_64-pc-windows-gnu -- --skip test_compile_fail

addr_san:
name: Address sanitizer
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions hdf5-conda/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "hdf5-conda"
version = "0.0.1" # !V
keywords = ["hdf5"]
build = "build.rs"
repository = "https://github.com/aldanor/hdf5-rust"
homepage = "https://github.com/aldanor/hdf5-rust"
description = "Build script for including hdf5 from conda."
edition = "2018"
links = "hdf5conda"

[build-dependencies]
attohttpc = { version = "0.18.0", default-features = false, features = ["compress", "tls-rustls"] }
bzip2 = "0.4.3"
cfg-if = "1.0.0"
tar = "0.4.37"
110 changes: 110 additions & 0 deletions hdf5-conda/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use std::env;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::time::Duration;

use bzip2::read::BzDecoder;
use cfg_if::cfg_if;
use tar::Archive;

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

let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());

let uri = format!("{}/{}", DOWNLOAD_URL, DOWNLOAD_BINARY);
let archive_path = out_dir.join("hdf5-conda.tar.bz2");
if archive_path.exists() {
println!("Using existing archive");
} else {
println!("Download archive");
download(&uri, "hdf5-conda.tar.bz2", &out_dir);
extract(&archive_path, &out_dir);
}

let inc_dir = out_dir.join(INC_PATH);
let root_dir = out_dir.join(LIB_PATH);

println!("cargo:library={}", LIB_NAME);
println!("cargo:root={}", root_dir.display());
println!("cargo:include={}", inc_dir.display());
}

pub const DOWNLOAD_URL: &str = "https://anaconda.org/conda-forge/hdf5/1.12.1/download";

const INC_PATH: &str = {
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos"))] {
"include"
} else if #[cfg(target_os = "windows")] {
"Library/include"
} else {
compile_error!("This crate can not be used on this platform");
}
}
};

const LIB_NAME: &str = {
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos"))] {
"hdf5"
} else if #[cfg(target_os = "windows")] {
"libhdf5"
} else {
compile_error!("This crate can not be used on this platform");
}
}
};

const LIB_PATH: &str = {
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos"))] {
"lib"
} else if #[cfg(target_os = "windows")] {
"Library/lib"
} else {
compile_error!("This crate can not be used on this platform");
}
}
};

const DOWNLOAD_BINARY: &str = {
cfg_if! {
if #[cfg(all(target_os = "linux", target_arch = "x86_64"))] {
"linux-64/hdf5-1.12.1-nompi_h2750804_102.tar.bz2"
} else if #[cfg(all(target_os = "linux", target_arch = "aarch64"))] {
"linux-aarch64/hdf5-1.12.1-nompi_h774d4d8_102.tar.bz2"
} else if #[cfg(all(target_os = "macos", target_arch = "x86_64"))] {
"osx-64/hdf5-1.12.1-nompi_h2f0ef1a_102.tar.bz2"
} else if #[cfg(all(target_os = "windows", target_arch = "x86_64"))] {
"win-64/hdf5-1.12.1-nompi_h57737ce_102.tar.bz2"
} else {
compile_error!("This package can not be used on this arch");
}
}
};

fn download(uri: &str, filename: &str, out_dir: &Path) {
let out = PathBuf::from(out_dir.join(filename));

let f = File::create(&out).unwrap();
let writer = io::BufWriter::new(f);

let req = attohttpc::get(uri).read_timeout(Duration::new(90, 0));

let response = req.send().unwrap();

if !response.is_success() {
panic!("Unexpected response code {:?} for {}", response.status(), uri);
}

response.write_to(writer).unwrap();
}

fn extract<P: AsRef<Path>, P2: AsRef<Path>>(archive_path: P, extract_to: P2) {
let file = File::open(archive_path).unwrap();
let unzipped = BzDecoder::new(file);
let mut a = Archive::new(unzipped);
a.unpack(extract_to).unwrap();
}
1 change: 1 addition & 0 deletions hdf5-conda/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! Dummy crate for linking to hdf5 from conda
2 changes: 2 additions & 0 deletions hdf5-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ libc = "0.2"
mpi-sys = { version = "0.1", optional = true }
libz-sys = { version = "1.0.25", optional = true, default-features = false }
hdf5-src = { path = "../hdf5-src", version = "0.8.1", optional = true } # !V
hdf5-conda = { path = "../hdf5-conda", version = "0.0.1", optional = true } # !V

# Please see README for further explanation of these feature flags
[features]
Expand All @@ -28,6 +29,7 @@ threadsafe = ["hdf5-src/threadsafe"]
zlib = ["libz-sys", "hdf5-src/zlib"]
static = ["hdf5-src"]
deprecated = ["hdf5-src/deprecated"]
conda = ["hdf5-conda"]

[build-dependencies]
libloading = "0.7"
Expand Down
23 changes: 23 additions & 0 deletions hdf5-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ impl Header {

fn get_conf_header<P: AsRef<Path>>(inc_dir: P) -> PathBuf {
let inc_dir = inc_dir.as_ref();
println!("{}", inc_dir.display());

for d in inc_dir.read_dir().unwrap() {
println!("{:?}", d.unwrap());
}

if inc_dir.join("H5pubconf.h").is_file() {
inc_dir.join("H5pubconf.h")
Expand Down Expand Up @@ -639,6 +644,8 @@ impl Config {
fn main() {
if feature_enabled("STATIC") && std::env::var_os("HDF5_DIR").is_none() {
get_build_and_emit();
} else if feature_enabled("CONDA") && std::env::var_os("HDF5_DIR").is_none() {
link_to_conda();
} else {
let mut searcher = LibrarySearcher::new_from_env();
searcher.try_locate_hdf5_library();
Expand Down Expand Up @@ -680,3 +687,19 @@ fn get_build_and_emit() {
let config = Config { header, inc_dir: "".into(), link_paths: Vec::new() };
config.emit_cfg_flags();
}

fn link_to_conda() {
let hdf5_root = env::var("DEP_HDF5CONDA_ROOT").unwrap();
println!("cargo:root={}", &hdf5_root);
let hdf5_incdir = env::var("DEP_HDF5CONDA_INCLUDE").unwrap();
println!("cargo:include={}", &hdf5_incdir);
let hdf5_lib = env::var("DEP_HDF5CONDA_LIBRARY").unwrap();
println!("cargo:library={}", &hdf5_lib);

println!("cargo:rustc-link-search={}", &hdf5_root);
println!("cargo:rustc-link-lib={}", &hdf5_lib);

let header = Header::parse(&hdf5_incdir);
let config = Config { header, inc_dir: "".into(), link_paths: Vec::new() };
config.emit_cfg_flags();
}