From c81a863e69c8e320beee3f607b29f2a054a13d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= <7822554+AlexTMjugador@users.noreply.github.com> Date: Sun, 24 Nov 2024 13:57:29 +0100 Subject: [PATCH] Move manpages generation to an xtask (#645) PR #596 brought forward automatic generation of Linux manual pages for Oxipng, which is executed every time Oxipng is built. However, while building manpages on every build is convenient for Oxipng development and doing so didn't catch my attention initially, it introduces noticeable inefficiencies for crates using Oxipng as a library: during their build, Oxipng manpages are also built, even though most dependent crates won't use such artifacts, as they are not considered part of the public Oxipng crate API or even appropriate for non-human consumption. Moreover, generating manpages depends on `clap`, which is a heavyweight dependency: according to a fresh `cargo build --timings --release` on my development workstation, its `clap_builder` dependency is the third most time consuming unit to build, totalling 1.5 s (out of 11.7 s, or 12.8%). And there is no way for dependent crates to turn this off: [`build-dependencies` cannot be conditional on crate features](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies). Potentially using other `cfg` hacks to either enable or disable manpage generation is unergonomic, if not outright disallowed. Besides reducing their compilation time cost, dependent crates may also want to trim the size of their dependency tree, avoiding unnecessary dependency downloads in the process. Therefore, a better solution to conditionally build manpages in a way convenient for both Oxipng maintainers and downstream consumers is needed. My proposal implemented in this PR is to leverage the [`cargo-xtask`](https://github.com/matklad/cargo-xtask) convention to define an auxiliary crate to move the manpage generation logic and dependencies to, which is not part of the `oxipng` crate published on `crates.io`. That way Oxipng maintainers and packagers can still generate manpages at request with ease, without any automation being noticeable to uninterested crate consumers. And as a side benefit, Oxipng maintainers can also benefit from slightly faster iteration times due to the lack of a build script for the main crate. The new `mangen` xtask can be run at any time with `cargo xtask mangen`. The generated manpages are now available at `target/xtask/mangen/manpages`. Existing deployment scripts were updated accordingly. --- .cargo/config.toml | 3 + .github/workflows/deploy.yml | 1 - Cargo.lock | 17 --- Cargo.toml | 7 +- MANUAL.txt | 6 ++ build.rs | 40 ------- scripts/manual.sh | 3 +- xtask/Cargo.lock | 200 +++++++++++++++++++++++++++++++++++ xtask/Cargo.toml | 10 ++ xtask/src/main.rs | 26 +++++ 10 files changed, 249 insertions(+), 64 deletions(-) delete mode 100644 build.rs create mode 100644 xtask/Cargo.lock create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 6265152b..dfe0a638 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,3 +1,6 @@ +[alias] +xtask = "run --manifest-path xtask/Cargo.toml --" + [target.'cfg(all(target_os = "linux", target_arch = "aarch64"))'] runner = "qemu-aarch64" # May need to remove this if targeting AArch64 from an AArch64 Linux box diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0f4062d6..f02786e3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -90,7 +90,6 @@ jobs: run: | mkdir -p "target/${{ matrix.target }}/release" mv target/oxipng "target/${{ matrix.target }}/release" - mv target/debug/assets "target/${{ matrix.target }}/release" cargo install --locked cargo-deb cargo deb --target "${{ matrix.target }}" --no-build --no-strip diff --git a/Cargo.lock b/Cargo.lock index 3154415b..0c560d0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,16 +148,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" -[[package]] -name = "clap_mangen" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbae9cbfdc5d4fa8711c09bd7b83f644cb48281ac35bf97af3e47b0675864bdf" -dependencies = [ - "clap", - "roff", -] - [[package]] name = "colorchoice" version = "1.0.3" @@ -412,7 +402,6 @@ version = "9.1.2" dependencies = [ "bitvec", "clap", - "clap_mangen", "crossbeam-channel", "env_logger", "filetime", @@ -484,12 +473,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "roff" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" - [[package]] name = "rustc-hash" version = "2.0.0" diff --git a/Cargo.toml b/Cargo.toml index 3cae1cc9..9969ee2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ exclude = [ "Dockerfile", "scripts/*", "tests/*", + "xtask/*", ] homepage = "https://github.com/shssoichiro/oxipng" license = "MIT" @@ -77,10 +78,6 @@ default-features = false features = ["png"] version = "0.25.5" -[build-dependencies] -clap = "4.5.21" -clap_mangen = "0.2.24" - [features] binary = ["dep:clap", "dep:glob", "dep:env_logger"] default = ["binary", "parallel", "zopfli", "filetime"] @@ -105,7 +102,7 @@ panic = "abort" [package.metadata.deb] assets = [ ["target/release/oxipng", "usr/bin/", "755"], - ["target/release/assets/oxipng.1", "usr/share/man/man1/", "644"], + ["target/xtask/mangen/manpages/oxipng.1", "usr/share/man/man1/", "644"], ["README.md", "usr/share/doc/oxipng/", "644"], ["CHANGELOG.md", "usr/share/doc/oxipng/", "644"], ] diff --git a/MANUAL.txt b/MANUAL.txt index 8c6dba9d..c77410aa 100644 --- a/MANUAL.txt +++ b/MANUAL.txt @@ -168,6 +168,12 @@ Options: Use the much slower but stronger Zopfli compressor for main compression trials. Recommended use is with '-o max' and '--fast'. + --zi + Set the number of iterations to use for Zopfli compression. Using fewer iterations may + speed up compression for large files. This option requires '--zopfli' to be set. + + [default: 15] + --timeout Maximum amount of time, in seconds, to spend on optimizations. Oxipng will check the timeout before each transformation or compression trial, and will stop trying to optimize diff --git a/build.rs b/build.rs deleted file mode 100644 index 12b545b1..00000000 --- a/build.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::{ - env, - fs::File, - io::{BufWriter, Error}, - path::Path, -}; - -use clap_mangen::Man; - -include!("src/cli.rs"); - -fn build_manpages(outdir: &Path) -> Result<(), Error> { - let app = build_command(); - - let file = Path::new(&outdir).join("oxipng.1"); - let mut file = BufWriter::new(File::create(file)?); - - Man::new(app).render(&mut file)?; - - Ok(()) -} - -fn main() -> Result<(), Error> { - println!("cargo:rerun-if-changed=src/cli.rs"); - println!("cargo:rerun-if-changed=src/display_chunks.rs"); - - // Create `target//assets/` folder. - let outdir = match env::var_os("OUT_DIR") { - None => return Ok(()), - Some(outdir) => outdir, - }; - let out_path = PathBuf::from(outdir); - let mut path = out_path.ancestors().nth(3).unwrap().to_owned(); - path.push("assets"); - std::fs::create_dir_all(&path).unwrap(); - - build_manpages(&path)?; - - Ok(()) -} diff --git a/scripts/manual.sh b/scripts/manual.sh index f8e2f4cc..be1fe60a 100755 --- a/scripts/manual.sh +++ b/scripts/manual.sh @@ -1,5 +1,6 @@ -#!/bin/bash +#!/bin/sh -eu cargo build +cargo xtask mangen ./target/debug/oxipng -V > MANUAL.txt #Redirect all streams to prevent detection of the terminal width and force an internal default of 100 diff --git a/xtask/Cargo.lock b/xtask/Cargo.lock new file mode 100644 index 00000000..3ea263df --- /dev/null +++ b/xtask/Cargo.lock @@ -0,0 +1,200 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "clap" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" + +[[package]] +name = "clap_mangen" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbae9cbfdc5d4fa8711c09bd7b83f644cb48281ac35bf97af3e47b0675864bdf" +dependencies = [ + "clap", + "roff", +] + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "roff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xtask" +version = "0.1.0" +dependencies = [ + "clap", + "clap_mangen", +] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 00000000..4d0d24a6 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "xtask" +description = "xtasks for the Oxipng project: https://github.com/matklad/cargo-xtask" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +clap = "4.5.21" +clap_mangen = "0.2.24" diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 00000000..13a34fce --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,26 @@ +use std::{env, error::Error, fs, fs::File, io::BufWriter}; + +use clap_mangen::Man; + +include!("../../src/cli.rs"); + +fn main() -> Result<(), Box> { + match &*env::args().nth(1).ok_or("No xtask to run provided")? { + "mangen" => build_manpages(), + _ => Err("Unknown xtask".into()), + } +} + +fn build_manpages() -> Result<(), Box> { + // Put manpages in /target/xtask/mangen/manpages. Our working directory is + // expected to be the root of the repository due to the xtask invocation alias + let manpages_dir = env::current_dir()?.join("target/xtask/mangen/manpages"); + fs::create_dir_all(&manpages_dir)?; + + let mut man_file = BufWriter::new(File::create(manpages_dir.join("oxipng.1"))?); + Man::new(build_command()).render(&mut man_file)?; + + println!("Manpages generated in {}", manpages_dir.display()); + + Ok(()) +}