• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

baoyachi / shadow-rs / 13480180066

23 Feb 2025 05:43AM UTC coverage: 76.585% (+3.5%) from 73.077%
13480180066

Pull #212

github

baoyachi
remove deprecated code
Pull Request #212: remove deprecated code

2 of 4 new or added lines in 1 file covered. (50.0%)

3 existing lines in 1 file now uncovered.

471 of 615 relevant lines covered (76.59%)

1.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.67
/src/lib.rs
1
#![doc(html_logo_url = "https://raw.githubusercontent.com/baoyachi/shadow-rs/master/shadow-rs.png")]
2
//! `shadow-rs`: Build-time information stored in your Rust project (binary, lib, cdylib, dylib).
3
//!
4
//! `shadow-rs` allows you to access properties of the build process and environment at runtime, including:
5
//!
6
//! * `Cargo.toml` information, such as the project version
7
//! * Dependency information
8
//! * Git information, such as the commit that produced the build artifact
9
//! * What version of the Rust toolchain was used in compilation
10
//! * The build variant, e.g. `debug` or `release`
11
//! * ... And more!
12
//!
13
//! You can use this crate to programmatically check where a binary came from and how it was built.
14
//!
15
//! # Examples
16
//! * Check out the [example_shadow](https://github.com/baoyachi/shadow-rs/tree/master/example_shadow) for a simple demonstration of how `shadow-rs` might be used to provide build-time information at run-time.
17
//! * Check out the [example_shadow_hook](https://github.com/baoyachi/shadow-rs/tree/master/example_shadow_hook) for a demonstration of how custom hooks can be used to add extra information to `shadow-rs`'s output.
18
//! * Check out the [`builtin_fn` example](https://github.com/baoyachi/shadow-rs/tree/master/examples/builtin_fn.rs) for a simple demonstration of the built-in functions that `shadow-rs` provides.
19
//!
20
//! # Setup
21
//!
22
//! ### 1) Modify `Cargo.toml` fields
23
//! Modify your `Cargo.toml` like so:
24
//!
25
//! ```toml
26
//! [package]
27
//! build = "build.rs"
28
//!
29
//! [dependencies]
30
//! shadow-rs = "{latest version}"
31
//!
32
//! [build-dependencies]
33
//! shadow-rs = "{latest version}"
34
//! ```
35
#![cfg_attr(feature = "document-features", doc = document_features::document_features!())]
36
//!
37
//! ### 2) Create `build.rs` file
38
//! Now in the root of your project (same directory as `Cargo.toml`) add a file `build.rs`:
39
//!
40
//! ```ignore
41
//! fn main() {
42
//!     ShadowBuilder::builder()
43
//!         .build_pattern(BuildPattern::RealTime)
44
//!         .build().unwrap();
45
//! }
46
//! ```
47
//!
48
//!
49
//! ### 3) Integrate Shadow
50
//! In your main Rust file (usually `main.rs` or `lib.rs`), add this:
51
//!
52
//! ```ignore
53
//! use shadow_rs::shadow;
54
//!
55
//! shadow!(build);
56
//! ```
57
//!
58
//! The `shadow!` macro uses the given identifier to create a module with that name.
59
//!
60
//! ### 4) Use Shadow Constants
61
//! You can now use the module defined with `shadow!` to access build-time information.
62
//!
63
//! ```ignore
64
//! fn main(){
65
//!     println!("debug:{}", shadow_rs::is_debug()); // check if this is a debug build. e.g 'true/false'
66
//!     println!("branch:{}", shadow_rs::branch()); // get current project branch. e.g 'master/develop'
67
//!     println!("tag:{}", shadow_rs::tag()); // get current project tag. e.g 'v1.3.5'
68
//!     println!("git_clean:{}", shadow_rs::git_clean()); // get current project clean. e.g 'true/false'
69
//!     println!("git_status_file:{}", shadow_rs::git_status_file()); // get current project statue file. e.g '  * examples/builtin_fn.rs (dirty)'
70
//!
71
//!     println!("{}", build::VERSION); //print version const
72
//!     println!("{}", build::CLAP_LONG_VERSION); //print CLAP_LONG_VERSION const
73
//!     println!("{}", build::BRANCH); //master
74
//!     println!("{}", build::SHORT_COMMIT);//8405e28e
75
//!     println!("{}", build::COMMIT_HASH);//8405e28e64080a09525a6cf1b07c22fcaf71a5c5
76
//!     println!("{}", build::COMMIT_DATE);//2021-08-04 12:34:03 +00:00
77
//!     println!("{}", build::COMMIT_AUTHOR);//baoyachi
78
//!     println!("{}", build::COMMIT_EMAIL);//xxx@gmail.com
79
//!
80
//!     println!("{}", build::BUILD_OS);//macos-x86_64
81
//!     println!("{}", build::RUST_VERSION);//rustc 1.45.0 (5c1f21c3b 2020-07-13)
82
//!     println!("{}", build::RUST_CHANNEL);//stable-x86_64-apple-darwin (default)
83
//!     println!("{}", build::CARGO_VERSION);//cargo 1.45.0 (744bd1fbb 2020-06-15)
84
//!     println!("{}", build::PKG_VERSION);//0.3.13
85
//!     println!("{}", build::CARGO_TREE); //like command:cargo tree
86
//!     println!("{}", build::CARGO_MANIFEST_DIR); // /User/baoyachi/shadow-rs/ |
87
//!
88
//!     println!("{}", build::PROJECT_NAME);//shadow-rs
89
//!     println!("{}", build::BUILD_TIME);//2020-08-16 14:50:25
90
//!     println!("{}", build::BUILD_RUST_CHANNEL);//debug
91
//!     println!("{}", build::GIT_CLEAN);//false
92
//!     println!("{}", build::GIT_STATUS_FILE);//* src/lib.rs (dirty)
93
//! }
94
//! ```
95
//!
96
//! ## Clap
97
//! You can also use `shadow-rs` to provide information to command-line interface crates such as [`clap`](https://docs.rs/clap/latest/clap/). An example of this can be found in [`example_shadow`](https://github.com/baoyachi/shadow-rs/blob/master/example_shadow/src/main.rs).
98
//!
99
//! For the user guide and further documentation, see the [README of `shadow-rs`](https://github.com/baoyachi/shadow-rs).
100
//!
101
//! # List of Generated Output Constants
102
//!
103
//! All constants produced by `shadow-rs` are documented in the module created with [`shadow!`], so `rustdoc` and your IDE will pick it up.
104
//!
105
//! ```
106
//! pub const PKG_VERSION: &str = "1.3.8-beta3";
107
//! pub const PKG_VERSION_MAJOR: &str = "1";
108
//! pub const PKG_VERSION_MINOR: &str = "3";
109
//! pub const PKG_VERSION_PATCH: &str = "8";
110
//! pub const PKG_VERSION_PRE: &str = "beta3";
111
//! pub const RUST_VERSION: &str = "rustc 1.45.0 (5c1f21c3b 2020-07-13)";
112
//! pub const BUILD_RUST_CHANNEL: &str = "debug";
113
//! pub const COMMIT_AUTHOR: &str = "baoyachi";
114
//! pub const BUILD_TIME: &str = "2020-08-16 13:48:52";
115
//! pub const BUILD_TIME_2822: &str = "Thu, 24 Jun 2021 21:44:14 +0800";
116
//! pub const BUILD_TIME_3339: &str = "2021-06-24T15:53:55+08:00";
117
//! pub const COMMIT_DATE: &str = "2021-08-04 12:34:03 +00:00";
118
//! pub const COMMIT_DATE_2822: &str = "Thu, 24 Jun 2021 21:44:14 +0800";
119
//! pub const COMMIT_DATE_3339: &str = "2021-06-24T21:44:14.473058+08:00";
120
//! pub const COMMIT_EMAIL: &str = "xxx@gmail.com";
121
//! pub const PROJECT_NAME: &str = "shadow-rs";
122
//! pub const RUST_CHANNEL: &str = "stable-x86_64-apple-darwin (default)";
123
//! pub const BRANCH: &str = "master";
124
//! pub const CARGO_LOCK: &str = r#"
125
//! ├── chrono v0.4.19
126
//! │   ├── libc v0.2.80
127
//! │   ├── num-integer v0.1.44
128
//! │   │   └── num-traits v0.2.14
129
//! │   │       [build-dependencies]
130
//! │   │       └── autocfg v1.0.1
131
//! │   ├── num-traits v0.2.14 (*)
132
//! │   └── time v0.1.44
133
//! │       └── libc v0.2.80
134
//! └── git2 v0.13.12
135
//! ├── log v0.4.11
136
//! │   └── cfg-if v0.1.10
137
//! └── url v2.2.0
138
//! ├── form_urlencoded v1.0.0
139
//! │   └── percent-encoding v2.1.0
140
//! └── percent-encoding v2.1.0"#;
141
//! pub const CARGO_VERSION: &str = "cargo 1.45.0 (744bd1fbb 2020-06-15)";
142
//! pub const BUILD_OS: &str = "macos-x86_64";
143
//! pub const COMMIT_HASH: &str = "386741540d73c194a3028b96b92fdeb53ca2788a";
144
//! pub const GIT_CLEAN: bool = true;
145
//! pub const GIT_STATUS_FILE: &str = "* src/lib.rs (dirty)";
146
//! ```
147
//!
148
#[cfg(feature = "metadata")]
149
pub extern crate cargo_metadata;
150
#[cfg(feature = "metadata")]
151
pub extern crate serde_json;
152

