mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-14 20:39:37 +00:00
feat: add dynamically generated sysconfig replacement mappings (#13441)
## Summary Implementation referenced in https://github.com/astral-sh/uv/pull/12239#issuecomment-2744880003 Closes #12919 #12901 This makes the sysconfig replacements mappings dynamically generated from https://github.com/astral-sh/python-build-standalone/blob/main/cpython-unix/targets.yml ## Test Plan cargo dev tests, and tested scenario from https://github.com/astral-sh/uv/issues/12901#issuecomment-2822107454
This commit is contained in:
parent
73eb2dfb1f
commit
d65c146b21
10 changed files with 387 additions and 117 deletions
100
crates/uv-python/src/sysconfig/generated_mappings.rs
Normal file
100
crates/uv-python/src/sysconfig/generated_mappings.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
//! DO NOT EDIT
|
||||
//!
|
||||
//! Generated with `cargo run dev generate-sysconfig-metadata`
|
||||
//! Targets from <https://github.com/astral-sh/python-build-standalone/blob/20250529/cpython-unix/targets.yml>
|
||||
//!
|
||||
#![allow(clippy::all)]
|
||||
#![cfg_attr(any(), rustfmt::skip)]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::sysconfig::replacements::{ReplacementEntry, ReplacementMode};
|
||||
|
||||
/// Mapping for sysconfig keys to lookup and replace with the appropriate entry.
|
||||
pub(crate) static DEFAULT_VARIABLE_UPDATES: LazyLock<BTreeMap<String, Vec<ReplacementEntry>>> = LazyLock::new(|| {
|
||||
BTreeMap::from_iter([
|
||||
("BLDSHARED".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "musl-clang".to_string() }, to: "cc".to_string() },
|
||||
]),
|
||||
("CC".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "musl-clang".to_string() }, to: "cc".to_string() },
|
||||
]),
|
||||
("CXX".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang++".to_string() }, to: "c++".to_string() },
|
||||
]),
|
||||
("LDCXXSHARED".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-g++".to_string() }, to: "c++".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang++".to_string() }, to: "c++".to_string() },
|
||||
]),
|
||||
("LDSHARED".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "musl-clang".to_string() }, to: "cc".to_string() },
|
||||
]),
|
||||
("LINKCC".to_string(), vec![
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/aarch64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabi-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/arm-linux-gnueabihf-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mips-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/mipsel-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/powerpc64le-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/riscv64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/s390x-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "/usr/bin/x86_64-linux-gnu-gcc".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "clang".to_string() }, to: "cc".to_string() },
|
||||
ReplacementEntry { mode: ReplacementMode::Partial { from: "musl-clang".to_string() }, to: "cc".to_string() },
|
||||
]),
|
||||
("AR".to_string(), vec![
|
||||
ReplacementEntry {
|
||||
mode: ReplacementMode::Full,
|
||||
to: "ar".to_string(),
|
||||
},
|
||||
]),
|
||||
])
|
||||
});
|
|
@ -25,131 +25,20 @@
|
|||
//! ```
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use itertools::{Either, Itertools};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::sysconfig::generated_mappings::DEFAULT_VARIABLE_UPDATES;
|
||||
use crate::sysconfig::parser::{Error as ParseError, SysconfigData, Value};
|
||||
|
||||
mod cursor;
|
||||
mod generated_mappings;
|
||||
mod parser;
|
||||
|
||||
/// Replacement mode for sysconfig values.
|
||||
#[derive(Debug)]
|
||||
enum ReplacementMode {
|
||||
Partial { from: String },
|
||||
Full,
|
||||
}
|
||||
|
||||
/// A replacement entry to patch in sysconfig data.
|
||||
#[derive(Debug)]
|
||||
struct ReplacementEntry {
|
||||
mode: ReplacementMode,
|
||||
to: String,
|
||||
}
|
||||
|
||||
impl ReplacementEntry {
|
||||
/// Patches a sysconfig value either partially (replacing a specific word) or fully.
|
||||
fn patch(&self, entry: &str) -> String {
|
||||
match &self.mode {
|
||||
ReplacementMode::Partial { from } => entry
|
||||
.split_whitespace()
|
||||
.map(|word| if word == from { &self.to } else { word })
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
ReplacementMode::Full => self.to.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mapping for sysconfig keys to lookup and replace with the appropriate entry.
|
||||
static DEFAULT_VARIABLE_UPDATES: LazyLock<BTreeMap<String, Vec<ReplacementEntry>>> =
|
||||
LazyLock::new(|| {
|
||||
BTreeMap::from_iter([
|
||||
(
|
||||
"CC".to_string(),
|
||||
vec![
|
||||
ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang".to_string(),
|
||||
},
|
||||
to: "cc".to_string(),
|
||||
},
|
||||
ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "/usr/bin/aarch64-linux-gnu-gcc".to_string(),
|
||||
},
|
||||
to: "cc".to_string(),
|
||||
},
|
||||
],
|
||||
),
|
||||
(
|
||||
"CXX".to_string(),
|
||||
vec![
|
||||
ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang++".to_string(),
|
||||
},
|
||||
to: "c++".to_string(),
|
||||
},
|
||||
ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "/usr/bin/x86_64-linux-gnu-g++".to_string(),
|
||||
},
|
||||
to: "c++".to_string(),
|
||||
},
|
||||
],
|
||||
),
|
||||
(
|
||||
"BLDSHARED".to_string(),
|
||||
vec![ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang".to_string(),
|
||||
},
|
||||
to: "cc".to_string(),
|
||||
}],
|
||||
),
|
||||
(
|
||||
"LDSHARED".to_string(),
|
||||
vec![ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang".to_string(),
|
||||
},
|
||||
to: "cc".to_string(),
|
||||
}],
|
||||
),
|
||||
(
|
||||
"LDCXXSHARED".to_string(),
|
||||
vec![ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang++".to_string(),
|
||||
},
|
||||
to: "c++".to_string(),
|
||||
}],
|
||||
),
|
||||
(
|
||||
"LINKCC".to_string(),
|
||||
vec![ReplacementEntry {
|
||||
mode: ReplacementMode::Partial {
|
||||
from: "clang".to_string(),
|
||||
},
|
||||
to: "cc".to_string(),
|
||||
}],
|
||||
),
|
||||
(
|
||||
"AR".to_string(),
|
||||
vec![ReplacementEntry {
|
||||
mode: ReplacementMode::Full,
|
||||
to: "ar".to_string(),
|
||||
}],
|
||||
),
|
||||
])
|
||||
});
|
||||
mod replacements;
|
||||
|
||||
/// Update the `sysconfig` data in a Python installation.
|
||||
pub(crate) fn update_sysconfig(
|
||||
|
|
27
crates/uv-python/src/sysconfig/replacements.rs
Normal file
27
crates/uv-python/src/sysconfig/replacements.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
/// Replacement mode for sysconfig values.
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum ReplacementMode {
|
||||
Partial { from: String },
|
||||
Full,
|
||||
}
|
||||
|
||||
/// A replacement entry to patch in sysconfig data.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ReplacementEntry {
|
||||
pub(crate) mode: ReplacementMode,
|
||||
pub(crate) to: String,
|
||||
}
|
||||
|
||||
impl ReplacementEntry {
|
||||
/// Patches a sysconfig value either partially (replacing a specific word) or fully.
|
||||
pub(crate) fn patch(&self, entry: &str) -> String {
|
||||
match &self.mode {
|
||||
ReplacementMode::Partial { from } => entry
|
||||
.split_whitespace()
|
||||
.map(|word| if word == from { &self.to } else { word })
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
ReplacementMode::Full => self.to.clone(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue