diff --git a/Cargo.lock b/Cargo.lock index f4299c78b8..66d3f1891d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,11 +384,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -1656,6 +1656,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-traits" version = "0.2.17" @@ -1864,9 +1870,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1932,9 +1938,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2365,6 +2371,7 @@ name = "roc_cli" version = "0.0.1" dependencies = [ "bumpalo", + "chrono", "clap 4.4.6", "cli_utils", "const_format", @@ -3297,9 +3304,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -3527,6 +3534,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -3940,12 +3953,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -3960,10 +3974,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index cd3ecedb87..73827b5afc 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -2,6 +2,7 @@ name = "roc_cli" description = "The Roc binary that brings together all functionality in the Roc toolset." default-run = "roc" +build = "build.rs" authors.workspace = true edition.workspace = true @@ -30,7 +31,13 @@ target-wasm32 = ["roc_build/target-wasm32"] target-x86 = ["roc_build/target-x86", "roc_repl_cli/target-x86"] target-x86_64 = ["roc_build/target-x86_64", "roc_repl_cli/target-x86_64"] -target-all = ["target-aarch64", "target-arm", "target-x86", "target-x86_64", "target-wasm32"] +target-all = [ + "target-aarch64", + "target-arm", + "target-x86", + "target-x86_64", + "target-wasm32", +] sanitizers = ["roc_build/sanitizers"] @@ -93,6 +100,9 @@ parking_lot.workspace = true pretty_assertions.workspace = true serial_test.workspace = true +[build-dependencies] +chrono = "0.4.26" + [[bench]] name = "time_bench" harness = false diff --git a/crates/cli/build.rs b/crates/cli/build.rs new file mode 100644 index 0000000000..5d7284642c --- /dev/null +++ b/crates/cli/build.rs @@ -0,0 +1,59 @@ +use chrono::prelude::*; +use std::fs; +use std::process::Command; +use std::str; + +fn main() { + // Rebuild if this build.rs file changes + println!("cargo:rerun-if-changed=build.rs"); + + // The version file is located at the root of the repository + let version_file_path = "../../version.txt"; + + // Rebuild if version file changes + println!("cargo:rerun-if-changed={}", version_file_path); + + // Read the version file + let version_file_contents = fs::read_to_string(version_file_path).unwrap(); + + // If the version is "built-from-source", replace it with the git commit information + let version = match version_file_contents.trim() { + "built-from-source" => { + // Rebuild if a new Git commit is made + println!("cargo:rerun-if-changed=.git/HEAD"); + + // Get the hash of the current commit + let git_describe_output = Command::new("git") + .arg("describe") + .arg("--always") + .arg("--dirty= with additional changes") // Add a suffix if the working directory is dirty + .output() + .expect("Failed to execute git describe command"); + let git_commit_hash = str::from_utf8(&git_describe_output.stdout) + .expect("Failed to parse git describe output") + .trim(); + + // Get the datetime of the last commit + let git_show_output = Command::new("git") + .arg("show") + .arg("--no-patch") + .arg("--format=%ct") // Outputting a UNIX timestamp is the only way to always use UTC + .output() + .expect("Failed to execute git show command"); + let git_commit_timestamp = { + let timestamp = str::from_utf8(&git_show_output.stdout) + .expect("Failed to parse git show output as a string") + .trim() + .parse::() + .expect("Failed to parse timestamp as an integer"); + DateTime::from_timestamp(timestamp, 0) + .expect("Failed to parse timestamp") + .format("%Y-%m-%d %H:%M:%S") + }; + format!("built from commit {git_commit_hash}, committed at {git_commit_timestamp}") + } + _ => version_file_contents.trim().to_string(), + }; + // Emit the version to a build-time environment variable + println!("cargo:rustc-env=ROC_VERSION={}", version); +} diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 0433651e5d..b4703e935d 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -90,7 +90,7 @@ pub const FLAG_PP_HOST: &str = "host"; pub const FLAG_PP_PLATFORM: &str = "platform"; pub const FLAG_PP_DYLIB: &str = "lib"; -const VERSION: &str = include_str!("../../../version.txt"); +pub const VERSION: &str = env!("ROC_VERSION"); const DEFAULT_GENERATED_DOCS_DIR: &str = "generated-docs"; pub fn build_app() -> Command { @@ -182,7 +182,7 @@ pub fn build_app() -> Command { PossibleValuesParser::new(Target::iter().map(Into::<&'static str>::into)); Command::new("roc") - .version(concatcp!(VERSION, "\n")) + .version(VERSION) .about("Run the given .roc file, if there are no compilation errors.\nYou can use one of the SUBCOMMANDS below to do something else!") .args_conflicts_with_subcommands(true) .subcommand(Command::new(CMD_BUILD) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 48574fe169..234cfa2d51 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -8,7 +8,7 @@ use roc_cli::{ CMD_RUN, CMD_TEST, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_MAIN, FLAG_NO_COLOR, FLAG_NO_HEADER, FLAG_NO_LINK, FLAG_OUTPUT, FLAG_PP_DYLIB, FLAG_PP_HOST, FLAG_PP_PLATFORM, FLAG_STDIN, FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, GLUE_DIR, GLUE_SPEC, - ROC_FILE, + ROC_FILE, VERSION, }; use roc_docs::generate_docs_html; use roc_error_macros::user_error; @@ -23,7 +23,6 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use target_lexicon::Triple; -#[macro_use] extern crate const_format; #[global_allocator] @@ -364,11 +363,7 @@ fn main() -> io::Result<()> { Ok(format_exit_code) } Some((CMD_VERSION, _)) => { - print!( - "{}", - concatcp!("roc ", include_str!("../../../version.txt")) - ); - + println!("roc {}", VERSION); Ok(0) } _ => unreachable!(),