153
mod build;
154
mod ci;
155
mod date_time;
156
mod env;
157
mod err;
158
mod gen_const;
159
mod git;
160
mod hook;
161

162
/// Re-exported from the is_debug crate
163
pub use is_debug::*;
164

165
use build::*;
166

167
use crate::ci::CiType;
168
pub use crate::date_time::DateTime;
169
pub use const_format::*;
170
use std::collections::{BTreeMap, BTreeSet};
171
use std::env as std_env;
172
use std::fs::File;
173
use std::io::Write;
174
use std::path::Path;
175

176
use crate::gen_const::{
177
    cargo_metadata_fn, clap_long_version_branch_const, clap_long_version_tag_const,
178
    version_branch_const, version_tag_const, BUILD_CONST_CLAP_LONG_VERSION, BUILD_CONST_VERSION,
179
};
180
pub use err::{SdResult, ShadowError};
181

182
pub use crate::build::{BuildPattern, ShadowBuilder};
183
pub use {build::ShadowConst, env::*, git::*};
184

185
pub trait Format {
186
    fn human_format(&self) -> String;
187
}
188

189
const DEFINE_SHADOW_RS: &str = "shadow.rs";
190

191
pub const CARGO_CLIPPY_ALLOW_ALL: &str =
192
    "#[allow(clippy::all, clippy::pedantic, clippy::restriction, clippy::nursery)]";
