mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-03 10:33:49 +00:00
Add support for dynamic musl Python distributions on x86-64 Linux (#12121)
Following the upstream release and #12120, removes gating preventing installation of the managed musl Python versions. Of note - The filtering of musl Python distributions has moved from the Rust runtime to the metadata fetcher - The filtering is now conditional on the PBS release date, removing all old static musl distributions - We could support the `+static` musl downloads in the future; right now, they are deprioritized when selecting a variant - I added test to CI which uses Alpine and installs numpy
This commit is contained in:
parent
f3fb1c5a17
commit
553bcccb6a
7 changed files with 52 additions and 10642 deletions
30
.github/workflows/ci.yml
vendored
30
.github/workflows/ci.yml
vendored
|
@ -737,6 +737,36 @@ jobs:
|
||||||
eval "$(./uv generate-shell-completion bash)"
|
eval "$(./uv generate-shell-completion bash)"
|
||||||
eval "$(./uvx --generate-shell-completion bash)"
|
eval "$(./uvx --generate-shell-completion bash)"
|
||||||
|
|
||||||
|
smoke-test-linux-musl:
|
||||||
|
timeout-minutes: 10
|
||||||
|
needs: build-binary-linux-musl
|
||||||
|
name: "check system | alpine"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: alpine:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: "Download binary"
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: uv-linux-musl-${{ github.sha }}
|
||||||
|
|
||||||
|
- name: "Prepare binary"
|
||||||
|
run: |
|
||||||
|
chmod +x ./uv
|
||||||
|
chmod +x ./uvx
|
||||||
|
|
||||||
|
- name: "Smoke test"
|
||||||
|
run: |
|
||||||
|
# Overwrite the 3.13.0 pin from the project, there are not functional
|
||||||
|
# musl distributions for it
|
||||||
|
./uv python pin 3.13
|
||||||
|
./uv venv -v
|
||||||
|
./uv pip install ruff -v
|
||||||
|
./uvx -v ruff --version
|
||||||
|
./uv pip install numpy -v
|
||||||
|
./uv run python -c "import numpy; print(numpy.__version__)"
|
||||||
|
|
||||||
smoke-test-macos:
|
smoke-test-macos:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
needs: build-binary-macos-x86_64
|
needs: build-binary-macos-x86_64
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -61,6 +61,10 @@ import httpx
|
||||||
SELF_DIR = Path(__file__).parent
|
SELF_DIR = Path(__file__).parent
|
||||||
VERSIONS_FILE = SELF_DIR / "download-metadata.json"
|
VERSIONS_FILE = SELF_DIR / "download-metadata.json"
|
||||||
|
|
||||||
|
# The date at which the default CPython musl builds became dynamically linked
|
||||||
|
# instead of statically.
|
||||||
|
CPYTHON_MUSL_STATIC_RELEASE_END = 20250311
|
||||||
|
|
||||||
|
|
||||||
def batched(iterable: Iterable, n: int) -> Generator[tuple, None, None]:
|
def batched(iterable: Iterable, n: int) -> Generator[tuple, None, None]:
|
||||||
"""Batch data into tuples of length n. The last batch may be shorter."""
|
"""Batch data into tuples of length n. The last batch may be shorter."""
|
||||||
|
@ -142,6 +146,7 @@ class Variant(StrEnum):
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PythonDownload:
|
class PythonDownload:
|
||||||
|
release: int
|
||||||
version: Version
|
version: Version
|
||||||
triple: PlatformTriple
|
triple: PlatformTriple
|
||||||
flavor: str
|
flavor: str
|
||||||
|
@ -253,6 +258,11 @@ class CPythonFinder(Finder):
|
||||||
download = self._parse_download_url(url)
|
download = self._parse_download_url(url)
|
||||||
if download is None:
|
if download is None:
|
||||||
continue
|
continue
|
||||||
|
if (
|
||||||
|
download.release < CPYTHON_MUSL_STATIC_RELEASE_END
|
||||||
|
and download.triple.libc == "musl"
|
||||||
|
):
|
||||||
|
continue
|
||||||
logging.debug("Found %s (%s)", download.key(), download.filename)
|
logging.debug("Found %s (%s)", download.key(), download.filename)
|
||||||
downloads_by_version.setdefault(download.version, []).append(
|
downloads_by_version.setdefault(download.version, []).append(
|
||||||
download
|
download
|
||||||
|
@ -341,6 +351,7 @@ class CPythonFinder(Finder):
|
||||||
if url.endswith(".sha256"):
|
if url.endswith(".sha256"):
|
||||||
return None
|
return None
|
||||||
filename = unquote(url.rsplit("/", maxsplit=1)[-1])
|
filename = unquote(url.rsplit("/", maxsplit=1)[-1])
|
||||||
|
release = int(url.rsplit("/")[-2])
|
||||||
|
|
||||||
match = self._filename_re.match(filename) or self._legacy_filename_re.match(
|
match = self._filename_re.match(filename) or self._legacy_filename_re.match(
|
||||||
filename
|
filename
|
||||||
|
@ -370,6 +381,7 @@ class CPythonFinder(Finder):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return PythonDownload(
|
return PythonDownload(
|
||||||
|
release=release,
|
||||||
version=version,
|
version=version,
|
||||||
triple=triple,
|
triple=triple,
|
||||||
flavor=flavor,
|
flavor=flavor,
|
||||||
|
@ -490,6 +502,7 @@ class PyPyFinder(Finder):
|
||||||
platform = self._normalize_os(file["platform"])
|
platform = self._normalize_os(file["platform"])
|
||||||
libc = "gnu" if platform == "linux" else "none"
|
libc = "gnu" if platform == "linux" else "none"
|
||||||
download = PythonDownload(
|
download = PythonDownload(
|
||||||
|
release=0,
|
||||||
version=python_version,
|
version=python_version,
|
||||||
triple=PlatformTriple(
|
triple=PlatformTriple(
|
||||||
platform=platform,
|
platform=platform,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -466,11 +466,7 @@ impl ManagedPythonDownload {
|
||||||
|
|
||||||
/// Iterate over all [`ManagedPythonDownload`]s.
|
/// Iterate over all [`ManagedPythonDownload`]s.
|
||||||
pub fn iter_all() -> impl Iterator<Item = &'static ManagedPythonDownload> {
|
pub fn iter_all() -> impl Iterator<Item = &'static ManagedPythonDownload> {
|
||||||
PYTHON_DOWNLOADS
|
PYTHON_DOWNLOADS.iter()
|
||||||
.iter()
|
|
||||||
// TODO(konsti): musl python-build-standalone builds are currently broken (statically
|
|
||||||
// linked), so we pretend they don't exist. https://github.com/astral-sh/uv/issues/4242
|
|
||||||
.filter(|download| download.key.libc != Libc::Some(target_lexicon::Environment::Musl))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn url(&self) -> &'static str {
|
pub fn url(&self) -> &'static str {
|
||||||
|
|
|
@ -126,6 +126,10 @@ impl Arch {
|
||||||
pub fn family(&self) -> target_lexicon::Architecture {
|
pub fn family(&self) -> target_lexicon::Architecture {
|
||||||
self.family
|
self.family
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_arm(&self) -> bool {
|
||||||
|
matches!(self.family, target_lexicon::Architecture::Arm(_))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Libc {
|
impl Display for Libc {
|
||||||
|
|
|
@ -17,7 +17,7 @@ use uv_python::downloads::{self, DownloadResult, ManagedPythonDownload, PythonDo
|
||||||
use uv_python::managed::{
|
use uv_python::managed::{
|
||||||
python_executable_dir, ManagedPythonInstallation, ManagedPythonInstallations,
|
python_executable_dir, ManagedPythonInstallation, ManagedPythonInstallations,
|
||||||
};
|
};
|
||||||
use uv_python::platform::Libc;
|
use uv_python::platform::{Arch, Libc};
|
||||||
use uv_python::{
|
use uv_python::{
|
||||||
PythonDownloads, PythonInstallationKey, PythonRequest, PythonVersionFile,
|
PythonDownloads, PythonInstallationKey, PythonRequest, PythonVersionFile,
|
||||||
VersionFileDiscoveryOptions, VersionFilePreference,
|
VersionFileDiscoveryOptions, VersionFilePreference,
|
||||||
|
@ -58,10 +58,11 @@ impl InstallRequest {
|
||||||
let download = match ManagedPythonDownload::from_request(&download_request) {
|
let download = match ManagedPythonDownload::from_request(&download_request) {
|
||||||
Ok(download) => download,
|
Ok(download) => download,
|
||||||
Err(downloads::Error::NoDownloadFound(request))
|
Err(downloads::Error::NoDownloadFound(request))
|
||||||
if request.libc().is_some_and(Libc::is_musl) =>
|
if request.libc().is_some_and(Libc::is_musl)
|
||||||
|
&& request.arch().is_some_and(Arch::is_arm) =>
|
||||||
{
|
{
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"uv does not yet provide musl Python distributions. See https://github.com/astral-sh/uv/issues/6890 to track support."
|
"uv does not yet provide musl Python distributions on aarch64."
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue