Skip to content
This repository has been archived by the owner on Mar 26, 2024. It is now read-only.

Commit

Permalink
Add an initial dist xtask for packaging release artifacts
Browse files Browse the repository at this point in the history
There's more work to be done here, but it's a start. Honestly, adding
miniserde just to parse out the Cargo metadata seems way more difficult
than it should be to get an accurate list of the binary artifacts for
the project. There is an unstable `--out-dir` feature to copy artifacts
for you after building, but it hasn't stabilized over the past couple of
years. Not ideal.

See:
- rust-lang/cargo#3757
- rust-lang/cargo#6790 (comment)
- matklad/cargo-xtask#3
  • Loading branch information
elasticdog committed May 20, 2023
1 parent 8540f62 commit 0d5b71b
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 2 deletions.
70 changes: 70 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ license = "MIT OR Apache-2.0"
[profile.dev]
# Disabling debug info speeds up builds a bunch,
# and we don't rely on it for debugging that much.
debug = 0
debug = 0

[profile.release]
strip = true
1 change: 1 addition & 0 deletions xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ publish = false
anyhow = "1.0.71"
is_ci = "1.1.1"
lexopt = "0.3.0"
miniserde = "0.1.30"
which = "4.4.0"
xshell = "0.2.2"
3 changes: 2 additions & 1 deletion xtask/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ pub(crate) fn actionlint_cmd<'a>(config: &Config, sh: &'a Shell) -> Result<Optio
}

pub(crate) fn cargo_cmd<'a>(config: &Config, sh: &'a Shell) -> Result<Option<Cmd<'a>>> {
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
create_cmd(
"cargo",
cargo.as_str(),
"https://www.rust-lang.org/learn/get-started",
config,
sh,
Expand Down
109 changes: 109 additions & 0 deletions xtask/src/dist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use std::env;
use std::fs;
use std::path::PathBuf;

use anyhow::Result;
use miniserde::{json, Deserialize};
use xshell::Shell;

use crate::commands::cargo_cmd;
use crate::utils::{project_root, verbose_cd};
use crate::Config;

#[derive(Debug, Deserialize)]
struct Metadata {
packages: Vec<Package>,
}

#[derive(Debug, Deserialize)]
struct Package {
#[allow(dead_code)]
name: String,
targets: Vec<Target>,
}

#[derive(Debug, Deserialize)]
struct Target {
kind: Vec<String>,
name: String,
}

pub fn dist(config: &Config) -> Result<()> {
let _ = fs::remove_dir_all(dist_dir());
fs::create_dir_all(dist_dir())?;

dist_binary(config)?;
// TODO: dist_manpage()?;

Ok(())
}

fn dist_binary(config: &Config) -> Result<()> {
let sh = Shell::new()?;
verbose_cd(&sh, project_root());

let cmd_option = cargo_cmd(config, &sh)?;
if let Some(cmd) = cmd_option {
let args = vec!["build", "--release", "--bins"];
cmd.args(args).run()?;
}

let binaries = project_binaries(config)?;
for binary in &binaries {
if binary == "xtask" {
eprintln!("Ignoring xtask binary");
continue;
}

let binary_filename = if cfg!(target_os = "windows") {
format!("{}.exe", binary)
} else {
binary.to_string()
};
let src = release_dir().join(&binary_filename);
let dest = dist_dir().join(&binary_filename);

eprintln!("Copying {} to {}", src.display(), dest.display());
fs::copy(&src, &dest)?;
}

Ok(())
}

fn project_binaries(config: &Config) -> Result<Vec<String>> {
let sh = Shell::new()?;
let mut binaries = Vec::new();

let cmd_option = cargo_cmd(config, &sh)?;
if let Some(cmd) = cmd_option {
let args = vec!["metadata", "--no-deps", "--format-version=1"];
let output = cmd.args(args).output()?;

let metadata_json = String::from_utf8(output.stdout)?;
let metadata: Metadata = json::from_str(&metadata_json)?;

for package in metadata.packages {
for target in &package.targets {
if target.kind.contains(&"bin".to_string()) {
eprintln!("{:?}", package);
binaries.push(target.name.clone());
}
}
}
}

Ok(binaries)
}

fn dist_dir() -> PathBuf {
target_dir().join("dist")
}

fn release_dir() -> PathBuf {
target_dir().join("release")
}

fn target_dir() -> PathBuf {
let relative_path = env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| "target".to_string());
PathBuf::from(relative_path)
}
5 changes: 5 additions & 0 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use anyhow::Result;

mod commands;
mod coverage;
mod dist;
mod fixup;
mod install;
mod utils;
Expand All @@ -21,6 +22,7 @@ OPTIONS:
TASKS:
coverage Generate and print a code coverage report summary
coverage.html Generate and open an HTML code coverage report
dist Package project assets into distributable artifacts
fixup Run all fixup xtasks, editing files in-place
fixup.github-actions Format CUE files in-place and regenerate CI YAML files
fixup.markdown Format Markdown files in-place
Expand All @@ -32,6 +34,7 @@ TASKS:
enum Task {
Coverage,
CoverageHtml,
Dist,
Fixup,
FixupGithubActions,
FixupMarkdown,
Expand All @@ -57,6 +60,7 @@ fn main() -> Result<()> {
match task {
Task::Coverage => coverage::report_summary(&config)?,
Task::CoverageHtml => coverage::html_report(&config)?,
Task::Dist => dist::dist(&config)?,
Task::Fixup => fixup::everything(&config)?,
Task::FixupGithubActions => fixup::github_actions(&config)?,
Task::FixupMarkdown => fixup::markdown(&config)?,
Expand Down Expand Up @@ -91,6 +95,7 @@ fn parse_args() -> Result<Config> {
let task = match value.as_str() {
"coverage" => Task::Coverage,
"coverage.html" => Task::CoverageHtml,
"dist" => Task::Dist,
"fixup" => Task::Fixup,
"fixup.github-actions" => Task::FixupGithubActions,
"fixup.markdown" => Task::FixupMarkdown,
Expand Down

0 comments on commit 0d5b71b

Please sign in to comment.