Skip to content

Commit 9d8fe6e

Browse files
authored
Merge pull request #31 from aldanor/feature/file_access
File-access property lists API (+MPI / direct VFD support)
2 parents 514f851 + 437ceec commit 9d8fe6e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2781
-247
lines changed

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ matrix:
3434
apt:
3535
packages:
3636
- libhdf5-serial-dev
37-
- name: macos-stable-brew-1.10.*
37+
- name: macos-stable-brew-1.8.*
3838
os: osx
3939
rust: stable
4040
env:
4141
- H5_BREW=1.8
42-
- name: macos-beta-brew-1.8.*
42+
- name: macos-beta-brew-1.10.*
4343
os: osx
4444
rust: beta
4545
env:

CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
- Implemented `#[derive(H5Type)]` proc macro that allows for seamless mapping of user-defined
1414
structs and enums to their HDF5 counterparts.
1515
- Added high-level wrappers for file-creation H5P API (`plist::FileCreate`) and
16-
file-access H5P API (`plist::FileAccess`).
16+
file-access H5P API (`plist::FileAccess`), covering almost the entirety of
17+
FCPL and FAPL property list functionality.
1718
- Various improvements and additions to `PropertyList` type.
1819
- Added support for various file drivers (sec2/stdio/core/family/multi/split/log).
20+
- Added support for MPIO driver (HDF5 has to be built with H5_HAVE_PARALLEL and
21+
the crate has to be built with "mpio" feature enabled).
22+
- Added support for direct VFD driver (HDF5 has to be built with H5_HAVE_DIRECT).
23+
- Added some missing bindings to `libhdf5-sys`: driver-related FAPL bindings
24+
in h5p/h5fd (including MPIO and direct VFD drivers), MPIO bindings in h5p/h5f/h5fd.
1925
- Added core reading/writing API in `Container`, with support for reading/writing scalars,
2026
1-d, 2-d, and dynamic-dimensional arrays, and raw slices. As a side effect, the main crate
2127
now depends on `ndarray`. `Dataset` now dereferences to `Container`.
@@ -56,6 +62,7 @@
5662
- Added missing bindings for previous versions (mostly in `h5p` and `h5fd` modules).
5763
- Querying the HDF5 error stack is now thread-safe.
5864
- Error silencing (`silence_errors()`) is now thread-safe.
65+
- Fixed wrong bindings for `H5AC_cache_config_t`.
5966

6067
### Removed
6168

Cargo.toml

+45-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,46 @@
1+
[package]
2+
name = "hdf5-rs"
3+
version = "0.2.0"
4+
authors = ["Ivan Smirnov <[email protected]>"]
5+
keywords = ["hdf5"]
6+
license = "MIT/Apache-2.0"
7+
readme = "README.md"
8+
description = "Thread-safe Rust bindings for the HDF5 library."
9+
repository = "https://github.com/aldanor/hdf5-rs"
10+
homepage = "https://github.com/aldanor/hdf5-rs"
11+
build = "build.rs"
12+
edition = "2018"
13+
14+
[lib]
15+
name = "h5"
16+
17+
[features]
18+
default = []
19+
mpio = ["mpi-sys", "libhdf5-sys/mpio"]
20+
121
[workspace]
2-
members = [
3-
"hdf5-rs",
4-
"hdf5-types",
5-
"hdf5-derive",
6-
"libhdf5-sys",
7-
]
8-
exclude = [
9-
"*.yml"
10-
]
22+
members = ["hdf5-types", "hdf5-derive", "libhdf5-sys"]
23+
exclude = ["*.yml", "ci/*"]
24+
25+
[dependencies]
26+
bitflags = "1.0"
27+
lazy_static = "1.2"
28+
libc = "0.2"
29+
parking_lot = "0.7"
30+
ndarray = "0.12"
31+
num-integer = "0.1"
32+
num-traits = "0.2"
33+
mpi-sys = { version = "0.1", optional = true }
34+
libhdf5-sys = { path = "libhdf5-sys", version = "0.2.0" }
35+
hdf5-types = { path = "hdf5-types", version = "0.2.0" }
36+
hdf5-derive = { path = "hdf5-derive", version = "0.2.0" }
37+
38+
[dev-dependencies]
39+
mashup = "0.1"
40+
rand = "0.6"
41+
regex = "1.1"
42+
scopeguard = "1.0"
43+
tempdir = "0.3"
44+
45+
[build-dependencies]
46+
libhdf5-sys = { path = "libhdf5-sys", version = "0.2.0" }

