mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Const eval all of version.rs (#7923)
`version.rs` essentially consists of constants that can be baked in at compile time. I moved most of `version.rs` to `build.rs`. The constants are passed via rustc's environment then stored in the binary.
This commit is contained in:
1 parent
1bb42adc73
commit
d1eec5d168
5 files changed
+178
-134
No files matched your search
@@ -99,6 +99,7 @@ widestring = { workspace = true }
|
||||
wasm-bindgen = { workspace = true, optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
chrono = { workspace = true }
|
||||
glob = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
reason = "build scripts cannot use rustpython-host_env"
|
||||
)]
|
||||
|
||||
use chrono::{Local, prelude::DateTime};
|
||||
use core::time::Duration;
|
||||
use itertools::Itertools;
|
||||
use std::{
|
||||
env,
|
||||
@@ -24,6 +26,9 @@ fn main() {
|
||||
}
|
||||
println!("cargo:rerun-if-changed=../../Lib/importlib/_bootstrap.py");
|
||||
|
||||
// = 3.14.0alpha
|
||||
python_version(3, 14, 0, "alpha", 0);
|
||||
|
||||
println!("cargo:rustc-env=RUSTPYTHON_GIT_HASH={}", git_hash());
|
||||
println!(
|
||||
"cargo:rustc-env=RUSTPYTHON_GIT_TIMESTAMP={}",
|
||||
@@ -31,10 +36,17 @@ fn main() {
|
||||
);
|
||||
println!("cargo:rustc-env=RUSTPYTHON_GIT_TAG={}", git_tag());
|
||||
println!("cargo:rustc-env=RUSTPYTHON_GIT_BRANCH={}", git_branch());
|
||||
println!(
|
||||
"cargo:rustc-env=RUSTPYTHON_GIT_IDENTIFIER={}",
|
||||
git_identifier()
|
||||
);
|
||||
println!("cargo:rustc-env=RUSTPYTHON_BUILD_INFO={}", get_build_info());
|
||||
println!("cargo:rustc-env=RUSTC_VERSION={}", rustc_version());
|
||||
|
||||
let release_level = option_env!("RUSTPYTHON_RELEASE_LEVEL").unwrap_or("alpha");
|
||||
println!("cargo:rustc-env=RUSTPYTHON_RELEASE_LEVEL={release_level}");
|
||||
let release_level_n = release_to_n(release_level);
|
||||
println!("cargo:rustc-env=RUSTPYTHON_RELEASE_LEVEL_N={release_level_n}");
|
||||
let release_serial = option_env!("RUSTPYTHON_RELEASE_SERIAL").unwrap_or("0");
|
||||
println!("cargo:rustc-env=RUSTPYTHON_RELEASE_SERIAL={release_serial}");
|
||||
|
||||
@@ -81,11 +93,119 @@ fn git(args: &[&str]) -> io::Result<String> {
|
||||
command("git", args)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_build_info() -> String {
|
||||
// See: https://reproducible-builds.org/docs/timestamps/
|
||||
let revision = git_hash();
|
||||
let separator = if revision.is_empty() { "" } else { ":" };
|
||||
let identifier = git_identifier();
|
||||
|
||||
format!(
|
||||
"{id}{sep}{revision}, {date:.20}, {time:.9}",
|
||||
id = if identifier.is_empty() {
|
||||
"default"
|
||||
} else {
|
||||
&identifier
|
||||
},
|
||||
sep = separator,
|
||||
revision = revision,
|
||||
date = get_git_date(),
|
||||
time = get_git_time(),
|
||||
)
|
||||
}
|
||||
|
||||
fn git_identifier() -> String {
|
||||
let tag = git_tag();
|
||||
if tag.is_empty() || tag.eq_ignore_ascii_case("undefined") {
|
||||
git_branch()
|
||||
} else {
|
||||
tag
|
||||
}
|
||||
}
|
||||
|
||||
fn get_git_timestamp_datetime() -> DateTime<Local> {
|
||||
let timestamp = git_timestamp().parse::<u64>().unwrap_or_default();
|
||||
let datetime = UNIX_EPOCH + Duration::from_secs(timestamp);
|
||||
datetime.into()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_git_date() -> String {
|
||||
let datetime = get_git_timestamp_datetime();
|
||||
|
||||
datetime.format("%b %e %Y").to_string()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_git_time() -> String {
|
||||
let datetime = get_git_timestamp_datetime();
|
||||
|
||||
datetime.format("%H:%M:%S").to_string()
|
||||
}
|
||||
|
||||
fn rustc_version() -> String {
|
||||
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
|
||||
command(rustc, &["-V"]).unwrap_or_else(|_| "rustc [unknown]".into())
|
||||
}
|
||||
|
||||
fn python_version(major: usize, minor: usize, micro: usize, release: &str, serial: usize) {
|
||||
println!("cargo:rustc-env=MAJOR_CPY={major}");
|
||||
println!("cargo:rustc-env=MINOR_CPY={minor}");
|
||||
println!("cargo:rustc-env=MICRO_CPY={micro}");
|
||||
println!("cargo:rustc-env=RELEASE_LEVEL_CPY={release}");
|
||||
println!(
|
||||
"cargo:rustc-env=RELEASE_LEVEL_N_CPY={}",
|
||||
release_to_n(release)
|
||||
);
|
||||
println!("cargo:rustc-env=SERIAL_CPY={serial}");
|
||||
|
||||
println!("cargo:rustc-env=WINVER_CPY={major}.{minor}",);
|
||||
|
||||
let cpy_version = format!("{major}.{minor}.{micro}.{release}");
|
||||
|
||||
let (left, right) = get_version(&cpy_version);
|
||||
println!("cargo:rustc-env=RUSTPYTHON_VERSION_LEFT={left}");
|
||||
println!("cargo:rustc-env=RUSTPYTHON_VERSION_RIGHT={right}");
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_version(cpy_version: &str) -> (String, String) {
|
||||
// Windows: include MSC v. for compatibility with ctypes.util.find_library
|
||||
// MSC v.1929 = VS 2019, version 14+ makes find_msvcrt() return None
|
||||
let msc_info = cfg_select! {
|
||||
windows => {{
|
||||
// Include both RustPython identifier and MSC v. for compatibility
|
||||
if cfg!(target_pointer_width = "64") {
|
||||
" MSC v.1929 64 bit (AMD64)"
|
||||
} else {
|
||||
" MSC v.1929 32 bit (Intel)"
|
||||
}
|
||||
}},
|
||||
_ => "",
|
||||
};
|
||||
|
||||
// `left` and `right` are split by \n like PyPy. Passing a string with a newline to rustc
|
||||
// truncates everything from the newline onward, so we have to manually combine them later.
|
||||
let left = format!("{:.80} ({:.80})", cpy_version, get_build_info());
|
||||
let right = format!(
|
||||
"[RustPython {} with {:.80}{}]",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
rustc_version(),
|
||||
msc_info,
|
||||
);
|
||||
(left, right)
|
||||
}
|
||||
|
||||
fn release_to_n(release: &str) -> usize {
|
||||
match release {
|
||||
"alpha" => 0xA,
|
||||
"beta" => 0xB,
|
||||
"candidate" => 0xC,
|
||||
"final" => 0xD,
|
||||
_ => panic!("`release` must be one of: 'alpha', 'beta', 'candidate', 'final'"),
|
||||
}
|
||||
}
|
||||
|
||||
fn command(cmd: impl AsRef<std::ffi::OsStr>, args: &[&str]) -> io::Result<String> {
|
||||
Command::new(&cmd).args(args).output().and_then(|output| {
|
||||
// TODO: Switch to exit_ok()? when stable.
|
||||
|
||||
@@ -649,7 +649,7 @@ pub mod sys {
|
||||
fn _git(vm: &VirtualMachine) -> PyTupleRef {
|
||||
vm.new_tuple((
|
||||
ascii!("RustPython"),
|
||||
version::get_git_identifier(),
|
||||
version::GIT_IDENTIFIER,
|
||||
version::GIT_REVISION,
|
||||
))
|
||||
}
|
||||
@@ -706,17 +706,13 @@ pub mod sys {
|
||||
vm.ctx.none()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
fn version(_vm: &VirtualMachine) -> String {
|
||||
version::get_version()
|
||||
}
|
||||
#[pyattr(name = "version")]
|
||||
const VERSION: &str = version::RUSTPYTHON_VERSION;
|
||||
|
||||
// Note: This is Python DLL version in CPython, but we arbitrary fill it for compatibility
|
||||
#[cfg(windows)]
|
||||
#[pyattr]
|
||||
fn winver(_vm: &VirtualMachine) -> String {
|
||||
// Note: This is Python DLL version in CPython, but we arbitrary fill it for compatibility
|
||||
version::get_winver_number()
|
||||
}
|
||||
#[pyattr(name = "winver")]
|
||||
const WINVER: &str = version::WINVER;
|
||||
|
||||
#[pyattr]
|
||||
fn _xoptions(vm: &VirtualMachine) -> PyDictRef {
|
||||
|
||||
+50
-123
@@ -1,145 +1,72 @@
|
||||
//! Several function to retrieve version information.
|
||||
//! Version info constants.
|
||||
//!
|
||||
//! Most of the constants are auto calculated at compile time. The main exception is the
|
||||
//! target CPython version. This is defined and updated in `build.rs`.
|
||||
|
||||
use chrono::{Local, prelude::DateTime};
|
||||
use core::time::Duration;
|
||||
use std::time::UNIX_EPOCH;
|
||||
macro_rules! parse_consts {
|
||||
($name: ident, $var: literal) => {
|
||||
pub const $name: usize = match usize::from_str_radix(env!($var), 10) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!(concat!("Compile with Cargo to get '", $var, "'")),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// = 3.14.0alpha
|
||||
pub const MAJOR: usize = 3;
|
||||
pub const MINOR: usize = 14;
|
||||
pub const MICRO: usize = 0;
|
||||
pub const RELEASELEVEL: &str = "alpha";
|
||||
pub const RELEASELEVEL_N: usize = 0xA;
|
||||
pub const SERIAL: usize = 0;
|
||||
// CPython target version info
|
||||
parse_consts!(MAJOR, "MAJOR_CPY");
|
||||
parse_consts!(MINOR, "MINOR_CPY");
|
||||
parse_consts!(MICRO, "MICRO_CPY");
|
||||
pub const RELEASELEVEL: &str = env!("RELEASE_LEVEL_CPY");
|
||||
parse_consts!(RELEASELEVEL_N, "RELEASE_LEVEL_N_CPY");
|
||||
parse_consts!(SERIAL, "SERIAL_CPY");
|
||||
pub const VERSION_HEX: usize =
|
||||
(MAJOR << 24) | (MINOR << 16) | (MICRO << 8) | (RELEASELEVEL_N << 4) | SERIAL;
|
||||
|
||||
#[cfg(windows)]
|
||||
pub const WINVER: &str = env!("WINVER_CPY");
|
||||
|
||||
pub const GIT_REVISION: &str = env!("RUSTPYTHON_GIT_HASH");
|
||||
const GIT_TAG: &str = env!("RUSTPYTHON_GIT_TAG");
|
||||
const GIT_BRANCH: &str = env!("RUSTPYTHON_GIT_BRANCH");
|
||||
pub const GIT_IDENTIFIER: &str = env!("RUSTPYTHON_GIT_IDENTIFIER");
|
||||
// const GIT_TAG: &str = env!("RUSTPYTHON_GIT_TAG");
|
||||
// const GIT_BRANCH: &str = env!("RUSTPYTHON_GIT_BRANCH");
|
||||
|
||||
// RustPython version
|
||||
pub const MAJOR_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_MAJOR"), 10) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_MAJOR'"),
|
||||
};
|
||||
pub const MINOR_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_MINOR"), 10) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_MINOR'"),
|
||||
};
|
||||
pub const MICRO_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_PATCH"), 10) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_PATCH'"),
|
||||
};
|
||||
parse_consts!(MAJOR_IMPL, "CARGO_PKG_VERSION_MAJOR");
|
||||
parse_consts!(MINOR_IMPL, "CARGO_PKG_VERSION_MINOR");
|
||||
parse_consts!(MICRO_IMPL, "CARGO_PKG_VERSION_PATCH");
|
||||
pub const RELEASELEVEL_IMPL: &str = env!("RUSTPYTHON_RELEASE_LEVEL");
|
||||
pub const SERIAL_IMPL: usize = match usize::from_str_radix(env!("RUSTPYTHON_RELEASE_SERIAL"), 10) {
|
||||
Ok(v) => v,
|
||||
Err(_) => panic!("Compile with Cargo to get 'RUSTPYTHON_RELEASE_SERIAL'"),
|
||||
};
|
||||
parse_consts!(RELEASELEVEL_N_IMPL, "RUSTPYTHON_RELEASE_LEVEL_N");
|
||||
parse_consts!(SERIAL_IMPL, "RUSTPYTHON_RELEASE_SERIAL");
|
||||
pub const VERSION_HEX_IMPL: usize = (MAJOR_IMPL << 24)
|
||||
| (MINOR_IMPL << 16)
|
||||
| (MICRO_IMPL << 8)
|
||||
| (RELEASELEVEL_N << 4)
|
||||
| (RELEASELEVEL_N_IMPL << 4)
|
||||
| SERIAL_IMPL;
|
||||
|
||||
#[must_use]
|
||||
pub fn get_version() -> String {
|
||||
// Windows: include MSC v. for compatibility with ctypes.util.find_library
|
||||
// MSC v.1929 = VS 2019, version 14+ makes find_msvcrt() return None
|
||||
let msc_info = cfg_select! {
|
||||
windows => {{
|
||||
let arch = if cfg!(target_pointer_width = "64") {
|
||||
"64 bit (AMD64)"
|
||||
} else {
|
||||
"32 bit (Intel)"
|
||||
};
|
||||
// Include both RustPython identifier and MSC v. for compatibility
|
||||
format!(" MSC v.1929 {arch}",)
|
||||
}},
|
||||
_ => String::new(),
|
||||
};
|
||||
pub const RUSTPYTHON_BUILD_INFO: &str = env!("RUSTPYTHON_BUILD_INFO");
|
||||
pub const RUSTPYTHON_VERSION: &str = const {
|
||||
const LEFT: &str = env!("RUSTPYTHON_VERSION_LEFT");
|
||||
const RIGHT: &str = env!("RUSTPYTHON_VERSION_RIGHT");
|
||||
const LEN: usize = LEFT.len() + RIGHT.len() + 1;
|
||||
|
||||
format!(
|
||||
"{:.80} ({:.80}) \n[RustPython {} with {:.80}{}]", // \n is PyPy convention
|
||||
get_version_number(),
|
||||
get_build_info(),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
COMPILER,
|
||||
msc_info,
|
||||
)
|
||||
}
|
||||
const fn concat() -> [u8; LEN] {
|
||||
let mut bytes_temp = [0u8; LEN];
|
||||
|
||||
#[must_use]
|
||||
pub fn get_version_number() -> String {
|
||||
format!("{MAJOR}.{MINOR}.{MICRO}{RELEASELEVEL}")
|
||||
}
|
||||
let (left, _) = bytes_temp.split_at_mut(LEFT.len());
|
||||
left.copy_from_slice(LEFT.as_bytes());
|
||||
let (_, right) = bytes_temp.split_at_mut(LEFT.len() + 1);
|
||||
right.copy_from_slice(RIGHT.as_bytes());
|
||||
bytes_temp[LEFT.len()] = b'\n';
|
||||
|
||||
#[must_use]
|
||||
pub fn get_winver_number() -> String {
|
||||
format!("{MAJOR}.{MINOR}")
|
||||
}
|
||||
|
||||
const COMPILER: &str = env!("RUSTC_VERSION");
|
||||
|
||||
#[must_use]
|
||||
pub fn get_build_info() -> String {
|
||||
// See: https://reproducible-builds.org/docs/timestamps/
|
||||
let separator = if GIT_REVISION.is_empty() { "" } else { ":" };
|
||||
let git_identifier = get_git_identifier();
|
||||
|
||||
format!(
|
||||
"{id}{sep}{revision}, {date:.20}, {time:.9}",
|
||||
id = if git_identifier.is_empty() {
|
||||
"default"
|
||||
} else {
|
||||
git_identifier
|
||||
},
|
||||
sep = separator,
|
||||
revision = GIT_REVISION,
|
||||
date = get_git_date(),
|
||||
time = get_git_time(),
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_git_identifier() -> &'static str {
|
||||
if GIT_TAG.is_empty() || GIT_TAG.eq_ignore_ascii_case("undefined") {
|
||||
GIT_BRANCH
|
||||
} else {
|
||||
GIT_TAG
|
||||
bytes_temp
|
||||
}
|
||||
}
|
||||
|
||||
fn get_git_timestamp_datetime() -> DateTime<Local> {
|
||||
let timestamp = option_env!("RUSTPYTHON_GIT_TIMESTAMP").unwrap_or_default();
|
||||
let timestamp = timestamp.parse::<u64>().unwrap_or_default();
|
||||
|
||||
let datetime = UNIX_EPOCH + Duration::from_secs(timestamp);
|
||||
|
||||
datetime.into()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_git_date() -> String {
|
||||
let datetime = get_git_timestamp_datetime();
|
||||
|
||||
datetime.format("%b %e %Y").to_string()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_git_time() -> String {
|
||||
let datetime = get_git_timestamp_datetime();
|
||||
|
||||
datetime.format("%H:%M:%S").to_string()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_git_datetime() -> String {
|
||||
let date = get_git_date();
|
||||
let time = get_git_time();
|
||||
|
||||
format!("{date} {time}")
|
||||
}
|
||||
const BUF: [u8; LEN] = concat();
|
||||
match str::from_utf8(&BUF) {
|
||||
Ok(v) => v,
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
// Must be aligned to Lib/importlib/_bootstrap_external.py
|
||||
// Bumped to 2994 for new CommonConstant discriminants (BuiltinList, BuiltinSet)
|
||||
|
||||
+1
-1
@@ -199,7 +199,7 @@ fn help(parser: lexopt::Parser) -> ! {
|
||||
}
|
||||
|
||||
fn version() -> ! {
|
||||
println!("Python {}", rustpython_vm::version::get_version());
|
||||
println!("Python {}", rustpython_vm::version::RUSTPYTHON_VERSION);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user