#[allow(unused)]
use std::env;
#[allow(unused)]
use std::path::PathBuf;
#[allow(dead_code)]
const PATH_SEPARATOR: &str = match cfg!(target_os = "windows") {
true => ";",
_ => ":",
};
fn main() {
#[cfg(feature = "exiv2")]
{
let exiv2_inc_dirs = find_library(
FromPkgConfig {
name: "exiv2".to_string(),
atleast_version: "0.27.6".to_string(),
},
FromEnv {
env_key_include_dirs: "EXIV2_INCLUDE_DIRS".to_string(),
env_key_lib_dirs: "EXIV2_LIB_DIRS".to_string(),
libs: vec!["exiv2".to_string()],
},
)
.unwrap();
cc::Build::new()
.cpp(true)
.flag("-std=c++17")
.file("lib/exif.cpp")
.include("lib")
.includes(exiv2_inc_dirs)
.compile("libexif");
println!("cargo:rerun-if-changed=lib/exif.h");
println!("cargo:rerun-if-changed=lib/exif.cpp");
}
}
#[allow(dead_code)]
struct FromPkgConfig {
name: String,
#[allow(unused)]
atleast_version: String,
}
#[allow(dead_code)]
struct FromEnv {
env_key_include_dirs: String,
env_key_lib_dirs: String,
libs: Vec<String>,
}
#[cfg(feature = "exiv2")]
fn find_library(from_pkg_config: FromPkgConfig, from_env: FromEnv) -> Result<Vec<PathBuf>, String> {
match find_library_from_env(&from_env) {
Ok(inc_dirs) => return Ok(inc_dirs),
_ => (),
}
find_library_internal(&from_pkg_config)
}
#[cfg(all(not(target_os = "windows"), feature = "exiv2"))]
fn find_library_internal(from_pkg_config: &FromPkgConfig) -> Result<Vec<PathBuf>, String> {
let name = from_pkg_config.name.as_str();
let library = pkg_config::Config::new()
.atleast_version(from_pkg_config.atleast_version.as_str())
.probe(name)
.map_err(|e| format!("Failed to find library '{}' from pkg_config: {}", name, e))?;
Ok(library.include_paths)
}
#[cfg(all(target_os = "windows", feature = "exiv2"))]
fn find_library_internal(from_pkg_config: &FromPkgConfig) -> Result<Vec<PathBuf>, String> {
let name = from_pkg_config.name.as_str();
let library = vcpkg::find_package(name)
.map_err(|e| format!("Failed to find library '{}' from pkg_config: {}", name, e))?;
Ok(library.include_paths)
}
#[cfg(feature = "exiv2")]
fn find_library_from_env(from_env: &FromEnv) -> Result<Vec<PathBuf>, String> {
let include_dirs = verify_directories_from_env(from_env.env_key_include_dirs.as_str())?;
for dir in include_dirs.iter() {
println!("cargo:rustc-link-search=native={}", dir.to_str().unwrap())
}
let lib_dirs = verify_directories_from_env(from_env.env_key_lib_dirs.as_str())?;
for dir in lib_dirs.iter() {
println!("cargo:rustc-link-search=native={}", dir.to_str().unwrap())
}
for lib in from_env.libs.iter() {
println!("cargo:rustc-link-lib={}", lib);
}
Ok(include_dirs)
}
#[cfg(feature = "exiv2")]
fn verify_directories_from_env(env_key: &str) -> Result<Vec<PathBuf>, String> {
println!("cargo:rerun-if-env-changed={}", env_key);
match env::var(env_key) {
Ok(val) => {
let dirs: Vec<String> = val.split(PATH_SEPARATOR).map(|x| x.to_string()).collect();
let mut paths = Vec::new();
for dir in dirs.iter() {
let path = PathBuf::from(dir);
let meta = match path.metadata() {
Ok(meta) => meta,
Err(e) => {
return Err(format!("Failed to get metadata from '{}': {}", dir, e));
}
};
if !meta.is_dir() {
return Err(format!("'{}' is not directory", dir));
}
paths.push(path);
}
Ok(paths)
}
Err(e) => Err(format!("failed to verify directories from env: {}", e)),
}
}