mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
* Align startup home and venv paths with canonical sysconfig closure Assisted-by: OpenAI Codex:model version unavailable * Preserve selected stdlib and empty home prefix fallback Assisted-by: OpenAI Codex:model version unavailable * Collapse startup exec-prefix fallback condition Assisted-by: OpenAI Codex:model version unavailable * Preserve startup search order and freeze the ZIP bootstrap Align zipimport and its tests with CPython 3.15.0 via update_lib, preserving inherited test guards. Keep build-time fallback paths after configured paths and the default ZIP, while respecting customized embedding paths. Assisted-by: OpenAI Codex:model version unavailable * Retire proven trace coverage guards through update_lib Both canonical coverage-file tests execute successfully after preserving startup search order. Preserve the other two inherited guards and restore canonical Python 3.15 JIT optimizer decorators. Assisted-by: OpenAI Codex:model version unavailable * Align Windows symlink helper with canonical Python home layout Import the pinned CPython 3.15 PythonSymlink class through a narrow, hash-pinned update_lib mode. Preserve canonical home/VPATH behavior and explicitly supply RustPython build stdlib to the Windows child without changing runtime PYTHONHOME semantics or skipping tests. Assisted-by: OpenAI Codex:model version unavailable * Reset surviving thread completion locks after fork Reinitialize every live thread handle completion mutex and condition variable before skipping the surviving or not-yet-started handle. Preserve their completion payload and state, and retain the existing dead-thread cleanup. Assisted-by: OpenAI Codex:model version unavailable
217 lines
6.6 KiB
Rust
217 lines
6.6 KiB
Rust
#![allow(
|
|
clippy::disallowed_methods,
|
|
reason = "build scripts cannot use rustpython-host_env"
|
|
)]
|
|
|
|
use jiff::{Timestamp, Zoned, tz::TimeZone};
|
|
use std::{
|
|
env, io,
|
|
process::Command,
|
|
time::{SystemTime, UNIX_EPOCH},
|
|
};
|
|
|
|
fn main() {
|
|
let frozen_libs = if cfg!(feature = "freeze-stdlib") {
|
|
"Lib/*/*.py"
|
|
} else {
|
|
"Lib/python_builtins/*.py"
|
|
};
|
|
for entry in glob::glob(frozen_libs).expect("Lib/ exists?").flatten() {
|
|
let display = entry.display();
|
|
println!("cargo:rerun-if-changed={display}");
|
|
}
|
|
println!("cargo:rerun-if-changed=../../Lib/importlib/_bootstrap.py");
|
|
println!("cargo:rerun-if-changed=../../Lib/zipimport.py");
|
|
|
|
// = 3.15.0alpha
|
|
python_version(3, 15, 0, "alpha", 0);
|
|
|
|
println!("cargo:rustc-env=RUSTPYTHON_GIT_HASH={}", git_hash());
|
|
println!(
|
|
"cargo:rustc-env=RUSTPYTHON_GIT_TIMESTAMP={}",
|
|
git_timestamp()
|
|
);
|
|
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}");
|
|
|
|
println!(
|
|
"cargo:rustc-env=RUSTPYTHON_TARGET_TRIPLE={}",
|
|
env::var("TARGET").unwrap()
|
|
);
|
|
}
|
|
|
|
fn git_hash() -> String {
|
|
git(&["rev-parse", "--short", "HEAD"]).unwrap_or_else(|_| "0000000".into())
|
|
}
|
|
|
|
fn git_timestamp() -> String {
|
|
git(&["log", "-1", "--format=%ct"]).unwrap_or_else(|_| {
|
|
SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap_or_default()
|
|
.as_secs()
|
|
.to_string()
|
|
})
|
|
}
|
|
|
|
fn git_tag() -> String {
|
|
git(&["describe", "--all", "--always", "--dirty"])
|
|
.unwrap_or_else(|_| "heads/unknown-branch".into())
|
|
}
|
|
|
|
fn git_branch() -> String {
|
|
git(&["name-rev", "--name-only", "HEAD"]).unwrap_or_else(|_| "unknown-branch".into())
|
|
}
|
|
|
|
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_raw() -> Option<Timestamp> {
|
|
let git_timestamp = git_timestamp().parse::<i64>().ok()?;
|
|
Timestamp::from_second(git_timestamp).ok()
|
|
}
|
|
|
|
fn get_git_timestamp_datetime() -> Zoned {
|
|
get_git_timestamp_raw().map_or_else(Zoned::now, |timestamp| {
|
|
Zoned::new(timestamp, TimeZone::system())
|
|
})
|
|
}
|
|
|
|
#[must_use]
|
|
fn get_git_date() -> String {
|
|
let datetime = get_git_timestamp_datetime();
|
|
datetime.strftime("%b %e %Y").to_string()
|
|
}
|
|
|
|
#[must_use]
|
|
fn get_git_time() -> String {
|
|
let datetime = get_git_timestamp_datetime();
|
|
datetime.strftime("%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.
|
|
if !output.status.success() {
|
|
Err(io::Error::other(format!(
|
|
"command '{}' exited with status {}",
|
|
cmd.as_ref().to_string_lossy(),
|
|
output.status
|
|
)))?
|
|
}
|
|
|
|
str::from_utf8(&output.stdout)
|
|
.map(|s| s.trim().to_owned())
|
|
.map_err(io::Error::other)
|
|
})
|
|
}
|