appveyor.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ environment:
2424
H5_SOURCE: conda
2525

2626
install:
27-
- python scripts\appveyor.py install-rust
28-
- python scripts\appveyor.py install-hdf5
27+
- python ci\appveyor.py install-rust
28+
- python ci\appveyor.py install-hdf5
2929

3030
test_script:
31-
- python scripts\appveyor.py run-tests
31+
- python ci\appveyor.py run-tests
File renamed without changes.
File renamed without changes.

hdf5-rs/Cargo.toml

-36
This file was deleted.

hdf5-rs/tests/test_plist.rs

-82
This file was deleted.

libhdf5-sys/Cargo.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ edition = "2018"
1212

1313
[dependencies]
1414
libc = "0.2"
15+
mpi-sys = { version = "0.1", optional = true }
16+
17+
[features]
18+
default = []
19+
mpio = ["mpi-sys"]
1520

1621
[build-dependencies]
17-
bindgen = "0.47"
18-
lazy_static = "1.2"
1922
libloading = "0.5"
2023
regex = "1.1"
2124

libhdf5-sys/build.rs

+44-49
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ use std::os::raw::{c_int, c_uint};
77
use std::path::{Path, PathBuf};
88
use std::process::Command;
99
use std::str;
10-
use std::sync::Mutex;
1110

12-
use bindgen::callbacks::IntKind;
13-
use bindgen::callbacks::ParseCallbacks;
14-
use lazy_static::lazy_static;
1511
use regex::Regex;
1612

1713
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
@@ -167,53 +163,43 @@ pub struct Header {
167163
pub version: Version,
168164
}
169165

