Skip to content

Commit

Permalink
feat(uv-python): support patching additional sysconfig data
Browse files Browse the repository at this point in the history
  • Loading branch information
samypr100 committed Dec 15, 2024
1 parent 9e2e9f2 commit 1d5086c
Showing 1 changed file with 132 additions and 2 deletions.
134 changes: 132 additions & 2 deletions crates/uv-python/src/sysconfig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
//! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//! ```
use std::collections::BTreeMap;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::LazyLock;

use tracing::trace;

Expand All @@ -35,6 +37,102 @@ use crate::sysconfig::parser::{Error as ParseError, SysconfigData, Value};
mod cursor;
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, ReplacementEntry>> =
LazyLock::new(|| {
BTreeMap::from_iter([
(
"CC".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang".to_string(),
},
to: "cc".to_string(),
},
),
(
"CXX".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang++".to_string(),
},
to: "c++".to_string(),
},
),
(
"BLDSHARED".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang".to_string(),
},
to: "cc".to_string(),
},
),
(
"LDSHARED".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang".to_string(),
},
to: "cc".to_string(),
},
),
(
"LDCXXSHARED".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang++".to_string(),
},
to: "c++".to_string(),
},
),
(
"LINKCC".to_string(),
ReplacementEntry {
mode: ReplacementMode::Partial {
from: "clang".to_string(),
},
to: "cc".to_string(),
},
),
(
"AR".to_string(),
ReplacementEntry {
mode: ReplacementMode::Full,
to: "ar".to_string(),
},
),
])
});

/// Update the `sysconfig` data in a Python installation.
pub(crate) fn update_sysconfig(
install_root: &Path,
Expand Down Expand Up @@ -157,7 +255,12 @@ fn patch_sysconfigdata(mut data: SysconfigData, real_prefix: &Path) -> Sysconfig
continue;
};
let patched = update_prefix(value, real_prefix);
let patched = remove_isysroot(&patched);
let mut patched = remove_isysroot(&patched);

if let Some(replacement_entry) = DEFAULT_VARIABLE_UPDATES.get(key) {
patched = replacement_entry.patch(&patched);
}

if *value != patched {
trace!("Updated `{key}` from `{value}` to `{patched}`");
count += 1;
Expand Down Expand Up @@ -233,6 +336,33 @@ mod tests {
Ok(())
}

#[test]
fn test_replacements() -> Result<(), Error> {
let sysconfigdata = [
("CC", "clang -pthread"),
("CXX", "clang++ -pthread"),
("AR", "/tools/llvm/bin/llvm-ar"),
]
.into_iter()
.map(|(k, v)| (k.to_string(), Value::String(v.to_string())))
.collect::<SysconfigData>();

let real_prefix = Path::new("/real/prefix");
let data = patch_sysconfigdata(sysconfigdata, real_prefix);

insta::assert_snapshot!(data.to_string_pretty()?, @r###"
# system configuration generated and used by the sysconfig module
build_time_vars = {
"AR": "ar",
"CC": "cc -pthread",
"CXX": "c++ -pthread",
"PYTHON_BUILD_STANDALONE": 1
}
"###);

Ok(())
}

#[test]
fn remove_isysroot() -> Result<(), Error> {
let sysconfigdata = [
Expand All @@ -248,7 +378,7 @@ mod tests {
insta::assert_snapshot!(data.to_string_pretty()?, @r###"
# system configuration generated and used by the sysconfig module
build_time_vars = {
"BLDSHARED": "clang -bundle -undefined dynamic_lookup -arch arm64",
"BLDSHARED": "cc -bundle -undefined dynamic_lookup -arch arm64",
"PYTHON_BUILD_STANDALONE": 1
}
"###);
Expand Down

0 comments on commit 1d5086c

Please sign in to comment.