193

194
/// Add a module with the provided name which contains the build information generated by `shadow-rs`.
195
///
196
/// # Example
197
///
198
/// ```ignore
199
/// use shadow_rs::shadow;
200
///
201
/// shadow!(my_build_information);
202
///
203
/// fn main() {
204
///     println!("I'm version {}!", my_build_information::VERSION);
205
/// }
206
/// ```
207
///
208
/// The convention, however, is to use `shadow!(build);`.
209
#[macro_export]
×
UNCOV
210
macro_rules! shadow {
×
211
    ($build_mod:ident) => {
×
212
        #[doc = r#"shadow-rs mod"#]
×
213
        pub mod $build_mod {
214
            include!(concat!(env!("OUT_DIR"), "/shadow.rs"));
×
215
        }
216
    };
217
}
218

219
/// Since [cargo metadata](https://crates.io/crates/cargo_metadata) details about workspace
220
/// membership and resolved dependencies for the current package, storing this data can result in
221
/// significantly larger crate sizes. As such, the CARGO_METADATA const is disabled by default.
222
///
223
/// Should you choose to retain this information, you have the option to customize a deny_const
224
/// object and override the `new_deny` method parameters accordingly.
225
///
226
#[allow(clippy::all, clippy::pedantic, clippy::restriction, clippy::nursery)]
227
pub fn default_deny() -> BTreeSet<ShadowConst> {
2✔
228
    BTreeSet::from([CARGO_METADATA])
2✔
229
}
230