170-
lazy_static! {
171-
static ref HEADER: Mutex<Header> = Default::default();
172-
}
173-
174-
#[derive(Debug)]
175-
struct HeaderParser;
176-
177-
impl ParseCallbacks for HeaderParser {
178-
fn int_macro(&self, name: &str, value: i64) -> Option<IntKind> {
179-
let mut hdr = HEADER.lock().unwrap();
180-
if name == "H5_HAVE_STDBOOL_H" {
181-
hdr.have_stdbool_h = value > 0;
182-
} else if name == "H5_HAVE_DIRECT" {
183-
hdr.have_direct = value > 0;
184-
} else if name == "H5_HAVE_PARALLEL" {
185-
hdr.have_parallel = value > 0;
186-
} else if name == "H5_HAVE_THREADSAFE" {
187-
hdr.have_threadsafe = value > 0;
188-
}
189-
None
190-
}
191-
192-
fn str_macro(&self, name: &str, value: &[u8]) {
193-
let mut hdr = HEADER.lock().unwrap();
194-
let str_value = unsafe { str::from_utf8_unchecked(value) };
195-
if name == "H5_VERSION" {
196-
if let Some(version) = Version::parse(str_value) {
197-
hdr.version = version;
198-
} else {
199-
panic!("Invalid H5_VERSION: {:?}", str_value);
200-
}
201-
}
202-
}
203-
}
204-
205166
impl Header {
206167
pub fn parse<P: AsRef<Path>>(inc_dir: P) -> Self {
207168
let inc_dir = inc_dir.as_ref();
208169
let header = inc_dir.join("H5pubconf.h");
209170
println!("Parsing HDF5 config from:\n {:?}", header);
210-
bindgen::builder()
211-
.header(header.to_str().unwrap())
212-
.clang_args(&["-I", inc_dir.to_str().unwrap()])
213-
.parse_callbacks(Box::new(HeaderParser))
214-
.generate()
215-
.unwrap();
216-
let hdr = HEADER.lock().unwrap().clone();
171+
172+
let contents = fs::read_to_string(header).unwrap();
173+
let mut hdr = Self::default();
174+
175+
let num_def_re = Regex::new(r"(?m)^#define\s+(H5_[A-Z_]+)\s+([0-9]+)\s*$").unwrap();
176+
for captures in num_def_re.captures_iter(&contents) {
177+
let name = captures.get(1).unwrap().as_str();
178+
let value = captures.get(2).unwrap().as_str().parse::<i64>().unwrap();
179+
if name == "H5_HAVE_STDBOOL_H" {
180+
hdr.have_stdbool_h = value > 0;
181+
} else if name == "H5_HAVE_DIRECT" {
182+
hdr.have_direct = value > 0;
183+
} else if name == "H5_HAVE_PARALLEL" {
184+
hdr.have_parallel = value > 0;
185+
} else if name == "H5_HAVE_THREADSAFE" {
186+
hdr.have_threadsafe = value > 0;
187+
}
188+
}
189+
190+
let str_def_re = Regex::new(r#"(?m)^#define\s+(H5_[A-Z_]+)\s+"([^"]+)"\s*$"#).unwrap();
191+
for captures in str_def_re.captures_iter(&contents) {
192+
let name = captures.get(1).unwrap().as_str();
193+
let value = captures.get(2).unwrap().as_str();
194+
if name == "H5_VERSION" {
195+
if let Some(version) = Version::parse(value) {
196+
hdr.version = version;
197+
} else {
198+
panic!("Invalid H5_VERSION: {:?}", value);
199+
}
200+
}
201+
}
202+
217203
if !hdr.version.is_valid() {
218204
panic!("Invalid H5_VERSION in the header: {:?}");
219205
}
@@ -226,6 +212,7 @@ pub struct LibrarySearcher {
226212
pub version: Option<Version>,
227213
pub inc_dir: Option<PathBuf>,
228214
pub link_paths: Vec<PathBuf>,
215+
pub user_provided_dir: bool,
229216
}
230217

231218
#[cfg(all(unix, not(target_os = "macos")))]
@@ -456,7 +443,15 @@ impl LibrarySearcher {
456443
if let Ok(var) = env::var("HDF5_DIR") {
457444
println!("Setting HDF5 root from environment variable:");
458445
println!(" HDF5_DIR = {:?}", var);
459-
config.inc_dir = Some(PathBuf::from(var).join("include"));
446+
let root = PathBuf::from(var);
447+
if root.is_relative() {
448+
panic!("HDF5_DIR cannot be relative.");
449+
}
450+
if !root.is_dir() {
451+
panic!("HDF5_DIR is not a directory.");
452+
}
453+
config.user_provided_dir = true;
454+
config.inc_dir = Some(root.join("include"));
460455
}
461456
if cfg!(target_env = "msvc") {
462457
// in order to allow HDF5_DIR to be pointed to a conda environment, we have
@@ -503,9 +498,9 @@ impl LibrarySearcher {
503498
if let Some(ref inc_dir) = self.inc_dir {
504499
if cfg!(unix) {
505500
if let Some(envdir) = inc_dir.parent() {
506-
if envdir.join("conda-meta").is_dir() {
501+
if self.user_provided_dir {
507502
let lib_dir = format!("{}/lib", envdir.to_string_lossy());
508-
println!("Conda environment detected, rpath can be set via:");
503+
println!("Custom HDF5_DIR provided; rpath can be set via:");
509504
println!(" RUSTFLAGS=\"-C link-args=-Wl,-rpath,{}\"", lib_dir);
510505
if cfg!(target_os = "macos") {
511506
println!("On some OS X installations, you may also need to set:");

0 commit comments

Comments
 (0)