Skip to content

Commit

Permalink
Add install_only_stripped binaries to release
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jul 14, 2024
1 parent 7dcdddd commit 861ffb3
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 7 deletions.
32 changes: 32 additions & 0 deletions src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use crate::release::produce_install_only_stripped;
use {
crate::release::{produce_install_only, RELEASE_TRIPLES},
anyhow::{anyhow, Result},
Expand Down Expand Up @@ -259,6 +260,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
install_paths
.par_iter()
.try_for_each(|path| -> Result<()> {
// Create the `install_only` archive.
println!(
"producing install_only archive from {}",
path.file_name()
Expand All @@ -276,6 +278,25 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
.to_string_lossy()
);

// Create the `install_only_stripped` archive.
println!(
"producing install_only_stripped archive from {}",
dest_path
.file_name()
.expect("should have file name")
.to_string_lossy()
);

let dest_path = produce_install_only_stripped(&dest_path)?;

println!(
"releasing {}",
dest_path
.file_name()
.expect("should have file name")
.to_string_lossy()
);

Ok(())
})?;

Expand Down Expand Up @@ -358,6 +379,17 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
),
format!("cpython-{}+{}-{}-install_only.tar.gz", version, tag, triple),
);

wanted_filenames.insert(
format!(
"cpython-{}-{}-install_only-{}.tar.gz",
version, triple, datetime
),
format!(
"cpython-{}+{}-{}-install_only_stripped.tar.gz",
version, tag, triple
),
);
}
}

Expand Down
30 changes: 24 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ fn main_impl() -> Result<()> {
),
);

let app = app.subcommand(
Command::new("convert-install-only-stripped")
.about("Convert an install_only .tar.gz archive to an install_only_stripped tar.gz archive")
.arg(
Arg::new("path")
.required(true)
.action(ArgAction::Append)
.value_parser(value_parser!(PathBuf))
.help("Path of archive to convert"),
),
);

let app = app.subcommand(
Command::new("upload-release-distributions")
.about("Upload release distributions to a GitHub release")
Expand Down Expand Up @@ -174,7 +186,15 @@ fn main_impl() -> Result<()> {
match matches.subcommand() {
Some(("convert-install-only", args)) => {
for path in args.get_many::<PathBuf>("path").unwrap() {
let dest_path = crate::release::produce_install_only(path)?;
let dest_path = release::produce_install_only(path)?;
println!("wrote {}", dest_path.display());
}

Ok(())
}
Some(("convert-install-only-stripped", args)) => {
for path in args.get_many::<PathBuf>("path").unwrap() {
let dest_path = release::produce_install_only_stripped(path)?;
println!("wrote {}", dest_path.display());
}

Expand All @@ -185,18 +205,16 @@ fn main_impl() -> Result<()> {
.enable_all()
.build()
.unwrap()
.block_on(crate::github::command_fetch_release_distributions(args))
.block_on(github::command_fetch_release_distributions(args))
}
Some(("upload-release-distributions", args)) => {
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(crate::github::command_upload_release_distributions(args))
}
Some(("validate-distribution", args)) => {
crate::validation::command_validate_distribution(args)
.block_on(github::command_upload_release_distributions(args))
}
Some(("validate-distribution", args)) => validation::command_validate_distribution(args),
_ => Err(anyhow!("invalid sub-command")),
}
}
Expand Down
114 changes: 113 additions & 1 deletion src/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
h
});

/// Convert a .tar.zst archive to an install only .tar.gz archive.
/// Convert a .tar.zst archive to an install-only .tar.gz archive.
pub fn convert_to_install_only<W: Write>(reader: impl BufRead, writer: W) -> Result<W> {
let dctx = zstd::stream::Decoder::new(reader)?;

Expand Down Expand Up @@ -279,6 +279,90 @@ pub fn convert_to_install_only<W: Write>(reader: impl BufRead, writer: W) -> Res
Ok(builder.into_inner()?.finish()?)
}