231
/// Returns the contents of [`std::env::vars`] as an ordered map.
232
pub(crate) fn get_std_env() -> BTreeMap<String, String> {
1✔
233
    let mut env_map = BTreeMap::new();
2✔
234
    for (k, v) in std_env::vars() {
8✔
235
        env_map.insert(k, v);
4✔
236
    }
237
    env_map
2✔
238
}
239

240
/// `shadow-rs` configuration.
241
///
242
/// This struct encapsulates the configuration for the `shadow-rs` build process. It allows for fine-grained control over
243
/// various aspects of the build, including file output, build constants, environment variables, deny lists, and build patterns.
244
///
245
/// While it is possible to construct a [`Shadow`] instance manually, it is highly recommended to use the [`ShadowBuilder`] builder pattern structure
246
/// provided by `shadow-rs`. The builder pattern simplifies the setup process and ensures that all necessary configurations are properly set up,
247
/// allowing you to customize multiple aspects simultaneously, such as using a denylist and a hook function at the same time.
248
///
249
/// # Fields
250
///
251
/// * `f`: The file that `shadow-rs` writes build information to. This file will contain serialized build constants and other metadata.
252
/// * `map`: A map of build constant identifiers to their corresponding `ConstVal`. These are the values that will be written into the file.
253
/// * `std_env`: A map of environment variables obtained through [`std::env::vars`]. These variables can influence the build process.
254
/// * `deny_const`: A set of build constant identifiers that should be excluded from the build process. This can be populated via [`ShadowBuilder::deny_const`].
255
/// * `out_path`: The path where the generated files will be placed. This is usually derived from the `OUT_DIR` environment variable but can be customized via [`ShadowBuilder::out_path`].
256
/// * `build_pattern`: Determines the strategy for triggering package rebuilds (`Lazy`, `RealTime`, or `Custom`). This affects when Cargo will rerun the build script and can be configured via [`ShadowBuilder::build_pattern`].
257
///
258
/// # Example
259
///
260
/// ```no_run
261
/// use std::collections::BTreeSet;
262
/// use shadow_rs::{ShadowBuilder, BuildPattern, CARGO_TREE, CARGO_METADATA};
263
///
264
/// ShadowBuilder::builder()
265
///    .build_pattern(BuildPattern::RealTime)
266
///    .deny_const(BTreeSet::from([CARGO_TREE, CARGO_METADATA]))
267
///    .build().unwrap();
268
/// ```
269
///
270
#[derive(Debug)]
271
pub struct Shadow {
272
    /// The file that `shadow-rs` writes build information to.
273
    ///
274
    /// This file will contain all the necessary information about the build, including serialized build constants and other metadata.
275
    pub f: File,
276

277
    /// The values of build constants to be written.
278
    ///
279
    /// This is a mapping from `ShadowConst` identifiers to their corresponding `ConstVal` objects. Each entry in this map represents a build constant that will be included in the final build.
280
    pub map: BTreeMap<ShadowConst, ConstVal>,
281

282
    /// Build environment variables, obtained through [`std::env::vars`].
283
    ///
284
    /// These environment variables can affect the build process and are captured here for consistency and reproducibility.
285
    pub std_env: BTreeMap<String, String>,
286

287
    /// Constants in the deny list, passed through [`ShadowBuilder::deny_const`].
288
    ///
289
    /// This set contains build constant identifiers that should be excluded from the build process. By specifying these, you can prevent certain constants from being written into the build file.
290
    pub deny_const: BTreeSet<ShadowConst>,
291

292
    /// The output path where generated files will be placed.
293
    ///
294
    /// This specifies the directory where the build script will write its output. It's typically set using the `OUT_DIR` environment variable but can be customized using [`ShadowBuilder::out_path`].
295
    pub out_path: String,
296

297
    /// Determines the strategy for triggering package rebuilds.
298
    ///
299
    /// This field sets the pattern for how often the package should be rebuilt. Options include `Lazy`, `RealTime`, and `Custom`, each with its own implications on the build frequency and conditions under which a rebuild is triggered.
300
    /// It can be configured using [`ShadowBuilder::build_pattern`].
301
    pub build_pattern: BuildPattern,
302
}
303

