mc_build_rs/
utils.rs

1// Copyright (c) 2023 The MobileCoin Foundation
2
3//! Utility methods
4
5use cargo_emit::rerun_if_changed;
6use lazy_static::lazy_static;
7use std::{
8    collections::HashSet,
9    ffi::OsStr,
10    path::Path,
11    sync::{Arc, Mutex},
12};
13use walkdir::WalkDir;
14
15const DEFAULT_EXTENSIONS: &[&str] = &["c", "cc", "cpp", "h", "hh", "hpp", "rs", "edl", "proto"];
16const DEFAULT_FILES: &[&str] = &["Cargo.toml", "Cargo.lock"];
17
18fn build_hash_set(str_contents: &'static [&'static str]) -> HashSet<&'static OsStr> {
19    str_contents.iter().map(OsStr::new).collect()
20}
21
22lazy_static! {
23    static ref EXTENSION_SET: Arc<Mutex<HashSet<&'static OsStr>>> =
24        Arc::new(Mutex::new(build_hash_set(DEFAULT_EXTENSIONS)));
25    static ref FILE_SET: Arc<Mutex<HashSet<&'static OsStr>>> =
26        Arc::new(Mutex::new(build_hash_set(DEFAULT_FILES)));
27}
28
29/// Adds all the known source files under the given path which match the given
30/// extensions and filenames.
31pub fn rerun_if_path_changed(path: &Path) {
32    let extensions = EXTENSION_SET
33        .lock()
34        .expect("Could not acquire lock on extensions");
35    let files = FILE_SET
36        .lock()
37        .expect("Could not acquire lock on extensions");
38
39    for entry in WalkDir::new(path).into_iter().flatten() {
40        if entry.path().components().any(|c| c.as_os_str() == "target") {
41            continue;
42        }
43
44        if entry.file_type().is_file() {
45            if let Some(ext) = entry.path().extension() {
46                if extensions.contains(ext) {
47                    rerun_if_changed!(entry.path().display());
48                    rerun_if_changed!(entry.path().parent().unwrap().display());
49                }
50            }
51            let fname = entry.file_name();
52            if files.contains(fname) {
53                rerun_if_changed!(entry.path().display());
54            }
55        }
56    }
57}