From bf39ecaf5aa8374229bb945162fa4e786d48a75f Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 19 Mar 2026 15:53:28 -0500 Subject: [PATCH 1/3] create install_only[_stripped] artifacts for freethreaded variant --- src/github.rs | 2 ++ src/release.rs | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/github.rs b/src/github.rs index aa5a87450..0d3079fe6 100644 --- a/src/github.rs +++ b/src/github.rs @@ -342,6 +342,8 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<() if build_suffix == release.install_only_suffix { install_paths.push(dest_path); + } else if build_suffix == release.freethreaded_install_only_suffix { + install_paths.push(dest_path); } } } diff --git a/src/release.rs b/src/release.rs index f37738354..e5ca46865 100644 --- a/src/release.rs +++ b/src/release.rs @@ -29,6 +29,8 @@ pub struct TripleRelease { pub suffixes: Vec<&'static str>, /// Build suffix to use for the `install_only` artifact. pub install_only_suffix: &'static str, + /// Build suffix to use for the freethreaded `install_only` artifact. + pub freethreaded_install_only_suffix: &'static str, /// Minimum Python version this triple is released for. pub python_version_requirement: Option, /// Additional build suffixes to release conditional on the Python version. @@ -84,6 +86,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: macos_suffixes.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13.0rc0").unwrap(), @@ -96,6 +99,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: macos_suffixes, install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13.0rc0").unwrap(), @@ -110,6 +114,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: vec!["pgo"], install_only_suffix: "pgo", + freethreaded_install_only_suffix: "freethreaded+pgo", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -122,6 +127,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: vec!["pgo"], install_only_suffix: "pgo", + freethreaded_install_only_suffix: "freethreaded+pgo", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -134,6 +140,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: vec!["pgo"], install_only_suffix: "pgo", + freethreaded_install_only_suffix: "freethreaded+pgo", python_version_requirement: Some(VersionSpecifier::from_str(">=3.11").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -170,6 +177,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_pgo.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -183,6 +191,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_nopgo.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -196,6 +205,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_nopgo.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -209,6 +219,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_nopgo.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -222,6 +233,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_nopgo.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -235,6 +247,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_nopgo.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -248,6 +261,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_pgo.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -260,6 +274,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_pgo.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -272,6 +287,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_pgo.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -284,6 +300,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_pgo.clone(), install_only_suffix: "pgo+lto", + freethreaded_install_only_suffix: "freethreaded+pgo+lto", python_version_requirement: Some(VersionSpecifier::from_str(">=3.10").unwrap()), conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -296,6 +313,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_musl.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -308,6 +326,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_musl.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -320,6 +339,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_musl.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -332,6 +352,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: linux_suffixes_musl.clone(), install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -344,6 +365,7 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: TripleRelease { suffixes: vec!["debug", "lto", "noopt"], install_only_suffix: "lto", + freethreaded_install_only_suffix: "freethreaded+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), @@ -605,8 +627,18 @@ pub fn produce_install_only(tar_zst_path: &Path) -> Result { .map(|x| x.to_string()) .collect::>(); let parts_len = name_parts.len(); + let flavor_idx = parts_len - 2; - name_parts[parts_len - 2] = "install_only".to_string(); + if name_parts[flavor_idx].contains("freethreaded") { + name_parts + .splice( + flavor_idx..flavor_idx + 1, + ["freethreaded".to_string(), "install_only".to_string()], + ) + .for_each(drop); + } else { + name_parts[flavor_idx] = "install_only".to_string(); + } let install_only_name = name_parts.join("-"); let install_only_name = install_only_name.replace(".tar.zst", ".tar.gz"); From e72b01d8fd04aea80fdf5d6019aee150ee6e74e8 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 19 Mar 2026 16:16:14 -0500 Subject: [PATCH 2/3] include freethreaded assets in upload --- src/release.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/release.rs b/src/release.rs index e5ca46865..f4381cd55 100644 --- a/src/release.rs +++ b/src/release.rs @@ -426,6 +426,22 @@ pub fn build_wanted_filenames( format!("cpython-{version}-{triple}-install_only_stripped-{datetime}.tar.gz"), format!("cpython-{version}+{tag}-{triple}-install_only_stripped.tar.gz"), ); + + // Free-threading only available for Python 3.13+ + let freethreaded_conditional = VersionSpecifier::from_str(">=3.13.0rc0").unwrap(); + if freethreaded_conditional.contains(&python_version) { + wanted_filenames.insert( + format!( + "cpython-{version}-{triple}-freethreaded-install_only-{datetime}.tar.gz" + ), + format!("cpython-{version}+{tag}-{triple}-freethreaded-install_only.tar.gz"), + ); + + wanted_filenames.insert( + format!("cpython-{version}-{triple}-freethreaded-install_only_stripped-{datetime}.tar.gz"), + format!("cpython-{version}+{tag}-{triple}-freethreaded-install_only_stripped.tar.gz"), + ); + } } } From da4f4781b6162497b76f47f128b96e2eb9cf7eb4 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 19 Mar 2026 16:19:46 -0500 Subject: [PATCH 3/3] update deprecated code --- src/release.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/release.rs b/src/release.rs index f4381cd55..557c197ec 100644 --- a/src/release.rs +++ b/src/release.rs @@ -776,7 +776,7 @@ pub async fn bootstrap_llvm() -> Result { Err(err) if err.kind() == std::io::ErrorKind::NotFound => {} Err(err) => return Err(err).context("failed to remove existing llvm directory"), } - tokio::fs::rename(temp_dir.into_path(), &llvm_dir).await?; + tokio::fs::rename(temp_dir.keep(), &llvm_dir).await?; Ok(llvm_dir.join("llvm")) }