-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.rs
158 lines (129 loc) · 4.45 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use std::env;
use std::path::PathBuf;
const PATH_SEPARATOR: &str = match cfg!(target_os = "windows") {
true => ";",
_ => ":",
};
fn main() {
// find 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();
// find libssh
let libssh_inc_dirs = find_library(
FromPkgConfig{
name: "libssh".to_string(),
atleast_version: "0.10.4".to_string(),
},
FromEnv{
env_key_include_dirs: "LIBSSH_INCLUDE_DIRS".to_string(),
env_key_lib_dirs: "LIBSSH_LIB_DIRS".to_string(),
libs: vec!["ssh".to_string()],
}
).unwrap();
// find libheif
find_library(
FromPkgConfig{
name: "libheif".to_string(),
atleast_version: "1.15.2".to_string(),
},
FromEnv{
env_key_include_dirs: "LIBHEIF_INCLUDE_DIRS".to_string(),
env_key_lib_dirs: "LIBHEIF_LIB_DIRS".to_string(),
libs: vec!["heif".to_string()],
}
).unwrap();
// compile c files
cc::Build::new()
.cpp(true)
.file("lib/exif.cpp")
.include("lib")
.includes(exiv2_inc_dirs)
.includes(libssh_inc_dirs)
.compile("libexif");
println!("cargo:rerun-if-changed=lib/exif.h");
println!("cargo:rerun-if-changed=lib/exif.cpp");
}
struct FromPkgConfig {
name: String,
#[allow(unused)]
atleast_version: String,
}
struct FromEnv {
env_key_include_dirs: String,
env_key_lib_dirs: String,
libs: Vec<String>,
}
fn find_library(from_pkg_config: FromPkgConfig, from_env: FromEnv) -> Result<Vec<PathBuf>, String> {
// try to find from env
match find_library_from_env(&from_env) {
Ok(inc_dirs) => return Ok(inc_dirs),
_ => (),
}
// try to find from pkg_config
find_library_internal(&from_pkg_config)
}
#[cfg(not(target_os = "windows"))]
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(target_os = "windows")]
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)
}
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)
}
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))
}
}
}