diff --git a/build.rs b/build.rs index ec34fc278c..5287d05f5c 100644 --- a/build.rs +++ b/build.rs @@ -25,6 +25,9 @@ use std::{ use toml::Value; use walkdir::WalkDir; +#[path = "version_env.rs"] +mod version_env; + // The following license text that should be present at the beginning of every source file. const EXPECTED_LICENSE_TEXT: &[u8] = include_bytes!(".resources/license_header"); @@ -312,6 +315,8 @@ fn main() { // Check if the tokio_console feature is correctly enabled. check_tokio_console_flags(); + // Register the release version for runtime version reporting. + version_env::emit_version_env(); // Register build-time information. built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/cli/build.rs b/cli/build.rs new file mode 100644 index 0000000000..9c799f223c --- /dev/null +++ b/cli/build.rs @@ -0,0 +1,21 @@ +// Copyright (c) 2019-2026 Provable Inc. +// This file is part of the snarkOS library. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[path = "../version_env.rs"] +mod version_env; + +fn main() { + version_env::emit_version_env(); +} diff --git a/cli/src/helpers/updater.rs b/cli/src/helpers/updater.rs index 40c5434ee4..d10bdf733f 100644 --- a/cli/src/helpers/updater.rs +++ b/cli/src/helpers/updater.rs @@ -47,7 +47,7 @@ impl Updater { .repo_owner(Self::SNARKOS_REPO_OWNER) .repo_name(Self::SNARKOS_REPO_NAME) .bin_name(Self::SNARKOS_BIN_NAME) - .current_version(env!("CARGO_PKG_VERSION")) + .current_version(env!("SNARKOS_VERSION")) .show_download_progress(show_output) .no_confirm(true) .show_output(show_output); @@ -66,7 +66,7 @@ impl Updater { .repo_owner(Self::SNARKOS_REPO_OWNER) .repo_name(Self::SNARKOS_REPO_NAME) .bin_name(Self::SNARKOS_BIN_NAME) - .current_version(env!("CARGO_PKG_VERSION")) + .current_version(env!("SNARKOS_VERSION")) .build()?; let current_version = updater.current_version(); @@ -92,6 +92,23 @@ impl Updater { } } +#[cfg(test)] +mod tests { + use std::{fs, path::Path}; + + #[test] + fn snarkos_version_matches_release_version() { + let release_version = Path::new(env!("CARGO_MANIFEST_DIR")) + .ancestors() + .map(|dir| dir.join(".cargo").join("release-version")) + .find(|path| path.is_file()) + .map(|path| fs::read_to_string(path).unwrap()) + .unwrap(); + + assert_eq!(env!("SNARKOS_VERSION"), release_version.trim().trim_start_matches('v')); + } +} + #[derive(Debug, Error)] pub enum UpdaterError { #[error("{}: {}", _0, _1)] diff --git a/node/cdn/build.rs b/node/cdn/build.rs new file mode 100644 index 0000000000..e0ab0243cc --- /dev/null +++ b/node/cdn/build.rs @@ -0,0 +1,21 @@ +// Copyright (c) 2019-2026 Provable Inc. +// This file is part of the snarkOS library. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[path = "../../version_env.rs"] +mod version_env; + +fn main() { + version_env::emit_version_env(); +} diff --git a/node/cdn/src/blocks.rs b/node/cdn/src/blocks.rs index fab03377b9..2815a542ea 100644 --- a/node/cdn/src/blocks.rs +++ b/node/cdn/src/blocks.rs @@ -57,7 +57,7 @@ pub const CDN_BASE_URL: &str = "https://cdn.provable.com/v0/blocks"; /// Returns the user-agent string for CDN requests. const fn cdn_user_agent() -> &'static str { - concat!("snarkos/", env!("CARGO_PKG_VERSION")) + concat!("snarkos/", env!("SNARKOS_VERSION")) } /// Updates the metrics during CDN sync. diff --git a/node/metrics/build.rs b/node/metrics/build.rs index af0e5b4f0c..9fcc289052 100644 --- a/node/metrics/build.rs +++ b/node/metrics/build.rs @@ -13,6 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[path = "../../version_env.rs"] +mod version_env; + fn main() { + version_env::emit_version_env(); built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/node/metrics/src/lib.rs b/node/metrics/src/lib.rs index 7e867dc8e3..2dc7ab230a 100644 --- a/node/metrics/src/lib.rs +++ b/node/metrics/src/lib.rs @@ -177,7 +177,7 @@ mod built_info { /// The resulting metric will show as: /// snarkos_build_info{version="4.2.1",git_commit="abc123",git_branch="main",features="cuda,metrics"} 1 pub fn set_build_info() { - let version = built_info::PKG_VERSION; + let version = env!("SNARKOS_VERSION"); let git_commit = built_info::GIT_COMMIT_HASH.unwrap_or("unknown"); let git_branch = built_info::GIT_HEAD_REF.unwrap_or("unknown"); let features = built_info::FEATURES_LOWERCASE_STR.replace(' ', ""); diff --git a/node/rest/build.rs b/node/rest/build.rs index af0e5b4f0c..9fcc289052 100644 --- a/node/rest/build.rs +++ b/node/rest/build.rs @@ -13,6 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[path = "../../version_env.rs"] +mod version_env; + fn main() { + version_env::emit_version_env(); built::write_built_file().expect("Failed to acquire build-time information"); } diff --git a/node/rest/src/version.rs b/node/rest/src/version.rs index 99a1c943e2..149fe018e2 100644 --- a/node/rest/src/version.rs +++ b/node/rest/src/version.rs @@ -50,7 +50,7 @@ impl VersionInfo { let consensus_heights: Vec = N::CONSENSUS_VERSION_HEIGHTS().iter().map(|(_, height)| *height).collect(); VERSION_INFO.get_or_init(|| VersionInfo { - version: built_info::PKG_VERSION.to_string(), + version: env!("SNARKOS_VERSION").to_string(), git_commit: built_info::GIT_COMMIT_HASH.unwrap_or("unknown").to_string(), git_branch: built_info::GIT_HEAD_REF.unwrap_or("unknown").to_string(), latest_consensus_version: latest_num, diff --git a/snarkos/main.rs b/snarkos/main.rs index 3ddca88939..5a46c10528 100644 --- a/snarkos/main.rs +++ b/snarkos/main.rs @@ -187,12 +187,13 @@ fn check_for_version() { if let Some(first_arg) = env::args().nth(1) && ["--version", "-V"].contains(&&*first_arg) { + let version = env!("SNARKOS_VERSION"); let branch = GIT_HEAD_REF.unwrap_or("unknown_branch"); let commit = GIT_COMMIT_HASH.unwrap_or("unknown_commit"); let mut features = FEATURES_LOWERCASE_STR.to_owned(); features.retain(|c| c != ' '); - print_info!("snarkos {branch} {commit} features=[{features}]"); + print_info!("snarkos {version} {branch} {commit} features=[{features}]"); exit(0); } diff --git a/version_env.rs b/version_env.rs new file mode 100644 index 0000000000..852ebc692b --- /dev/null +++ b/version_env.rs @@ -0,0 +1,48 @@ +// Copyright (c) 2019-2026 Provable Inc. +// This file is part of the snarkOS library. + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{ + env, + fs, + path::{Path, PathBuf}, +}; + +pub fn emit_version_env() { + let release_version = find_release_version_path().unwrap_or_else(|| { + panic!( + "Failed to locate '.cargo/release-version' starting from '{}'", + env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "".to_string()) + ) + }); + + println!("cargo:rerun-if-changed={}", release_version.display()); + + let version = fs::read_to_string(&release_version) + .unwrap_or_else(|err| panic!("Failed to read '{}': {err}", release_version.display())); + let version = version.trim(); + let version = version.strip_prefix('v').unwrap_or(version); + assert!(!version.is_empty(), "'{}' did not contain a version", release_version.display()); + + println!("cargo:rustc-env=SNARKOS_VERSION={version}"); +} + +fn find_release_version_path() -> Option { + let manifest_dir = env::var_os("CARGO_MANIFEST_DIR")?; + + Path::new(&manifest_dir) + .ancestors() + .map(|dir| dir.join(".cargo").join("release-version")) + .find(|path| path.is_file()) +}