cargo_emit/
rerun_if_changed.rs

1/// Tells Cargo to run again if the file or directory at `$path` changes.
2///
3/// This is equivalent to:
4///
5/// ```
6/// println!("cargo:rerun-if-changed=$path");
7/// ```
8///
9/// `$path` is a path to a file or directory which indicates that the build
10/// script should be re-run if it changes (detected by a more-recent
11/// last-modified timestamp on the file). Normally build scripts are re-run if
12/// any file inside the crate root changes, but this can be used to scope
13/// changes to just a small set of files. (If this path points to a directory
14/// the entire directory will not be traversed for changes -- only changes to
15/// the timestamp of the directory itself (which corresponds to some types of
16/// changes within the directory, depending on platform) will trigger a rebuild.
17/// To request a re-run on any changes within an entire directory, print a line
18/// for the directory and another line for everything inside it, recursively.)
19/// Note that if the build script itself (or one of its dependencies) changes,
20/// then it's rebuilt and rerun unconditionally, so
21/// `rerun_if_changed!("build.rs")` is almost always redundant (unless you want
22/// to ignore changes in all other files except for `build.rs`).
23///
24/// # Examples
25///
26/// This is useful for tracking build-dependent files that Cargo does not
27/// already know.
28///
29/// ```
30/// cargo_emit::rerun_if_changed!(
31///     "/path/to/resource1",
32///     "/path/to/resource2",
33/// );
34/// ```
35///
36/// or, in case you want it to emit to a custom stream:
37///
38/// ```
39/// let mut stdout = std::io::stdout();
40/// // ..
41/// cargo_emit::rerun_if_changed!(
42///     to: stdout,
43///     "/path/to/resource1",
44///     "/path/to/resource2",
45/// );
46/// ```
47#[macro_export]
48macro_rules! rerun_if_changed {
49    (to: $stream:expr, $($path:expr),+ $(,)?) => {
50        $($crate::pair!(to: $stream, "rerun-if-changed", "{}", $path);)+
51    };
52    ($($path:expr),+ $(,)?) => {
53        $crate::rerun_if_changed!(to: std::io::stdout(), $($path),+);
54    };
55}
56
57#[cfg(test)]
58mod tests {
59    use std::path::PathBuf;
60
61    #[test]
62    fn single_literal() {
63        insta::assert_display_snapshot!(
64            crate::capture_output(|output| {
65                crate::rerun_if_changed!(
66                    to: output,
67                    "/path/to/resource"
68                );
69            }),
70            @"cargo:rerun-if-changed=/path/to/resource\n"
71        );
72    }
73
74    #[test]
75    fn single_expression() {
76        insta::assert_display_snapshot!(
77            crate::capture_output(|output| {
78                crate::rerun_if_changed!(
79                    to: output,
80                    PathBuf::from("/path/to/resource").display()
81                );
82            }),
83            @"cargo:rerun-if-changed=/path/to/resource\n"
84        );
85    }
86
87    #[test]
88    fn multiple_literals() {
89        insta::assert_display_snapshot!(
90            crate::capture_output(|output| {
91                crate::rerun_if_changed!(
92                    to: output,
93                    "/path/to/resource1",
94                    "/path/to/resource2",
95                    "/path/to/resource3",
96                    "/path/to/resource4",
97                );
98            }),
99            @"cargo:rerun-if-changed=/path/to/resource1\n\
100              cargo:rerun-if-changed=/path/to/resource2\n\
101              cargo:rerun-if-changed=/path/to/resource3\n\
102              cargo:rerun-if-changed=/path/to/resource4\n"
103        );
104    }
105
106    #[test]
107    fn multiple_expressions() {
108        insta::assert_display_snapshot!(
109            crate::capture_output(|output| {
110                crate::rerun_if_changed!(
111                    to: output,
112                    PathBuf::from("/path/to/resource1").display(),
113                    PathBuf::from("/path/to/resource2").display(),
114                    PathBuf::from("/path/to/resource3").display(),
115                    PathBuf::from("/path/to/resource4").display(),
116                );
117            }),
118            @"cargo:rerun-if-changed=/path/to/resource1\n\
119              cargo:rerun-if-changed=/path/to/resource2\n\
120              cargo:rerun-if-changed=/path/to/resource3\n\
121              cargo:rerun-if-changed=/path/to/resource4\n"
122        );
123    }
124
125    #[test]
126    fn multiple_mixed() {
127        insta::assert_display_snapshot!(
128            crate::capture_output(|output| {
129                crate::rerun_if_changed!(
130                    to: output,
131                    "/path/to/resource1",
132                    PathBuf::from("/path/to/resource2").display(),
133                    "/path/to/resource3",
134                    PathBuf::from("/path/to/resource4").display(),
135                );
136            }),
137            @"cargo:rerun-if-changed=/path/to/resource1\n\
138              cargo:rerun-if-changed=/path/to/resource2\n\
139              cargo:rerun-if-changed=/path/to/resource3\n\
140              cargo:rerun-if-changed=/path/to/resource4\n"
141        );
142    }
143}