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
#![recursion_limit = "128"] extern crate proc_macro; use proc_macro::TokenStream; use proc_macro2::Span; use proc_macro_hack::proc_macro_hack; use quote::quote; use std::process::Command; use syn::{parse_macro_input, LitStr}; fn to_str(s: &[u8]) -> String { String::from_utf8_lossy(s).trim_end().to_string() } macro_rules! cmd { ($c:expr; $d:expr) => { LitStr::new( &Command::new($c) .output() .map(|s| to_str(&s.stdout)) .unwrap_or($d.into()), Span::call_site(), ) }; ($c:expr, $($a:expr),*; $d:expr) => { LitStr::new( &Command::new($c) .args(&[$($a,)*]) .output() .map(|s| to_str(&s.stdout)) .unwrap_or($d.into()), Span::call_site(), ) }; } #[proc_macro_hack] pub fn ever(input: TokenStream) -> TokenStream { let version_env = if input.is_empty() { LitStr::new("VERSION", Span::call_site()) } else { parse_macro_input!(input as LitStr) }; let date = cmd!("date"; "<unknown_date>"); let commit = cmd!("git", "rev-parse", "HEAD"; "<unknown_commit>" ); let user = cmd!("whoami"; "<unknown_user>"); let host = cmd!("hostname"; "<unknown_host>"); let builddir = cmd!("pwd"; "<unknown_dir>"); let rustc = cmd!("rustc", "--version"; "<unknown_rustc_version>"); let s = quote! { if std::env::var(#version_env).unwrap_or("0".into()) == "1" { let name = option_env!("CARGO_PKG_NAME").unwrap_or("<unknown_package>"); let version = option_env!("CARGO_PKG_VERSION").unwrap_or("<unknown_version>"); let about = option_env!("CARGO_PKG_DESCRIPTION").unwrap_or("<no_description>"); #[cfg(debug_assertions)] let mode = "debug"; #[cfg(not(debug_assertions))] let mode = "release"; println!( r#"{name} {version} ({mode}): {about} date: {date} commit: {commit} user: {user} host: {host} builddir: {builddir} rustc: {rustc}"#, name = name, version = version, about = about, date = #date, commit = #commit, user = #user, host = #host, builddir = #builddir, rustc = #rustc, mode = mode, ); std::process::exit(1); } }; s.into() }