Skip to content

Commit f009fe9

Browse files
authored
Simplify build.rs of fitsio-sys (#377)
While trying to add alternative Windows build mode, I couldn't help but notice that build.rs has a lot of duplicate code that could be better expressed through cfg branching. I extracted it as such, so now each build step is defined only in one place.
1 parent 1904d1d commit f009fe9

File tree

1 file changed

+50
-121
lines changed

1 file changed

+50
-121
lines changed

fitsio-sys/build.rs

Lines changed: 50 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
use std::path::PathBuf;
22

3-
#[allow(dead_code)]
4-
fn compile_cfitsio() -> PathBuf {
3+
fn generate_bindings<'p>(include_paths: impl Iterator<Item = &'p PathBuf>) {
4+
#[cfg(feature = "with-bindgen")]
5+
{
6+
let out_path = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
7+
8+
bindgen::builder()
9+
.header("wrapper.h")
10+
.block_extern_crate(true)
11+
.clang_args(include_paths.map(|p| format!("-I{}", p.to_str().unwrap())))
12+
.opaque_type("fitsfile")
13+
.opaque_type("FITSfile")
14+
.rust_target(bindgen::RustTarget::stable(47, 0).unwrap_or_else(|_| unreachable!()))
15+
.generate()
16+
.expect("Unable to generate bindings")
17+
.write_to_file(out_path.join("bindings.rs"))
18+
.expect("Couldn't write bindings");
19+
}
20+
21+
#[cfg(not(feature = "with-bindgen"))]
22+
{
23+
let _ = include_paths;
24+
}
25+
}
26+
27+
#[cfg(feature = "fitsio-src")]
28+
fn main() {
529
use autotools::Config;
630

731
let cfitsio_project_dir = PathBuf::from("ext/cfitsio");
@@ -45,48 +69,15 @@ fn compile_cfitsio() -> PathBuf {
4569
.cflag("-fPIE")
4670
.insource(true)
4771
.build();
48-
dst
49-
}
5072

51-
#[cfg(all(feature = "fitsio-src", feature = "bindgen"))]
52-
fn bind_cfitsio() {
53-
use bindgen::RustTarget;
54-
use std::env;
73+
generate_bindings(std::iter::once(&dst));
5574

56-
let dst = compile_cfitsio();
57-
let include_args = vec![format!("-I{}", dst.display())];
58-
let bindings = bindgen::builder()
59-
.header("wrapper.h")
60-
.block_extern_crate(true)
61-
.clang_args(include_args)
62-
.opaque_type("fitsfile")
63-
.opaque_type("FITSfile")
64-
.rust_target(RustTarget::Stable_1_47)
65-
.generate()
66-
.expect("Unable to generate bindings");
67-
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
68-
bindings
69-
.write_to_file(out_path.join("bindings.rs"))
70-
.expect("Couldn't write bindings");
7175
println!("cargo:rustc-link-search=native={}", dst.display());
7276
println!("cargo:rustc-link-lib=static=cfitsio");
7377
}
7478

75-
#[cfg(all(feature = "fitsio-src", not(feature = "bindgen")))]
76-
fn bind_cfitsio() {
77-
let dst = compile_cfitsio();
78-
79-
println!("cargo:rustc-link-search=native={}", dst.display());
80-
println!("cargo:rustc-link-lib=static=cfitsio");
81-
}
82-
83-
#[cfg(all(not(feature = "fitsio-src"), feature = "bindgen"))]
84-
fn bind_cfitsio() {
85-
use bindgen::RustTarget;
86-
use pkg_config::Error;
87-
use std::env;
88-
use std::io::Write;
89-
79+
#[cfg(not(feature = "fitsio-src"))]
80+
fn main() {
9081
// `msys2` does not report the version of cfitsio correctly, so ignore the version specifier for now.
9182
let package_name = if cfg!(windows) {
9283
let msg = "No version specifier available for pkg-config on windows, so the version of cfitsio used when compiling this program is unspecified";
@@ -100,91 +91,29 @@ fn bind_cfitsio() {
10091
config.print_system_cflags(true);
10192
match config.probe(package_name) {
10293
Ok(lib) => {
103-
let include_args: Vec<_> = lib
104-
.include_paths
105-
.into_iter()
106-
.map(|p| format!("-I{}", p.to_str().unwrap()))
107-
.collect();
108-
let bindings = bindgen::builder()
109-
.header("wrapper.h")
110-
.block_extern_crate(true)
111-
.clang_args(include_args)
112-
.opaque_type("fitsfile")
113-
.opaque_type("FITSfile")
114-
.rust_target(RustTarget::Stable_1_47)
115-
.generate()
116-
.expect("Unable to generate bindings");
117-
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
118-
bindings
119-
.write_to_file(out_path.join("bindings.rs"))
120-
.expect("Couldn't write bindings");
94+
generate_bindings(lib.include_paths.iter());
12195
}
122-
Err(Error::Failure { output, .. }) => {
123-
// Handle the case where the user has not installed cfitsio, and thusly it is not on
124-
// the PKG_CONFIG_PATH
125-
let stderr = String::from_utf8(output.stderr).unwrap();
126-
if stderr.contains::<&str>(
127-
format!("{package_name} was not found in the pkg-config search path").as_ref(),
128-
) {
129-
let err_msg = format!(
130-
"
131-
Cannot find {package_name} on the pkg-config search path. Consider installing the library for your
132-
system (e.g. through homebrew, apt-get etc.). Alternatively if it is installed, then add
133-
the directory that contains `cfitsio.pc` on your PKG_CONFIG_PATH, e.g.:
134-
135-
PKG_CONFIG_PATH=<blah> cargo build
136-
"
137-
);
138-
std::io::stderr().write_all(err_msg.as_bytes()).unwrap();
139-
std::process::exit(output.status.code().unwrap());
96+
Err(e) => {
97+
if let pkg_config::Error::Failure { output, .. } = &e {
98+
// Handle the case where the user has not installed cfitsio, and thusly it is not on
99+
// the PKG_CONFIG_PATH
100+
let stderr = String::from_utf8_lossy(&output.stderr);
101+
if stderr.contains(
102+
format!("{package_name} was not found in the pkg-config search path").as_str(),
103+
) {
104+
eprintln!(
105+
"
106+
Cannot find {package_name} on the pkg-config search path. Consider installing the library for your
107+
system (e.g. through homebrew, apt-get etc.). Alternatively if it is installed, then add
108+
the directory that contains `cfitsio.pc` on your PKG_CONFIG_PATH, e.g.:
109+
110+
PKG_CONFIG_PATH=<blah> cargo build
111+
"
112+
);
113+
std::process::exit(output.status.code().unwrap_or(1));
114+
}
140115
}
116+
panic!("Unhandled error: {:?}", e);
141117
}
142-
Err(e) => panic!("Unhandled error: {:?}", e),
143118
};
144119
}
145-
146-
#[cfg(all(not(feature = "fitsio-src"), not(feature = "bindgen")))]
147-
fn bind_cfitsio() {
148-
use pkg_config::Error;
149-
use std::io::Write;
150-
151-
// `msys2` does not report the version of cfitsio correctly, so ignore the version specifier for now.
152-
let package_name = if cfg!(windows) {
153-
let msg = "No version specifier available for pkg-config on windows, so the version of cfitsio used when compiling this program is unspecified";
154-
println!("cargo:warning={msg}");
155-
"cfitsio"
156-
} else {
157-
"cfitsio >= 3.37"
158-
};
159-
let mut config = pkg_config::Config::new();
160-
config.print_system_libs(true);
161-
config.print_system_cflags(true);
162-
match config.probe(package_name) {
163-
Ok(_) => {}
164-
Err(Error::Failure { output, .. }) => {
165-
// Handle the case where the user has not installed cfitsio, and thusly it is not on
166-
// the PKG_CONFIG_PATH
167-
let stderr = String::from_utf8(output.stderr).unwrap();
168-
if stderr.contains::<&str>(
169-
format!("{package_name} was not found in the pkg-config search path").as_ref(),
170-
) {
171-
let err_msg = format!(
172-
"
173-
Cannot find {package_name} on the pkg-config search path. Consider installing the library for your
174-
system (e.g. through homebrew, apt-get etc.). Alternatively if it is installed, then add
175-
the directory that contains `cfitsio.pc` on your PKG_CONFIG_PATH, e.g.:
176-
177-
PKG_CONFIG_PATH=<blah> cargo build
178-
"
179-
);
180-
std::io::stderr().write_all(err_msg.as_bytes()).unwrap();
181-
std::process::exit(output.status.code().unwrap());
182-
}
183-
}
184-
Err(e) => panic!("Unhandled error: {:?}", e),
185-
};
186-
}
187-
188-
fn main() {
189-
bind_cfitsio();
190-
}

0 commit comments

Comments
 (0)