/// Given an install-only .tar.gz archive, strip the underlying build.
pub fn convert_to_stripped<W: Write>(reader: impl BufRead, writer: W) -> Result<W> {
// Untar the reader to disk, so that we can run `strip` on the files in-place.
let dctx = flate2::read::GzDecoder::new(reader);
let mut tar_in = tar::Archive::new(dctx);
let temp_dir = tempfile::tempdir()?;
tar_in.unpack(temp_dir.path())?;

// On macOS, strip the `.dylib` files.
if cfg!(target_os = "macos") {
for file in std::fs::read_dir(temp_dir.path().join("python/lib"))? {
let file = file?;

if file.path().extension().is_some_and(|ext| ext == "dylib") {
let size_before = file.metadata()?.len();

let output = std::process::Command::new("strip")
.arg("-S")
.arg("-x")
.arg(file.path())
.output()?;
if !output.status.success() {
return Err(anyhow!("strip failed: {:?}", output));
}

let size_after = file.metadata()?.len();
println!(
"stripped {} from {size_before} to {size_after} bytes",
file.path().strip_prefix(temp_dir.path()).unwrap().display(),
);
}
}
}

// On macOS, strip the `.dylib` files.
if cfg!(target_os = "linux") {
for file in std::fs::read_dir(temp_dir.path().join("python/lib"))? {
let file = file?;

if file.path().extension().is_some_and(|ext| ext == "so") {
let size_before = file.metadata()?.len();

let output = std::process::Command::new("strip")
.arg("--strip-unneeded")
.arg(file.path())
.output()?;
if !output.status.success() {
return Err(anyhow!("strip failed: {:?}", output));
}

let size_after = file.metadata()?.len();
println!(
"stripped {} from {size_before} to {size_after} bytes",
file.path().strip_prefix(temp_dir.path()).unwrap().display(),
);
}
}
}

// On Windows, remove `.pdb` files.
if cfg!(target_os = "windows") {
for file in std::fs::read_dir(temp_dir.path().join("python"))? {
let file = file?;
if file.path().extension().is_some_and(|ext| ext == "pdb") {
std::fs::remove_file(file.path())?;
}
}

for file in std::fs::read_dir(temp_dir.path().join("python/DLLs"))? {
let file = file?;
if file.path().extension().is_some_and(|ext| ext == "pdb") {
std::fs::remove_file(file.path())?;
}
}
}

// Tar the directory back up and write it to the writer.
let writer = flate2::write::GzEncoder::new(writer, flate2::Compression::default());
let mut builder = tar::Builder::new(writer);
builder.append_dir_all("python", temp_dir.path())?;
Ok(builder.into_inner()?.finish()?)
}

/// Create an install-only .tar.gz archive from a .tar.zst archive.
pub fn produce_install_only(tar_zst_path: &Path) -> Result<PathBuf> {
let buf = std::fs::read(tar_zst_path)?;

Expand Down Expand Up @@ -306,3 +390,31 @@ pub fn produce_install_only(tar_zst_path: &Path) -> Result<PathBuf> {

Ok(dest_path)
}

pub fn produce_install_only_stripped(tar_gz_path: &Path) -> Result<PathBuf> {
let buf = std::fs::read(tar_gz_path)?;

let gz_data =
convert_to_stripped(std::io::Cursor::new(buf), std::io::Cursor::new(vec![]))?.into_inner();

let filename = tar_gz_path
.file_name()
.expect("should have filename")
.to_string_lossy();

let mut name_parts = filename
.split('-')
.map(|x| x.to_string())
.collect::<Vec<_>>();
let parts_len = name_parts.len();

name_parts[parts_len - 1] = "install_only_stripped".to_string();

let install_only_name = name_parts.join("-");
let install_only_name = format!("{install_only_name}.tar.gz");

let dest_path = tar_gz_path.with_file_name(install_only_name);
std::fs::write(&dest_path, gz_data)?;

Ok(dest_path)
}

0 comments on commit 861ffb3

Please sign in to comment.