Skip to content

Commit de95f57

Browse files
wetnebdginev
authored andcommitted
Call bindgen at build time on UNIX platforms
Fixes #73.
1 parent 4e41905 commit de95f57

7 files changed

Lines changed: 10988 additions & 21087 deletions

File tree

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ pkg-config = "0.3.2"
2929
[target.'cfg(unix)'.build-dependencies]
3030
pkg-config = "0.3.2"
3131

32+
[build-dependencies.bindgen]
33+
version = "0.71"
34+
features = [
35+
"runtime",
36+
"which-rustfmt",
37+
]
38+
default-features = false
39+
3240
[dev-dependencies]
3341
rayon = "1.0.0"
3442
criterion = "0.5.1"

build.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
fn main() {
1+
use std::{env, fs, path::{Path, PathBuf}};
2+
3+
/// Finds libxml2 and optionally return a list of header
4+
/// files from which the bindings can be generated.
5+
fn find_libxml2() -> Option<Vec<PathBuf>> {
6+
#![allow(unreachable_code)] // for platform-dependent dead code
7+
28
if let Ok(ref s) = std::env::var("LIBXML2") {
39
// println!("{:?}", std::env::vars());
410
// panic!("set libxml2.");
@@ -27,32 +33,54 @@ fn main() {
2733
.expect("no library path in LIBXML2 env")
2834
.to_string_lossy()
2935
);
30-
} else {
36+
None
37+
} else {
3138
#[cfg(any(target_family = "unix", target_os = "macos"))]
3239
{
33-
if pkg_config_dep::find() {
34-
return;
35-
}
40+
let lib = pkg_config::Config::new()
41+
.probe("libxml-2.0")
42+
.expect("Couldn't find libxml2 via pkg-config");
43+
return Some(lib.include_paths)
3644
}
3745

3846
#[cfg(windows)]
3947
{
4048
if vcpkg_dep::find() {
41-
return;
49+
return None
4250
}
4351
}
44-
52+
4553
panic!("Could not find libxml2.")
4654
}
4755
}
4856

49-
#[cfg(any(target_family = "unix", target_os = "macos"))]
50-
mod pkg_config_dep {
51-
pub fn find() -> bool {
52-
if pkg_config::find_library("libxml-2.0").is_ok() {
53-
return true;
54-
}
55-
false
57+
fn generate_bindings(header_dirs: Vec<PathBuf>, output_path: &Path) {
58+
let bindings = bindgen::Builder::default()
59+
.header("src/wrapper.h")
60+
// invalidate build as soon as the wrapper changes
61+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
62+
.layout_tests(true)
63+
.clang_args(&["-DPKG-CONFIG"])
64+
.clang_args(
65+
header_dirs.iter()
66+
.map(|dir| format!("-I{}", dir.display()))
67+
);
68+
bindings
69+
.generate()
70+
.expect("failed to generate bindings with bindgen")
71+
.write_to_file(output_path)
72+
.expect("Failed to write bindings.rs");
73+
}
74+
75+
fn main() {
76+
let bindings_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("bindings.rs");
77+
if let Some(header_dirs) = find_libxml2() {
78+
// if we could find header files, generate fresh bindings from them
79+
generate_bindings(header_dirs, &bindings_path);
80+
} else {
81+
// otherwise, use the default bindings on platforms where pkg-config isn't available
82+
fs::copy(PathBuf::from("src/default_bindings.rs"), bindings_path)
83+
.expect("Failed to copy the default bindings to the build directory");
5684
}
5785
}
5886

0 commit comments

Comments
 (0)