304
impl Shadow {
1✔
305
    /// Write the build configuration specified by this [`Shadow`] instance.
306
    /// The hook function is run as well, allowing it to append to `shadow-rs`'s output.
307
    pub fn hook<F>(&self, f: F) -> SdResult<()>
×
308
    where
309
        F: Fn(&File) -> SdResult<()>,
310
    {
311
        let desc = r#"// Below code generated by project custom from by build.rs"#;
×
312
        writeln!(&self.f, "\n{desc}\n")?;
×
313
        f(&self.f)?;
×
314
        Ok(())
×
315
    }
316

317
    /// Try to infer the CI system that we're currently running under.
318
    ///
319
    /// TODO: Recognize other CI types, especially Travis and Jenkins.
320
    fn try_ci(&self) -> CiType {
1✔
321
        if let Some(c) = self.std_env.get("GITLAB_CI") {
1✔
322
            if c == "true" {
×
323
                return CiType::Gitlab;
×
324
            }
325
        }
326

327
        if let Some(c) = self.std_env.get("GITHUB_ACTIONS") {
2✔
328
            if c == "true" {
1✔
329
                return CiType::Github;
1✔
330
            }
331
        }
332

333
        CiType::None
×
334
    }
335

336
    /// Checks if the specified build constant is in the deny list.
337
    ///
338
    /// # Arguments
339
    /// * `deny_const` - A value of type `ShadowConst` representing the build constant to check.
340
    ///
341
    /// # Returns
342
    /// * `true` if the build constant is present in the deny list; otherwise, `false`.
343
    pub fn deny_contains(&self, deny_const: ShadowConst) -> bool {
1✔
344
        self.deny_const.contains(&deny_const)
1✔
345
    }
346

347
    fn build_inner(builder: ShadowBuilder) -> SdResult<Shadow> {
1✔
348
        let out_path = builder.get_out_path()?;
3✔
349
        let src_path = builder.get_src_path()?;
4✔
350
        let build_pattern = builder.get_build_pattern().clone();
4✔
351
        let deny_const = builder.get_deny_const().clone();
4✔
352

353
        let out = {
×
354
            let path = Path::new(out_path);
4✔
355
            if !out_path.ends_with('/') {
2✔
356
                path.join(format!("{out_path}/{DEFINE_SHADOW_RS}"))
×
357
            } else {
358
                path.join(DEFINE_SHADOW_RS)
4✔
359
            }
360
        };
361

362
        let mut shadow = Shadow {
363
            f: File::create(out)?,
4✔
364
            map: Default::default(),
2✔
365
            std_env: Default::default(),
2✔
366
            deny_const,
367
            out_path: out_path.to_string(),
2✔
368
            build_pattern,
369
        };
370
        shadow.std_env = get_std_env();
3✔
371

372
        let ci_type = shadow.try_ci();
1✔
373
        let src_path = Path::new(src_path.as_str());
1✔
374

375
        let mut map = new_git(src_path, ci_type, &shadow.std_env);
1✔
376
        for (k, v) in new_project(&shadow.std_env) {
8✔
377
            map.insert(k, v);
4✔
378
        }
379
        for (k, v) in new_system_env(&shadow) {
4✔
380
            map.insert(k, v);
2✔
381
        }
382
        shadow.map = map;
1✔
383

384
        // deny const
385
        shadow.filter_deny();
1✔
386

387
        shadow.write_all()?;
1✔
388

389
        // handle hook
390
        if let Some(h) = builder.get_hook() {
2✔
391
            shadow.hook(h.hook_inner())?
×
392
        }
393

394
        Ok(shadow)
1✔
395
    }
396

397
    fn filter_deny(&mut self) {
1✔
398
        self.deny_const.iter().for_each(|x| {
2✔
399
            self.map.remove(&**x);
1✔
400
        })
401
    }
402

403
    fn write_all(&mut self) -> SdResult<()> {
1✔
404
        self.gen_header()?;
1✔
405

406
        self.gen_const()?;
1✔
407

408
        //write version function
409
        let gen_version = self.gen_version()?;
2✔
410

411
        self.gen_build_in(gen_version)?;
2✔
412

413
        Ok(())
1✔
414
    }
415

416
    fn gen_const(&mut self) -> SdResult<()> {
1✔
417
        let out_dir = &self.out_path;
1✔
418
        self.build_pattern.rerun_if(self.map.keys(), out_dir);
1✔
419

420
        for (k, v) in self.map.clone() {
3✔
421
            self.write_const(k, v)?;
2✔
422
        }
423
        Ok(())
1✔
424
    }
425

426
    fn gen_header(&self) -> SdResult<()> {
1✔
427
        let desc = format!(
1✔
428
            r#"// Code automatically generated by `shadow-rs` (https://github.com/baoyachi/shadow-rs), do not edit.
429
// Author: https://www.github.com/baoyachi
430
// Generation time: {}
431
"#,
432
            DateTime::now().to_rfc2822()
1✔
433
        );
434
        writeln!(&self.f, "{desc}\n\n")?;
2✔
435
        Ok(())
1✔
436
    }
437

438
    fn write_const(&mut self, shadow_const: ShadowConst, val: ConstVal) -> SdResult<()> {
1✔
439
        let desc = format!("#[doc=r#\"{}\"#]", val.desc);
2✔
440
        let define = match val.t {
1✔
441
            ConstType::Str => format!(
3✔
442
                "#[allow(dead_code)]\n\
443
                {}\n\
444
            pub const {} :{} = r#\"{}\"#;",
UNCOV
445
                CARGO_CLIPPY_ALLOW_ALL,
×
446
                shadow_const.to_ascii_uppercase(),
1✔
UNCOV
447
                ConstType::Str,
×
448
                val.v
449
            ),
450
            ConstType::Bool => format!(
4✔
451
                "#[allow(dead_code)]\n\
452
                    {}\n\
453
            pub const {} :{} = {};",
454
                CARGO_CLIPPY_ALLOW_ALL,
×
455
                shadow_const.to_ascii_uppercase(),
1✔
456
                ConstType::Bool,
×
457
                val.v.parse::<bool>().unwrap()
2✔
458
            ),
459
            ConstType::Slice => format!(
4✔
460
                "#[allow(dead_code)]\n\
461
                    {}\n\
462
            pub const {} :{} = &{:?};",
463
                CARGO_CLIPPY_ALLOW_ALL,
464
                shadow_const.to_ascii_uppercase(),
1✔
465
                ConstType::Slice,
×
466
                val.v.as_bytes()
1✔
467
            ),
468
        };
469

470
        writeln!(&self.f, "{desc}")?;
2✔
471
        writeln!(&self.f, "{define}\n")?;
2✔
472
        Ok(())
1✔
473
    }
474

475
    fn gen_version(&mut self) -> SdResult<Vec<&'static str>> {
1✔
476
        let (ver_fn, clap_long_ver_fn) = match self.map.get(TAG) {
2✔
NEW
477
            None => (version_branch_const(), clap_long_version_branch_const()),
×
478
            Some(tag) => {
1✔
479
                if !tag.v.is_empty() {
2✔
NEW
480
                    (version_tag_const(), clap_long_version_tag_const())
×
481
                } else {
482
                    (version_branch_const(), clap_long_version_branch_const())
1✔
483
                }
484
            }
485
        };
486
        writeln!(&self.f, "{ver_fn}\n")?;
2✔
487
        writeln!(&self.f, "{clap_long_ver_fn}\n")?;
2✔
488

489
        Ok(vec![BUILD_CONST_VERSION, BUILD_CONST_CLAP_LONG_VERSION])
2✔
490
    }
