build.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /// The version string isn’t the simplest: we want to show the version,
  2. /// current Git hash, and compilation date when building *debug* versions, but
  3. /// just the version for *release* versions so the builds are reproducible.
  4. ///
  5. /// This script generates the string from the environment variables that Cargo
  6. /// adds (http://doc.crates.io/environment-variables.html) and runs `git` to
  7. /// get the SHA1 hash. It then writes the string into a file, which exa then
  8. /// includes at build-time.
  9. ///
  10. /// - https://stackoverflow.com/q/43753491/3484614
  11. /// - https://crates.io/crates/vergen
  12. use std::env;
  13. use std::fs::File;
  14. use std::io::{self, Write};
  15. use std::path::PathBuf;
  16. use chrono::prelude::*;
  17. /// The build script entry point.
  18. fn main() -> io::Result<()> {
  19. #![allow(clippy::write_with_newline)]
  20. let tagline = "eza - A modern, maintained replacement for ls";
  21. let url = "https://github.com/eza-community/eza";
  22. let ver = if is_debug_build() {
  23. format!(
  24. "{}\nv{} \\1;31m(pre-release debug build!)\\0m\n\\1;4;34m{}\\0m",
  25. tagline,
  26. version_string(),
  27. url
  28. )
  29. } else if is_development_version() {
  30. format!(
  31. "{}\nv{} [{}] built on {} \\1;31m(pre-release!)\\0m\n\\1;4;34m{}\\0m",
  32. tagline,
  33. version_string(),
  34. git_hash(),
  35. build_date(),
  36. url
  37. )
  38. } else {
  39. format!("{}\nv{}\n\\1;4;34m{}\\0m", tagline, version_string(), url)
  40. };
  41. // We need to create these files in the Cargo output directory.
  42. let out = PathBuf::from(env::var("OUT_DIR").unwrap());
  43. let path = &out.join("version_string.txt");
  44. // Bland version text
  45. let mut f =
  46. File::create(path).unwrap_or_else(|_| panic!("{}", path.to_string_lossy().to_string()));
  47. writeln!(f, "{}", strip_codes(&ver))?;
  48. Ok(())
  49. }
  50. /// Removes escape codes from a string.
  51. fn strip_codes(input: &str) -> String {
  52. input
  53. .replace("\\0m", "")
  54. .replace("\\1;31m", "")
  55. .replace("\\1;4;34m", "")
  56. }
  57. /// Retrieve the project’s current Git hash, as a string.
  58. fn git_hash() -> String {
  59. use std::process::Command;
  60. String::from_utf8_lossy(
  61. &Command::new("git")
  62. .args(["rev-parse", "--short", "HEAD"])
  63. .output()
  64. .unwrap()
  65. .stdout,
  66. )
  67. .trim()
  68. .to_string()
  69. }
  70. /// Whether we should show pre-release info in the version string.
  71. ///
  72. /// Both weekly releases and actual releases are --release releases,
  73. /// but actual releases will have a proper version number.
  74. fn is_development_version() -> bool {
  75. cargo_version().ends_with("-pre") || env::var("PROFILE").unwrap() == "debug"
  76. }
  77. /// Whether we are building in debug mode.
  78. fn is_debug_build() -> bool {
  79. env::var("PROFILE").unwrap() == "debug"
  80. }
  81. /// Retrieves the [package] version in Cargo.toml as a string.
  82. fn cargo_version() -> String {
  83. env::var("CARGO_PKG_VERSION").unwrap()
  84. }
  85. /// Returns the version and build parameters string.
  86. fn version_string() -> String {
  87. let mut ver = cargo_version();
  88. let feats = nonstandard_features_string();
  89. if !feats.is_empty() {
  90. ver.push_str(&format!(" [{}]", &feats));
  91. }
  92. ver
  93. }
  94. /// Finds whether a feature is enabled by examining the Cargo variable.
  95. fn feature_enabled(name: &str) -> bool {
  96. env::var(format!("CARGO_FEATURE_{}", name))
  97. .map(|e| !e.is_empty())
  98. .unwrap_or(false)
  99. }
  100. /// A comma-separated list of non-standard feature choices.
  101. fn nonstandard_features_string() -> String {
  102. let mut s = Vec::new();
  103. if feature_enabled("GIT") {
  104. s.push("+git");
  105. } else {
  106. s.push("-git");
  107. }
  108. s.join(", ")
  109. }
  110. /// Formats the current date as an ISO 8601 string.
  111. fn build_date() -> String {
  112. let now = Local::now();
  113. now.date_naive().format("%Y-%m-%d").to_string()
  114. }