Skip to content

Commit f13fe17

Browse files
committed
Patch pkg-config files to be relocatable
Previously, we patched pkg-config .pc files to have the absolute path to the directory where we unpack a python-build-standalone release. As discussed in astral-sh#11028, we can use ${pcfiledir} in a .pc file to indicate paths relative to the location of the file itself. This change was implemented in astral-sh/python-build-standalone#507, so for newer python-build-standalone releases, we don't need to do any patching. Optimize this case by only modifying the .pc file if an actual change is needed (which might be helpful down the line with hard links or something). For older releases, change uv's patch to match what python-build-standalone now does.
1 parent cfd1e67 commit f13fe17

File tree

1 file changed

+29
-19
lines changed
  • crates/uv-python/src/sysconfig

1 file changed

+29
-19
lines changed

crates/uv-python/src/sysconfig/mod.rs

+29-19
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,16 @@ pub(crate) fn update_sysconfig(
172172

173173
// Update the `pkgconfig` file in-memory.
174174
let contents = fs_err::read_to_string(&pkgconfig)?;
175-
let contents = patch_pkgconfig(&contents, &real_prefix);
176-
177-
// Write the updated `pkgconfig` file.
178-
let mut file = fs_err::OpenOptions::new()
179-
.write(true)
180-
.truncate(true)
181-
.create(true)
182-
.open(&pkgconfig)?;
183-
file.write_all(contents.as_bytes())?;
184-
file.sync_data()?;
175+
if let Some(new_contents) = patch_pkgconfig(&contents) {
176+
// Write the updated `pkgconfig` file.
177+
let mut file = fs_err::OpenOptions::new()
178+
.write(true)
179+
.truncate(true)
180+
.create(true)
181+
.open(&pkgconfig)?;
182+
file.write_all(new_contents.as_bytes())?;
183+
file.sync_data()?;
184+
}
185185
}
186186

187187
Ok(())
@@ -327,12 +327,17 @@ fn find_pkgconfigs(
327327

328328
/// Patch the given `pkgconfig` contents.
329329
///
330-
/// Returns the updated contents.
331-
fn patch_pkgconfig(contents: &str, real_prefix: &Path) -> String {
332-
contents
330+
/// Returns the updated contents, if an update is needed.
331+
fn patch_pkgconfig(contents: &str) -> Option<String> {
332+
let mut changed = false;
333+
let new_contents = contents
333334
.lines()
334335
.map(|line| {
335-
// Given, e.g., `prefix=/install`, replace with `prefix=/real/prefix`.
336+
// python-build-standalone is compiled with a prefix of
337+
// /install. Replace lines like `prefix=/install` with
338+
// `prefix=${pcfiledir}/../..` (since the .pc file is in
339+
// lib/pkgconfig/). Newer versions of python-build-standalone
340+
// already have this change.
336341
let Some((prefix, suffix)) = line.split_once('=') else {
337342
return Cow::Borrowed(line);
338343
};
@@ -347,9 +352,15 @@ fn patch_pkgconfig(contents: &str, real_prefix: &Path) -> String {
347352
return Cow::Borrowed(line);
348353
}
349354

350-
Cow::Owned(format!("{}={}", prefix, real_prefix.display()))
355+
changed = true;
356+
Cow::Owned(format!("{prefix}=${{pcfiledir}}/../.."))
351357
})
352-
.join("\n")
358+
.join("\n");
359+
if changed {
360+
Some(new_contents)
361+
} else {
362+
None
363+
}
353364
}
354365

355366
#[derive(thiserror::Error, Debug)]
@@ -479,12 +490,11 @@ mod tests {
479490
"
480491
};
481492

482-
let real_prefix = Path::new("/real/prefix");
483-
let pkgconfig = patch_pkgconfig(pkgconfig, real_prefix);
493+
let pkgconfig = patch_pkgconfig(pkgconfig).unwrap();
484494

485495
insta::assert_snapshot!(pkgconfig, @r###"
486496
# See: man pkg-config
487-
prefix=/real/prefix
497+
prefix=${pcfiledir}/../..
488498
exec_prefix=${prefix}
489499
libdir=${exec_prefix}/lib
490500
includedir=${prefix}/include

0 commit comments

Comments
 (0)