use crate::builder::{BuildConfig, BuildResult, Builder, CrateBuilder};
use crate::crate_name::CrateName;
use crate::error::Result;
use crate::output::{success_message, write_stderr_line};
use crate::scanner::lints_for_library_with_experimental;
use crate::stager::Stager;
use crate::toolchain::Toolchain;
use camino::{Utf8Path, Utf8PathBuf};
use std::io::Write;
#[must_use]
pub fn build_config_from_context(context: &PipelineContext<'_>) -> BuildConfig {
BuildConfig {
toolchain: context.toolchain.clone(),
target_dir: context.workspace_root.join("target"),
jobs: context.jobs,
verbosity: context.verbosity,
experimental: context.experimental,
}
}
pub struct PipelineContext<'a> {
pub workspace_root: &'a Utf8Path,
pub toolchain: &'a Toolchain,
pub target_dir: &'a Utf8Path,
pub jobs: Option<usize>,
pub verbosity: u8,
pub experimental: bool,
pub quiet: bool,
}
pub fn perform_build(
context: &PipelineContext<'_>,
crates: &[CrateName],
stderr: &mut dyn Write,
) -> Result<Vec<BuildResult>> {
let config = build_config_from_context(context);
let builder = Builder::new(config);
perform_build_with(context, crates, &builder, stderr)
}
pub(crate) fn perform_build_with(
context: &PipelineContext<'_>,
crates: &[CrateName],
builder: &dyn CrateBuilder,
stderr: &mut dyn Write,
) -> Result<Vec<BuildResult>> {
if !context.quiet {
write_stderr_line(
stderr,
format!(
"Building {} lint crate(s) with toolchain {}...",
crates.len(),
context.toolchain.channel()
),
);
write_stderr_line(stderr, " Crates to build:");
for crate_name in crates {
write_stderr_line(stderr, format!(" - {crate_name}"));
}
write_stderr_line(stderr, "");
}
builder.build_all(crates)
}
pub fn stage_libraries(
context: &PipelineContext<'_>,
build_results: &[BuildResult],
stderr: &mut dyn Write,
) -> Result<Utf8PathBuf> {
let stager = Stager::new(context.target_dir.to_owned(), context.toolchain.channel());
let staging_path = stager.staging_path();
if !context.quiet {
write_stderr_line(stderr, format!("Staging libraries to {staging_path}..."));
}
stager.prepare()?;
stager.stage_all(build_results)?;
if !context.quiet {
log_staging_results(stderr, build_results, &staging_path, context.experimental);
}
Ok(staging_path)
}
fn log_staging_results(
stderr: &mut dyn Write,
build_results: &[BuildResult],
staging_path: &Utf8Path,
include_experimental: bool,
) {
write_stderr_line(stderr, "");
write_stderr_line(stderr, success_message(build_results.len(), staging_path));
write_stderr_line(stderr, "");
write_stderr_line(stderr, "Installed lints:");
for result in build_results {
for lint in lints_for_library_with_experimental(&result.crate_name, include_experimental) {
write_stderr_line(stderr, format!(" - {lint}"));
}
}
}
#[cfg(test)]
#[path = "pipeline_tests.rs"]
mod tests;