From b99632be839d65982d58b97ad9d3ee621e7c85a1 Mon Sep 17 00:00:00 2001 From: Sean Smith Date: Tue, 11 Jul 2023 15:49:31 -0500 Subject: [PATCH] chore: Cross platform zipping --- justfile | 6 +- xtask/src/main.rs | 169 +++++++++----------------------------------- xtask/src/target.rs | 98 ------------------------- xtask/src/util.rs | 36 ---------- 4 files changed, 39 insertions(+), 270 deletions(-) delete mode 100644 xtask/src/target.rs delete mode 100644 xtask/src/util.rs diff --git a/justfile b/justfile index da9a9230d..df75ae4bb 100644 --- a/justfile +++ b/justfile @@ -30,7 +30,8 @@ dist triple=target_triple: protoc just build --release --target {{triple}} src_path="target/{{triple}}/release/{{executable_name}}" dest_path="target/dist/glaredb-{{triple}}.zip" - zip -j $dest_path $src_path + mkdir -p target/dist + cargo xtask zip --src $src_path --dst $dest_path # Run tests with arbitrary arguments. test *args: protoc @@ -98,6 +99,7 @@ default_target_triple := if os_arch == "macos-x86_64" { } else { error("Unsupported platform: " + os_arch) } + target_triple:= env_var_or_default("DIST_TARGET_TRIPLE", default_target_triple) protoc_url := if os_arch == "macos-x86_64" { @@ -114,4 +116,4 @@ protoc_url := if os_arch == "macos-x86_64" { error("Unsupported platform: " + os_arch) } -executable_name:= if os() == "windows" {"glaredb.exe"} else {"glaredb"} \ No newline at end of file +executable_name:= if os() == "windows" {"glaredb.exe"} else {"glaredb"} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 676f1205c..66d9d0d85 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,12 +1,11 @@ use anyhow::Result; use clap::{Parser, Subcommand}; -use std::{ffi::OsStr, io::Cursor}; -use target::Target; -use xshell::{cmd, Shell}; -use zip::ZipArchive; - -mod target; -mod util; +use std::fs::File; +use std::io; +use std::path::{Path, PathBuf}; +use xshell::Shell; +use zip::write::FileOptions; +use zip::ZipWriter; #[derive(Parser)] #[clap(name = "xtask")] @@ -18,147 +17,49 @@ struct Cli { #[derive(Subcommand)] enum Commands { - /// Build glaredb. - Build { - /// Build with the release profile. - #[clap(short, long)] - release: bool, - }, - - /// Run unit tests. - UnitTests, - - /// Run doc tests. - DocTests, - - /// Run SQL Logic Tests. - #[clap(alias = "slt")] - SqlLogicTests { - rest: Vec, - }, - - /// Run tests with arbitrary arguments. - Test { - rest: Vec, - }, - - /// Run clippy. - Clippy, - - /// Check formatting. - FmtCheck, - - /// Build the dist binary for release. - /// - /// A zip archive will be placed in `target/dist` containing the release - /// binary. + /// Zip a folder to some destination. /// - /// By default, the compilation target matches the host machine. This can be - /// overridden via the `DIST_TARGET_TRIPLE` environment variable. - Dist, - Protoc, + /// Useful for cross-platform zipping. + Zip { + /// Source folder. + #[clap(long)] + src: String, + /// Destination path. + #[clap(long)] + dst: String, + }, } fn main() -> Result<()> { let cli = Cli::parse(); let sh = &Shell::new()?; - sh.change_dir(util::project_root()); sh.set_var("CARGO_TERM_COLOR", "always"); // Always print output with color. - let target = Target::from_cfg()?; - ensure_protoc(sh, &target)?; - match cli.command { - Commands::Build { release } => run_build(sh, release)?, - Commands::UnitTests => run_tests(sh, ["--lib", "--bins"])?, - Commands::DocTests => run_tests(sh, ["--doc"])?, - Commands::SqlLogicTests { rest } => { - let args = ["--test", "sqllogictests", "--"] - .into_iter() - .chain(rest.iter().map(|s| s.as_str())); - run_tests(sh, args)? + Commands::Zip { src, dst } => { + let src = PathBuf::from(src); + let dst = PathBuf::from(dst); + zip(&src, &dst)? } - Commands::Test { rest } => run_tests(sh, rest)?, - Commands::Clippy => run_clippy(sh)?, - Commands::FmtCheck => run_fmt_check(sh)?, - Commands::Dist => run_dist(sh, &target)?, - Commands::Protoc => {} } Ok(()) } -fn run_build(sh: &Shell, release: bool) -> Result<()> { - let mut cmd = cmd!(sh, "cargo build --bin glaredb"); - if release { - cmd = cmd.arg("--release"); - } - cmd.run()?; - Ok(()) -} - -fn run_tests(sh: &Shell, rest: I) -> Result<()> -where - I: IntoIterator, - I::Item: AsRef, -{ - let cmd = sh.cmd("cargo").arg("test").args(rest); - cmd.run()?; - Ok(()) -} - -fn run_clippy(sh: &Shell) -> Result<()> { - cmd!(sh, "cargo clippy --all-features -- --deny warnings").run()?; - Ok(()) -} - -fn run_fmt_check(sh: &Shell) -> Result<()> { - cmd!(sh, "cargo fmt --check").run()?; - Ok(()) -} - -fn run_dist(sh: &Shell, target: &Target) -> Result<()> { - let triple = target.dist_target_triple()?; - cmd!(sh, "cargo build --release --bin glaredb --target {triple}").run()?; - - // TODO: Code signing goes here. - - sh.remove_path(util::project_root().join("target").join("dist"))?; - sh.create_dir(util::project_root().join("target").join("dist"))?; - - let src_path = util::project_root() - .join("target") - .join(target.dist_target_triple()?) - .join("release") - .join(target.executable_name()); - let dest_path = util::project_root() - .join("target") - .join("dist") - .join(target.dist_zip_name()?); - - util::zip(&src_path, &dest_path)?; - - println!("Dist zip: {:?}", dest_path); - Ok(()) -} - -/// Check if protoc is in path. If not, download and set the PROTOC env var. -fn ensure_protoc(sh: &Shell, target: &Target) -> Result<()> { - const PROTOC_OUT_DIR: &str = "deps/protoc"; - const PROTOC_PATH: &str = "deps/protoc/bin/protoc"; - - if cmd!(sh, "protoc --version").run().is_err() { - if sh.path_exists(util::project_root().join(PROTOC_PATH)) { - println!("Downloaded protoc already exists"); - } else { - println!("Missing protoc, downloading..."); - sh.remove_path(util::project_root().join(PROTOC_OUT_DIR))?; - let res = reqwest::blocking::get(target.protoc_url()?)?; - ZipArchive::new(Cursor::new(res.bytes()?))? - .extract(util::project_root().join(PROTOC_OUT_DIR))?; - } - - sh.set_var("PROTOC", util::project_root().join(PROTOC_PATH)); - } +/// Zip a source file and write a zip to some destination dest. +fn zip(src_path: &Path, dest_path: &Path) -> Result<()> { + let file = File::create(dest_path)?; + let mut writer = ZipWriter::new(io::BufWriter::new(file)); + writer.start_file( + src_path.file_name().unwrap().to_str().unwrap(), + FileOptions::default() + .unix_permissions(0o755) + .compression_method(zip::CompressionMethod::Deflated) + .compression_level(Some(9)), + )?; + let mut input = io::BufReader::new(File::open(src_path)?); + io::copy(&mut input, &mut writer)?; + + writer.finish()?; Ok(()) } diff --git a/xtask/src/target.rs b/xtask/src/target.rs deleted file mode 100644 index 80cfc888f..000000000 --- a/xtask/src/target.rs +++ /dev/null @@ -1,98 +0,0 @@ -use anyhow::{anyhow, Result}; -use std::env; - -pub struct Target { - arch: Arch, - os: Os, -} - -impl Target { - pub fn from_cfg() -> Result { - Ok(Target { - arch: Arch::from_cfg()?, - os: Os::from_cfg()?, - }) - } - - /// Get the target triple to use for building the dist binary for releases. - /// - /// This can be overridden by the `DIST_TARGET_TRIPLE` environment - /// variable. - pub fn dist_target_triple(&self) -> Result { - if let Ok(triple) = env::var("DIST_TARGET_TRIPLE") { - println!("Using target triple override: {triple}"); - return Ok(triple); - } - - Ok(match (&self.arch, &self.os) { - (Arch::X86_64, Os::Mac) => "x86_64-apple-darwin", - (Arch::Aarch64, Os::Mac) => "aarch64-apple-darwin", - (Arch::X86_64, Os::Linux) => "x86_64-unknown-linux-gnu", - (Arch::Aarch64, Os::Linux) => "aarch64-unknown-linux-gnu", - (Arch::X86_64, Os::Windows) => "x86_64-pc-windows-msvc", - _ => return Err(anyhow!("unsupported target")), - } - .to_string()) - } - - /// Get the url to use for downloading a protoc binary. - pub fn protoc_url(&self) -> Result<&'static str> { - Ok(match (&self.arch, &self.os) { - (Arch::X86_64, Os::Mac) => "https://github.com/protocolbuffers/protobuf/releases/download/v23.1/protoc-23.1-osx-universal_binary.zip", - (Arch::Aarch64, Os::Mac) => "https://github.com/protocolbuffers/protobuf/releases/download/v23.1/protoc-23.1-osx-universal_binary.zip", - (Arch::X86_64, Os::Linux) => "https://github.com/protocolbuffers/protobuf/releases/download/v23.1/protoc-23.1-linux-x86_64.zip", - (Arch::Aarch64, Os::Linux) => "https://github.com/protocolbuffers/protobuf/releases/download/v23.1/protoc-23.1-linux-aarch_64.zip", - (Arch::X86_64, Os::Windows) => "https://github.com/protocolbuffers/protobuf/releases/download/v23.1/protoc-23.1-win64.zip", - _ => return Err(anyhow!("unsupported target")), - }) - } - - pub fn dist_zip_name(&self) -> Result { - let target = self.dist_target_triple()?; - Ok(format!("glaredb-{target}.zip")) - } - - pub fn executable_name(&self) -> &'static str { - match self.os { - Os::Windows => "glaredb.exe", - Os::Mac | Os::Linux => "glaredb", - } - } -} - -enum Arch { - X86_64, - Aarch64, -} - -impl Arch { - fn from_cfg() -> Result { - if cfg!(target_arch = "x86_64") { - Ok(Arch::X86_64) - } else if cfg!(target_arch = "aarch64") { - Ok(Arch::Aarch64) - } else { - Err(anyhow!("unsupported arch")) - } - } -} - -enum Os { - Mac, - Linux, - Windows, -} - -impl Os { - fn from_cfg() -> Result { - if cfg!(target_os = "macos") { - Ok(Os::Mac) - } else if cfg!(target_os = "linux") { - Ok(Os::Linux) - } else if cfg!(target_os = "windows") { - Ok(Os::Windows) - } else { - Err(anyhow!("unsupported os")) - } - } -} diff --git a/xtask/src/util.rs b/xtask/src/util.rs deleted file mode 100644 index db674ee6f..000000000 --- a/xtask/src/util.rs +++ /dev/null @@ -1,36 +0,0 @@ -use anyhow::Result; -use std::env; -use std::fs::File; -use std::io; -use std::path::{Path, PathBuf}; -use zip::write::FileOptions; -use zip::ZipWriter; - -/// Get the path to the root of the project. -pub fn project_root() -> PathBuf { - Path::new( - &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()), - ) - .ancestors() - .nth(1) - .unwrap() - .to_path_buf() -} - -/// Zip a source file and write a zip to some destination dest. -pub fn zip(src_path: &Path, dest_path: &Path) -> Result<()> { - let file = File::create(dest_path)?; - let mut writer = ZipWriter::new(io::BufWriter::new(file)); - writer.start_file( - src_path.file_name().unwrap().to_str().unwrap(), - FileOptions::default() - .unix_permissions(0o755) - .compression_method(zip::CompressionMethod::Deflated) - .compression_level(Some(9)), - )?; - let mut input = io::BufReader::new(File::open(src_path)?); - io::copy(&mut input, &mut writer)?; - - writer.finish()?; - Ok(()) -}