491

492
    fn gen_build_in(&self, gen_const: Vec<&'static str>) -> SdResult<()> {
1✔
493
        let mut print_val = String::from("\n");
1✔
494

495
        // append gen const
496
        for (k, v) in &self.map {
3✔
497
            let tmp = match v.t {
1✔
498
                ConstType::Str | ConstType::Bool => {
499
                    format!(r#"{}println!("{k}:{{{k}}}\n");{}"#, "\t", "\n")
3✔
500
                }
501
                ConstType::Slice => {
502
                    format!(r#"{}println!("{k}:{{:?}}\n",{});{}"#, "\t", k, "\n",)
3✔
503
                }
504
            };
505
            print_val.push_str(tmp.as_str());
2✔
506
        }
507

508
        // append gen fn
509
        for k in gen_const {
4✔
510
            let tmp = format!(r#"{}println!("{k}:{{{k}}}\n");{}"#, "\t", "\n");
2✔
511
            print_val.push_str(tmp.as_str());
2✔
512
        }
513

514
        let everything_define = format!(
1✔
515
            "/// Prints all built-in `shadow-rs` build constants to standard output.\n\
516
            #[allow(dead_code)]\n\
517
            {CARGO_CLIPPY_ALLOW_ALL}\n\
518
            pub fn print_build_in() {\
519
            {{print_val}}\
520
            }\n",
521
        );
522
        writeln!(&self.f, "{everything_define}")?;
2✔
523

524
        writeln!(&self.f, "{}", cargo_metadata_fn(self))?;
2✔
525

526
        Ok(())
1✔
527
    }
528
}
529

530
#[cfg(test)]
531
mod tests {
532
    use super::*;
533
    use std::fs;
534

535
    #[test]
536
    fn test_build() -> SdResult<()> {
537
        ShadowBuilder::builder()
538
            .src_path("./")
539
            .out_path("./")
540
            .build()?;
541
        let shadow = fs::read_to_string(DEFINE_SHADOW_RS)?;
542
        assert!(!shadow.is_empty());
543
        assert!(shadow.lines().count() > 0);
544
        Ok(())
545
    }
546

547
    #[test]
548
    fn test_build_deny() -> SdResult<()> {
549
        ShadowBuilder::builder()
550
            .src_path("./")
551
            .out_path("./")
552
            .deny_const(BTreeSet::from([CARGO_TREE]))
553
            .build()?;
554

555
        let shadow = fs::read_to_string(DEFINE_SHADOW_RS)?;
556
        assert!(!shadow.is_empty());
557
        assert!(shadow.lines().count() > 0);
558
        // println!("{shadow}");
559
        let expect = "pub const CARGO_TREE :&str";
560
        assert!(!shadow.contains(expect));
561
        Ok(())
562
    }
563

564
    #[test]
565
    fn test_env() {
566
        for (k, v) in std::env::vars() {
567
            println!("K:{k},V:{v}");
568
        }
569
    }
570
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc