From 5c0b32d2ccd94be9e2b128413ea338acfd0ded06 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 14 May 2024 13:46:55 -0400 Subject: [PATCH] Create lib64 symlink for 64-bit, non-macOS, POSIX environments --- .../python/get_interpreter_info.py | 5 ++++- crates/uv-interpreter/src/interpreter.rs | 10 +++++++++ crates/uv-interpreter/src/lib.rs | 2 ++ crates/uv-interpreter/src/pointer_size.rs | 21 +++++++++++++++++++ crates/uv-virtualenv/src/bare.rs | 20 +++++++++++++++++- 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 crates/uv-interpreter/src/pointer_size.rs diff --git a/crates/uv-interpreter/python/get_interpreter_info.py b/crates/uv-interpreter/python/get_interpreter_info.py index 46045d4469b3..c74b5e0245a1 100644 --- a/crates/uv-interpreter/python/get_interpreter_info.py +++ b/crates/uv-interpreter/python/get_interpreter_info.py @@ -555,9 +555,12 @@ def main() -> None: "scheme": get_scheme(), "virtualenv": get_virtualenv(), "platform": get_operating_system_and_architecture(), - # The `t` abiflag for freethreading python + # The `t` abiflag for freethreading Python. # https://peps.python.org/pep-0703/#build-configuration-changes "gil_disabled": bool(sysconfig.get_config_var("Py_GIL_DISABLED")), + # Determine if the interpreter is 32-bit or 64-bit. + # https://github.com/python/cpython/blob/b228655c227b2ca298a8ffac44d14ce3d22f6faa/Lib/venv/__init__.py#L136 + "pointer_size": "64" if sys.maxsize > 2 ** 32 else "32", } print(json.dumps(interpreter_info)) diff --git a/crates/uv-interpreter/src/interpreter.rs b/crates/uv-interpreter/src/interpreter.rs index 1331d60b1206..5538af9bc22a 100644 --- a/crates/uv-interpreter/src/interpreter.rs +++ b/crates/uv-interpreter/src/interpreter.rs @@ -17,6 +17,7 @@ use pypi_types::Scheme; use uv_cache::{Cache, CacheBucket, CachedByTimestamp, Freshness, Timestamp}; use uv_fs::{write_atomic_sync, PythonExt, Simplified}; +use crate::pointer_size::PointerSize; use crate::{Error, PythonVersion, Target, VirtualEnvironment}; /// A Python executable and its associated platform markers. @@ -35,6 +36,7 @@ pub struct Interpreter { stdlib: PathBuf, tags: OnceCell, target: Option, + pointer_size: PointerSize, gil_disabled: bool, } @@ -56,6 +58,7 @@ impl Interpreter { virtualenv: info.virtualenv, prefix: info.prefix, base_exec_prefix: info.base_exec_prefix, + pointer_size: info.pointer_size, gil_disabled: info.gil_disabled, base_prefix: info.base_prefix, base_executable: info.base_executable, @@ -95,6 +98,7 @@ impl Interpreter { stdlib: PathBuf::from("/dev/null"), tags: OnceCell::new(), target: None, + pointer_size: PointerSize::_64, gil_disabled: false, } } @@ -326,6 +330,11 @@ impl Interpreter { &self.virtualenv } + /// Return the [`PointerSize`] of the Python interpreter (i.e., 32- vs. 64-bit). + pub fn pointer_size(&self) -> PointerSize { + self.pointer_size + } + /// Return whether this is a Python 3.13+ freethreading Python, as specified by the sysconfig var /// `Py_GIL_DISABLED`. /// @@ -429,6 +438,7 @@ struct InterpreterInfo { sys_executable: PathBuf, sys_path: Vec, stdlib: PathBuf, + pointer_size: PointerSize, gil_disabled: bool, } diff --git a/crates/uv-interpreter/src/lib.rs b/crates/uv-interpreter/src/lib.rs index f0a359e00d84..e0f8e54ad654 100644 --- a/crates/uv-interpreter/src/lib.rs +++ b/crates/uv-interpreter/src/lib.rs @@ -20,6 +20,7 @@ pub use crate::environment::PythonEnvironment; pub use crate::find_python::{find_best_python, find_default_python, find_requested_python}; pub use crate::interpreter::Interpreter; use crate::interpreter::InterpreterInfoError; +pub use crate::pointer_size::PointerSize; pub use crate::python_version::PythonVersion; pub use crate::target::Target; pub use crate::virtualenv::{PyVenvConfiguration, VirtualEnvironment}; @@ -30,6 +31,7 @@ mod implementation; mod interpreter; pub mod managed; pub mod platform; +mod pointer_size; mod py_launcher; mod python_version; mod target; diff --git a/crates/uv-interpreter/src/pointer_size.rs b/crates/uv-interpreter/src/pointer_size.rs new file mode 100644 index 000000000000..bfad9b63545b --- /dev/null +++ b/crates/uv-interpreter/src/pointer_size.rs @@ -0,0 +1,21 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +pub enum PointerSize { + /// 32-bit architecture. + #[serde(rename = "32")] + _32, + /// 64-bit architecture. + #[serde(rename = "64")] + _64, +} + +impl PointerSize { + pub const fn is_32(self) -> bool { + matches!(self, Self::_32) + } + + pub const fn is_64(self) -> bool { + matches!(self, Self::_64) + } +} diff --git a/crates/uv-virtualenv/src/bare.rs b/crates/uv-virtualenv/src/bare.rs index d3c53465c536..c90b53670454 100644 --- a/crates/uv-virtualenv/src/bare.rs +++ b/crates/uv-virtualenv/src/bare.rs @@ -265,9 +265,27 @@ pub fn create_bare_venv( // Construct the path to the `site-packages` directory. let site_packages = location.join(&interpreter.virtualenv().purelib); + fs::create_dir_all(&site_packages)?; + + // If necessary, create a symlink from `lib64` to `lib`. + // See: https://github.com/python/cpython/blob/b228655c227b2ca298a8ffac44d14ce3d22f6faa/Lib/venv/__init__.py#L135C11-L135C16 + #[cfg(unix)] + if interpreter.pointer_size().is_64() + && interpreter.markers().os_name() == "posix" + && interpreter.markers().sys_platform() != "darwin" + { + let lib64 = location.join("lib64"); + let lib = location.join("lib"); + match std::os::unix::fs::symlink(lib, lib64) { + Ok(()) => {} + Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {} + Err(err) => { + return Err(err.into()); + } + } + } // Populate `site-packages` with a `_virtualenv.py` file. - fs::create_dir_all(&site_packages)?; fs::write(site_packages.join("_virtualenv.py"), VIRTUALENV_PATCH)?; fs::write(site_packages.join("_virtualenv.pth"), "import _virtualenv")?;