bind_builder/types/
cmake_builder.rs1use std::{env, fs};
2use std::ffi::OsStr;
3use std::path::{Path, PathBuf};
4use std::process::Command;
5use cmake::Config;
6use crate::variables::{get_profile, target_directory};
7
8fn cmake_executable() -> String {
9 env::var("CMAKE")
10 .unwrap_or_else(|_| String::from("cmake"))
11}
12
13pub struct CMakeBuilder {
15 name: String,
16 cmake_config: Option<Config>,
17 build_directory: Option<PathBuf>,
18 install_directory: PathBuf,
19 build_target: Option<String>
20}
21
22impl CMakeBuilder {
23
24 pub fn clone(
29 name: &str,
30 url: &str,
31 tag: &str,
32 ) -> CMakeBuilder {
33
34 let target_directory = target_directory();
35 let clone_directory = target_directory.parent().unwrap()
36 .join("git")
37 .join(name);
38
39 if !clone_directory.exists() {
42 fs::create_dir_all(clone_directory.as_path())
43 .expect("Could not create directory, does the path exist?");
44
45 Command::new("git")
46 .arg("init")
47 .current_dir(clone_directory.as_path())
48 .status()
49 .expect("Could not init repo, is git installed?");
50
51 Command::new("git")
52 .arg("remote")
53 .arg("add")
54 .arg("origin")
55 .arg(url)
56 .current_dir(clone_directory.as_path())
57 .status()
58 .expect("Could not add remote, is git installed?");
59 }
60
61 Command::new("git")
62 .arg("fetch")
63 .arg("origin")
64 .arg(tag)
65 .current_dir(clone_directory.as_path())
66 .status()
67 .expect("Could not fetch repo, is git installed?");
68
69 Command::new("git")
70 .arg("reset")
71 .arg("--hard")
72 .arg(tag)
73 .current_dir(clone_directory.as_path())
74 .status()
75 .expect("Could not checkout tag, is git installed?");
76
77 Command::new("git")
78 .arg("submodule")
79 .arg("update")
80 .arg("--init")
81 .arg("--recursive")
82 .current_dir(clone_directory.as_path())
83 .status()
84 .expect("Could not init submodules, is git installed?");
85
86 CMakeBuilder::from(name, clone_directory.as_path())
87 }
88
89 pub fn from(
91 name: &str,
92 path: &Path,
93 ) -> CMakeBuilder {
94
95 let absolute_path = if cfg!(windows) {
100 path.to_path_buf()
101 } else {
102 fs::canonicalize(path)
103 .expect("Path not found, make sure the build directory exists.")
104 };
105
106 let configure_directory = absolute_path
107 .join(format!("cmake-bind-builder-{}", get_profile().as_str()));
108
109 let install_directory = configure_directory
110 .join("install");
111
112 let mut project = CMakeBuilder {
113 name: name.to_string(),
114 cmake_config: Some(Config::new(absolute_path)),
115 build_directory: None,
116 install_directory: install_directory.clone(),
117 build_target: None
118 };
119
120 project.cmake_config.as_mut().unwrap().out_dir(configure_directory);
121 project.cmake_config.as_mut().unwrap().define("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY", "true");
122
123 project
124 }
125
126 pub fn from_build_directory(
128 name: &str,
129 build_path: &Path,
130 ) -> CMakeBuilder {
131
132 let absolute_path = if cfg!(windows) {
137 build_path.to_path_buf()
138 } else {
139 fs::canonicalize(build_path)
140 .expect("Path not found, make sure the build directory exists.")
141 };
142
143 let install_directory = absolute_path
144 .join(format!("cmake-bind-builder-{}", get_profile().as_str()))
145 .join("install");
146
147 let project = CMakeBuilder {
148 name: name.to_string(),
149 cmake_config: None,
150 build_directory: Some(absolute_path),
151 install_directory: install_directory.clone(),
152 build_target: None
153 };
154
155 project
156 }
157
158 pub fn generator<T: AsRef<OsStr>>(&mut self, generator: T) -> &mut CMakeBuilder {
164 if let Some(config) = self.cmake_config.as_mut() {
165 config.generator(generator);
166 }
167
168 self
169 }
170
171 pub fn generator_toolset<T: AsRef<OsStr>>(&mut self, toolset_name: T) -> &mut CMakeBuilder {
176 if let Some(config) = self.cmake_config.as_mut() {
177 config.generator_toolset(toolset_name);
178 }
179
180 self
181 }
182
183 pub fn cflag<P: AsRef<OsStr>>(&mut self, flag: P) -> &mut CMakeBuilder {
186 if let Some(config) = self.cmake_config.as_mut() {
187 config.cflag(flag);
188 }
189
190 self
191 }
192
193 pub fn cxxflag<P: AsRef<OsStr>>(&mut self, flag: P) -> &mut CMakeBuilder {
196 if let Some(config) = self.cmake_config.as_mut() {
197 config.cxxflag(flag);
198 }
199
200 self
201 }
202
203 pub fn asmflag<P: AsRef<OsStr>>(&mut self, flag: P) -> &mut CMakeBuilder {
206 if let Some(config) = self.cmake_config.as_mut() {
207 config.asmflag(flag);
208 }
209
210 self
211 }
212
213 pub fn define<K, V>(&mut self, k: K, v: V) -> &mut CMakeBuilder
215 where
216 K: AsRef<OsStr>,
217 V: AsRef<OsStr>,
218 {
219 if let Some(config) = self.cmake_config.as_mut() {
220 config.define(k, v);
221 }
222
223 self
224 }
225
226 pub fn register_dep(&mut self, dep: &str) -> &mut CMakeBuilder {
232 if let Some(config) = self.cmake_config.as_mut() {
233 config.register_dep(dep);
234 }
235
236 self
237 }
238
239 pub fn target(&mut self, target: &str) -> &mut CMakeBuilder {
244 if let Some(config) = self.cmake_config.as_mut() {
245 config.target(target);
246 }
247
248 self
249 }
250
251 pub fn host(&mut self, host: &str) -> &mut CMakeBuilder {
256 if let Some(config) = self.cmake_config.as_mut() {
257 config.host(host);
258 }
259
260 self
261 }
262
263 pub fn profile(&mut self, profile: &str) -> &mut CMakeBuilder {
274 if let Some(config) = self.cmake_config.as_mut() {
275 config.profile(profile);
276 }
277
278 self
279 }
280
281 pub fn static_crt(&mut self, static_crt: bool) -> &mut CMakeBuilder {
285 if let Some(config) = self.cmake_config.as_mut() {
286 config.static_crt(static_crt);
287 }
288
289 self
290 }
291
292 pub fn configure_arg<A: AsRef<OsStr>>(&mut self, arg: A) -> &mut CMakeBuilder {
294 if let Some(config) = self.cmake_config.as_mut() {
295 config.configure_arg(arg);
296 }
297
298 self
299 }
300
301 pub fn build_arg<A: AsRef<OsStr>>(&mut self, arg: A) -> &mut CMakeBuilder {
303 if let Some(config) = self.cmake_config.as_mut() {
304 config.build_arg(arg);
305 }
306
307 self
308 }
309
310 pub fn env<K, V>(&mut self, key: K, value: V) -> &mut CMakeBuilder
313 where
314 K: AsRef<OsStr>,
315 V: AsRef<OsStr>,
316 {
317 if let Some(config) = self.cmake_config.as_mut() {
318 config.env(key, value);
319 }
320
321 self
322 }
323
324 pub fn always_configure(&mut self, always_configure: bool) -> &mut CMakeBuilder {
329 if let Some(config) = self.cmake_config.as_mut() {
330 config.always_configure(always_configure);
331 }
332
333 self
334 }
335
336 pub fn very_verbose(&mut self, value: bool) -> &mut CMakeBuilder {
338 if let Some(config) = self.cmake_config.as_mut() {
339 config.very_verbose(value);
340 }
341
342 self
343 }
344
345 pub fn build_target(
348 &mut self,
349 target: &str
350 ) -> &mut CMakeBuilder {
351 self.build_target = Some(target.to_string());
352 self
353 }
354
355 pub fn build(&mut self) -> CMakeBuilder {
361
362 let build_directory = match self.cmake_config.as_mut() {
363 Some(config) => {
364 config.build_target(
365 self.build_target.clone().unwrap_or("all".to_string()).as_str()
366 )
367 .define("CMAKE_INSTALL_PREFIX", self.install_directory.clone().to_str().unwrap())
370
371 .build()
372 .join("build")
373 },
374 None => {
375 self.build_directory.clone()
376 .expect("Could not find build directory argument, is it set?")
377 }
378 };
379
380 Command::new(cmake_executable())
381 .arg("--install")
383 .arg(".")
384
385 .arg("--prefix")
386 .arg(self.install_directory.clone().to_str().unwrap())
387
388 .current_dir(build_directory.clone())
389 .status()
390 .expect("Could not install repo, is cmake installed?");
391
392 let name = self.name.clone();
394 let install_directory = self.install_directory.clone();
395 let build_target = self.build_target.clone();
396
397 CMakeBuilder {
398 name,
399 cmake_config: None,
400 build_directory: Some(build_directory.clone()),
401 install_directory,
402 build_target
403 }
404 }
405
406 pub (crate) fn get_install_directory(&self) -> &PathBuf {
407 &self.install_directory
408 }
409
410 pub (crate) fn get_build_target(&self) -> &Option<String> { &self.build_target }
411}