|
1 | | -//! Several function to retrieve version information. |
2 | | -
|
3 | | -use chrono::{Local, prelude::DateTime}; |
4 | | -use core::time::Duration; |
5 | | -use std::time::UNIX_EPOCH; |
| 1 | +//! Version info constants. |
| 2 | +//! |
| 3 | +//! Most of the constants are auto calculated at compile time. The main exception is the |
| 4 | +//! target CPython version. This is defined and updated in `build.rs`. |
| 5 | +
|
| 6 | +macro_rules! parse_consts { |
| 7 | + ($name: ident, $var: literal) => { |
| 8 | + pub const $name: usize = match usize::from_str_radix(env!($var), 10) { |
| 9 | + Ok(v) => v, |
| 10 | + Err(_) => panic!(concat!("Compile with Cargo to get '", $var, "'")), |
| 11 | + }; |
| 12 | + }; |
| 13 | +} |
6 | 14 |
|
7 | | -// = 3.14.0alpha |
8 | | -pub const MAJOR: usize = 3; |
9 | | -pub const MINOR: usize = 14; |
10 | | -pub const MICRO: usize = 0; |
11 | | -pub const RELEASELEVEL: &str = "alpha"; |
12 | | -pub const RELEASELEVEL_N: usize = 0xA; |
13 | | -pub const SERIAL: usize = 0; |
| 15 | +// CPython target version info |
| 16 | +parse_consts!(MAJOR, "MAJOR_CPY"); |
| 17 | +parse_consts!(MINOR, "MINOR_CPY"); |
| 18 | +parse_consts!(MICRO, "MICRO_CPY"); |
| 19 | +pub const RELEASELEVEL: &str = env!("RELEASE_LEVEL_CPY"); |
| 20 | +parse_consts!(RELEASELEVEL_N, "RELEASE_LEVEL_N_CPY"); |
| 21 | +parse_consts!(SERIAL, "SERIAL_CPY"); |
14 | 22 | pub const VERSION_HEX: usize = |
15 | 23 | (MAJOR << 24) | (MINOR << 16) | (MICRO << 8) | (RELEASELEVEL_N << 4) | SERIAL; |
16 | 24 |
|
| 25 | +#[cfg(windows)] |
| 26 | +pub const WINVER: &str = env!("WINVER_CPY"); |
| 27 | + |
17 | 28 | pub const GIT_REVISION: &str = env!("RUSTPYTHON_GIT_HASH"); |
18 | | -const GIT_TAG: &str = env!("RUSTPYTHON_GIT_TAG"); |
19 | | -const GIT_BRANCH: &str = env!("RUSTPYTHON_GIT_BRANCH"); |
| 29 | +pub const GIT_IDENTIFIER: &str = env!("RUSTPYTHON_GIT_IDENTIFIER"); |
| 30 | +// const GIT_TAG: &str = env!("RUSTPYTHON_GIT_TAG"); |
| 31 | +// const GIT_BRANCH: &str = env!("RUSTPYTHON_GIT_BRANCH"); |
20 | 32 |
|
21 | 33 | // RustPython version |
22 | | -pub const MAJOR_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_MAJOR"), 10) { |
23 | | - Ok(v) => v, |
24 | | - Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_MAJOR'"), |
25 | | -}; |
26 | | -pub const MINOR_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_MINOR"), 10) { |
27 | | - Ok(v) => v, |
28 | | - Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_MINOR'"), |
29 | | -}; |
30 | | -pub const MICRO_IMPL: usize = match usize::from_str_radix(env!("CARGO_PKG_VERSION_PATCH"), 10) { |
31 | | - Ok(v) => v, |
32 | | - Err(_) => panic!("Compile with Cargo to get 'CARGO_PKG_VERSION_PATCH'"), |
33 | | -}; |
| 34 | +parse_consts!(MAJOR_IMPL, "CARGO_PKG_VERSION_MAJOR"); |
| 35 | +parse_consts!(MINOR_IMPL, "CARGO_PKG_VERSION_MINOR"); |
| 36 | +parse_consts!(MICRO_IMPL, "CARGO_PKG_VERSION_PATCH"); |
34 | 37 | pub const RELEASELEVEL_IMPL: &str = env!("RUSTPYTHON_RELEASE_LEVEL"); |
35 | | -pub const SERIAL_IMPL: usize = match usize::from_str_radix(env!("RUSTPYTHON_RELEASE_SERIAL"), 10) { |
36 | | - Ok(v) => v, |
37 | | - Err(_) => panic!("Compile with Cargo to get 'RUSTPYTHON_RELEASE_SERIAL'"), |
38 | | -}; |
| 38 | +parse_consts!(RELEASELEVEL_N_IMPL, "RUSTPYTHON_RELEASE_LEVEL_N"); |
| 39 | +parse_consts!(SERIAL_IMPL, "RUSTPYTHON_RELEASE_SERIAL"); |
39 | 40 | pub const VERSION_HEX_IMPL: usize = (MAJOR_IMPL << 24) |
40 | 41 | | (MINOR_IMPL << 16) |
41 | 42 | | (MICRO_IMPL << 8) |
42 | | - | (RELEASELEVEL_N << 4) |
| 43 | + | (RELEASELEVEL_N_IMPL << 4) |
43 | 44 | | SERIAL_IMPL; |
44 | 45 |
|
45 | | -#[must_use] |
46 | | -pub fn get_version() -> String { |
47 | | - // Windows: include MSC v. for compatibility with ctypes.util.find_library |
48 | | - // MSC v.1929 = VS 2019, version 14+ makes find_msvcrt() return None |
49 | | - let msc_info = cfg_select! { |
50 | | - windows => {{ |
51 | | - let arch = if cfg!(target_pointer_width = "64") { |
52 | | - "64 bit (AMD64)" |
53 | | - } else { |
54 | | - "32 bit (Intel)" |
55 | | - }; |
56 | | - // Include both RustPython identifier and MSC v. for compatibility |
57 | | - format!(" MSC v.1929 {arch}",) |
58 | | - }}, |
59 | | - _ => String::new(), |
60 | | - }; |
61 | | - |
62 | | - format!( |
63 | | - "{:.80} ({:.80}) \n[RustPython {} with {:.80}{}]", // \n is PyPy convention |
64 | | - get_version_number(), |
65 | | - get_build_info(), |
66 | | - env!("CARGO_PKG_VERSION"), |
67 | | - COMPILER, |
68 | | - msc_info, |
69 | | - ) |
70 | | -} |
71 | | - |
72 | | -#[must_use] |
73 | | -pub fn get_version_number() -> String { |
74 | | - format!("{MAJOR}.{MINOR}.{MICRO}{RELEASELEVEL}") |
75 | | -} |
76 | | - |
77 | | -#[must_use] |
78 | | -pub fn get_winver_number() -> String { |
79 | | - format!("{MAJOR}.{MINOR}") |
80 | | -} |
81 | | - |
82 | | -const COMPILER: &str = env!("RUSTC_VERSION"); |
| 46 | +pub const RUSTPYTHON_BUILD_INFO: &str = env!("RUSTPYTHON_BUILD_INFO"); |
| 47 | +pub const RUSTPYTHON_VERSION: &str = const { |
| 48 | + const LEFT: &str = env!("RUSTPYTHON_VERSION_LEFT"); |
| 49 | + const RIGHT: &str = env!("RUSTPYTHON_VERSION_RIGHT"); |
| 50 | + const LEN: usize = LEFT.len() + RIGHT.len() + 1; |
83 | 51 |
|
84 | | -#[must_use] |
85 | | -pub fn get_build_info() -> String { |
86 | | - // See: https://reproducible-builds.org/docs/timestamps/ |
87 | | - let separator = if GIT_REVISION.is_empty() { "" } else { ":" }; |
88 | | - let git_identifier = get_git_identifier(); |
| 52 | + const fn concat() -> [u8; LEN] { |
| 53 | + let mut bytes_temp = [0u8; LEN]; |
89 | 54 |
|
90 | | - format!( |
91 | | - "{id}{sep}{revision}, {date:.20}, {time:.9}", |
92 | | - id = if git_identifier.is_empty() { |
93 | | - "default" |
94 | | - } else { |
95 | | - git_identifier |
96 | | - }, |
97 | | - sep = separator, |
98 | | - revision = GIT_REVISION, |
99 | | - date = get_git_date(), |
100 | | - time = get_git_time(), |
101 | | - ) |
102 | | -} |
| 55 | + let (left, _) = bytes_temp.split_at_mut(LEFT.len()); |
| 56 | + left.copy_from_slice(LEFT.as_bytes()); |
| 57 | + let (_, right) = bytes_temp.split_at_mut(LEFT.len() + 1); |
| 58 | + right.copy_from_slice(RIGHT.as_bytes()); |
| 59 | + bytes_temp[LEFT.len()] = b'\n'; |
103 | 60 |
|
104 | | -#[must_use] |
105 | | -pub const fn get_git_identifier() -> &'static str { |
106 | | - if GIT_TAG.is_empty() || GIT_TAG.eq_ignore_ascii_case("undefined") { |
107 | | - GIT_BRANCH |
108 | | - } else { |
109 | | - GIT_TAG |
| 61 | + bytes_temp |
110 | 62 | } |
111 | | -} |
112 | | - |
113 | | -fn get_git_timestamp_datetime() -> DateTime<Local> { |
114 | | - let timestamp = option_env!("RUSTPYTHON_GIT_TIMESTAMP").unwrap_or_default(); |
115 | | - let timestamp = timestamp.parse::<u64>().unwrap_or_default(); |
116 | | - |
117 | | - let datetime = UNIX_EPOCH + Duration::from_secs(timestamp); |
118 | | - |
119 | | - datetime.into() |
120 | | -} |
121 | | - |
122 | | -#[must_use] |
123 | | -pub fn get_git_date() -> String { |
124 | | - let datetime = get_git_timestamp_datetime(); |
125 | | - |
126 | | - datetime.format("%b %e %Y").to_string() |
127 | | -} |
128 | | - |
129 | | -#[must_use] |
130 | | -pub fn get_git_time() -> String { |
131 | | - let datetime = get_git_timestamp_datetime(); |
132 | | - |
133 | | - datetime.format("%H:%M:%S").to_string() |
134 | | -} |
135 | 63 |
|
136 | | -#[must_use] |
137 | | -pub fn get_git_datetime() -> String { |
138 | | - let date = get_git_date(); |
139 | | - let time = get_git_time(); |
140 | | - |
141 | | - format!("{date} {time}") |
142 | | -} |
| 64 | + const BUF: [u8; LEN] = concat(); |
| 65 | + match str::from_utf8(&BUF) { |
| 66 | + Ok(v) => v, |
| 67 | + Err(_) => unreachable!(), |
| 68 | + } |
| 69 | +}; |
143 | 70 |
|
144 | 71 | // Must be aligned to Lib/importlib/_bootstrap_external.py |
145 | 72 | // Bumped to 2994 for new CommonConstant discriminants (BuiltinList, BuiltinSet) |
|
0 commit comments